Skip to content

Commit 2cb8c5a

Browse files
Merge pull request #418 from supertokens/chores/finish-mt
fix: Minor changes to finish multitenancy TODO items
2 parents 3e5ad0d + d27b122 commit 2cb8c5a

File tree

40 files changed

+234
-131
lines changed

40 files changed

+234
-131
lines changed

examples/with-django/with-thirdpartyemailpassword/project/settings.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,10 +72,12 @@ def get_website_domain():
7272
thirdpartyemailpassword.ProviderClientConfig(
7373
client_id=os.environ["GOOGLE_CLIENT_ID"],
7474
client_secret=os.environ["GOOGLE_CLIENT_SECRET"],
75+
client_type="web",
7576
),
7677
thirdpartyemailpassword.ProviderClientConfig(
7778
client_id=os.environ["GOOGLE_CLIENT_ID_MOBILE"],
7879
client_secret=os.environ["GOOGLE_CLIENT_SECRET_MOBILE"],
80+
client_type="mobile",
7981
),
8082
],
8183
),
@@ -87,10 +89,12 @@ def get_website_domain():
8789
thirdpartyemailpassword.ProviderClientConfig(
8890
client_id=os.environ["GITHUB_CLIENT_ID"],
8991
client_secret=os.environ["GITHUB_CLIENT_SECRET"],
92+
client_type="web",
9093
),
9194
thirdpartyemailpassword.ProviderClientConfig(
9295
client_id=os.environ["GITHUB_CLIENT_ID_MOBILE"],
9396
client_secret=os.environ["GITHUB_CLIENT_SECRET_MOBILE"],
97+
client_type="mobile",
9498
),
9599
],
96100
)
@@ -101,6 +105,7 @@ def get_website_domain():
101105
clients=[
102106
thirdpartyemailpassword.ProviderClientConfig(
103107
client_id=os.environ["APPLE_CLIENT_ID"],
108+
client_type="web",
104109
additional_config={
105110
"keyId": os.environ["APPLE_KEY_ID"],
106111
"teamId": os.environ["APPLE_TEAM_ID"],
@@ -109,6 +114,7 @@ def get_website_domain():
109114
),
110115
thirdpartyemailpassword.ProviderClientConfig(
111116
client_id=os.environ["APPLE_CLIENT_ID_MOBILE"],
117+
client_type="mobile",
112118
additional_config={
113119
"keyId": os.environ["APPLE_KEY_ID"],
114120
"teamId": os.environ["APPLE_TEAM_ID"],
@@ -120,7 +126,7 @@ def get_website_domain():
120126
),
121127
thirdpartyemailpassword.ProviderInput(
122128
config=thirdpartyemailpassword.ProviderConfig(
123-
third_party_id="googleworkspaces",
129+
third_party_id="google-workspaces",
124130
clients=[
125131
thirdpartyemailpassword.ProviderClientConfig(
126132
client_id=os.environ["GOOGLE_WORKSPACES_CLIENT_ID"],

examples/with-fastapi/with-thirdpartyemailpassword/main.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
emailverification,
2020
session,
2121
thirdpartyemailpassword,
22+
usermetadata,
2223
)
2324
from supertokens_python.recipe.session import SessionContainer
2425
from supertokens_python.recipe.session.framework.fastapi import verify_session
@@ -54,6 +55,7 @@ def get_website_domain():
5455
session.init(),
5556
dashboard.init(),
5657
emailverification.init("REQUIRED"),
58+
usermetadata.init(),
5759
thirdpartyemailpassword.init(
5860
providers=[
5961
thirdpartyemailpassword.ProviderInput(
@@ -63,10 +65,12 @@ def get_website_domain():
6365
thirdpartyemailpassword.ProviderClientConfig(
6466
client_id=os.environ["GOOGLE_CLIENT_ID"],
6567
client_secret=os.environ["GOOGLE_CLIENT_SECRET"],
68+
client_type="web",
6669
),
6770
thirdpartyemailpassword.ProviderClientConfig(
6871
client_id=os.environ["GOOGLE_CLIENT_ID_MOBILE"],
6972
client_secret=os.environ["GOOGLE_CLIENT_SECRET_MOBILE"],
73+
client_type="mobile",
7074
),
7175
],
7276
),
@@ -78,10 +82,12 @@ def get_website_domain():
7882
thirdpartyemailpassword.ProviderClientConfig(
7983
client_id=os.environ["GITHUB_CLIENT_ID"],
8084
client_secret=os.environ["GITHUB_CLIENT_SECRET"],
85+
client_type="web",
8186
),
8287
thirdpartyemailpassword.ProviderClientConfig(
8388
client_id=os.environ["GITHUB_CLIENT_ID_MOBILE"],
8489
client_secret=os.environ["GITHUB_CLIENT_SECRET_MOBILE"],
90+
client_type="mobile",
8591
),
8692
],
8793
)
@@ -92,6 +98,7 @@ def get_website_domain():
9298
clients=[
9399
thirdpartyemailpassword.ProviderClientConfig(
94100
client_id=os.environ["APPLE_CLIENT_ID"],
101+
client_type="web",
95102
additional_config={
96103
"keyId": os.environ["APPLE_KEY_ID"],
97104
"teamId": os.environ["APPLE_TEAM_ID"],
@@ -100,6 +107,7 @@ def get_website_domain():
100107
),
101108
thirdpartyemailpassword.ProviderClientConfig(
102109
client_id=os.environ["APPLE_CLIENT_ID_MOBILE"],
110+
client_type="mobile",
103111
additional_config={
104112
"keyId": os.environ["APPLE_KEY_ID"],
105113
"teamId": os.environ["APPLE_TEAM_ID"],
@@ -111,7 +119,7 @@ def get_website_domain():
111119
),
112120
thirdpartyemailpassword.ProviderInput(
113121
config=thirdpartyemailpassword.ProviderConfig(
114-
third_party_id="googleworkspaces",
122+
third_party_id="google-workspaces",
115123
clients=[
116124
thirdpartyemailpassword.ProviderClientConfig(
117125
client_id=os.environ["GOOGLE_WORKSPACES_CLIENT_ID"],

examples/with-flask/with-thirdpartyemailpassword/app.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,12 @@ def get_website_domain():
5555
thirdpartyemailpassword.ProviderClientConfig(
5656
client_id=os.environ["GOOGLE_CLIENT_ID"],
5757
client_secret=os.environ["GOOGLE_CLIENT_SECRET"],
58+
client_type="web",
5859
),
5960
thirdpartyemailpassword.ProviderClientConfig(
6061
client_id=os.environ["GOOGLE_CLIENT_ID_MOBILE"],
6162
client_secret=os.environ["GOOGLE_CLIENT_SECRET_MOBILE"],
63+
client_type="mobile",
6264
),
6365
],
6466
),
@@ -70,10 +72,12 @@ def get_website_domain():
7072
thirdpartyemailpassword.ProviderClientConfig(
7173
client_id=os.environ["GITHUB_CLIENT_ID"],
7274
client_secret=os.environ["GITHUB_CLIENT_SECRET"],
75+
client_type="web",
7376
),
7477
thirdpartyemailpassword.ProviderClientConfig(
7578
client_id=os.environ["GITHUB_CLIENT_ID_MOBILE"],
7679
client_secret=os.environ["GITHUB_CLIENT_SECRET_MOBILE"],
80+
client_type="mobile",
7781
),
7882
],
7983
)
@@ -84,6 +88,7 @@ def get_website_domain():
8488
clients=[
8589
thirdpartyemailpassword.ProviderClientConfig(
8690
client_id=os.environ["APPLE_CLIENT_ID"],
91+
client_type="web",
8792
additional_config={
8893
"keyId": os.environ["APPLE_KEY_ID"],
8994
"teamId": os.environ["APPLE_TEAM_ID"],
@@ -92,6 +97,7 @@ def get_website_domain():
9297
),
9398
thirdpartyemailpassword.ProviderClientConfig(
9499
client_id=os.environ["APPLE_CLIENT_ID_MOBILE"],
100+
client_type="mobile",
95101
additional_config={
96102
"keyId": os.environ["APPLE_KEY_ID"],
97103
"teamId": os.environ["APPLE_TEAM_ID"],
@@ -103,7 +109,7 @@ def get_website_domain():
103109
),
104110
thirdpartyemailpassword.ProviderInput(
105111
config=thirdpartyemailpassword.ProviderConfig(
106-
third_party_id="googleworkspaces",
112+
third_party_id="google-workspaces",
107113
clients=[
108114
thirdpartyemailpassword.ProviderClientConfig(
109115
client_id=os.environ["GOOGLE_WORKSPACES_CLIENT_ID"],

supertokens_python/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,5 @@
2727
FDI_KEY_HEADER = "fdi-version"
2828
API_VERSION = "/apiversion"
2929
API_VERSION_HEADER = "cdi-version"
30-
DASHBOARD_VERSION = "0.6"
30+
DASHBOARD_VERSION = "0.7"
3131
HUNDRED_YEARS_IN_MS = 3153600000000

supertokens_python/recipe/dashboard/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414

1515
from __future__ import annotations
1616

17-
from typing import Callable, Optional, Union
17+
from typing import Callable, Optional, Union, TYPE_CHECKING
1818

1919
from supertokens_python import AppInfo, RecipeModule
20-
from supertokens_python.recipe.dashboard.utils import InputOverrideConfig
2120

2221
from .recipe import DashboardRecipe
2322

23+
if TYPE_CHECKING:
24+
from supertokens_python.recipe.dashboard.utils import InputOverrideConfig
25+
2426

2527
def init(
2628
api_key: Union[str, None] = None,

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

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

1818
async def handle_sessions_get(
1919
_api_interface: APIInterface,
20-
tenant_id: str,
20+
_tenant_id: str,
2121
api_options: APIOptions,
2222
user_context: Dict[str, Any],
2323
) -> UserSessionsGetAPIResponse:

supertokens_python/recipe/dashboard/interfaces.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,23 @@
1616
from abc import ABC, abstractmethod
1717
from typing import TYPE_CHECKING, Any, Awaitable, Callable, Dict, List, Optional, Union
1818

19-
from supertokens_python.recipe.session.interfaces import SessionInformationResult
2019
from supertokens_python.types import User
2120

2221
from ...types import APIResponse
2322

2423
if TYPE_CHECKING:
25-
from supertokens_python.framework import BaseRequest, BaseResponse
26-
2724
from ...supertokens import AppInfo
2825
from .utils import DashboardConfig, UserWithMetadata
2926

27+
from supertokens_python.recipe.session.interfaces import SessionInformationResult
28+
from supertokens_python.framework import BaseRequest, BaseResponse
29+
30+
from supertokens_python.recipe.multitenancy.interfaces import (
31+
EmailPasswordConfig,
32+
PasswordlessConfig,
33+
ThirdPartyConfig,
34+
)
35+
3036

3137
class SessionInfo:
3238
def __init__(self, info: SessionInformationResult) -> None:
@@ -36,6 +42,7 @@ def __init__(self, info: SessionInformationResult) -> None:
3642
self.expiry = info.expiry
3743
self.access_token_payload = info.custom_claims_in_access_token_payload
3844
self.time_created = info.time_created
45+
self.tenant_id = info.tenant_id
3946

4047

4148
class RecipeInterface(ABC):
@@ -101,13 +108,6 @@ def to_json(self) -> Dict[str, Any]:
101108
}
102109

103110

104-
from supertokens_python.recipe.multitenancy.interfaces import (
105-
EmailPasswordConfig,
106-
PasswordlessConfig,
107-
ThirdPartyConfig,
108-
)
109-
110-
111111
class DashboardListTenantItem:
112112
def __init__(
113113
self,
@@ -124,7 +124,7 @@ def __init__(
124124
def to_json(self):
125125
res = {
126126
"tenantId": self.tenant_id,
127-
"emailpassword": self.emailpassword.to_json(),
127+
"emailPassword": self.emailpassword.to_json(),
128128
"passwordless": self.passwordless.to_json(),
129129
"thirdParty": self.third_party.to_json(),
130130
}
@@ -210,7 +210,7 @@ def __init__(self, sessions: List[SessionInfo]):
210210
"accessTokenPayload": s.access_token_payload,
211211
"expiry": s.expiry,
212212
"sessionDataInDatabase": s.session_data_in_database,
213-
"status": "OK",
213+
"tenantId": s.tenant_id,
214214
"timeCreated": s.time_created,
215215
"userId": s.user_id,
216216
"sessionHandle": s.session_handle,

supertokens_python/recipe/dashboard/utils.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ def from_user(
8888
self.last_name = last_name
8989

9090
self.user_id = user.user_id
91+
# from_user() is called in /api/users (note extra s)
92+
# here we DashboardUsersGetResponse() doesn't maintain
93+
# recipe id for each user on its own. That's why we need
94+
# to set self.recipe_id here.
9195
self.recipe_id = user.recipe_id
9296
self.time_joined = user.time_joined
9397
self.email = user.email
@@ -101,22 +105,28 @@ def from_user(
101105

102106
def from_dict(
103107
self,
104-
user_dict: Dict[str, Any],
108+
user_obj_dict: Dict[str, Any],
105109
first_name: Optional[str] = None,
106110
last_name: Optional[str] = None,
107111
):
108112
self.first_name = first_name
109113
self.last_name = last_name
110114

111-
self.user_id = user_dict["user_id"]
112-
self.recipe_id = user_dict.get("recipe_id")
113-
self.time_joined = user_dict["time_joined"]
114-
self.email = user_dict.get("email")
115-
self.phone_number = user_dict.get("phone_number")
115+
self.user_id = user_obj_dict["user_id"]
116+
# from_dict() is used in `/api/user` where
117+
# recipe_id is already passed seperately to
118+
# GetUserForRecipeIdResult object
119+
# So we set recipe_id to None here
120+
self.recipe_id = None
121+
self.time_joined = user_obj_dict["time_joined"]
122+
self.tenant_ids = user_obj_dict.get("tenant_ids", [])
123+
124+
self.email = user_obj_dict.get("email")
125+
self.phone_number = user_obj_dict.get("phone_number")
116126
self.tp_info = (
117127
None
118-
if user_dict.get("third_party_info") is None
119-
else user_dict["third_party_info"].__dict__
128+
if user_obj_dict.get("third_party_info") is None
129+
else user_obj_dict["third_party_info"].__dict__
120130
)
121131

122132
return self
@@ -125,6 +135,7 @@ def to_json(self) -> Dict[str, Any]:
125135
user_json: Dict[str, Any] = {
126136
"id": self.user_id,
127137
"timeJoined": self.time_joined,
138+
"tenantIds": self.tenant_ids,
128139
}
129140
if self.tp_info is not None:
130141
user_json["thirdParty"] = {

supertokens_python/recipe/multitenancy/api/implementation.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,6 @@
2525

2626
from ..interfaces import APIInterface, ThirdPartyProvider
2727

28-
from supertokens_python.recipe.thirdparty.providers.config_utils import (
29-
merge_providers_from_core_and_static,
30-
find_and_create_provider_instance,
31-
)
32-
from supertokens_python.recipe.thirdparty.exceptions import ClientTypeNotFoundError
33-
3428

3529
class APIImplementation(APIInterface):
3630
async def login_methods_get(
@@ -40,6 +34,14 @@ async def login_methods_get(
4034
api_options: APIOptions,
4135
user_context: Dict[str, Any],
4236
) -> Union[LoginMethodsGetOkResult, GeneralErrorResponse]:
37+
from supertokens_python.recipe.thirdparty.providers.config_utils import (
38+
merge_providers_from_core_and_static,
39+
find_and_create_provider_instance,
40+
)
41+
42+
from supertokens_python.recipe.thirdparty.exceptions import (
43+
ClientTypeNotFoundError,
44+
)
4345

4446
tenant_config = await api_options.recipe_implementation.get_tenant(
4547
tenant_id, user_context

supertokens_python/recipe/multitenancy/interfaces.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ def __init__(
128128
def to_json(self):
129129
res = {
130130
"tenantId": self.tenant_id,
131-
"emailpassword": self.emailpassword.to_json(),
131+
"emailPassword": self.emailpassword.to_json(),
132132
"passwordless": self.passwordless.to_json(),
133133
"thirdParty": self.third_party.to_json(),
134134
"coreConfig": self.core_config,

0 commit comments

Comments
 (0)