flex_roles_plan.md 11 KB

План внедрения гибкой ролевой модели (RBAC)

Обзор

Внедрение системы RBAC (Role-Based Access Control) для Stroyprofit CRM с возможностью создания новых ролей и назначения им прав через UI.

Текущее состояние

Компонент Описание
Хранение ролей Поле role (string) в таблице users
Класс Role Статический класс с константами app/Models/Role.php
Проверка ролей Helper функция hasRole() в app/Helpers/roles.php
Middleware EnsureUserHasRole - проверка через in_array()
Точки проверки 155+ вызовов hasRole() в Blade, контроллерах, FormRequest

Текущие роли: admin, manager, brigadier


Фаза 1: База данных

Миграции

1.1 Таблица roles

database/migrations/2026_02_03_000001_create_roles_table.php
  • id, slug (unique), name, description, is_system (boolean), timestamps

1.2 Таблица permissions

database/migrations/2026_02_03_000002_create_permissions_table.php
  • id, slug (unique), name, module, action, description, timestamps

1.3 Связь ролей и прав role_has_permissions

database/migrations/2026_02_03_000003_create_role_has_permissions_table.php
  • role_id (FK), permission_id (FK), составной PK

1.4 Добавление role_id в users

database/migrations/2026_02_03_000004_add_role_id_to_users_table.php
  • role_id (FK nullable) - связь с таблицей roles

Фаза 2: Модели

2.1 Обновление app/Models/Role.php

Преобразовать из статического класса в Eloquent модель:

  • Сохранить константы для обратной совместимости (ADMIN, MANAGER, BRIGADIER)
  • Добавить связь permissions() (belongsToMany)
  • Добавить связь users() (hasMany)
  • Методы: hasPermission(), givePermissions(), syncPermissions()

2.2 Новая модель app/Models/Permission.php

  • Связь roles() (belongsToMany)
  • Статический метод getGroupedByModule()

2.3 Обновление app/Models/User.php

Добавить:

  • Поле role_id в $fillable
  • Связь roleModel() (belongsTo Role)
  • Метод hasRole() - сначала проверяет role_id, fallback на role
  • Метод hasPermission() - админ имеет все права
  • Метод hasAnyPermission()
  • Метод getAllPermissions()

Фаза 3: Helper функции

Обновление app/Helpers/roles.php

  • getRoles() - сначала из БД, fallback на константы
  • hasRole() - использовать метод модели User
  • hasPermission() - новая функция
  • hasAnyPermission() - новая функция
  • roleName() - сначала из БД, fallback на константы

Фаза 4: Middleware

4.1 Обновить app/Http/Middleware/EnsureUserHasRole.php

  • Использовать метод $user->hasRole() вместо прямой проверки

4.2 Новый app/Http/Middleware/EnsureUserHasPermission.php

  • Использование: middleware('permission:orders.create')

4.3 Новый app/Http/Middleware/EnsureUserHasAnyPermission.php

  • Использование: middleware('permission.any:orders.create,orders.update')

4.4 Регистрация в bootstrap/app.php

$middleware->alias([
    'role' => EnsureUserHasRole::class,
    'permission' => EnsureUserHasPermission::class,
    'permission.any' => EnsureUserHasAnyPermission::class,
]);

Фаза 5: Blade директивы

Добавить в app/Providers/AppServiceProvider.php

Blade::if('role', fn($roles) => hasRole($roles));
Blade::if('permission', fn($permission) => hasPermission($permission));
Blade::if('anypermission', fn($permissions) => hasAnyPermission($permissions));

Использование:

@role('admin')...@endrole
@permission('orders.delete')...@endpermission

Фаза 6: Сидер данных

database/seeders/RbacSeeder.php

  1. Создать 73 права (permissions) по модулям
  2. Создать системные роли (admin, manager, brigadier) с is_system=true
  3. Назначить права ролям
  4. Мигрировать существующих пользователей: заполнить role_id на основе role

Фаза 7: UI управления ролями

7.1 Контроллер app/Http/Controllers/Admin/RoleController.php

  • CRUD для ролей
  • Назначение прав через чекбоксы

7.2 Маршруты (добавить в routes/web.php)

Route::prefix('admin/roles')->middleware('role:admin')->group(function(){
    Route::get('', [RoleController::class, 'index'])->name('admin.roles.index');
    Route::get('create', [RoleController::class, 'create'])->name('admin.roles.create');
    Route::post('', [RoleController::class, 'store'])->name('admin.roles.store');
    Route::get('{role}', [RoleController::class, 'show'])->name('admin.roles.show');
    Route::put('{role}', [RoleController::class, 'update'])->name('admin.roles.update');
    Route::delete('{role}', [RoleController::class, 'destroy'])->name('admin.roles.destroy');
});

7.3 Views

  • resources/views/admin/roles/index.blade.php - список ролей
  • resources/views/admin/roles/edit.blade.php - создание/редактирование с чекбоксами прав

7.4 Меню

Добавить в resources/views/layouts/menu.blade.php:

<li><a href="{{ route('admin.roles.index') }}">Роли и права</a></li>

Фаза 8: Обновление формы пользователя

Обновить app/Http/Requests/User/StoreUser.php

  • Заменить role на role_id

Обновить view редактирования пользователя

  • Выпадающий список ролей из БД вместо констант

Список прав (73 права)

Модуль Права
orders view, create, update, delete, export, documents, photos, maf, generate
reclamations view, create, update, delete, documents, photos, spare_parts
maf view, update, import, export, passports
maf_orders view, create, update, delete
catalog view, create, update, delete, import, export, certificates
schedule view, create, update, delete, export
spare_parts view, create, update, delete, import, export
spare_part_orders view, create, update, delete, ship
spare_part_reservations view, manage
spare_part_inventory view
contracts view, create, update, delete
users view, create, update, delete
responsibles view, create, update, delete
reports view
import view, create
districts view, manage
areas view, manage
pricing_codes view, manage
admin clear_data, year_data, roles

Права по ролям (по умолчанию)

Admin

Все права (*)

Manager

  • orders: view, create, update, documents, photos, generate
  • reclamations: view, create, update, documents, photos, spare_parts
  • maf: view, update
  • catalog: view
  • schedule: view, create, update
  • spare_parts: view
  • spare_part_orders: view, create, update
  • spare_part_reservations: view, manage
  • spare_part_inventory: view
  • contracts: view, create, update
  • responsibles: view, create, update
  • reports: view

Brigadier

  • orders: view, photos
  • reclamations: view, photos
  • schedule: view

Порядок выполнения

  1. Создать миграции (4 файла)
  2. Создать модель Permission
  3. Обновить модель Role (сохранить константы)
  4. Обновить модель User
  5. Обновить helpers/roles.php
  6. Обновить EnsureUserHasRole middleware
  7. Создать новые middleware (permission, permission.any)
  8. Зарегистрировать middleware в bootstrap/app.php
  9. Добавить Blade директивы в AppServiceProvider
  10. Создать RbacSeeder
  11. Запустить: php artisan migrate && php artisan db:seed --class=RbacSeeder
  12. Создать RoleController
  13. Создать views для ролей
  14. Обновить меню
  15. Обновить форму пользователя (role → role_id)

Обратная совместимость

  • Функция hasRole() продолжает работать
  • Middleware role:admin,manager работает без изменений
  • Blade шаблоны с @if(hasRole('admin')) работают
  • Постепенная миграция на hasPermission() опциональна

Критические файлы для изменения

Файл Действие
app/Models/Role.php Переработать в Eloquent модель
app/Models/User.php Добавить role_id, методы hasPermission
app/Models/Permission.php Создать новую модель
app/Helpers/roles.php Обновить с поддержкой БД
app/Http/Middleware/EnsureUserHasRole.php Использовать метод модели
bootstrap/app.php Зарегистрировать новые middleware
app/Providers/AppServiceProvider.php Добавить Blade директивы
database/seeders/RbacSeeder.php Создать сидер
app/Http/Controllers/Admin/RoleController.php Создать контроллер
resources/views/admin/roles/*.blade.php Создать views
resources/views/layouts/menu.blade.php Добавить пункт меню
routes/web.php Добавить маршруты ролей

Верификация

После внедрения:

  1. Проверить авторизацию существующих пользователей
  2. Создать новую роль через UI
  3. Назначить права новой роли
  4. Создать пользователя с новой ролью
  5. Проверить доступ к разделам согласно правам
  6. Проверить что системные роли нельзя удалить