Права доступа
Мы используем ролевую модель доступов (RBAC) в системе. У пользователя есть роль в системе (CompanyUser.role), а у каждой роли есть права доступа (RolePermission).
Описание прав доступа RolePermission
RolePermission состоит из двух сущностей и набора свойста.
Сущности:
- Роль (
Role) — описание Роли в системе - Право доступа (
Permission) — описание права доступа, где оно расположено (Permission.module), уникальный ключ (Permission.alias). Право доступа олицетворяет сущность, бизнес единицу, в 99% случаев это модель, например, Файл или Папка в диске, Проект или Объект в сервисе проектов и так далее.
Свойства:
RolePermission.read— может ли эта роль читать объекты из права доступа (чтение как одного объекта так и списка объектов).RolePermission.create— может ли эта роль создавать объекты из права доступа.RolePermission.update— может ли эта роль изменять объекты из права доступа.RolePermission.delete— может ли эта роль удалять объекты из права доступа.RolePermission.actions— может ли эта роль выполнять дополнительные действия над сущностью из права доступа. Не все сущности имеют дополнительные действия.RolePermission.scope— когда роль выполняет действие над конкретным объектом, то какие объекты ей доступны (только те, что создал пользователь, все объекты компании, любые объекты в системе).
Как применяются RolePermission
В django проектах ASU мы используем один ModelViewSet для конкретной модели и описываем все бизнес процессы (действия) в рамках этого вьюсета.
Пример:
FileView из диска это ModelViewSet для модели File, мы можем его читать, создавать, изменять итд. У нас есть Permission(alias="file", module="disk"), который описывает эту модель. Этот Permission задан для конкретной роли и настроен в RolePermission.
FileView для проверки прав доступа имеет несколько свойств:
permission_classes, который включает в себяasu_s_sdk.utils.rest_framework.permissions.permission.AsuPermission("file"), который во время выполнения запроса проверяет права доступаpermission_scope_pathэто словарь в котором мы описываем какие поля из модели нужно проверять для доступа к объекту. Например:
from asu_s_sdk.utils.rest_framework.permissions.permission import AsuPermissionScope
permission_scope_path = {
AsuPermissionScope.COMPANY: "file.company_id",
AsuPermissionScope.SELF: ["author_id", "file.user_id"],
}- Для скоупа объектов компании мы у объекта ищем поле obj.file.company_id и сравниваем его с request.user.company_id
- Для скоупа собственных объектов мы у объекта сравниваем два поля obj.author_id или obj.fle.user_id с request.user.id
У FileView также есть дополнительные действия, которые мы описываем с помощью декоратора @action(methods=..., detail=...), этот action также должен быть добавлен в право доступа (Permission)
Если добавляется новая модель
- Добавить новую запись в конце фикстуры permissions.json. defaults всегда заполняем в false.
- После деплоя для всех
Roleобъектов нужно добавить новые права доступа. В django-admin есть удобный actionupdate_permissionsдляRoleAdmin, чтобы это сделать.
Если добавляется допольнительное действие над моделью
- Найти нужный объект права доступа в фикстуре permissions.json.
- В объекте actions добавить ключ (название action из вьюсета) и значение false.
- После деплоя для всех
Roleобъектов нужно добавить новые права доступа. В django-admin есть удобный actionupdate_permissionsдляRoleAdmin, чтобы это сделать.
Важно
- При изменении прав доступа у
RolePermissionони не всегда применяются моментально, т.к. межсервисные запросы кэшируются. Кэш обновится максимум через 2 минуты. - Следить за тем, чтобы при каждом деплое помимо миграций вызывалась команда
manage.py loaddata permissions, которая будет добавлять новые права доступа.