Policies (ZonePolicy/DevicePolicy/AutomationRulePolicy): не multi-tenant изоляция по user_id, а household-wide RBAC — все авторизованные видят одни и те же данные, только owner может создавать/менять/удалять. user_id на записи — это created_by, а не граница видимости. Form Requests с authorize() через политики; DeviceRequest учитывает unique external_id с ignore на update. AutomationRuleRequest: action_type остаётся строкой (не enum), т.к. это открытый список из device_types.capabilities; для действия set_level в форме есть отдельное поле "level" (Alpine.js переключает его видимость), которое контроллер мапит в action_params — без сырого JSON-редактора для MVP. Контроллеры без show (index+create/edit достаточно), Blade-формы на базе Breeze-компонентов. Навигация и дашборд (счётчики зон/устройств/активных правил) обновлены. Добавлен DemoGrowboxSeeder (демо-зона с датчиком, вентилятором и правилом) и viewer-пользователь в сидер. Восстановлен трейт AuthorizesRequests в базовом Controller (Laravel 11+ убрал его по умолчанию) — нужен для $this->authorize(). Проверено: 33/33 теста (включая новые ZoneControllerTest, AutomationRuleControllerTest — маппинг level→action_params, 403 для viewer), полный CRUD-цикл вживую через браузер под owner (создание зоны, правила с set_level, Alpine-переключение поля "Уровень"), доступ viewer подтверждён как read-only (нет кнопок изменения, прямой заход на /zones/create отдаёт 403).
39 lines
1.4 KiB
PHP
39 lines
1.4 KiB
PHP
<?php
|
|
|
|
use App\Http\Controllers\AutomationRuleController;
|
|
use App\Http\Controllers\DeviceController;
|
|
use App\Http\Controllers\ProfileController;
|
|
use App\Http\Controllers\ZoneController;
|
|
use App\Models\AutomationRule;
|
|
use App\Models\Device;
|
|
use App\Models\Zone;
|
|
use Illuminate\Support\Facades\Route;
|
|
|
|
Route::get('/', function () {
|
|
return view('welcome');
|
|
});
|
|
|
|
Route::get('/dashboard', function () {
|
|
return view('dashboard', [
|
|
'zonesCount' => Zone::count(),
|
|
'devicesCount' => Device::count(),
|
|
'activeRulesCount' => AutomationRule::where('is_active', true)->count(),
|
|
]);
|
|
})->middleware(['auth', 'verified'])->name('dashboard');
|
|
|
|
Route::middleware(['auth', 'verified'])->group(function () {
|
|
Route::resource('zones', ZoneController::class)->except('show');
|
|
Route::resource('devices', DeviceController::class)->except('show');
|
|
Route::resource('automation-rules', AutomationRuleController::class)
|
|
->except('show')
|
|
->parameters(['automation-rules' => 'automation_rule']);
|
|
});
|
|
|
|
Route::middleware('auth')->group(function () {
|
|
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
|
|
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
|
|
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
|
|
});
|
|
|
|
require __DIR__.'/auth.php';
|