PostgreSQL - 在关系策略中检测到无限递归

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

数据库中有 3 个表 - 部门、员工、帐户。一个部门有很多员工。员工包含列

department_id bigint
帐户表包含列
login varchar
employee_id bigint
,用于将 Postgres 用户(角色)绑定到 Employee 中的行。

我的目标是让用户仅查看和使用

department_id
值与用户相同的 Employee 行。

一定有这样的东西:

CREATE POLICY locale_policy ON employee
TO justuser, operator
USING (department_id =
    (SELECT department_id FROM employee WHERE id =
        (SELECT employee_id FROM account WHERE login = CURRENT_USER)
    )
)

但是由于 Employee 的子查询,它正在提高

infinite recursion detected in policy for relation employee

编辑:关系定义为:

create table department(
    id serial primary key);
create table employee(
    id serial primary key,
    department_id int8 not null references department(id));
create table account(
    id serial primary key,
    login varchar(100) not null unique,
    employee_id int8 not null unique references employee(id));
sql postgresql policy row-level-security
3个回答
3
投票

我不知道它有多好,但它对我有用。我找到了一个解决方案,创建一个视图,其中 current_user 的部门 id,然后检查它是否匹配:

CREATE VIEW curr_department AS
    (SELECT department_id as id FROM employee WHERE id =
        (SELECT employee_id FROM account WHERE login = current_user)
    );

CREATE POLICY locale_policy ON employee
    TO justuser, operator
    USING (department_id =
        (SELECT id FROM curr_department)
    );

0
投票

las rexter 不允许创建角色.. http://rextester.com/QDYC6798

create table department(
    id serial primary key);
create table employee(
    id serial primary key,
    department_id int8 not null references department(id));
create table account(
    id serial primary key,
    login varchar(100) not null unique,
    employee_id int8 not null unique references employee(id));
insert into department default values;
insert into department default values;
insert into employee (department_id ) select 1;
insert into employee (department_id ) select 2;
insert into account (login,employee_id) select 'justuser',1;
insert into account (login,employee_id) select 'operator',2;
create role justuser;
create role operator;
set role justuser;
select * from employee;

无法重现。这不是一个答案 - 只是一个格式化的脚本。解决后我会删除它


0
投票

这是我使用的更简洁的解决方案。我使用

auth
表中的一个单独的用户表来管理用户。从该表中,我使用自定义枚举类型并在 RLS 策略上使用辅助函数。

CREATE TYPE user_role AS enum ('USER', 'ADMIN');

CREATE TABLE users (
  id uuid PRIMARY KEY NOT NULL REFERENCES auth.users(id),
  name text NOT NULL,
  role user_role NOT NULL DEFAULT 'USER'::user_role,
  email text UNIQUE NOT NULL,
  created_at timestamp with time zone NOT NULL DEFAULT timezone('utc'::text, now()),
  updated_at timestamp with time zone NOT NULL DEFAULT timezone('utc'::text, now())
);


CREATE OR REPLACE FUNCTION is_admin (user_id UUID)
RETURNS BOOL AS $$
BEGIN
  PERFORM
  FROM public.users
  WHERE id = user_id AND role = 'ADMIN'::user_role;
  RETURN FOUND;
END;
$$ LANGUAGE plpgsql SECURITY definer;

CREATE POLICY "Admins can view all users data" ON public.users
  FOR SELECT
  TO authenticated
  USING (is_admin(auth.uid()));

PERFORM
语句用于执行查询而不返回任何结果数据。在本例中,它检查
public.users
表中是否存在行。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.