13
13
# under the License.
14
14
import os
15
15
import typing
16
- from typing import Any , Dict , List , Union , Optional
16
+ from typing import Any , Dict , List , Optional , Union
17
17
18
18
import uvicorn # type: ignore
19
19
from dotenv import load_dotenv
36
36
from supertokens_python .framework .request import BaseRequest
37
37
from supertokens_python .recipe import (
38
38
emailpassword ,
39
+ emailverification ,
39
40
passwordless ,
40
41
session ,
41
42
thirdparty ,
42
43
thirdpartyemailpassword ,
43
44
thirdpartypasswordless ,
44
- emailverification ,
45
+ userroles ,
45
46
)
46
47
from supertokens_python .recipe .emailpassword import EmailPasswordRecipe
47
48
from supertokens_python .recipe .emailpassword .interfaces import (
55
56
InputFormField ,
56
57
User ,
57
58
)
58
- from supertokens_python .recipe .emailverification import EmailVerificationRecipe
59
+ from supertokens_python .recipe .emailverification import (
60
+ EmailVerificationClaim ,
61
+ EmailVerificationRecipe ,
62
+ )
59
63
from supertokens_python .recipe .emailverification import (
60
64
InputOverrideConfig as EVInputOverrideConfig ,
61
65
)
66
+ from supertokens_python .recipe .emailverification .asyncio import unverify_email
62
67
from supertokens_python .recipe .emailverification .interfaces import (
63
68
APIInterface as EmailVerificationAPIInterface ,
64
69
)
65
70
from supertokens_python .recipe .emailverification .interfaces import (
66
71
APIOptions as EVAPIOptions ,
67
72
)
73
+ from supertokens_python .recipe .emailverification .types import User as EVUser
68
74
from supertokens_python .recipe .jwt import JWTRecipe
69
75
from supertokens_python .recipe .passwordless import (
70
76
ContactEmailOnlyConfig ,
84
90
APIInterface as SessionAPIInterface ,
85
91
)
86
92
from supertokens_python .recipe .session .interfaces import APIOptions as SAPIOptions
93
+ from supertokens_python .recipe .session .interfaces import SessionClaimValidator
87
94
from supertokens_python .recipe .thirdparty import (
88
95
Facebook ,
89
96
Github ,
113
120
from supertokens_python .recipe .thirdpartypasswordless .interfaces import (
114
121
APIInterface as ThirdpartyPasswordlessAPIInterface ,
115
122
)
123
+ from supertokens_python .recipe .userroles import (
124
+ PermissionClaim ,
125
+ UserRoleClaim ,
126
+ UserRolesRecipe ,
127
+ )
128
+ from supertokens_python .recipe .userroles .asyncio import (
129
+ add_role_to_user ,
130
+ create_new_role_or_add_permissions ,
131
+ )
116
132
from supertokens_python .types import GeneralErrorResponse
117
133
from typing_extensions import Literal
118
- from supertokens_python .recipe .emailverification .types import User as EVUser
119
134
120
135
load_dotenv ()
121
136
@@ -275,12 +290,14 @@ def custom_init(
275
290
None , Literal ["USER_INPUT_CODE" , "MAGIC_LINK" , "USER_INPUT_CODE_AND_MAGIC_LINK" ]
276
291
] = None ,
277
292
):
293
+ UserRolesRecipe .reset ()
278
294
PasswordlessRecipe .reset ()
279
295
ThirdPartyPasswordlessRecipe .reset ()
280
296
JWTRecipe .reset ()
281
297
EmailVerificationRecipe .reset ()
282
298
SessionRecipe .reset ()
283
299
ThirdPartyRecipe .reset ()
300
+ EmailVerificationRecipe .reset ()
284
301
EmailPasswordRecipe .reset ()
285
302
ThirdPartyEmailPasswordRecipe .reset ()
286
303
Supertokens .reset ()
@@ -903,10 +920,11 @@ async def authorisation_url_get(
903
920
)
904
921
905
922
recipe_list = [
923
+ userroles .init (),
906
924
session .init (override = session .InputOverrideConfig (apis = override_session_apis )),
907
925
emailverification .init (
908
926
mode = "REQUIRED" ,
909
- create_and_send_custom_email = ev_create_and_send_custom_email , # TODO: Is this correct?
927
+ create_and_send_custom_email = ev_create_and_send_custom_email ,
910
928
override = EVInputOverrideConfig (apis = override_email_verification_apis ),
911
929
),
912
930
emailpassword .init (
@@ -988,7 +1006,7 @@ def test_get_device(request: Request):
988
1006
989
1007
@app .get ("/test/featureFlags" )
990
1008
def test_feature_flags (request : Request ):
991
- available = ["passwordless" , "thirdpartypasswordless" , "generalerror" ]
1009
+ available = ["passwordless" , "thirdpartypasswordless" , "generalerror" , "userroles" ]
992
1010
return JSONResponse ({"available" : available })
993
1011
994
1012
@@ -1015,6 +1033,58 @@ async def get_token():
1015
1033
return JSONResponse ({"latestURLWithToken" : latest_url_with_token })
1016
1034
1017
1035
1036
+ @app .get ("/unverifyEmail" )
1037
+ async def unverify_email_api (session_ : SessionContainer = Depends (verify_session ())):
1038
+ await unverify_email (session_ .get_user_id ())
1039
+ await session_ .fetch_and_set_claim (EmailVerificationClaim )
1040
+ return JSONResponse ({"status" : "OK" })
1041
+
1042
+
1043
+ @app .post ("/setRole" )
1044
+ async def set_role_api (
1045
+ request : Request , session_ : SessionContainer = Depends (verify_session ())
1046
+ ):
1047
+ body = await request .json ()
1048
+ await create_new_role_or_add_permissions (body ["role" ], body ["permissions" ])
1049
+ await add_role_to_user (session_ .get_user_id (), body ["role" ])
1050
+ await session_ .fetch_and_set_claim (UserRoleClaim )
1051
+ await session_ .fetch_and_set_claim (PermissionClaim )
1052
+ return JSONResponse ({"status" : "OK" })
1053
+
1054
+
1055
+ async def override_global_claim_validators (
1056
+ gv : List [SessionClaimValidator ],
1057
+ _session : SessionContainer ,
1058
+ user_context : Dict [str , Any ],
1059
+ ):
1060
+ validators = gv .copy ()
1061
+ req = user_context ["_default" ]["request" ]
1062
+ body = await req .json ()
1063
+
1064
+ if body .get ("role" ):
1065
+ info = body ["role" ]
1066
+ validator = getattr (UserRoleClaim .validators , info ["validator" ])
1067
+ validators .append (validator (* info ["args" ]))
1068
+
1069
+ if body .get ("permission" ):
1070
+ info = body ["permission" ]
1071
+ validator = getattr (PermissionClaim .validators , info ["validator" ])
1072
+ validators .append (validator (* info ["args" ]))
1073
+
1074
+ return validators
1075
+
1076
+
1077
+ @app .post ("/checkRole" )
1078
+ async def check_role_api (
1079
+ _ : SessionContainer = Depends (
1080
+ verify_session (
1081
+ override_global_claim_validators = override_global_claim_validators
1082
+ )
1083
+ ),
1084
+ ):
1085
+ return JSONResponse ({"status" : "OK" })
1086
+
1087
+
1018
1088
@app .exception_handler (405 ) # type: ignore
1019
1089
def f_405 (_ , e ): # type: ignore
1020
1090
return PlainTextResponse ("" , status_code = 404 )
0 commit comments