Каркас Laravel-приложения: Breeze+Sanctum, схема БД, модели, Docker

Laravel 13 в laravel-app/, Breeze (Blade) для сессионного логина + Sanctum
для API-токенов (задел под Vue/Flutter на этапе 3). Схема Postgres
перенесена из сырого SQL в Laravel-миграции (владелец схемы теперь Laravel,
Go-сервисы как читали/писали эти таблицы, так и продолжают). Роли/категории/
операторы условий — закрытые PHP-enum'ы (UserRole, DeviceCategory,
ConditionOperator); action_type правил намеренно остаётся строкой — открытый,
управляемый данными список, а не код. Сидер device_types с growbox-типами
как пример данных, не бизнес-логика.

Docker: один контейнер (php-fpm + nginx через supervisord, multi-stage
сборка vendor/assets). Образ пока не --no-dev — сидер использует fake()
для демо-аккаунта.

Проверено: миграции применяются на реальном Postgres (в докере и локально),
дефолтные тесты Breeze проходят (25/25), Breeze-логин подтверждён вживую
через браузер, Sanctum корректно отдаёт 401 на защищённый /api/user без
токена.
This commit is contained in:
2026-07-28 08:15:26 +05:00
parent abc83faf05
commit bb492785a4
132 changed files with 15894 additions and 72 deletions
@@ -0,0 +1,51 @@
<?php
namespace Tests\Feature\Auth;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Hash;
use Tests\TestCase;
class PasswordUpdateTest extends TestCase
{
use RefreshDatabase;
public function test_password_can_be_updated(): void
{
$user = User::factory()->create();
$response = $this
->actingAs($user)
->from('/profile')
->put('/password', [
'current_password' => 'password',
'password' => 'new-password',
'password_confirmation' => 'new-password',
]);
$response
->assertSessionHasNoErrors()
->assertRedirect('/profile');
$this->assertTrue(Hash::check('new-password', $user->refresh()->password));
}
public function test_correct_password_must_be_provided_to_update_password(): void
{
$user = User::factory()->create();
$response = $this
->actingAs($user)
->from('/profile')
->put('/password', [
'current_password' => 'wrong-password',
'password' => 'new-password',
'password_confirmation' => 'new-password',
]);
$response
->assertSessionHasErrorsIn('updatePassword', 'current_password')
->assertRedirect('/profile');
}
}