Сначало кратко)
Доброго дня!
Прошу помощи с проектированием/перепроектированием системы управления доступом. Или выбором готовой, выбором библиотек, паттернов, чего угодно.
Теперь подробно)Что есть
Приложение с большим колличеством связей между данными, рест апи написаное на nodejs с использованием фреймворка
loopback.io. Приложение уже в продакшене, но активно развивается - добавляются еженедельно новые модели, поля, связи.
Что хочется
1) Разрешать действия пользователям(чтение, редактирование) по следующим критериям:
- принадлежность к текущему пользователю - пример: действие происходит с моделью мероприятия, у неё есть связь с менеджером со стороны клиента (contactFromCustomerId), если он текущий пользователь, то ему разрешено это действие.
- принадлежность к другой модели, к которой принадлежит текущий пользователь - пример: действие происходит с моделью мероприятия, у текущего пользователя есть связь с компанией, у меророприятия есть связь с пользователем, у которого есть связь с компанией, если компании одинаковые, действие разрешено.
- поля, которые затрагиваются действием - пример: пользователю с данной ролью разрешено просматривать только часть полей мероприятия, а обновлять вообще одно.
- состояние полей модели, к которой обращено действие - например: мероприятие текущему пользователю можно редактировать только в статусе new.
- состояние полей связанной модели - пример: пользователь может обновлять поля модели сметы, только если связанное со сметой мероприятие имеет статус new.
Критерии могу наслаиваться друг на друга, например пользователь может редактировать только определённые поля модели сметы и только когда мероприятие относится к его компании и находится в статусе new.
Критерии могут и будут появляться новые.
2) Давать пользователям самим создавать права, включать/выключать имеющиеся разрешения.
3) Создавать разрешения, управляющие видимостью контента - например менеджер0 работающий в системе должен видеть информацию в окне А, менеджер1 должен ту же информацию видеть в окне Б.
Что было
Рассмотрели n колличество библиотек, где реализованы системы контроля доступа.
Почитали о ACL.
Решили(возможно ошибочно) что ни одна из реализаций нам не подходит и мы в приемлемые(точно ошибочно) сроки запилим свою.
Что есть/Что с этим уже сделали
Разрешения обрабатываются в отдельной библиотеке.
Разрешения только положительные. (разрешают что-то делать)
Мета инфромация разрешений хранятся в конфигах, конфиги лежат рядом с файлом, описывающим модель, пример:
{
// ... ,
"event_create": {
"remoteMethod": [
"create",
"upsert"
],
"httpMethod": [
"post",
"put",
"patch"
],
"modelName": "Event",
"actionType": "write"
},
"event_read": {
"remoteMethod": [
"find",
"findOne",
"findById",
"exists",
"count",
"get"
],
"httpMethod": "get",
"modelName": "Event",
"actionType": "read"
},
// ...
}
У пользователей есть много ролей, у роли есть много разрешений.
К каждому действию пользователя генерируется объект с описанием, например:
{
"remoteMethod": "get"
"httpMethod": "get",
"modelName": "Event",
"actionType": "read"
}
Действие сравнивается с имеющимися у пользователя разрешениями, которые мы получили из его ролей.
Принимается решение, запрещать действие, модифицировать (отправить не все поля мероприятия, а только часть), или разрешать.
Часто результатом запрещения/модификации запроса пользователя становится изменение фильтра запроса в бд.
к пимеру пользоатель запрашивает /events , ему можно видеть только свои мероприятия, запрос в базу по умолчанию будет в нашем случае { where: {} },
после контроля доступа { where: { contactFromCustomerId: "id текущего пользователя" } }.
Текущие проблемы
- гигантское колличество разрешений, и оно увеличивается.
особенно из-за пересекающихся критериев - например мы,
кроме статусов воодим типы мероприятий и хотим разрешать/запрещать работу с определёнными типами в определённом статусе.
С таким колличеством разрешений тяжело работать. Пользователям не хочется заполнять их все.
- общая сложность системы. Отчасти это, конечно, следствие реализации, но часто гложат мысли - может изначально всё плохо спроектировано?
- производительность - из за большого колличества критериев, основанных на данных других моделей приходится запрашивать большое колличество дополнительных данных
- гложат сомнения на счёт правильности контроля доступа посредством изменения запроса в бд - с одной стороны мы не получаем лишних данных, с другой - запросы бывает очень длинные и страшные получаются.
Собственно сами вопросы- Определённо кто-то сталкивался с подобными задачами. Хочется услышать, как вы с этим справились?
- Мы делаем что-то не так? Что?
- Что думаете про подшаманивание запроса пользователя?
- Огромное колличество разрешений - это норм?
- Чтобы сгруппировать разрешения для пользователей создать разрешение, включающее в себя остальные, или сделать чисто визуальную группировку для пользователей?
- Может есть паттерн, который рассказывает как рулить контролем доступа, а я его каким-то образом пропустил?
- Может даже есть примеры?
Буду благодарен за любую помощь)
P.S. Вопрос большой, контекста много, постарался описать всё, что нужно для понимания ситуации. Если не удалось -
напишите об этом пожалуйста.