Как спроектировать систему управления доступом в приложение?

Сначало кратко)
Доброго дня!
Прошу помощи с проектированием/перепроектированием системы управления доступом. Или выбором готовой, выбором библиотек, паттернов, чего угодно.

Теперь подробно)
Что есть
Приложение с большим колличеством связей между данными, рест апи написаное на 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. Вопрос большой, контекста много, постарался описать всё, что нужно для понимания ситуации. Если не удалось -
напишите об этом пожалуйста.
  • Вопрос задан
  • 1319 просмотров
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы