feat(core) : RBAC #345 - AdminHeadcountGuard domain service
This commit is contained in:
127
tests/Module/Core/Domain/Security/AdminHeadcountGuardTest.php
Normal file
127
tests/Module/Core/Domain/Security/AdminHeadcountGuardTest.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Tests\Module\Core\Domain\Security;
|
||||
|
||||
use App\Module\Core\Domain\Entity\User;
|
||||
use App\Module\Core\Domain\Exception\LastAdminProtectionException;
|
||||
use App\Module\Core\Domain\Repository\UserRepositoryInterface;
|
||||
use App\Module\Core\Domain\Security\AdminHeadcountGuard;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Tests unitaires du gardien d'invariant AdminHeadcountGuard.
|
||||
*
|
||||
* Aucun acces base de donnees : UserRepositoryInterface est mocke.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
class AdminHeadcountGuardTest extends TestCase
|
||||
{
|
||||
// ---------------------------------------------------------------
|
||||
// Demote (retrait du flag admin)
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Autorise la demote quand il reste plus d'un admin (cas nominal).
|
||||
*/
|
||||
public function testAllowsDemotionWhenMoreThanOneAdmin(): void
|
||||
{
|
||||
$repo = $this->createMock(UserRepositoryInterface::class);
|
||||
$repo->method('countAdmins')->willReturn(2);
|
||||
|
||||
$guard = new AdminHeadcountGuard($repo);
|
||||
$user = new User();
|
||||
$user->setUsername('alice');
|
||||
|
||||
// Aucune exception ne doit etre levee
|
||||
$guard->ensureAtLeastOneAdminRemainsAfterDemotion($user);
|
||||
$this->addToAssertionCount(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bloque la demote quand il ne reste exactement qu'un admin.
|
||||
*/
|
||||
public function testBlocksDemotionWhenExactlyOneAdmin(): void
|
||||
{
|
||||
$repo = $this->createMock(UserRepositoryInterface::class);
|
||||
$repo->method('countAdmins')->willReturn(1);
|
||||
|
||||
$guard = new AdminHeadcountGuard($repo);
|
||||
$user = new User();
|
||||
$user->setUsername('alice');
|
||||
|
||||
$this->expectException(LastAdminProtectionException::class);
|
||||
$guard->ensureAtLeastOneAdminRemainsAfterDemotion($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bloque la demote de facon defensive si le compteur est a 0 (etat incoherent).
|
||||
*/
|
||||
public function testBlocksDemotionDefensivelyWhenZeroAdmin(): void
|
||||
{
|
||||
$repo = $this->createMock(UserRepositoryInterface::class);
|
||||
$repo->method('countAdmins')->willReturn(0);
|
||||
|
||||
$guard = new AdminHeadcountGuard($repo);
|
||||
$user = new User();
|
||||
$user->setUsername('alice');
|
||||
|
||||
$this->expectException(LastAdminProtectionException::class);
|
||||
$guard->ensureAtLeastOneAdminRemainsAfterDemotion($user);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Deletion (suppression de l'utilisateur)
|
||||
// ---------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Autorise la suppression quand il reste plus d'un admin (cas nominal).
|
||||
*/
|
||||
public function testAllowsDeletionWhenMoreThanOneAdmin(): void
|
||||
{
|
||||
$repo = $this->createMock(UserRepositoryInterface::class);
|
||||
$repo->method('countAdmins')->willReturn(2);
|
||||
|
||||
$guard = new AdminHeadcountGuard($repo);
|
||||
$user = new User();
|
||||
$user->setUsername('bob');
|
||||
|
||||
// Aucune exception ne doit etre levee
|
||||
$guard->ensureAtLeastOneAdminRemainsAfterDeletion($user);
|
||||
$this->addToAssertionCount(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bloque la suppression quand il ne reste exactement qu'un admin.
|
||||
*/
|
||||
public function testBlocksDeletionWhenExactlyOneAdmin(): void
|
||||
{
|
||||
$repo = $this->createMock(UserRepositoryInterface::class);
|
||||
$repo->method('countAdmins')->willReturn(1);
|
||||
|
||||
$guard = new AdminHeadcountGuard($repo);
|
||||
$user = new User();
|
||||
$user->setUsername('bob');
|
||||
|
||||
$this->expectException(LastAdminProtectionException::class);
|
||||
$guard->ensureAtLeastOneAdminRemainsAfterDeletion($user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bloque la suppression de facon defensive si le compteur est a 0 (etat incoherent).
|
||||
*/
|
||||
public function testBlocksDeletionDefensivelyWhenZeroAdmin(): void
|
||||
{
|
||||
$repo = $this->createMock(UserRepositoryInterface::class);
|
||||
$repo->method('countAdmins')->willReturn(0);
|
||||
|
||||
$guard = new AdminHeadcountGuard($repo);
|
||||
$user = new User();
|
||||
$user->setUsername('bob');
|
||||
|
||||
$this->expectException(LastAdminProtectionException::class);
|
||||
$guard->ensureAtLeastOneAdminRemainsAfterDeletion($user);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user