Skip to content

Commit c0f5322

Browse files
committed
fix: Suggested changes
1 parent 832afa3 commit c0f5322

File tree

4 files changed

+123
-171
lines changed

4 files changed

+123
-171
lines changed

supertokens_python/recipe/multitenancy/asyncio/__init__.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@
2323
CreateOrUpdateThirdPartyConfigOkResult,
2424
DeleteThirdPartyConfigOkResult,
2525
AssociateUserToTenantOkResult,
26-
AssociateUserToTenantUnknownUserIdErrorResult,
27-
AssociateUserToTenantEmailAlreadyExistsErrorResult,
28-
AssociateUserToTenantPhoneNumberAlreadyExistsErrorResult,
29-
AssociateUserToTenantThirdPartyUserAlreadyExistsErrorResult,
26+
AssociateUserToTenantUnknownUserIdError,
27+
AssociateUserToTenantEmailAlreadyExistsError,
28+
AssociateUserToTenantPhoneNumberAlreadyExistsError,
29+
AssociateUserToTenantThirdPartyUserAlreadyExistsError,
3030
DisassociateUserFromTenantOkResult,
3131
)
3232
from ..recipe import MultitenancyRecipe
@@ -117,10 +117,10 @@ async def associate_user_to_tenant(
117117
user_context: Optional[Dict[str, Any]] = None,
118118
) -> Union[
119119
AssociateUserToTenantOkResult,
120-
AssociateUserToTenantUnknownUserIdErrorResult,
121-
AssociateUserToTenantEmailAlreadyExistsErrorResult,
122-
AssociateUserToTenantPhoneNumberAlreadyExistsErrorResult,
123-
AssociateUserToTenantThirdPartyUserAlreadyExistsErrorResult,
120+
AssociateUserToTenantUnknownUserIdError,
121+
AssociateUserToTenantEmailAlreadyExistsError,
122+
AssociateUserToTenantPhoneNumberAlreadyExistsError,
123+
AssociateUserToTenantThirdPartyUserAlreadyExistsError,
124124
]:
125125
if user_context is None:
126126
user_context = {}

supertokens_python/recipe/multitenancy/interfaces.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -129,19 +129,19 @@ def __init__(self, was_already_associated: bool):
129129
self.was_already_associated = was_already_associated
130130

131131

132-
class AssociateUserToTenantUnknownUserIdErrorResult:
132+
class AssociateUserToTenantUnknownUserIdError:
133133
status = "UNKNOWN_USER_ID_ERROR"
134134

135135

136-
class AssociateUserToTenantEmailAlreadyExistsErrorResult:
136+
class AssociateUserToTenantEmailAlreadyExistsError:
137137
status = "EMAIL_ALREADY_EXISTS_ERROR"
138138

139139

140-
class AssociateUserToTenantPhoneNumberAlreadyExistsErrorResult:
140+
class AssociateUserToTenantPhoneNumberAlreadyExistsError:
141141
status = "PHONE_NUMBER_ALREADY_EXISTS_ERROR"
142142

143143

144-
class AssociateUserToTenantThirdPartyUserAlreadyExistsErrorResult:
144+
class AssociateUserToTenantThirdPartyUserAlreadyExistsError:
145145
status = "THIRD_PARTY_USER_ALREADY_EXISTS_ERROR"
146146

147147

@@ -218,10 +218,10 @@ async def associate_user_to_tenant(
218218
user_context: Dict[str, Any],
219219
) -> Union[
220220
AssociateUserToTenantOkResult,
221-
AssociateUserToTenantUnknownUserIdErrorResult,
222-
AssociateUserToTenantEmailAlreadyExistsErrorResult,
223-
AssociateUserToTenantPhoneNumberAlreadyExistsErrorResult,
224-
AssociateUserToTenantThirdPartyUserAlreadyExistsErrorResult,
221+
AssociateUserToTenantUnknownUserIdError,
222+
AssociateUserToTenantEmailAlreadyExistsError,
223+
AssociateUserToTenantPhoneNumberAlreadyExistsError,
224+
AssociateUserToTenantThirdPartyUserAlreadyExistsError,
225225
]:
226226
pass
227227

supertokens_python/recipe/multitenancy/recipe_implementation.py

Lines changed: 105 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
from typing import TYPE_CHECKING, Optional, Dict, Any, Union, List
1717
from supertokens_python.recipe.multitenancy.interfaces import (
1818
AssociateUserToTenantOkResult,
19-
AssociateUserToTenantUnknownUserIdErrorResult,
20-
AssociateUserToTenantEmailAlreadyExistsErrorResult,
21-
AssociateUserToTenantPhoneNumberAlreadyExistsErrorResult,
22-
AssociateUserToTenantThirdPartyUserAlreadyExistsErrorResult,
19+
AssociateUserToTenantUnknownUserIdError,
20+
AssociateUserToTenantEmailAlreadyExistsError,
21+
AssociateUserToTenantPhoneNumberAlreadyExistsError,
22+
AssociateUserToTenantThirdPartyUserAlreadyExistsError,
2323
DisassociateUserFromTenantOkResult,
2424
)
2525

@@ -47,6 +47,76 @@
4747
from .constants import DEFAULT_TENANT_ID
4848

4949

50+
def parse_tenant_config(tenant: Dict[str, Any]) -> TenantConfigResponse:
51+
from supertokens_python.recipe.thirdparty.provider import (
52+
UserInfoMap,
53+
UserFields,
54+
ProviderClientConfig,
55+
)
56+
57+
providers: List[ProviderConfig] = []
58+
for p in tenant["thirdParty"]["providers"]:
59+
user_info_map: Optional[UserInfoMap] = None
60+
if "userInfoMap" in p:
61+
map_from_payload = p["userInfoMap"].get("fromIdTokenPayload", {})
62+
map_from_api = p["userInfoMap"].get("fromUserInfoAPI", {})
63+
user_info_map = UserInfoMap(
64+
UserFields(
65+
map_from_payload.get("userId"),
66+
map_from_payload.get("email"),
67+
map_from_payload.get("emailVerified"),
68+
),
69+
UserFields(
70+
map_from_api.get("userId"),
71+
map_from_api.get("email"),
72+
map_from_api.get("emailVerified"),
73+
),
74+
)
75+
76+
providers.append(
77+
ProviderConfig(
78+
third_party_id=p["thirdPartyId"],
79+
name=p["name"],
80+
clients=[
81+
ProviderClientConfig(
82+
client_id=c["clientId"],
83+
client_secret=c["clientSecret"],
84+
client_type=c["clientType"],
85+
scope=c["scope"],
86+
force_pkce=c["forcePkce"],
87+
additional_config=c["additionalConfig"],
88+
)
89+
for c in p["clients"]
90+
],
91+
authorization_endpoint=p["authorizationEndpoint"],
92+
authorization_endpoint_query_params=p[
93+
"authorizationEndpointQueryParams"
94+
],
95+
token_endpoint=p["tokenEndpoint"],
96+
token_endpoint_body_params=p["tokenEndpointBodyParams"],
97+
user_info_endpoint=p["userInfoEndpoint"],
98+
user_info_endpoint_query_params=p["userInfoEndpointQueryParams"],
99+
user_info_endpoint_headers=p["userInfoEndpointHeaders"],
100+
jwks_uri=p["jwksUri"],
101+
oidc_discovery_endpoint=p["oidcDiscoveryEndpoint"],
102+
user_info_map=user_info_map,
103+
require_email=p["requireEmail"],
104+
validate_id_token_payload=p["validateIdTokenPayload"],
105+
generate_fake_email=p["generateFakeEmail"],
106+
)
107+
)
108+
109+
return TenantConfigResponse(
110+
emailpassword=EmailPasswordConfig(tenant["emailPassword"]["enabled"]),
111+
passwordless=PasswordlessConfig(tenant["passwordless"]["enabled"]),
112+
third_party=ThirdPartyConfig(
113+
tenant["thirdParty"]["enabled"],
114+
providers,
115+
),
116+
core_config=tenant["coreConfig"],
117+
)
118+
119+
50120
class RecipeImplementation(RecipeInterface):
51121
def __init__(self, querier: Querier, config: MultitenancyConfig):
52122
super().__init__()
@@ -89,93 +159,24 @@ async def delete_tenant(
89159
async def get_tenant(
90160
self, tenant_id: Optional[str], user_context: Dict[str, Any]
91161
) -> GetTenantOkResult:
92-
from supertokens_python.recipe.thirdparty.provider import (
93-
ProviderConfig,
94-
UserInfoMap,
95-
UserFields,
96-
ProviderClientConfig,
97-
)
98-
99162
res = await self.querier.send_get_request(
100163
NormalisedURLPath(
101164
f"{tenant_id or DEFAULT_TENANT_ID}/recipe/multitenancy/tenant"
102165
),
103166
)
104167

105-
providers: List[ProviderConfig] = []
106-
for p in res["thirdParty"]["providers"]:
107-
user_info_map: Optional[UserInfoMap] = None
108-
if "userInfoMap" in p:
109-
map_from_payload = p["userInfoMap"].get("fromIdTokenPayload", {})
110-
map_from_api = p["userInfoMap"].get("fromUserInfoAPI", {})
111-
user_info_map = UserInfoMap(
112-
UserFields(
113-
map_from_payload.get("userId"),
114-
map_from_payload.get("email"),
115-
map_from_payload.get("emailVerified"),
116-
),
117-
UserFields(
118-
map_from_api.get("userId"),
119-
map_from_api.get("email"),
120-
map_from_api.get("emailVerified"),
121-
),
122-
)
123-
124-
providers.append(
125-
ProviderConfig(
126-
third_party_id=p["thirdPartyId"],
127-
name=p["name"],
128-
clients=[
129-
ProviderClientConfig(
130-
client_id=c["clientId"],
131-
client_secret=c.get("clientSecret"),
132-
client_type=c.get("clientType"),
133-
scope=c.get("scope"),
134-
force_pkce=c.get("forcePkce"),
135-
additional_config=c.get("additionalConfig"),
136-
)
137-
for c in p["clients"]
138-
],
139-
authorization_endpoint=p.get("authorizationEndpoint"),
140-
authorization_endpoint_query_params=p.get(
141-
"authorizationEndpointQueryParams"
142-
),
143-
token_endpoint=p.get("tokenEndpoint"),
144-
token_endpoint_body_params=p.get("tokenEndpointBodyParams"),
145-
user_info_endpoint=p.get("userInfoEndpoint"),
146-
user_info_endpoint_query_params=p.get(
147-
"userInfoEndpointQueryParams"
148-
),
149-
user_info_endpoint_headers=p.get("userInfoEndpointHeaders"),
150-
jwks_uri=p.get("jwksUri"),
151-
oidc_discovery_endpoint=p.get("oidcDiscoveryEndpoint"),
152-
user_info_map=user_info_map,
153-
require_email=p.get("requireEmail"),
154-
validate_id_token_payload=None,
155-
generate_fake_email=None,
156-
)
157-
)
168+
tenant_config = parse_tenant_config(res)
158169

159170
return GetTenantOkResult(
160-
emailpassword=EmailPasswordConfig(res["emailPassword"]["enabled"]),
161-
passwordless=PasswordlessConfig(res["passwordless"]["enabled"]),
162-
third_party=ThirdPartyConfig(
163-
res["thirdParty"]["enabled"],
164-
providers,
165-
),
166-
core_config=res["coreConfig"],
171+
emailpassword=tenant_config.emailpassword,
172+
passwordless=tenant_config.passwordless,
173+
third_party=tenant_config.third_party,
174+
core_config=tenant_config.core_config,
167175
)
168176

169177
async def list_all_tenants(
170178
self, user_context: Dict[str, Any]
171179
) -> ListAllTenantsOkResult:
172-
from supertokens_python.recipe.thirdparty.provider import (
173-
ProviderConfig,
174-
ProviderClientConfig,
175-
UserFields,
176-
UserInfoMap,
177-
)
178-
179180
response = await self.querier.send_get_request(
180181
NormalisedURLPath("/recipe/multitenancy/tenant/list"),
181182
{},
@@ -184,73 +185,7 @@ async def list_all_tenants(
184185
tenant_configs: List[TenantConfigResponse] = []
185186

186187
for tenant in response["tenants"]:
187-
providers: List[ProviderConfig] = []
188-
for p in tenant["thirdParty"]["providers"]:
189-
user_info_map: Optional[UserInfoMap] = None
190-
if "userInfoMap" in p:
191-
map_from_payload = p["userInfoMap"].get("fromIdTokenPayload", {})
192-
map_from_api = p["userInfoMap"].get("fromUserInfoAPI", {})
193-
user_info_map = UserInfoMap(
194-
UserFields(
195-
map_from_payload.get("userId"),
196-
map_from_payload.get("email"),
197-
map_from_payload.get("emailVerified"),
198-
),
199-
UserFields(
200-
map_from_api.get("userId"),
201-
map_from_api.get("email"),
202-
map_from_api.get("emailVerified"),
203-
),
204-
)
205-
206-
providers.append(
207-
ProviderConfig(
208-
third_party_id=p["thirdPartyId"],
209-
name=p["name"],
210-
clients=[
211-
ProviderClientConfig(
212-
client_id=c["clientId"],
213-
client_secret=c["clientSecret"],
214-
client_type=c["clientType"],
215-
scope=c["scope"],
216-
force_pkce=c["forcePkce"],
217-
additional_config=c["additionalConfig"],
218-
)
219-
for c in p["clients"]
220-
],
221-
authorization_endpoint=p["authorizationEndpoint"],
222-
authorization_endpoint_query_params=p[
223-
"authorizationEndpointQueryParams"
224-
],
225-
token_endpoint=p["tokenEndpoint"],
226-
token_endpoint_body_params=p["tokenEndpointBodyParams"],
227-
user_info_endpoint=p["userInfoEndpoint"],
228-
user_info_endpoint_query_params=p[
229-
"userInfoEndpointQueryParams"
230-
],
231-
user_info_endpoint_headers=p["userInfoEndpointHeaders"],
232-
jwks_uri=p["jwksUri"],
233-
oidc_discovery_endpoint=p["oidcDiscoveryEndpoint"],
234-
user_info_map=user_info_map,
235-
require_email=p["requireEmail"],
236-
validate_id_token_payload=p["validateIdTokenPayload"],
237-
generate_fake_email=p["generateFakeEmail"],
238-
)
239-
)
240-
241-
tenant_configs.append(
242-
TenantConfigResponse(
243-
emailpassword=EmailPasswordConfig(
244-
tenant["emailPassword"]["enabled"]
245-
),
246-
passwordless=PasswordlessConfig(tenant["passwordless"]["enabled"]),
247-
third_party=ThirdPartyConfig(
248-
tenant["thirdParty"]["enabled"],
249-
providers,
250-
),
251-
core_config=tenant["coreConfig"],
252-
)
253-
)
188+
tenant_configs.append(parse_tenant_config(tenant))
254189

255190
return ListAllTenantsOkResult(
256191
tenants=tenant_configs,
@@ -300,12 +235,12 @@ async def associate_user_to_tenant(
300235
self, tenant_id: str | None, user_id: str, user_context: Dict[str, Any]
301236
) -> Union[
302237
AssociateUserToTenantOkResult,
303-
AssociateUserToTenantUnknownUserIdErrorResult,
304-
AssociateUserToTenantEmailAlreadyExistsErrorResult,
305-
AssociateUserToTenantPhoneNumberAlreadyExistsErrorResult,
306-
AssociateUserToTenantThirdPartyUserAlreadyExistsErrorResult,
238+
AssociateUserToTenantUnknownUserIdError,
239+
AssociateUserToTenantEmailAlreadyExistsError,
240+
AssociateUserToTenantPhoneNumberAlreadyExistsError,
241+
AssociateUserToTenantThirdPartyUserAlreadyExistsError,
307242
]:
308-
response = await self.querier.send_post_request(
243+
response: Dict[str, Any] = await self.querier.send_post_request(
309244
NormalisedURLPath(
310245
f"{tenant_id or DEFAULT_TENANT_ID}/recipe/multitenancy/tenant/user"
311246
),
@@ -314,9 +249,26 @@ async def associate_user_to_tenant(
314249
},
315250
)
316251

317-
return AssociateUserToTenantOkResult(
318-
was_already_associated=response["wasAlreadyAssociated"],
319-
)
252+
if response["status"] == "OK":
253+
return AssociateUserToTenantOkResult(
254+
was_already_associated=response["wasAlreadyAssociated"],
255+
)
256+
if response["status"] == AssociateUserToTenantUnknownUserIdError.status:
257+
return AssociateUserToTenantUnknownUserIdError()
258+
if response["status"] == AssociateUserToTenantEmailAlreadyExistsError.status:
259+
return AssociateUserToTenantEmailAlreadyExistsError()
260+
if (
261+
response["status"]
262+
== AssociateUserToTenantPhoneNumberAlreadyExistsError.status
263+
):
264+
return AssociateUserToTenantPhoneNumberAlreadyExistsError()
265+
if (
266+
response["status"]
267+
== AssociateUserToTenantThirdPartyUserAlreadyExistsError.status
268+
):
269+
return AssociateUserToTenantThirdPartyUserAlreadyExistsError()
270+
271+
raise Exception("Should never come here")
320272

321273
async def dissociate_user_from_tenant(
322274
self, tenant_id: str | None, user_id: str, user_context: Dict[str, Any]

supertokens_python/recipe/thirdparty/provider.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,8 +252,8 @@ def to_json(self) -> Dict[str, Any]:
252252
"thirdPartyId": self.third_party_id,
253253
"name": self.name,
254254
"clients": [c.to_json() for c in self.clients]
255-
if isinstance(self.clients, list)
256-
else None,
255+
if self.clients is not None
256+
else [],
257257
"authorizationEndpoint": self.authorization_endpoint,
258258
"authorizationEndpointQueryParams": self.authorization_endpoint_query_params,
259259
"tokenEndpoint": self.token_endpoint,

0 commit comments

Comments
 (0)