Paillasse/portail/tests/Feature/WebdavTest.php
Adam Belkacemi e549f03e1b ajoute le dossier WebDAV de l'élève (bloc C)
Dossier personnel de l'élève monté comme lecteur réseau : rclone
sert le dossier local, l'authentification est déléguée au portail
via auth_request Nginx (mêmes identifiants que la connexion), sans
nouveau système de comptes. Nettoyé par la purge RGPD comme les
autres données d'élève.

Corrige au passage un vrai bug d'isolation trouvé en testant avec
deux comptes jetables : rewrite injectait la variable posée par
auth_request_set, mais rewrite s'exécute dans une phase Nginx
antérieure à cette variable, donc toujours vide - un élève pouvait
lire le fichier d'un autre en devinant son nom. Corrigé par une
location à regex nommée + proxy_pass. Détails : ADR 0008.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-10-14 13:04:40 +02:00

69 lines
2.3 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
use App\Models\Classe;
use App\Models\Eleve;
use Illuminate\Support\Facades\RateLimiter;
use Illuminate\Support\Facades\Storage;
beforeEach(function () {
Storage::fake('webdav');
});
test('la sous-requête Nginx refuse sans identifiants', function () {
$this->get(route('interne.webdav-auth'))->assertStatus(401);
});
test('la sous-requête Nginx refuse un code secret incorrect', function () {
$eleve = Eleve::factory()->create();
$this->withBasicAuth($eleve->identifiant, 'mauvais-code')
->get(route('interne.webdav-auth'))
->assertStatus(401);
});
test('la sous-requête Nginx accepte les identifiants de connexion et pose le dossier de l’élève', function () {
$eleve = Eleve::factory()->create(['code_secret' => bcrypt('monCode123')]);
$this->withBasicAuth($eleve->identifiant, 'monCode123')
->get(route('interne.webdav-auth'))
->assertStatus(200)
->assertHeader('X-Eleve-Dossier', (string) $eleve->id);
Storage::disk('webdav')->assertExists((string) $eleve->id);
});
test('5 échecs de suite bloquent temporairement même avec le bon code juste après', function () {
$eleve = Eleve::factory()->create(['code_secret' => bcrypt('monCode123')]);
for ($i = 0; $i < 5; $i++) {
$this->withBasicAuth($eleve->identifiant, 'mauvais')
->get(route('interne.webdav-auth'))
->assertStatus(401);
}
$this->withBasicAuth($eleve->identifiant, 'monCode123')
->get(route('interne.webdav-auth'))
->assertStatus(401);
RateLimiter::clear('webdav:'.$eleve->identifiant.'|127.0.0.1');
});
test('un élève connecté voit l’adresse de son dossier WebDAV', function () {
$eleve = Eleve::factory()->create();
eleve($this, $eleve)->get(route('mes-fichiers'))
->assertOk()
->assertSee('/webdav/')
->assertSee($eleve->identifiant);
});
test('purger une classe archivée supprime aussi le dossier WebDAV de ses élèves', function () {
$classe = Classe::factory()->create();
$eleve = Eleve::factory()->create(['classe_id' => $classe->id]);
Storage::disk('webdav')->put($eleve->id.'/photo.jpg', 'contenu');
$classe->forceFill(['archivee_a' => now()->subDays(91)])->save();
$this->artisan('classes:purger-archivees');
Storage::disk('webdav')->assertMissing($eleve->id.'/photo.jpg');
});