Роли и права
Модуль 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:
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 (или любом другом провайдере):
use App\Frame\Permissions\AppPermissions;
use Frame\Permissions\Contracts\DefinesPermissions;
public function register(): void
{
$this->app->bind(DefinesPermissions::class, AppPermissions::class);
}
frame:sync-permissions) падает с BindingResolutionException: Target [Frame\Permissions\Contracts\DefinesPermissions] is not instantiable.4. Подключите trait к модели User
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, ...):
import { registerPermissionsModule } from '@frame/permissions'
import permissionsLocale from '../../vendor/frame/permissions/resources/lang/ru.json'
registerPermissionsModule()
app.use(FramePlugin, {
i18n: { ...locale, ...permissionsLocale },
// ...
})
И добавьте @source в 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}/update | Toggle 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.