# План внедрения гибкой ролевой модели (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` ```php $middleware->alias([ 'role' => EnsureUserHasRole::class, 'permission' => EnsureUserHasPermission::class, 'permission.any' => EnsureUserHasAnyPermission::class, ]); ``` --- ## Фаза 5: Blade директивы ### Добавить в `app/Providers/AppServiceProvider.php` ```php Blade::if('role', fn($roles) => hasRole($roles)); Blade::if('permission', fn($permission) => hasPermission($permission)); Blade::if('anypermission', fn($permissions) => hasAnyPermission($permissions)); ``` **Использование:** ```blade @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`) ```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`: ```blade
  • Роли и права
  • ``` --- ## Фаза 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. Проверить что системные роли нельзя удалить