-
I have an
I'm trying to write a policy on the This is the
the problem is this creates infinite recursion:
Question: how do you enforce a SELECT policy when the criteria is based on the same table? or is there a different approach that is preferable here? |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 4 replies
-
You can try using a function that bypasses RLS: -- Parameters need to be prefixed because the name clashes with `om`'s columns
CREATE FUNCTION is_member_of(_user_id uuid, _organization_id uuid) RETURNS bool AS $$
SELECT EXISTS (
SELECT 1
FROM organization_memberships om
WHERE om.organization_id = _organization_id
AND om.user_id = _user_id
);
$$ LANGUAGE sql SECURITY DEFINER;
-- Function is owned by postgres which bypasses RLS Then in the policy definition: is_member_of(auth.uid(), organization_id) |
Beta Was this translation helpful? Give feedback.
-
We did end up with such a query: schema: CREATE OR REPLACE FUNCTION is_member_of(_user_id uuid, _workspace_id uuid) RETURNS bool AS $$
SELECT
EXISTS (
SELECT
1
FROM
workspace_member
WHERE
-- workspace doesn't exist yet
NOT EXISTS (
SELECT
1
from
workspace
WHERE
workspace.id = _workspace_id
)
-- you're owner
OR EXISTS (
SELECT
1
from
workspace
WHERE
workspace.id = _workspace_id
AND workspace.owner_id = _user_id
)
-- you're member
OR EXISTS (
SELECT
1
FROM
workspace_member
LEFT JOIN workspace ON workspace.id = workspace_member.workspace_id
WHERE
workspace.id = _workspace_id
AND workspace_member.user_id = _user_id
)
);
$$ LANGUAGE sql SECURITY DEFINER; It also solves some edge case: seems supabase is checking 'SELECT' permission before allowing 'INSERT' permission. This was not working, as you cannot be a member or owner of a workspace that does not exist yet (what the heck supabase?). Thus the first condition is a bit absurd - 'yes, you have permission to workspace if this workspace doesn't exist', but it was needed in our case. |
Beta Was this translation helpful? Give feedback.
-
Also ran in to this issue, the recursion I got involved two tables instead of one, each having multiple select policies, the problem I had was that one policy of each table is referencing each other. What I failed to understand was that policies aren't ran in order and aren't "short-circuited", if a policy already "lets you through" it would still go through all the other policies. Another interaction you could get stuck on is assuming conditions in SQL can "short-circuit", for example you shouldn't expect a condition like this to solve the problem: is_admin(auth.uid) or id in (select id from another_table) it seems SQL is purely declarative and assumptions from procedural languages will likely cause more problems than helping. |
Beta Was this translation helpful? Give feedback.
You can try using a function that bypasses RLS:
Then in the policy definition: