启用RLS后,Supabase父表触发子表插入报错的解决方法
问题描述
在Supabase中向父表TEAM插入行时(本应通过触发器自动向子表MEMBERS插入对应行),遇到错误:new row violates row-level security policy for table "members",同时出现两个问题:
a) 新团队未添加到TEAM表中;
b) 触发上述RLS违规错误。
表结构如下:
TEAM ---- id (uuid) owner (uuid) --> 与public.users.id的外键关联 MEMBERS ---- team_id (uuid) --> 与TEAM.id的外键关联 member_id (uuid) --> 与public.users.id的外键关联
已设置AFTER INSERT触发器,在TEAM表插入行后,自动将team_id和所有者的user_id插入MEMBERS表。
MEMBERS表的RLS策略规定仅团队所有者可添加成员,通过SECURITY DEFINER函数is_team_owner(_team_id uuid)校验,原函数代码:
SELECT EXISTS ( SELECT 1 FROM members m, team t WHERE m.team_id = t.id AND t.owner_id = auth.uid() AND t.id = _team_id )
MEMBERS表的INSERT策略为WITH CHECK (is_team_owner(_team_id))。
解决方案
1. 修复is_team_owner函数的核心逻辑
原函数错误地关联了members表,而新团队的第一条成员记录正是触发器要插入的内容,此时members表中还没有对应行,导致EXISTS返回false,触发RLS校验失败。
正确的逻辑应该直接检查team表中该团队的所有者是否为当前用户,无需依赖members表:
CREATE OR REPLACE FUNCTION is_team_owner(_team_id uuid) RETURNS boolean AS $$ SELECT EXISTS ( SELECT 1 FROM team t WHERE t.id = _team_id AND t.owner = auth.uid() -- 注意:你的team表字段是owner,不是owner_id ) $$ LANGUAGE sql SECURITY DEFINER;
2. 关于TEAM插入失败的说明
触发器属于事务的一部分,如果触发器内的MEMBERS插入操作失败,整个事务会回滚,因此TEAM表的插入也会被撤销,这就是问题(a)的原因。修复函数逻辑后,RLS校验通过,触发器执行成功,TEAM和MEMBERS的插入都会完成。
内容的提问来源于stack exchange,提问作者Sai Ramachandran
相关产品推荐
相关产品推荐

