Извините за длину здесь ... надеюсь, я не пошел за борт ...
Я работаю над своим первым рабочим приложением MVC, и япытаясь придерживаться принципов DDD в процессе.Я столкнулся с некоторыми вопросами, связанными с тем, как справиться с требованиями безопасности приложения, и подумал, что я смогу посмотреть, может ли сообщество SO предложить несколько рекомендаций.
Информация о домене
Чтобы использовать упрощенное объяснение, это приложение будет иметь AffiliateCompanies
, Users
и Customers
.
AffiliateCompanies
являются иерархическими, поэтому один филиал может подписатьи быть привязанным к деятельности другого партнера.Корень - это основная компания, предоставляющая продукты / услуги. Users
все принадлежат аффилированному лицу. Customers
- это организации, которым продаются продукты / услуги.Филиалы назначаются клиентам таким образом, чтобы два иерархически не связанных филиала могли разделить клиента.
Информация о безопасности
Права на выполнение определенных действий взаявка будет определяться на основе типа ACL.Каждый объект User
имеет свойство, представляющее собой коллекцию SystemAccessRules
, определяющую, какие действия они могут выполнять и каковы области их разрешений (их собственные объекты, объекты их аффилированных лиц или объекты всей их иерархии).Пользователи также могут принадлежать к ролям, которые сами имеют ту же коллекцию SystemAccessRules
.
. В результате, если пользователь входит в систему и хочет видеть список "своих" клиентов, список может быть составленклиентов, которым они назначены индивидуально, клиенты, которым назначен любой сотрудник их аффилированной организации, или клиенты, которым назначены сотрудники их организаций или дочерних организаций.
Соображения базы данных *За исключением 1040 *
DDD, в какой-то момент стратегия хранения должна вступить в игру.В этом простом сценарии таблицы выровнены с указанными выше объектами (включая таблицу ролей) с несколькими вспомогательными таблицами для поддержки отношений между объектами:
AffiliateCustomers
- эта таблица позволяетотношения «многие ко многим» между филиалами и клиентами, храня PK каждого объекта в виде пары FK, которые сами являются составным PK для этой таблицы. ACL
- в этой таблице хранится информация о безопасности, в частностисубъект записи (пользователь или роль), рассматриваемое действие (например, «CreateCustomer»), разрешение (разрешить или запретить) и область действия (их собственный материал, их организация или сеть).
Вопрос ... Наконец-то
Я использую комбинацию репозиториев и сервисов.Я пытаюсь сохранить бизнес-логику в сервисах и вне репозиториев или базы данных, но из-за безопасности здесь простой запрос списка «их» клиентов может быть чрезвычайно обременительным, особенно по мере роста набора данных.Я пытался использовать Linq, где это возможно, но эта архитектура, кажется, не очень подходит.На мой взгляд, вот мой выбор:
Примите запрашивающего пользователя в качестве аргумента для методов обслуживания (или определите его по контексту) и попросите метод службы заполнить список несколькимизапросы к репозиторию Linq.Это потребует перетаскивания списка клиентов, затем итерацию каждого клиента для выдачи другого запроса на получение данных ACL, а затем использование этих данных для фильтрации первого списка на основе разрешений.Проблема иерархии потребует некоторой изящной работы Linq (например, this ), если это вообще возможно.
Даже если проблема иерархии может быть решена, кажется, что это решение выиграло 'очень хорошо работают ...
Примите запрашивающего пользователя в качестве аргумента, но передайте его и требуемое разрешение (например, «Просмотр клиентов») в хранилище, чтобы извлечь соответствующие данные из базы данных через хранимую процедуру, которая будет использовать несколько предложений EXISTSв запросе CTE, который может объяснить иерархическую природу данных и необходимость проверки роли и безопасности пользователя.
Это выдвигает достаточное количество логики в базу данных, что кажется очень анти-DDD и обычноплохо.
Я больше склоняюсь ко второму варианту, но это может быть потому, что в моих прошлых проектах я так и делал.Я даже не уверен, что мой дизайн в целом находится на правильном пути (в прошлом декларации разрешений делались с использованием битовых флагов, поэтому было еще проще выполнить запрос к БД с помощью побитового оператора).
Кто-нибудь был в подобных ситуациях, и если да, можете ли вы прокомментировать производительность и ремонтопригодность решения, которое вы использовали?Я хочу придерживаться передовых принципов программирования, но не за счет простоты и здравого смысла.