What I’m trying to do is to have a table that assigns a subscription to a user. All the samples I found so far do this via:
(auth.uid() = user_id)
However I would like to keep track of reassignments. With a table structured like this:
// assigments //
user_id | subscription_id | comment | created_at
---------------------------------------------------
3 | 1001 | re-assign | 2023-06-06
---------------------------------------------------
2 | 1002 | intial | 2023-06-05
---------------------------------------------------
1 | 1001 | intial | 2023-06-05
---------------------------------------------------
I’m having a difficult time wrapping my head around writing policy for this. I think it needs to be something like
auth.uid() IN (SELECT DISTINCT ON (subscription_id) user_id FROM assignments ORDER BY created_at)
Is this the right track? auth.uid() IN (...)
feels super inefficient. Is it possible to first see if there is a row that matches user_id == auth.uid()
and to a subquery on the resulting subscription_id with a ORDER BY created_at, LIMIT 1
and somehow use the result for the auth.uid()
comparison?
2
Answers
With the help of @dshukertjr found a solution. Trying to run a sub query on the table for which the policy is written results in
infinite recursion detected in policy for relation "assignments" (Error: 42P17)
. With this I was able to find https://github.com/orgs/supabase/discussions/3328 and https://github.com/orgs/supabase/discussions/1138.The answer is to use a function that bypasses RLS to do the check.
And use the function in the policy like:
If the user and "active" subscription have one to one relationship, then you should be able to do something like this
Within the
a.subscription_id = assignments.subscription_id
,a.subscription_id
is the subscription id from the sub query, andassignments.subscription_id
is the current row that is being evaluated within this RLS policy.