https://supertokens.com/ logo
Title
c

Creepwood

12/25/2022, 12:38 PM
Hi and happy christmas! I'm implementing SuperTokens EmailPassword recipe with react and python. Found out, that after verifying the email my user role is missing. Have to log out and in again to get the role with the token. As the docs say, i force the user to log in and create a session for verifying the email. And this token doesn't have the role because probably the email is not verified. What do you think is the best solution? Force logout and signin after verifying the email? Is it possible to add the roles to the token although the email is not yet verified? Thank you all!
r

rp

12/25/2022, 12:40 PM
Hey @Creepwood
When do you add a role to the user? If you do that in the post sign up function override on the backend, it should add it to the session and keep it in there
c

Creepwood

12/26/2022, 10:50 AM
I do it this way: def override_email_password_apis(original_implementation: APIInterface): original_sign_up_post = original_implementation.sign_up_post async def sign_up_post(form_fields: List[FormField], api_options: APIOptions, user_context: Dict[str, Any]): # First we call the original implementation of signInPOST. response = await original_sign_up_post(form_fields, api_options, user_context) # Post sign up response, we check if it was successful if isinstance(response, SignUpPostOkResult): # TODO: use the input form fields values for custom logic account_type = list(filter(lambda x: x.id == 'account_type', form_fields))[0].value if(account_type == 1): add_role_to_user_func(response.user.user_id, "pflegedienst") elif(account_type == 0): add_role_to_user_func(response.user.user_id, "user") return response original_implementation.sign_up_post = sign_up_post return original_implementation
maybe this is to late?
r

rp

12/26/2022, 11:32 AM
So this is fine, except that you also need to add the roles to the session after adding them to the user. See this: https://supertokens.com/docs/userroles/managing-roles-and-users (search for
add_roles_and_permissions_to_session
function). The session can be accessed via the
response.session
object. Finally, I think you also need to add
await
in front of
add_role_to_user_func
.
c

Creepwood

12/26/2022, 12:51 PM
Nice
add_roles_and_permissions_to_session
did it! But i definitely struggling with asyncio... I think it is not possible to run a second async function in the sign_up_post override. It end up in: raise RuntimeError('This event loop is already running') And
add_role_to_user()
from "supertokens_python.recipe.userroles.asyncio import add_role_to_user" can not be awaited? After adding
import nest_asyncio
and calling
nest_asyncio.apply()
it worked this way:
```python import nest_asyncio nest_asyncio.apply() async def add_roles_and_permissions_to_session(session: SessionContainer): # we add the user's roles to the user's session await session.fetch_and_set_claim(UserRoleClaim) # we add the user's permissions to the user's session await session.fetch_and_set_claim(PermissionClaim) async def add_role_to_user_func(user_id: str, role: str): res = add_role_to_user(user_id, role) if isinstance(res, UnknownRoleError): # No such role exists return if res.did_user_already_have_role: # User already had this role pass def override_email_password_apis(original_implementation: APIInterface): original_sign_up_post = original_implementation.sign_up_post async def sign_up_post(form_fields: List[FormField], api_options: APIOptions, user_context: Dict[str, Any]): # First we call the original implementation of signInPOST. response = await original_sign_up_post(form_fields, api_options, user_context) # Post sign up response, we check if it was successful if isinstance(response, SignUpPostOkResult): # TODO: use the input form fields values for custom logic account_type = list(filter(lambda x: x.id == 'account_type', form_fields))[0].value if(account_type == 1): await add_role_to_user_func(response.user.user_id, "pflegedienst") await add_roles_and_permissions_to_session(response.session) elif(account_type == 0): await add_role_to_user_func(response.user.user_id, "user") await add_roles_and_permissions_to_session(response.session) return response original_implementation.sign_up_post = sign_up_post return original_implementation
r

rp

12/26/2022, 1:00 PM
> And add_role_to_user() from "supertokens_python.recipe.userroles.asyncio import add_role_to_user" can not be awaited? It should be awaitable. Are you not seeing that?
@KShivendu can help here
k

KShivendu

12/26/2022, 1:10 PM
Let me try replicating this.
I think you missed this
await
.
python
async def add_role_to_user_func(user_id: str, role: str):
    res = await add_role_to_user(user_id, role)
Also, I didn't get any error. It's working fine for me. Can you please tell more about which framework are you using and how are you running it?
You may also share the trace of the error if possible.
c

Creepwood

12/26/2022, 1:37 PM
for sure. Just a moment. Do u use
nest_asyncio
?
flask==2.0.1 flask_cors==3.0.10 python-dotenv==0.19.2 supertokens-python nest-asyncio==1.5.6
127.0.0.1 - - [26/Dec/2022 14:39:05] "OPTIONS /auth/signup HTTP/1.1" 200 - rv = self.ensure_sync(func)() File "D:\Projekte\CareHelp\pflege-match\backend\venv\Lib\site-packages\supertokens_python\framework\flask\flask_middleware.py", line 54, in _ result: Union[BaseResponse, None] = sync(st.middleware(request_, response_)) File "D:\Projekte\CareHelp\pflege-match\backend\venv\Lib\site-packages\supertokens_python\async_to_sync_wrapper.py", line 33, in sync return loop.run_until_complete(co) File "C:\Python310\Lib\asyncio\base_events.py", line 649, in run_until_complete return future.result() File "D:\Projekte\CareHelp\pflege-match\backend\venv\Lib\site-packages\supertokens_python\supertokens.py", line 598, in middleware api_resp = await matched_recipe.handle_api_request( File "D:\Projekte\CareHelp\pflege-match\backend\venv\Lib\site-packages\supertokens_python\recipe\emailpassword\recipe.py", line 181, in handle_api_request return await handle_sign_up_api(self.api_implementation, api_options)
File "D:\Projekte\CareHelp\pflege-match\backend\venv\Lib\site-packages\supertokens_python\recipe\emailpassword\api\signup.py", line 42, in handle_sign_up_api response = await api_implementation.sign_up_post( File "D:\Projekte\CareHelp\pflege-match\backend\config.py", line 67, in sign_up_post await add_role_to_user_func(response.user.user_id, "user") File "D:\Projekte\CareHelp\pflege-match\backend\config.py", line 41, in add_role_to_user_func res = await add_role_to_user(user_id, role) File "D:\Projekte\CareHelp\pflege-match\backend\venv\Lib\site-packages\supertokens_python\recipe\userroles\syncio\__init__.py", line 38, in add_role_to_user return sync(add_role_to_user(user_id, role, user_context)) File "D:\Projekte\CareHelp\pflege-match\backend\venv\Lib\site-packages\supertokens_python\async_to_sync_wrapper.py", line 33, in sync return loop.run_until_complete(co) File "C:\Python310\Lib\asyncio\base_events.py", line 625, in run_until_complete self._check_running() File "C:\Python310\Lib\asyncio\base_events.py", line 584, in _check_running raise RuntimeError('This event loop is already running') RuntimeError: This event loop is already running
running with Python 3.10.8 64-bit
Without this await it is working. But only using
nest_asyncio
k

KShivendu

12/27/2022, 5:03 AM
Not in my current setup.
How are you running your flask server? Can you please share the command?
It's working for me with
nest_asyncio
when doing
python app.py
(Flask)
Works with
gunicorn --bind 0.0.0.0:3001 app:app
as well.
c

Creepwood

12/27/2022, 8:09 PM
Just starting flask this way: if __name__ == "__main__": app.run(host="0.0.0.0", port=int("3001"), debug=True)
Can not get it... you are sure? 😄 All these functions using sync wrapper
Maybe we should schedule a call? Will be easier 😄
k

KShivendu

12/28/2022, 5:30 AM
Okay. Let me check.
I didn't get any error. Let's have a call. Please choose a slot from https://calendly.com/shivendu-supertokens/30min
c

Creepwood

12/28/2022, 12:46 PM
👍 alright, see u tomorrow at 10:30 (MEZ) 😀
k

KShivendu

12/28/2022, 1:06 PM
Cool. Thanks!
Hi @Creepwood, are you comfortable with Google meet?
c

Creepwood

12/29/2022, 9:25 AM
Hi, not used before. Can u send me an invite?
Or i can send you a Microsoft Teams link
k

KShivendu

12/29/2022, 9:34 AM
If I can join without logging in, we can use Microsoft Teams.
c

Creepwood

12/29/2022, 9:35 AM
Doesn't remember if login is required. Try it out. I send you a personal message with a link
k

KShivendu

12/29/2022, 9:36 AM
Sure.