Политика Postgres RLS: разрешить ВЫБОР только в строке на основе наличия внешнего отношения

#sql #postgresql #row-level-security

Вопрос:

У меня есть следующие таблицы Postgres:

Пользователи

  --------- -------------- 
| id (PK) |  full_name   |
 --------- -------------- 
| uuid()  | varchar      |
 --------- -------------- 
 

организации

  --------- --------- 
| id (PK) |  name   |
 --------- --------- 
| uuid()  | varchar |
 --------- --------- 
 

организация_memberships

  --------- ---------------------- -------------- 
| id (PK) | organization_id (FK) | user_id (FK) |
 --------- ---------------------- -------------- 
| uuid()  | uuid()               | uuid()       |
 --------- ---------------------- -------------- 
 

Я пытаюсь написать политику безопасности на уровне строк Postgres (RLS).

Политика должна обеспечивать, чтобы пользователи могли SELECT organizations использовать таблицу только в том случае, если в таблице есть соответствующая запись organization_memberships .

Это то, что у меня есть в настоящее время, но, похоже, работает не так, как я ожидал. Примечание.Этот uid() метод предоставляется моим решением DBAAS для получения идентификатора аутентифицированного пользователя.

 ALTER POLICY "User can only Select organizations where they are members" ON public.organizations USING (
  (
    EXISTS (
      SELECT
        orgmembs.user_id,
        orgmembs.organization_id
      FROM
        organization_memberships orgmembs
      WHERE
        (
          (orgmembs.organization_id = organizations.id)
          AND (orgmembs.user_id = uid())
        )
    )
  )
);
 

Я также пробовал эту немного другую версию, но я получаю сообщение об ошибке, Error updating policy: missing FROM-clause entry for table "organization" :

 ALTER POLICY "User can only Select organizations where they are member" ON public.organizations USING (
  auth.uid() IN (
    SELECT
      user_id
    FROM
      organization_memberships
    WHERE
      organization_memberships.organization_id = organization.id
  )
);
 

Комментарии:

1. Ваша политика выглядит нормально. Пожалуйста, опишите, как он себя ведет. Возможно, пользователь, выполняющий запрос, владеет таблицей или иным образом освобожден от RLS.

Ответ №1:

 alter POLICY "User can only Select organizations where they are member"
      ON organizations 
      USING (id  IN (
                        SELECT organization_id 
                        FROM organization_memberships om 
                        JOIN users u ON om.user_id = u.id
                    )
            )
 

Комментарии:

1. Спасибо за ответ. Похоже, это не работает как есть. Не могли бы вы подробнее рассказать?

2. Я не правильно понял ваш вопрос. Какой именно вы хотите, чтобы была политика?

3. Цель состоит в том, что пользователь может выбирать строки из organizations таблицы только в том случае, если есть соответствующая строка, в organization_memberships которой содержится user.id и organization.id .

4. Правильный.. organization_memberships Таблица соответствует users organizations . Я не хочу, чтобы пользователи могли SELECT создавать организации, к которым они не принадлежат. Неужели такое поведение невозможно? Это похоже на общую схему отношений

5. Я отредактировал код. По запросу организации отображаются те, которые пользователь присоединяет к organization_memberships.