Перейти к основному содержимому

Ролевая модель и права доступа в АП

Текущая реализация ролевой модели и прав доступа позволяет создавать неограниченное число ролей, назначать им любые права доступа и привязывать произвольный набор ролей к пользователю. Для этого в административной панели предусмотрен конструктор прав доступа при создании/редактировании роли.

Как работают права доступа​

На бэкенде​

Набор возможных прав доступа хранится в enum в units/admin-auth. Затем используется симбиоз из Laravel features: Policies, Gates, Middleware в admin-gui-backend:

  1. Связь прав с методами (эндпоинтами) хранится в политиках
  2. Метод в политике описывает права на доступ к аналогичному (по неймингу) методу в контроллере
  3. 1 политика – 1 контроллер
  4. Через фасад Gate проверяется политика в Middleware при запросе API
  5. В зависимости от выполнения условия описанного в методе политики для этого контроллера@метода API – доступ либо предоставляется, либо выбрасывается 403 ошибка

Автоматический поиск политик работает по такому принципу:

Gate::guessPolicyNamesUsing(
fn ($className) => str_replace('Controllers', 'Policies', $className) . 'Policy'
);

На фронте​

Для фронта справочник прав доступа возращается методом: GET /api/v1/units/admin-users/right-access. Фронт сравнивает набор прав доступа текущего пользователя со справочником, исходя из этого допускает пользователя к тем или иным действиям.

Добавление прав доступа​

Сначала нужно добавить новые права в rights_access_enum.yaml:

  description: |
* `9xx` Для информационных страниц:
* `901` - Пользователю доступен табличный список с информационными страницами
* `902` - Пользователю доступна детальная страница информационной страницы
enum:
- 901
- 902
x-enum-varnames:
- PAGE_LIST_READ
- PAGE_DETAIL_READ
x-enum-descriptions:
- Пользователю доступен табличный список с информационными страницами
- Пользователю доступна детальная страница информационной страницы

Этот же enum необходимо будет продублировать в admin-gui-backend в units_admin_user_role_rights_access_enum.yaml.

Затем в справочнике RightsAccess:

  1. Создать константу с названием раздела, в контексте которого будут выдаваться права.
  2. Добавить метод возвращающий массив новых прав доступа.
  3. В методе all() добавить в результирующий массив новый раздел и его права доступа по аналогии:
    public static function all(): array
{
return [
['section' => self::PAGES, 'items' => self::pages()],
];
}

public static function pages(): array
{
return [
new static(
RightsAccessEnum::PAGE_LIST_READ,
'Пользователю доступен табличный список с информационными страницами'
),
];
}

На этом этапе, после генерации клиента сервиса units/admin-auth права считаются добавленными, но еще никак не используются. Чтобы была возможность их использовать, т.е ограничивать доступ к методам, необходимо прописать политики прав доступа в admin-gui-backend.

Использование прав доступа​

  1. Создать новую политику {controller_name}Policy.php для контроллера, методы которого необходимо ограничить:
├── Orders
│   ├── Controllers
│   │   ├── BasketsCommon
│   │   ├── OmsCommon
│   │   ├── Orders
│   │   └── Refunds
│   │   └── RefundsController.php
│   ├── Policies
│   │   ├── BasketsCommon
│   │   ├── OmsCommon
│   │   ├── Orders
│   │   └── Refunds
│   │   └── RefundsControllerPolicy.php
│   ├── Queries
│   ├── Requests
│   ├── Resources
│   └── Tests
  1. В политике объявить метод с названием анологичным закрываемому методу контроллера, который будет возвращать объект Illuminate\Auth\Access\Response.
  2. Проверить через кастомные методы модели пользователя allowOneOf() или allowAllOf() наличие необходимых прав:
use App\Domain\Auth\Models\User;
use Ensi\AdminAuthClient\Dto\RightsAccessEnum;
use Illuminate\Auth\Access\HandlesAuthorization;
use Illuminate\Auth\Access\Response;

class RefundsControllerPolicy
{
use HandlesAuthorization;

public function create(User $user): Response
{
return $user->allowOneOf([
RightsAccessEnum::ORDER_DETAIL_REFUND_CREATE,
]);
}
}
  • allowOneOf() - если пользователю достаточно иметь хотя бы одно право из переданного набора
  • allowAllOf() - если пользователю необходимо иметь все права из переданного набора

Выдача прав доступа​

После добавления новых прав доступа необходимо реализовать их автоматическую выдачу администратору. Для этого необходимо использовать миграции, пример можно посмотреть здесь.