@extends('documentation.application.squelette') @section('titre') {{ __("Backend (Laravel API)") }} @endsection @section('menu') @endsection @section('contenu')

Architecture Multi-Clients

Architecture

Chaque client dispose de :

  • Sa propre API Laravel
  • Sa propre base de données
  • Son propre domaine

Authentification JWT

Configuration


// config/jwt.php
return [
    'ttl' => env('JWT_TTL', 10080), // Durée de validité en minutes
    'refresh_ttl' => env('JWT_REFRESH_TTL', 20160), // 2 semaines
    'secret' => env('JWT_SECRET'),
];

// app/Models/User.php
use Tymon\JWTAuth\Contracts\JWTSubject;

class User extends Authenticatable implements JWTSubject
{
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }

    public function getJWTCustomClaims()
    {
        return [];
    }
}
                

Routes API

Structure des Routes


// routes/api.php

Route::get('/client-logo', [AuthController::class, 'getClientLogo']);
Route::post('/vue/login', [AuthController::class, 'login']);

Route::middleware('auth:api')->group(function () {
    // Auth
    Route::post('/vue/logout', [AuthController::class, 'logout']);
    Route::get('/vue/me', [AuthController::class, 'me']);
    Route::get('/verifyToken', [AuthController::class, 'verifyToken']);

    // Interventions
    Route::get('/getUserInterventions', [InterventionController::class, 'getUserInterventions']);
    Route::get('/getInterventionCountsByMonth', [InterventionController::class, 'getInterventionCountsByMonth']);
    Route::post('/update_intervention_status', [InterventionController::class, 'update_intervention_status'])->name("update_intervention_status");
    Route::get('/getSiteFiles', [InterventionController::class, 'getSiteFiles'])->name("getSiteFiles");
    Route::post('/save_bi_intervention_tech', [InterventionController::class, 'save_bi_intervention_tech'])->name("save_bi_intervention_tech");

    // Fichiers
    Route::get('/getFile/{type}/{id}', [FileController::class, 'getFile'])->name("getFile");
    Route::post('/uploadFile', [FileController::class, 'uploadFile'])->name("uploadFile");
    Route::get('/getCategories', [FileController::class, 'getCategories'])->name("getCategories");
    Route::delete('/deleteFile/{id}', [FileController::class, 'destroyFile'])->name("deleteFile");

    // Messages
    Route::get('/getInterventionMessages', [InterventionController::class, 'getInterventionMessages'])->name("getInterventionMessages");
    Route::post('/addMessageIntervention', [InterventionController::class, 'addMessageIntervention'])->name("addMessageIntervention");

    // Pour les select options
    Route::get('/getCustomers', [InterventionController::class, 'getCustomers'])->name("getCustomers");
    Route::get('/getActivities', [InterventionController::class, 'getActivities'])->name("getActivities");

    // Notifications
    Route::post('/markAsRead/{id}', [NotificationsController::class, 'markAsRead'])->name("markAsRead");
    Route::get('/notifications-stream', [NotificationsController::class, 'stream'])->name('notifications.stream');
});
                

Controllers


// app/Http/Controllers/API/InterventionController.php
public function getInterventionCountsByMonth(Request $request)
{
    $user = JWTAuth::parseToken()->authenticate();

    $query = InterventionDetail::where('use_idAssigned', $user->id)
        ->whereNotNull('intDet_planStartDate')
        ->selectRaw('DATE(intDet_planStartDate) as date, COUNT(*) as count')
        ->groupBy('date')
        ->orderBy('date')
        ->get();
    
    $result = [];
    foreach ($query as $item) {
        $result[$item->date] = $item->count;
    }

    return response()->json($result);
}
...
...
                

Configuration CORS


// config/cors.php
return [
    'paths' => ['api/*'],
    'allowed_methods' => ['*'],
    'allowed_origins' => ['*'],
    'allowed_origins_patterns' => [],
    'allowed_headers' => ['*'],
    'exposed_headers' => [],
    'max_age' => 0,
    'supports_credentials' => true,
];
    
@endsection