|
@@ -0,0 +1,289 @@
|
|
|
|
|
+# План внедрения гибкой ролевой модели (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
|
|
|
|
|
+<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. Проверить что системные роли нельзя удалить
|