feat: Gestion des sessions utilisateur
Permet aux utilisateurs de visualiser et gérer leurs sessions actives sur différents appareils, avec la possibilité de révoquer des sessions à distance en cas de suspicion d'activité non autorisée. Fonctionnalités : - Liste des sessions actives avec métadonnées (appareil, navigateur, localisation) - Identification de la session courante - Révocation individuelle d'une session - Révocation de toutes les autres sessions - Déconnexion avec nettoyage des cookies sur les deux chemins (legacy et actuel) Sécurité : - Cache frontend scopé par utilisateur pour éviter les fuites entre comptes - Validation que le refresh token appartient à l'utilisateur JWT authentifié - TTL des sessions Redis aligné sur l'expiration du refresh token - Événements d'audit pour traçabilité (SessionInvalidee, ToutesSessionsInvalidees) @see Story 1.6 - Gestion des sessions
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Unit\Administration\Domain\Model\Session;
|
||||
|
||||
use App\Administration\Domain\Model\Session\Location;
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class LocationTest extends TestCase
|
||||
{
|
||||
#[Test]
|
||||
public function fromIpCreatesLocationWithCountryAndCity(): void
|
||||
{
|
||||
$location = Location::fromIp('192.168.1.1', 'France', 'Paris');
|
||||
|
||||
self::assertSame('France', $location->country);
|
||||
self::assertSame('Paris', $location->city);
|
||||
self::assertSame('192.168.1.1', $location->ip);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function fromIpCreatesLocationWithCountryOnly(): void
|
||||
{
|
||||
$location = Location::fromIp('10.0.0.1', 'Germany', null);
|
||||
|
||||
self::assertSame('Germany', $location->country);
|
||||
self::assertNull($location->city);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function unknownCreatesUnknownLocation(): void
|
||||
{
|
||||
$location = Location::unknown();
|
||||
|
||||
self::assertNull($location->country);
|
||||
self::assertNull($location->city);
|
||||
self::assertNull($location->ip);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function formatReturnsCountryAndCity(): void
|
||||
{
|
||||
$location = Location::fromIp('192.168.1.1', 'France', 'Paris');
|
||||
|
||||
self::assertSame('France, Paris', $location->format());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function formatReturnsCountryOnlyWhenNoCityAvailable(): void
|
||||
{
|
||||
$location = Location::fromIp('10.0.0.1', 'Germany', null);
|
||||
|
||||
self::assertSame('Germany', $location->format());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function formatReturnsInconnuWhenUnknown(): void
|
||||
{
|
||||
$location = Location::unknown();
|
||||
|
||||
self::assertSame('Inconnu', $location->format());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function formatReturnsInconnuForPrivateIpRanges(): void
|
||||
{
|
||||
$location = Location::fromIp('192.168.1.1', null, null);
|
||||
|
||||
self::assertSame('Inconnu', $location->format());
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function reconstituteRestoresFromStorage(): void
|
||||
{
|
||||
$location = Location::reconstitute(
|
||||
ip: '8.8.8.8',
|
||||
country: 'United States',
|
||||
city: 'Mountain View',
|
||||
);
|
||||
|
||||
self::assertSame('8.8.8.8', $location->ip);
|
||||
self::assertSame('United States', $location->country);
|
||||
self::assertSame('Mountain View', $location->city);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user