16
16
from typing import TYPE_CHECKING , Optional , Dict , Any , Union , List
17
17
from supertokens_python .recipe .multitenancy .interfaces import (
18
18
AssociateUserToTenantOkResult ,
19
- AssociateUserToTenantUnknownUserIdErrorResult ,
20
- AssociateUserToTenantEmailAlreadyExistsErrorResult ,
21
- AssociateUserToTenantPhoneNumberAlreadyExistsErrorResult ,
22
- AssociateUserToTenantThirdPartyUserAlreadyExistsErrorResult ,
19
+ AssociateUserToTenantUnknownUserIdError ,
20
+ AssociateUserToTenantEmailAlreadyExistsError ,
21
+ AssociateUserToTenantPhoneNumberAlreadyExistsError ,
22
+ AssociateUserToTenantThirdPartyUserAlreadyExistsError ,
23
23
DisassociateUserFromTenantOkResult ,
24
24
)
25
25
47
47
from .constants import DEFAULT_TENANT_ID
48
48
49
49
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
+
50
120
class RecipeImplementation (RecipeInterface ):
51
121
def __init__ (self , querier : Querier , config : MultitenancyConfig ):
52
122
super ().__init__ ()
@@ -89,93 +159,24 @@ async def delete_tenant(
89
159
async def get_tenant (
90
160
self , tenant_id : Optional [str ], user_context : Dict [str , Any ]
91
161
) -> GetTenantOkResult :
92
- from supertokens_python .recipe .thirdparty .provider import (
93
- ProviderConfig ,
94
- UserInfoMap ,
95
- UserFields ,
96
- ProviderClientConfig ,
97
- )
98
-
99
162
res = await self .querier .send_get_request (
100
163
NormalisedURLPath (
101
164
f"{ tenant_id or DEFAULT_TENANT_ID } /recipe/multitenancy/tenant"
102
165
),
103
166
)
104
167
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 )
158
169
159
170
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 ,
167
175
)
168
176
169
177
async def list_all_tenants (
170
178
self , user_context : Dict [str , Any ]
171
179
) -> ListAllTenantsOkResult :
172
- from supertokens_python .recipe .thirdparty .provider import (
173
- ProviderConfig ,
174
- ProviderClientConfig ,
175
- UserFields ,
176
- UserInfoMap ,
177
- )
178
-
179
180
response = await self .querier .send_get_request (
180
181
NormalisedURLPath ("/recipe/multitenancy/tenant/list" ),
181
182
{},
@@ -184,73 +185,7 @@ async def list_all_tenants(
184
185
tenant_configs : List [TenantConfigResponse ] = []
185
186
186
187
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 ))
254
189
255
190
return ListAllTenantsOkResult (
256
191
tenants = tenant_configs ,
@@ -300,12 +235,12 @@ async def associate_user_to_tenant(
300
235
self , tenant_id : str | None , user_id : str , user_context : Dict [str , Any ]
301
236
) -> Union [
302
237
AssociateUserToTenantOkResult ,
303
- AssociateUserToTenantUnknownUserIdErrorResult ,
304
- AssociateUserToTenantEmailAlreadyExistsErrorResult ,
305
- AssociateUserToTenantPhoneNumberAlreadyExistsErrorResult ,
306
- AssociateUserToTenantThirdPartyUserAlreadyExistsErrorResult ,
238
+ AssociateUserToTenantUnknownUserIdError ,
239
+ AssociateUserToTenantEmailAlreadyExistsError ,
240
+ AssociateUserToTenantPhoneNumberAlreadyExistsError ,
241
+ AssociateUserToTenantThirdPartyUserAlreadyExistsError ,
307
242
]:
308
- response = await self .querier .send_post_request (
243
+ response : Dict [ str , Any ] = await self .querier .send_post_request (
309
244
NormalisedURLPath (
310
245
f"{ tenant_id or DEFAULT_TENANT_ID } /recipe/multitenancy/tenant/user"
311
246
),
@@ -314,9 +249,26 @@ async def associate_user_to_tenant(
314
249
},
315
250
)
316
251
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" )
320
272
321
273
async def dissociate_user_from_tenant (
322
274
self , tenant_id : str | None , user_id : str , user_context : Dict [str , Any ]
0 commit comments