Поддержка

Роли и права

Модуль управления ролями и abilities на базе silber/bouncer

Модуль Permissions (frame/permissions) добавляет в Frame UI и API для управления ролями, abilities и назначениями ролей записям ресурсов. Под капотом — silber/bouncer.

Возможности

  • Страница /permissions с деревом прав и списком ролей
  • Создание, дублирование, редактирование и удаление ролей
  • Назначение ролей конкретным записям ресурсов (вкладка «Назначения»)
  • Default-abilities для ролей, non-editable роли (например admin)
  • Gate frame-permissions для контроля доступа к UI

Установка

1. Composer

composer require frame/permissions

Если bouncer не был установлен ранее, опубликуйте и выполните его миграции:

php artisan vendor:publish --tag=bouncer.migrations
php artisan migrate

2. Определите схему прав

Создайте класс, реализующий Frame\Permissions\Contracts\DefinesPermissions:

app/Frame/Permissions/AppPermissions.php
namespace App\Frame\Permissions;

use Frame\Permissions\Contracts\DefinesPermissions;
use Frame\Permissions\Data\ResourcePermissions;
use Frame\Permissions\Entities\PermissionEntity as PE;
use Frame\Permissions\Entities\RoleEntity as RE;

class AppPermissions implements DefinesPermissions
{
    public function tree(): array
    {
        return [
            PE::make('General', 'general', [
                PE::make('Roles & permissions', 'roles'),
            ]),
            ResourcePermissions::forResource('users', 'Users'),
        ];
    }

    public function roles(): array
    {
        return [
            RE::make('Administrator', 'admin')
                ->editable(false)
                ->defaultPermissions(['*']),
        ];
    }
}

3. Привяжите биндинг

В FrameServiceProvider (или любом другом провайдере):

app/Providers/FrameServiceProvider.php
use App\Frame\Permissions\AppPermissions;
use Frame\Permissions\Contracts\DefinesPermissions;

public function register(): void
{
    $this->app->bind(DefinesPermissions::class, AppPermissions::class);
}
Без биндинга любая операция над permissions (в т.ч. команда frame:sync-permissions) падает с BindingResolutionException: Target [Frame\Permissions\Contracts\DefinesPermissions] is not instantiable.

4. Подключите trait к модели User

app/Models/User.php
use Frame\Permissions\Concerns\HasPermissionRoles;

class User extends Authenticatable
{
    use HasPermissionRoles;
}

5. Синхронизируйте права

php artisan frame:sync-permissions

Команда создаёт недостающие роли и abilities в БД на основе tree() и roles(). Запускайте после каждого изменения AppPermissions.

6. Подключите фронтенд

В resources/js/frame.ts до app.use(FramePlugin, ...):

resources/js/frame.ts
import { registerPermissionsModule } from '@frame/permissions'
import permissionsLocale from '../../vendor/frame/permissions/resources/lang/ru.json'

registerPermissionsModule()

app.use(FramePlugin, {
  i18n: { ...locale, ...permissionsLocale },
  // ...
})

И добавьте @source в CSS:

resources/css/frame.css
@source '../../node_modules/@frame/permissions';

Контроль доступа

По умолчанию доступ к UI модуля разрешён всем авторизованным пользователям через gate frame-permissions. Переопределите в FrameServiceProvider или AuthServiceProvider:

use Illuminate\Support\Facades\Gate;

Gate::define('frame-permissions', fn ($user) => $user?->hasRole('admin'));

API

Все эндпоинты доступны под префиксом Frame API (по умолчанию /api/frame):

МетодЭндпоинтОписание
GET/permissionsДерево прав + все роли
POST/permissions/roles/{role?}Создать / обновить роль
POST/permissions/roles/{role}/duplicateДублировать роль
POST/permissions/roles/{role}/updateToggle abilities роли
DELETE/permissions/roles/{role}Удалить роль
GET/permissions/resources/{resource}/{id}Роли конкретной записи
POST/permissions/resources/{resource}/{id}Синхронизировать роли записи

Переводы

Фронтенд-переводы лежат в vendor/frame/permissions/resources/lang. Добавьте недостающие ключи в свой lang/ru.json или используйте объединение в i18n как показано выше.

Backend-переводы подхватываются автоматически через loadJsonTranslationsFrom в PermissionsServiceProvider.