如何正确实施多对多关系的RLS策略? [Supabase] [PostgreSQL]

问题描述 投票:0回答:1

我有一个

trips
表和
users
表,以及一个
trip_user
连接表来处理
trips
users
表的多对多关系。

我想实施一项 RLS 策略,仅允许经过身份验证的用户查看

users
的数据,这些数据是同一行程的一部分。

我一直在尝试在我的 Supabase 应用程序中实现此功能,但我一直遇到错误:

在关系“trip_user”的策略中检测到无限递归

这是我当前实现的片段。

alter policy "Enable users to view their trips"
on "public"."trips"
to authenticated
using (
(id IN ( SELECT trip_user.trip_id
   FROM trip_user))
);
alter policy "Enable users to view their users that are part of the same trip"
on "public"."trips"
to authenticated
using (
(trip_id IN ( SELECT trip.id
   FROM trip))
);
sql postgresql supabase row-level-security
1个回答
0
投票

您收到

infinite recursion detected in policy
错误,因为
trips
表和
users
表上的当前 RLS 策略直接引用它们所应用的相同表,从而导致无限循环。

要在 PostgreSQL(或 Supabase)中实现多对多关系的行级安全性 (RLS),您需要依靠

trip_user
连接表进行过滤逻辑来避免递归:

我们假设:

users
表:用户详细信息(id 为主键)。

trips
表:行程详情(id 为主键)。

trip_user
表:链接行程和用户的连接表(
trip_id
user_id
作为外键)。

trips
的 RLS 政策:

ALTER POLICY "Enable users to view their trips"
ON public.trips
TO authenticated
USING (
  EXISTS (
    SELECT 1
    FROM public.trip_user
    WHERE trip_user.trip_id = trips.id
      AND trip_user.user_id = auth.uid()
  )
);

RLS 政策

users

ALTER POLICY "Enable users to view users in the same trips"
ON public.users
TO authenticated
USING (
  EXISTS (
    SELECT 1
    FROM public.trip_user AS tu1
    JOIN public.trip_user AS tu2
      ON tu1.trip_id = tu2.trip_id
    WHERE tu1.user_id = auth.uid()
      AND tu2.user_id = users.id
  )
);

trip_user

 的 RLS 策略(可选 - 如果用户需要查询 
trip_user
 表,请使用此策略):

ALTER POLICY "Enable users to view trip-user relationships for their trips" ON public.trip_user TO authenticated USING ( EXISTS ( SELECT 1 FROM public.trip_user WHERE trip_user.trip_id = trip_user.trip_id AND trip_user.user_id = auth.uid() ) );
说明

    避免无限递归:策略使用
  • trip_user
     表
    过滤,避免对 
    trips
    users
     表进行递归查询。
  • 动态用户识别:
  • auth.uid()
    功能(可在
    Supabase)获取当前用户的 ID,确保策略有效
    动态应用于经过身份验证的用户。
  • 共享行程的自加入:
  • users
     政策使用自加入
    
    trip_user
     表,用于识别与该用户共享相同行程的用户
    经过身份验证的用户。
确保运行此命令以启用 RLS:

ALTER TABLE public.trips ENABLE ROW LEVEL SECURITY; ALTER TABLE public.users ENABLE ROW LEVEL SECURITY; ALTER TABLE public.trip_user ENABLE ROW LEVEL SECURITY;
    
© www.soinside.com 2019 - 2024. All rights reserved.