Chapitre 12Projet SunuLearn

Autorisation — qui peut faire quoi

Gates, Policies et middleware d'autorisation

Concepts Théoriques

Tous les utilisateurs ne doivent pas avoir les mêmes droits. Un étudiant s'inscrit aux formations. Un enseignant crée et modifie SES formations. Un admin gère tout. C'est l'autorisation — différente de l'authentification (qui vérifie l'identité).

Rôles simples avec une colonne

La solution la plus simple : ajouter une colonne role à la table users.

php artisan make:migration add_role_to_users_table
$table->string('role')->default('student'); // student, teacher, admin

Middleware personnalisé

php artisan make:middleware EnsureUserIsTeacher
// app/Http/Middleware/EnsureUserIsTeacher.php
class EnsureUserIsTeacher
{
    public function handle(Request $request, Closure $next): Response
    {
        if (!auth()->check() || !in_array(auth()->user()->role, ['teacher', 'admin'])) {
            abort(403, 'Accès réservé aux enseignants.');
        }
        return $next($request);
    }
}

Enregistrer dans bootstrap/app.php (Laravel 12) :

->withMiddleware(function (Middleware $middleware) {
    $middleware->alias([
        'teacher' => EnsureUserIsTeacher::class,
    ]);
})

Utiliser :

Route::middleware(['auth', 'teacher'])->group(function () {
    Route::get('/formations/create', [FormationController::class, 'create']);
    Route::post('/formations', [FormationController::class, 'store']);
});

Policies — autorisation fine

Un middleware vérifie le rôle global. Une Policy vérifie des permissions spécifiques : "cet utilisateur peut-il modifier CETTE formation ?"

php artisan make:policy FormationPolicy --model=Formation
// app/Policies/FormationPolicy.php
class FormationPolicy
{
    public function update(User $user, Formation $formation): bool
    {
        return $user->id === $formation->user_id || $user->role === 'admin';
    }

    public function delete(User $user, Formation $formation): bool
    {
        return $user->id === $formation->user_id || $user->role === 'admin';
    }
}

Dans le contrôleur :

public function update(Request $request, Formation $formation)
{
    $this->authorize('update', $formation);
    // Si l'utilisateur n'est pas autorisé → 403 automatique
    
    $formation->update($request->validated());
}

Dans Blade :

@can('update', $formation)
    <a href="{{ route('formations.edit', $formation) }}">Modifier</a>
@endcan