You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

基于关联表数据的Supabase行级安全(Row-level-security)配置问题求助

解决Supabase行级安全(RLS)多用户网站关联的问题

你已经理清了表结构的关联逻辑,核心问题就是如何在website表的RLS策略中关联user_website表的权限数据。下面是一步步的实操解决方案:

1. 先确保RLS已开启

首先要给涉及的核心表开启行级安全,这是RLS生效的前提:

-- 开启website表的RLS
ALTER TABLE website ENABLE ROW LEVEL SECURITY;

-- 开启user_website表的RLS(避免用户直接篡改关联权限)
ALTER TABLE user_website ENABLE ROW LEVEL SECURITY;

2. 创建website表的基础查询策略

要让用户只能查看自己有权访问的网站,我们可以用EXISTS子查询关联user_website表,检查当前登录用户(auth.uid())是否在关联表中有对应记录:

CREATE POLICY "用户可查看有权访问的网站" ON website
FOR SELECT USING (
  EXISTS (
    SELECT 1 FROM user_website
    WHERE user_website.website_id = website.website_id
      AND user_website.user_id = auth.uid()
  )
);

这个策略的逻辑很直白:当用户查询website表时,只有那些在user_website表中存在当前用户关联记录的网站行才会被返回。

3. 针对不同操作的权限细化策略

如果你需要支持创建、修改、删除网站,可以结合user_role字段进一步细化权限:

3.1 允许用户创建网站(自动关联到自己)

用户创建网站后,通常需要自动把自己和网站关联起来。我们可以先创建INSERT策略,再配合触发器自动添加关联记录:

-- 允许登录用户创建网站
CREATE POLICY "用户可创建网站" ON website
FOR INSERT WITH CHECK (auth.uid() IS NOT NULL);

-- 创建触发器,插入website后自动在user_website添加当前用户的关联记录(默认设为owner角色)
CREATE OR REPLACE FUNCTION add_user_website_association()
RETURNS TRIGGER AS $$
BEGIN
  INSERT INTO user_website (user_id, website_id, user_role)
  VALUES (auth.uid(), NEW.website_id, 'owner');
  RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

CREATE TRIGGER trigger_add_user_website
AFTER INSERT ON website
FOR EACH ROW EXECUTE FUNCTION add_user_website_association();

3.2 允许特定角色的用户修改/删除网站

比如只有owneradmin角色的用户才能修改网站,只有owner能删除:

-- 修改网站策略:仅所有者或管理员可操作
CREATE POLICY "仅有权限的用户可修改网站" ON website
FOR UPDATE USING (
  EXISTS (
    SELECT 1 FROM user_website
    WHERE user_website.website_id = website.website_id
      AND user_website.user_id = auth.uid()
      AND user_website.user_role IN ('owner', 'admin')
  )
);

-- 删除网站策略:仅所有者可操作
CREATE POLICY "仅所有者可删除网站" ON website
FOR DELETE USING (
  EXISTS (
    SELECT 1 FROM user_website
    WHERE user_website.website_id = website.website_id
      AND user_website.user_id = auth.uid()
      AND user_website.user_role = 'owner'
  )
);

4. 验证策略是否生效

登录Supabase Studio或通过API登录测试用户后,执行简单查询:

SELECT * FROM website;

你应该只能看到当前用户在user_website表中关联的网站记录,而不是所有网站数据。

另外你之前写的JOIN查询本身是正确的,但通过RLS策略,你不需要每次查询都手动JOIN,RLS会自动帮你过滤出有权限的数据,让业务查询更简洁。

内容的提问来源于stack exchange,提问作者st_phan

火山引擎 最新活动