d8d755d4c5
Un user supprimé physiquement laissait des références orphelines (task.assignee, time entries, notifications) car les FK vers "user" ont été créées NOT VALID lors du refactor modular-monolith : elles n'ont jamais nettoyé les orphelins legacy. La sérialisation API Platform d'une tâche embarquant un assignee inexistant levait une EntityNotFoundException non rattrapable (HTTP 500 sur tout PATCH/GET de ces tickets). - User::$archived (bool) + migration (soft delete) - Delete de User -> UserArchiveProcessor : archive (archived=true, apiToken vidé) au lieu de supprimer, préservant l'intégrité référentielle - ArchivedUserChecker : login bloqué pour un user archivé (firewalls login + api) - ExcludeArchivedUserExtension : archivés exclus de GET /api/users (assignation), les références existantes restent sérialisées normalement - Commande app:restore-missing-users : recrée (en archivés) les users encore référencés mais supprimés, restaurant l'intégrité sans perte de données. Idempotente, option --dry-run. À lancer une fois en prod après déploiement.
29 lines
1.0 KiB
PHP
29 lines
1.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Module\Core\Infrastructure\Security;
|
|
|
|
use App\Module\Core\Domain\Entity\User;
|
|
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
|
|
use Symfony\Component\Security\Core\Exception\CustomUserMessageAccountStatusException;
|
|
use Symfony\Component\Security\Core\User\UserCheckerInterface;
|
|
use Symfony\Component\Security\Core\User\UserInterface;
|
|
|
|
/**
|
|
* Rejects authentication for archived (soft-deleted) users, both at password
|
|
* login and on every JWT-authenticated request, so an archived account is
|
|
* effectively locked out while its data is preserved.
|
|
*/
|
|
final class ArchivedUserChecker implements UserCheckerInterface
|
|
{
|
|
public function checkPreAuth(UserInterface $user, ?TokenInterface $token = null): void
|
|
{
|
|
if ($user instanceof User && $user->isArchived()) {
|
|
throw new CustomUserMessageAccountStatusException('This account has been archived.');
|
|
}
|
|
}
|
|
|
|
public function checkPostAuth(UserInterface $user, ?TokenInterface $token = null): void {}
|
|
}
|