Skip to content

Commit e8a65bf

Browse files
committed
added functions and updateed interface for email-pasword-login
1 parent 7eb9f11 commit e8a65bf

File tree

7 files changed

+142
-89
lines changed

7 files changed

+142
-89
lines changed

supertokens_python/recipe/dashboard/api/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,13 @@
1313
# under the License.
1414
from .api_key_protector import api_key_protector
1515
from .dashboard import handle_dashboard_api
16+
from .signin import handle_sign_in_api
17+
from .signout import handle_signout
1618
from .userdetails.user_delete import handle_user_delete
1719
from .userdetails.user_email_verify_get import handle_user_email_verify_get
1820
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
21+
from .userdetails.user_email_verify_token_post import \
22+
handle_email_verify_token_post
2023
from .userdetails.user_get import handle_user_get
2124
from .userdetails.user_metadata_get import handle_metadata_get
2225
from .userdetails.user_metadata_put import handle_metadata_put
@@ -45,4 +48,6 @@
4548
"handle_user_sessions_post",
4649
"handle_user_password_put",
4750
"handle_email_verify_token_post",
51+
"handle_sign_in_api",
52+
"handle_signout"
4853
]
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.
2+
#
3+
# This software is licensed under the Apache License, Version 2.0 (the
4+
# "License") as published by the Apache Software Foundation.
5+
#
6+
# You may not use this file except in compliance with the License. You may
7+
# obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
from __future__ import annotations
15+
16+
from typing import TYPE_CHECKING
17+
18+
if TYPE_CHECKING:
19+
from supertokens_python.recipe.dashboard.interfaces import (APIInterface,
20+
APIOptions)
21+
22+
23+
async def handle_sign_in_api(api_implementation: APIInterface, api_options: APIOptions):
24+
pass
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Copyright (c) 2021, VRAI Labs and/or its affiliates. All rights reserved.
2+
#
3+
# This software is licensed under the Apache License, Version 2.0 (the
4+
# "License") as published by the Apache Software Foundation.
5+
#
6+
# You may not use this file except in compliance with the License. You may
7+
# obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12+
# License for the specific language governing permissions and limitations
13+
# under the License.
14+
from __future__ import annotations
15+
16+
from typing import TYPE_CHECKING
17+
18+
if TYPE_CHECKING:
19+
from supertokens_python.recipe.dashboard.interfaces import (APIInterface,
20+
APIOptions)
21+
22+
from ..interfaces import SignOutOK
23+
24+
25+
async def handle_signout(api_implementation: APIInterface, api_options: APIOptions) -> SignOutOK:
26+
pass

supertokens_python/recipe/dashboard/constants.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,5 @@
88
USER_SESSION_API = "/api/user/sessions"
99
USER_PASSWORD_API = "/api/user/password"
1010
USER_EMAIL_VERIFY_TOKEN_API = "/api/user/email/verify/token"
11+
EMAIL_PASSWORD_SIGN_IN = "/api/signin"
12+
EMAIL_PASSSWORD_SIGNOUT = "/api/signout"

supertokens_python/recipe/dashboard/interfaces.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
from __future__ import annotations
1515

1616
from abc import ABC, abstractmethod
17-
from typing import TYPE_CHECKING, Any, Awaitable, Callable, Dict, List, Optional, Union
17+
from typing import (TYPE_CHECKING, Any, Awaitable, Callable, Dict, List,
18+
Optional, Union)
1819

19-
from supertokens_python.recipe.session.interfaces import SessionInformationResult
20+
from supertokens_python.recipe.session.interfaces import \
21+
SessionInformationResult
2022
from supertokens_python.types import User
2123

2224
from ...supertokens import AppInfo
@@ -285,3 +287,7 @@ def __init__(self, error: str) -> None:
285287

286288
def to_json(self) -> Dict[str, Any]:
287289
return {"status": self.status, "error": self.error}
290+
291+
class SignOutOK(APIResponse):
292+
def to_json(self):
293+
return {"status": "OK"}

supertokens_python/recipe/dashboard/recipe.py

Lines changed: 24 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -19,24 +19,14 @@
1919
from supertokens_python.normalised_url_path import NormalisedURLPath
2020
from supertokens_python.recipe_module import APIHandled, RecipeModule
2121

22-
from .api import (
23-
api_key_protector,
24-
handle_dashboard_api,
25-
handle_email_verify_token_post,
26-
handle_metadata_get,
27-
handle_metadata_put,
28-
handle_sessions_get,
29-
handle_user_delete,
30-
handle_user_email_verify_get,
31-
handle_user_email_verify_put,
32-
handle_user_get,
33-
handle_user_password_put,
34-
handle_user_put,
35-
handle_user_sessions_post,
36-
handle_users_count_get_api,
37-
handle_users_get_api,
38-
handle_validate_key_api,
39-
)
22+
from .api import (api_key_protector, handle_dashboard_api,
23+
handle_email_verify_token_post, handle_metadata_get,
24+
handle_metadata_put, handle_sessions_get, handle_sign_in_api,
25+
handle_signout, handle_user_delete,
26+
handle_user_email_verify_get, handle_user_email_verify_put,
27+
handle_user_get, handle_user_password_put, handle_user_put,
28+
handle_user_sessions_post, handle_users_count_get_api,
29+
handle_users_get_api, handle_validate_key_api)
4030
from .api.implementation import APIImplementation
4131
from .exceptions import SuperTokensDashboardError
4232
from .interfaces import APIInterface, APIOptions
@@ -48,26 +38,16 @@
4838
from supertokens_python.supertokens import AppInfo
4939
from supertokens_python.types import APIResponse
5040

51-
from supertokens_python.exceptions import SuperTokensError, raise_general_exception
52-
53-
from .constants import (
54-
DASHBOARD_API,
55-
USER_API,
56-
USER_EMAIL_VERIFY_API,
57-
USER_EMAIL_VERIFY_TOKEN_API,
58-
USER_METADATA_API,
59-
USER_PASSWORD_API,
60-
USER_SESSION_API,
61-
USERS_COUNT_API,
62-
USERS_LIST_GET_API,
63-
VALIDATE_KEY_API,
64-
)
65-
from .utils import (
66-
InputOverrideConfig,
67-
get_api_if_matched,
68-
is_api_path,
69-
validate_and_normalise_user_input,
70-
)
41+
from supertokens_python.exceptions import (SuperTokensError,
42+
raise_general_exception)
43+
44+
from .constants import (DASHBOARD_API, EMAIL_PASSSWORD_SIGNOUT,
45+
EMAIL_PASSWORD_SIGN_IN, USER_API,
46+
USER_EMAIL_VERIFY_API, USER_EMAIL_VERIFY_TOKEN_API,
47+
USER_METADATA_API, USER_PASSWORD_API, USER_SESSION_API,
48+
USERS_COUNT_API, USERS_LIST_GET_API, VALIDATE_KEY_API)
49+
from .utils import (InputOverrideConfig, get_api_if_matched, is_api_path,
50+
validate_and_normalise_user_input)
7151

7252

7353
class DashboardRecipe(RecipeModule):
@@ -136,6 +116,8 @@ async def handle_api_request(
136116
return await handle_dashboard_api(self.api_implementation, api_options)
137117
if request_id == VALIDATE_KEY_API:
138118
return await handle_validate_key_api(self.api_implementation, api_options)
119+
if request_id == EMAIL_PASSWORD_SIGN_IN:
120+
return await handle_sign_in_api(self.api_implementation, api_options)
139121

140122
# Do API key validation for the remaining APIs
141123
api_function: Optional[
@@ -171,6 +153,8 @@ async def handle_api_request(
171153
api_function = handle_user_password_put
172154
elif request_id == USER_EMAIL_VERIFY_TOKEN_API:
173155
api_function = handle_email_verify_token_post
156+
elif request_id == EMAIL_PASSSWORD_SIGNOUT:
157+
api_function = handle_signout
174158

175159
if api_function is not None:
176160
return await api_key_protector(
@@ -221,7 +205,8 @@ def reset():
221205
if ("SUPERTOKENS_ENV" not in environ) or (
222206
environ["SUPERTOKENS_ENV"] != "testing"
223207
):
224-
raise_general_exception("calling testing function in non testing env")
208+
raise_general_exception(
209+
"calling testing function in non testing env")
225210
DashboardRecipe.__instance = None
226211

227212
def return_api_id_if_can_handle_request(

supertokens_python/recipe/dashboard/utils.py

Lines changed: 52 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -15,47 +15,36 @@
1515

1616
from typing import TYPE_CHECKING, Any, Callable, Dict, Optional, Union
1717

18+
if TYPE_CHECKING:
19+
from supertokens_python.framework.request import BaseRequest
20+
1821
from supertokens_python.recipe.emailpassword import EmailPasswordRecipe
19-
from supertokens_python.recipe.emailpassword.asyncio import (
20-
get_user_by_id as ep_get_user_by_id,
21-
)
22+
from supertokens_python.recipe.emailpassword.asyncio import \
23+
get_user_by_id as ep_get_user_by_id
2224
from supertokens_python.recipe.passwordless import PasswordlessRecipe
23-
from supertokens_python.recipe.passwordless.asyncio import (
24-
get_user_by_id as pless_get_user_by_id,
25-
)
25+
from supertokens_python.recipe.passwordless.asyncio import \
26+
get_user_by_id as pless_get_user_by_id
2627
from supertokens_python.recipe.thirdparty import ThirdPartyRecipe
27-
from supertokens_python.recipe.thirdparty.asyncio import (
28-
get_user_by_id as tp_get_user_by_idx,
29-
)
30-
from supertokens_python.recipe.thirdpartyemailpassword import (
31-
ThirdPartyEmailPasswordRecipe,
32-
)
33-
from supertokens_python.recipe.thirdpartyemailpassword.asyncio import (
34-
get_user_by_id as tpep_get_user_by_id,
35-
)
36-
from supertokens_python.recipe.thirdpartypasswordless import (
37-
ThirdPartyPasswordlessRecipe,
38-
)
39-
from supertokens_python.recipe.thirdpartypasswordless.asyncio import (
40-
get_user_by_id as tppless_get_user_by_id,
41-
)
28+
from supertokens_python.recipe.thirdparty.asyncio import \
29+
get_user_by_id as tp_get_user_by_idx
30+
from supertokens_python.recipe.thirdpartyemailpassword import \
31+
ThirdPartyEmailPasswordRecipe
32+
from supertokens_python.recipe.thirdpartyemailpassword.asyncio import \
33+
get_user_by_id as tpep_get_user_by_id
34+
from supertokens_python.recipe.thirdpartypasswordless import \
35+
ThirdPartyPasswordlessRecipe
36+
from supertokens_python.recipe.thirdpartypasswordless.asyncio import \
37+
get_user_by_id as tppless_get_user_by_id
4238
from supertokens_python.types import User
4339
from supertokens_python.utils import Awaitable
4440

4541
from ...normalised_url_path import NormalisedURLPath
4642
from ...supertokens import AppInfo
47-
from .constants import (
48-
DASHBOARD_API,
49-
USER_API,
50-
USER_EMAIL_VERIFY_API,
51-
USER_EMAIL_VERIFY_TOKEN_API,
52-
USER_METADATA_API,
53-
USER_PASSWORD_API,
54-
USER_SESSION_API,
55-
USERS_COUNT_API,
56-
USERS_LIST_GET_API,
57-
VALIDATE_KEY_API,
58-
)
43+
from .constants import (DASHBOARD_API, EMAIL_PASSSWORD_SIGNOUT,
44+
EMAIL_PASSWORD_SIGN_IN, USER_API,
45+
USER_EMAIL_VERIFY_API, USER_EMAIL_VERIFY_TOKEN_API,
46+
USER_METADATA_API, USER_PASSWORD_API, USER_SESSION_API,
47+
USERS_COUNT_API, USERS_LIST_GET_API, VALIDATE_KEY_API)
5948

6049
if TYPE_CHECKING:
6150
from .interfaces import APIInterface, RecipeInterface
@@ -143,7 +132,8 @@ def to_json(self) -> Dict[str, Any]:
143132
class InputOverrideConfig:
144133
def __init__(
145134
self,
146-
functions: Union[Callable[[RecipeInterface], RecipeInterface], None] = None,
135+
functions: Union[Callable[[RecipeInterface],
136+
RecipeInterface], None] = None,
147137
apis: Union[Callable[[APIInterface], APIInterface], None] = None,
148138
):
149139
self.functions = functions
@@ -153,7 +143,8 @@ def __init__(
153143
class OverrideConfig:
154144
def __init__(
155145
self,
156-
functions: Union[Callable[[RecipeInterface], RecipeInterface], None] = None,
146+
functions: Union[Callable[[RecipeInterface],
147+
RecipeInterface], None] = None,
157148
apis: Union[Callable[[APIInterface], APIInterface], None] = None,
158149
):
159150
self.functions = functions
@@ -165,18 +156,18 @@ def __init__(
165156
self,
166157
api_key: str,
167158
override: OverrideConfig,
159+
auth_mode: str
168160
):
169161
self.api_key = api_key
170162
self.override = override
163+
self.auth_mode = auth_mode
171164

172165

173166
def validate_and_normalise_user_input(
174167
# app_info: AppInfo,
175168
api_key: str,
176169
override: Optional[InputOverrideConfig] = None,
177170
) -> DashboardConfig:
178-
if api_key.strip() == "":
179-
raise Exception("apiKey provided to Dashboard recipe cannot be empty")
180171

181172
if override is None:
182173
override = InputOverrideConfig()
@@ -187,6 +178,7 @@ def validate_and_normalise_user_input(
187178
functions=override.functions,
188179
apis=override.apis,
189180
),
181+
"api-key" if api_key else "email-password"
190182
)
191183

192184

@@ -198,7 +190,8 @@ def is_api_path(path: NormalisedURLPath, app_info: AppInfo) -> bool:
198190
if not path.startswith(dashboard_recipe_base_path):
199191
return False
200192

201-
path_without_dashboard_path = path.get_as_string_dangerous().split(DASHBOARD_API)[1]
193+
path_without_dashboard_path = path.get_as_string_dangerous().split(DASHBOARD_API)[
194+
1]
202195

203196
if len(path_without_dashboard_path) > 0 and path_without_dashboard_path[0] == "/":
204197
path_without_dashboard_path = path_without_dashboard_path[1:]
@@ -230,6 +223,10 @@ def get_api_if_matched(path: NormalisedURLPath, method: str) -> Optional[str]:
230223
return USER_PASSWORD_API
231224
if path_str.endswith(USER_EMAIL_VERIFY_TOKEN_API) and method == "post":
232225
return USER_EMAIL_VERIFY_TOKEN_API
226+
if path_str.endswith(EMAIL_PASSWORD_SIGN_IN) and method == "post":
227+
return EMAIL_PASSWORD_SIGN_IN
228+
if path_str.endswith(EMAIL_PASSSWORD_SIGNOUT) and method == "post":
229+
return EMAIL_PASSSWORD_SIGNOUT
233230

234231
return None
235232

@@ -245,15 +242,16 @@ def __init__(self, user: UserWithMetadata, recipe: str):
245242

246243

247244
if TYPE_CHECKING:
248-
from supertokens_python.recipe.emailpassword.types import User as EmailPasswordUser
249-
from supertokens_python.recipe.passwordless.types import User as PasswordlessUser
250-
from supertokens_python.recipe.thirdparty.types import User as ThirdPartyUser
251-
from supertokens_python.recipe.thirdpartyemailpassword.types import (
252-
User as ThirdPartyEmailPasswordUser,
253-
)
254-
from supertokens_python.recipe.thirdpartypasswordless.types import (
255-
User as ThirdPartyPasswordlessUser,
256-
)
245+
from supertokens_python.recipe.emailpassword.types import \
246+
User as EmailPasswordUser
247+
from supertokens_python.recipe.passwordless.types import \
248+
User as PasswordlessUser
249+
from supertokens_python.recipe.thirdparty.types import \
250+
User as ThirdPartyUser
251+
from supertokens_python.recipe.thirdpartyemailpassword.types import \
252+
User as ThirdPartyEmailPasswordUser
253+
from supertokens_python.recipe.thirdpartypasswordless.types import \
254+
User as ThirdPartyPasswordlessUser
257255

258256
GetUserResult = Union[
259257
EmailPasswordUser,
@@ -385,3 +383,10 @@ def is_recipe_initialised(recipeId: str) -> bool:
385383
pass
386384

387385
return isRecipeInitialised
386+
387+
388+
def validate_APIKey(req: BaseRequest, config: DashboardConfig) -> bool:
389+
apiKeyHeaderValue = req.get_header("authorization")
390+
if not apiKeyHeaderValue:
391+
return False
392+
return apiKeyHeaderValue == config.api_key

0 commit comments

Comments
 (0)