initial commit

This commit is contained in:
bastien
2026-06-28 12:29:53 +02:00
parent 03e85d2f9d
commit b2443b654c
220 changed files with 24969 additions and 1 deletions
@@ -0,0 +1,31 @@
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class AuthenticateMachineIntegration
{
public function handle(Request $request, Closure $next): Response
{
$apiKey = config('laverie.machine_api_key');
if ($apiKey === null || $apiKey === '') {
return response()->json([
'message' => 'Intégration machine non configurée.',
], 503);
}
$providedKey = $request->header('X-API-Key');
if (! is_string($providedKey) || ! hash_equals($apiKey, $providedKey)) {
return response()->json([
'message' => 'Clé API machine invalide.',
], 401);
}
return $next($request);
}
}
@@ -0,0 +1,47 @@
<?php
namespace App\Http\Middleware;
use App\Models\Supervisor;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Laravel\Sanctum\PersonalAccessToken;
use Symfony\Component\HttpFoundation\Response;
class AuthenticateSupervisor
{
public function handle(Request $request, Closure $next): Response
{
if ($request->bearerToken() !== null) {
$token = PersonalAccessToken::findToken($request->bearerToken());
if ($token !== null
&& $token->tokenable instanceof Supervisor
&& $token->can('supervisor')
&& $token->tokenable->is_active
) {
Auth::guard('supervisor')->setUser($token->tokenable);
$request->setUserResolver(fn () => $token->tokenable);
return $next($request);
}
return response()->json([
'message' => 'Token superviseur invalide.',
], 401);
}
if (Auth::guard('supervisor')->check()) {
$supervisor = Auth::guard('supervisor')->user();
if ($supervisor instanceof Supervisor && $supervisor->is_active) {
return $next($request);
}
}
return response()->json([
'message' => 'Superviseur non authentifié.',
], 401);
}
}
+30
View File
@@ -0,0 +1,30 @@
<?php
namespace App\Http\Middleware;
use App\Models\User;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class EnsureApiUser
{
public function handle(Request $request, Closure $next): Response
{
$user = $request->user();
if (! $user instanceof User) {
return response()->json([
'message' => 'Authentification utilisateur requise.',
], 401);
}
if (! $user->is_active) {
return response()->json([
'message' => 'Compte utilisateur désactivé.',
], 403);
}
return $next($request);
}
}
@@ -0,0 +1,120 @@
<?php
namespace App\Http\Middleware;
use App\Models\Booking;
use App\Models\DailyEstablishmentStat;
use App\Models\Machine;
use App\Models\PricingRule;
use App\Models\Promotion;
use App\Models\Supervisor;
use App\Models\Wash;
use Closure;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class EnsureSupervisorScope
{
public function handle(Request $request, Closure $next): Response
{
$supervisor = $this->resolveSupervisor($request);
if ($supervisor === null) {
return response()->json([
'message' => 'Superviseur non authentifié.',
], 401);
}
if (! $supervisor->is_active) {
return response()->json([
'message' => 'Compte superviseur désactivé.',
], 403);
}
$request->attributes->set('supervisor', $supervisor);
return $next($request);
}
public static function resolveSupervisor(Request $request): ?Supervisor
{
$user = $request->user();
return $user instanceof Supervisor ? $user : null;
}
public static function machinesQuery(Supervisor $supervisor): Builder
{
$query = Machine::query()->with(['establishment', 'machineIntegration']);
return self::applyEstablishmentScope($query, $supervisor, 'establishment_id');
}
public static function bookingsQuery(Supervisor $supervisor): Builder
{
$query = Booking::query()
->with(['user', 'machine.establishment'])
->whereHas('machine.establishment', function (Builder $query) use ($supervisor) {
self::applyOrganizationFilter($query, $supervisor);
});
if ($supervisor->establishment_id !== null) {
$query->whereHas('machine', fn (Builder $q) => $q->where('establishment_id', $supervisor->establishment_id));
}
return $query;
}
public static function washesQuery(Supervisor $supervisor): Builder
{
$query = Wash::query()
->with(['user', 'machine.establishment', 'booking'])
->whereHas('machine.establishment', function (Builder $query) use ($supervisor) {
self::applyOrganizationFilter($query, $supervisor);
});
if ($supervisor->establishment_id !== null) {
$query->whereHas('machine', fn (Builder $q) => $q->where('establishment_id', $supervisor->establishment_id));
}
return $query;
}
public static function pricingRulesQuery(Supervisor $supervisor): Builder
{
$query = PricingRule::query()->with(['establishment', 'machine']);
return self::applyEstablishmentScope($query, $supervisor, 'establishment_id');
}
public static function promotionsQuery(Supervisor $supervisor): Builder
{
$query = Promotion::query()->with('establishment');
return self::applyEstablishmentScope($query, $supervisor, 'establishment_id');
}
public static function dailyStatsQuery(Supervisor $supervisor): Builder
{
$query = DailyEstablishmentStat::query()->with('establishment');
return self::applyEstablishmentScope($query, $supervisor, 'establishment_id');
}
private static function applyEstablishmentScope(Builder $query, Supervisor $supervisor, string $column): Builder
{
if ($supervisor->establishment_id !== null) {
return $query->where($column, $supervisor->establishment_id);
}
return $query->whereHas('establishment', function (Builder $query) use ($supervisor) {
self::applyOrganizationFilter($query, $supervisor);
});
}
private static function applyOrganizationFilter(Builder $query, Supervisor $supervisor): void
{
$query->where('organization_id', $supervisor->organization_id);
}
}
@@ -0,0 +1,51 @@
<?php
namespace App\Http\Middleware;
use Illuminate\Http\Request;
use Inertia\Middleware;
class HandleInertiaRequests extends Middleware
{
/**
* The root template that is loaded on the first page visit.
*
* @var string
*/
protected $rootView = 'app';
/**
* Determine the current asset version.
*/
public function version(Request $request): ?string
{
return parent::version($request);
}
/**
* Define the props that are shared by default.
*
* @return array<string, mixed>
*/
public function share(Request $request): array
{
$supervisor = $request->user('supervisor');
return [
...parent::share($request),
'auth' => [
'supervisor' => $supervisor ? [
'uuid' => $supervisor->uuid,
'name' => trim($supervisor->first_name.' '.$supervisor->last_name),
'email' => $supervisor->email,
'role' => $supervisor->role,
'organization_id' => $supervisor->organization_id,
'establishment_id' => $supervisor->establishment_id,
] : null,
],
'flash' => [
'success' => fn () => $request->session()->get('success'),
],
];
}
}