SQLAlchemy и сложные запросы

Я должен реализовать ACL для существующего приложения.
Поэтому я добавил в базу данных таблицу user, group и groupmembers.
Я определил отношение ManyToMany между пользователем и группой через членов таблицы ассоциации.
Чтобы защитить некоторые ресурсы приложения (элемент...), я добавил дополнительную таблицу ассоциации auth_items, которую следует использовать в качестве таблицы ассоциации для отношений ManyToMany между группами / пользователями и конкретным элементом.

Элемент имеет следующие столбцы:

  • user_id -> таблица пользователей
  • group_id -> групповая таблица
  • item_id -> таблица элементов

как минимум один из столбцов user_id и group_id. Таким образом, можно определить доступ для группы или пользователя к определенному элементу.

Я использовал AssociationProxy для определения отношений между пользователями / группами и элементами.

Теперь я хочу отобразить все элементы, к которым у пользователя есть доступ, и мне действительно трудно это делать. Используются следующие критерии:

  • Все элементы, принадлежащие пользователю, должны быть показаны (item.owner_id = user.id)
  • Все публичные предметы должны быть показаны (item.access = public)
  • Должны быть показаны все элементы, к которым у пользователя есть доступ (auth_item.user_id = user.id)
  • Все элементы, к которым имеет доступ группа пользователей, должны быть показаны.

Первые три критерия довольно просты, но мне трудно справиться с четвертым.

Вот мой подход:

clause = and_(item.access == 'public')
if user is not None:
   clause = or_(clause,item.owner == user,item.users.contains(user),item.groups.contains(group for group in user.groups))

Третий критерий дает ошибку.

item.groups.contains(group for group in user.groups)

Я на самом деле не уверен, что это хороший подход вообще.
Каков наилучший подход при фильтрации многих отношений?
Как я могу отфильтровать множество отношений на основе другого списка / отношения?

Кстати, я использую последнюю версию sqlalchemy (6.0) и эликсира

Спасибо за любые идеи.

1 ответ

Решение

contains() Метод для проверки одного элемента. Предполагая, что ваша групповая таблица сопоставлена ​​с Group класс попробуйте следующее:

item.groups.any(Group.id.in_([group.id for group in user.groups])
Другие вопросы по тегам