Description
A new refactor? or a way to handle sessions
Describe the chore
I a normal flow (just following the docs (python api reference)) to insert some data into a table called X
would kinda look like this
- A user would init a client
from supabase.client import AsyncClient, create_async_client
client = await create_async_client(
settings.SUPABASE_PROJECT_URL, settings.SUPABASE_API_KEY
)
- Get the user
access_token = "getting-it-from-the-frontend"
user = await client.auth.get_user(jwt=access_token)
- inserting data into table
X
response = await client.table("X").insert(data, returning="minimal").execute()
Now, if the developer has implemented RLS such as enabling insert for users based on user_id and them being authenticated
we would get this kind of error
postgrest.exceptions.APIError: {'code': '42501', 'details': None, 'hint': None, 'message': 'new row violates row-level security policy for table "X"'}
Now the main reason for that upon further investigations, is what happens in our RLS policy which looks like this
alter policy "Enable insert for users based on user_id"
on "public"."X"
to public
with check (
7
(( SELECT auth.uid() AS uid) = user_id)
);
and what happens when inserting, kinda like the following
postgrest.exceptions.APIError: {'code': '42501', 'details': None, 'hint': None, 'message': 'new row violates row-level security policy for table "X"'}
Now the main reason for that upon further investigations, is what happens in our RLS policy which looks like this
alter policy "Enable insert for users based on user_id"
on "public"."X"
to public
with check (
7
(( Null ) = "some-user-id"
);
now it auth.uid()
happens to be null because when inserting and calling the db api the information of the user is not sent or the session idk.
now there are a hacky ways to solve it and a (right) way.
-
is by using the
set_session
function.
This function would require you to set both theaccess_token
andrefresh_token
but this didn't make sense to make me to send them both from the frontend due to security purposes -
Using the secret key to bypass RLS policy.
Still doesn't make sense due to security purposes. -
A problem with the
get_session
function is that it doesn't take any param and so it wouldn't give us the user's session to solve the problem -
the Right way is to use
ClientOptions
client = await create_async_client(
settings.SUPABASE_PROJECT_URL,
settings.SUPABASE_API_KEY,
options=ClientOptions(headers={"Authorization": f"Bearer {access_token}"}),
)
and the problem would go away and it would work normally, although the get_session still wouldn't work properly.
So, what is the problem.
That this problem is not well documented in the docs from a python perspective and one has to delve deep to find the proper solution.
Second, is that the get_session
function would be more proper if it can take an access_token
or an id or whatever to get the same session we have. it would save so much hassle and the use would make more sense.
After all, thanks for the team for their hard work maintaining this project