Skip to content

Commit b5341ab

Browse files
Merge pull request #258 from supertokens/feat/dashboard-user-details
feat: Dashboard user details APIs
2 parents 115779f + c78bbff commit b5341ab

28 files changed

+1427
-92
lines changed

CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## unreleased
99

10+
## [0.11.8] - 2022-11-28
11+
12+
### Added:
13+
- APIs for user details to the dashboard recipe
14+
15+
### Changed:
16+
- Updates dashboard version to 0.2
1017
- Add tests for different scenarios while revoking session during session refresh call
1118

1219
## [0.11.7] - 2022-11-21

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@
7070

7171
setup(
7272
name="supertokens_python",
73-
version="0.11.7",
73+
version="0.11.8",
7474
author="SuperTokens",
7575
license="Apache 2.0",
7676
author_email="[email protected]",

supertokens_python/constants.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
1414
SUPPORTED_CDI_VERSIONS = ["2.9", "2.10", "2.11", "2.12", "2.13", "2.14", "2.15"]
15-
VERSION = "0.11.7"
15+
VERSION = "0.11.8"
1616
TELEMETRY = "/telemetry"
1717
USER_COUNT = "/users/count"
1818
USER_DELETE = "/user/remove"
@@ -25,4 +25,4 @@
2525
FDI_KEY_HEADER = "fdi-version"
2626
API_VERSION = "/apiversion"
2727
API_VERSION_HEADER = "cdi-version"
28-
DASHBOARD_VERSION = "0.1"
28+
DASHBOARD_VERSION = "0.2"

supertokens_python/exceptions.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
# under the License.
1414
from __future__ import annotations
1515

16-
from typing import Union
16+
from typing import Union, NoReturn
1717

1818

1919
def raise_general_exception(
@@ -26,7 +26,7 @@ def raise_general_exception(
2626
raise GeneralError(msg) from previous
2727

2828

29-
def raise_bad_input_exception(msg: str):
29+
def raise_bad_input_exception(msg: str) -> NoReturn:
3030
raise BadInputError(msg)
3131

3232

supertokens_python/recipe/dashboard/api/__init__.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,19 @@
1111
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
1212
# License for the specific language governing permissions and limitations
1313
# under the License.
14-
from .dashboard import handle_dashboard_api
1514
from .api_key_protector import api_key_protector
15+
from .dashboard import handle_dashboard_api
16+
from .userdetails.user_delete import handle_user_delete
17+
from .userdetails.user_email_verify_get import handle_user_email_verify_get
18+
from .userdetails.user_email_verify_put import handle_user_email_verify_put
19+
from .userdetails.user_email_verify_token_post import handle_email_verify_token_post
20+
from .userdetails.user_get import handle_user_get
21+
from .userdetails.user_metadata_get import handle_metadata_get
22+
from .userdetails.user_metadata_put import handle_metadata_put
23+
from .userdetails.user_password_put import handle_user_password_put
24+
from .userdetails.user_put import handle_user_put
25+
from .userdetails.user_sessions_get import handle_sessions_get
26+
from .userdetails.user_sessions_post import handle_user_sessions_post
1627
from .users_count_get import handle_users_count_get_api
1728
from .users_get import handle_users_get_api
1829
from .validate_key import handle_validate_key_api
@@ -23,4 +34,15 @@
2334
"handle_users_count_get_api",
2435
"handle_users_get_api",
2536
"handle_validate_key_api",
37+
"handle_user_email_verify_get",
38+
"handle_user_get",
39+
"handle_metadata_get",
40+
"handle_sessions_get",
41+
"handle_user_delete",
42+
"handle_user_put",
43+
"handle_user_email_verify_put",
44+
"handle_metadata_put",
45+
"handle_user_sessions_post",
46+
"handle_user_password_put",
47+
"handle_email_verify_token_post",
2648
]

supertokens_python/recipe/dashboard/api/api_key_protector.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,19 @@
2222
APIOptions,
2323
APIInterface,
2424
)
25+
from supertokens_python.types import APIResponse
2526

2627
from supertokens_python.utils import (
2728
default_user_context,
29+
send_200_response,
2830
send_non_200_response_with_message,
2931
)
3032

3133

3234
async def api_key_protector(
3335
api_implementation: APIInterface,
3436
api_options: APIOptions,
35-
api_function: Callable[
36-
[APIInterface, APIOptions], Awaitable[Optional[BaseResponse]]
37-
],
37+
api_function: Callable[[APIInterface, APIOptions], Awaitable[APIResponse]],
3838
) -> Optional[BaseResponse]:
3939
user_context = default_user_context(api_options.request)
4040
should_allow_access = await api_options.recipe_implementation.should_allow_access(
@@ -43,7 +43,8 @@ async def api_key_protector(
4343

4444
if should_allow_access is False:
4545
return send_non_200_response_with_message(
46-
"Unauthorized access", 401, api_options.response
46+
"Unauthorised access", 401, api_options.response
4747
)
4848

49-
return await api_function(api_implementation, api_options)
49+
response = await api_function(api_implementation, api_options)
50+
return send_200_response(response.to_json(), api_options.response)

supertokens_python/recipe/dashboard/api/userdetails/__init__.py

Whitespace-only changes.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
from ...interfaces import APIInterface, APIOptions, UserDeleteAPIResponse
2+
from supertokens_python.exceptions import raise_bad_input_exception
3+
from supertokens_python import Supertokens
4+
5+
6+
async def handle_user_delete(
7+
_api_interface: APIInterface, api_options: APIOptions
8+
) -> UserDeleteAPIResponse:
9+
user_id = api_options.request.get_query_param("userId")
10+
11+
if user_id is None:
12+
raise_bad_input_exception("Missing required parameter 'userId'")
13+
14+
await Supertokens.get_instance().delete_user(user_id)
15+
16+
return UserDeleteAPIResponse()
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
from supertokens_python.exceptions import raise_bad_input_exception
2+
from supertokens_python.recipe.emailverification import EmailVerificationRecipe
3+
from supertokens_python.recipe.emailverification.asyncio import is_email_verified
4+
from ...interfaces import (
5+
APIInterface,
6+
APIOptions,
7+
UserEmailVerifyGetAPIResponse,
8+
FeatureNotEnabledError,
9+
)
10+
11+
from typing import Union
12+
13+
14+
async def handle_user_email_verify_get(
15+
_api_interface: APIInterface, api_options: APIOptions
16+
) -> Union[UserEmailVerifyGetAPIResponse, FeatureNotEnabledError]:
17+
req = api_options.request
18+
user_id = req.get_query_param("userId")
19+
20+
if user_id is None:
21+
raise_bad_input_exception("Missing required parameter 'userId'")
22+
23+
try:
24+
EmailVerificationRecipe.get_instance()
25+
except Exception:
26+
return FeatureNotEnabledError()
27+
28+
is_verified = await is_email_verified(user_id)
29+
return UserEmailVerifyGetAPIResponse(is_verified)
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from typing import Any, Dict
2+
3+
from supertokens_python.exceptions import raise_bad_input_exception
4+
from supertokens_python.recipe.emailverification.asyncio import (
5+
create_email_verification_token,
6+
unverify_email,
7+
verify_email_using_token,
8+
)
9+
from supertokens_python.recipe.emailverification.interfaces import (
10+
CreateEmailVerificationTokenEmailAlreadyVerifiedError,
11+
VerifyEmailUsingTokenInvalidTokenError,
12+
)
13+
14+
from ...interfaces import (
15+
APIInterface,
16+
APIOptions,
17+
UserEmailVerifyPutAPIResponse,
18+
)
19+
20+
21+
async def handle_user_email_verify_put(
22+
_api_interface: APIInterface, api_options: APIOptions
23+
) -> UserEmailVerifyPutAPIResponse:
24+
request_body: Dict[str, Any] = await api_options.request.json() # type: ignore
25+
user_id = request_body.get("userId")
26+
verified = request_body.get("verified")
27+
28+
if user_id is None or not isinstance(user_id, str):
29+
raise_bad_input_exception(
30+
"Required parameter 'userId' is missing or has an invalid type"
31+
)
32+
33+
if verified is None or not isinstance(verified, bool):
34+
raise_bad_input_exception(
35+
"Required parameter 'verified' is missing or has an invalid type"
36+
)
37+
38+
if verified:
39+
token_response = await create_email_verification_token(user_id)
40+
41+
if isinstance(
42+
token_response, CreateEmailVerificationTokenEmailAlreadyVerifiedError
43+
):
44+
return UserEmailVerifyPutAPIResponse()
45+
46+
verify_response = await verify_email_using_token(token_response.token)
47+
48+
if isinstance(verify_response, VerifyEmailUsingTokenInvalidTokenError):
49+
# This should never happen because we consume the token immediately after creating it
50+
raise Exception("Should not come here")
51+
52+
else:
53+
await unverify_email(user_id)
54+
55+
return UserEmailVerifyPutAPIResponse()

0 commit comments

Comments
 (0)