Symfony ACL позволяет мне предоставлять доступ к объекту, а затем проверять его:
if (false === $securityContext->isGranted('EDIT', $comment)) { throw new AccessDeniedException(); }
Однако, если у меня есть тысячи объектов в базе данных, и у пользователя есть доступ только к 10 из них, я не хочу загружать все объекты в памяти и убирать их.
Как я могу сделать простой «SELECT * FROM X» при фильтрации только на сущности, к которым у пользователя есть доступ (на уровне SQL)?
Ну вот он: это невозможно .
В прошлом году я работал над альтернативной системой ACL, которая позволяла напрямую фильтровать запросы к базе данных.
Моя компания недавно согласилась открыть исходный код, поэтому вот оно: http://myclabs.github.io/ACL/
Как было указано в предыдущем обсуждении,
В первом запросе получите список (с пользовательским запросом) всех объектов object_identity_ids (для определенного объекта / класса X), к которому пользователь имеет доступ.
Затем, при запросе списка объектов для объекта / класса X, добавьте в запрос «IN (object_identity_ids)» .
Маттье, меня не устраивало, отвечая на большее количество догадок (так как мои предположения не добавляют ничего полезного для разговора). Поэтому я сделал несколько этапов для этого подхода (Digital Ocean 5 $ / mo VPS).
Как и ожидалось, размер таблицы не имеет значения при использовании подхода массива IN. Но большой размер массива действительно заставляет вещи выходить из-под контроля.
Итак, Join approach
IN array approach
?
JOIN действительно лучше, когда размер массива огромен. НО, это предполагает, что мы не должны рассматривать размер таблицы. Оказывается, на практике массив IN быстрее – за исключением случаев, когда имеется большая таблица объектов, а записи acl охватывают почти каждый объект (см. Связанный вопрос).
Я расширил свои рассуждения по отдельному вопросу. См. При использовании ACL от Symfony лучше использовать запрос JOIN или запрос массива IN?
Вы могли бы взглянуть на фильтры Doctrine . Таким образом, вы можете расширить все запросы. Я еще не сделал этого, и есть некоторые ограничения, о которых идет речь. Но, возможно, это поможет вам. Здесь вы найдете описание таблиц базы данных ACL.
ОБНОВИТЬ
Каждый фильтр возвращает строку, и все эти строки будут добавлены к SQL-запросам следующим образом:
SELECT ... FROM ... WHERE ... AND (<result of filter 1> AND <result of filter 2> ...)
Также псевдоним таблицы передается методу фильтра. Поэтому я думаю, что вы можете добавить подзапросы здесь, чтобы отфильтровать ваши сущности.