From aa4a6e63a3244bfdedd629d796b6f3a06003dd9a Mon Sep 17 00:00:00 2001 From: Bas Date: Wed, 15 Jan 2025 16:29:50 +0100 Subject: [PATCH] Fix missing deprovision data --- .../Controller/DeprovisionController.php | 28 ++++++++++++++++++- .../Identity/Projector/IdentityProjector.php | 6 ++++ .../Repository/IdentityRepository.php | 17 +++++++++++ .../Repository/RaListingRepository.php | 5 ++++ .../Repository/RaSecondFactorRepository.php | 10 +++++++ .../ApiBundle/Resources/config/services.yml | 3 ++ 6 files changed, 68 insertions(+), 1 deletion(-) diff --git a/src/Surfnet/StepupMiddleware/ApiBundle/Controller/DeprovisionController.php b/src/Surfnet/StepupMiddleware/ApiBundle/Controller/DeprovisionController.php index 08db563fe..d2d7c0715 100644 --- a/src/Surfnet/StepupMiddleware/ApiBundle/Controller/DeprovisionController.php +++ b/src/Surfnet/StepupMiddleware/ApiBundle/Controller/DeprovisionController.php @@ -19,8 +19,14 @@ namespace Surfnet\StepupMiddleware\ApiBundle\Controller; use Exception; +use RuntimeException; use Surfnet\Stepup\Exception\DomainException; use Surfnet\Stepup\Helper\UserDataFormatterInterface; +use Surfnet\Stepup\Identity\Value\IdentityId; +use Surfnet\Stepup\Identity\Value\NameId; +use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\IdentityRepository; +use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\RaListingRepository; +use Surfnet\StepupMiddleware\ApiBundle\Identity\Repository\SraaRepository; use Surfnet\StepupMiddleware\ApiBundle\Service\DeprovisionServiceInterface; use Surfnet\StepupMiddleware\ApiBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\JsonResponse; @@ -30,6 +36,9 @@ class DeprovisionController extends AbstractController public function __construct( private readonly DeprovisionServiceInterface $deprovisionService, private readonly UserDataFormatterInterface $formatHelper, + private readonly IdentityRepository $identityRepository, + private readonly SraaRepository $sraaRepository, + private readonly RaListingRepository $raListingRepository, ) { } @@ -42,11 +51,12 @@ public function deprovision(string $collabPersonId): JsonResponse if ($userData !== []) { $this->deprovisionService->deprovision($collabPersonId); } - } catch (DomainException) { + } catch (DomainException $e) { // On domain exceptions, like when the identity is forgotten, we return OK, with empty data // just so the deprovision run does not end prematurely. At this point, no other domain exceptions // are thrown. $userData = []; + $errors = [$e->getMessage()]; } catch (Exception $e) { $userData = []; $errors = [$e->getMessage()]; @@ -57,6 +67,22 @@ public function deprovision(string $collabPersonId): JsonResponse public function dryRun(string $collabPersonId): JsonResponse { $this->denyAccessUnlessGrantedOneOff(['ROLE_DEPROVISION']); + + $nameId = new NameId($collabPersonId); + $identity = $this->identityRepository->findOneByNameId($nameId); + + if ($identity === null) { + throw new RuntimeException('Cannot forget an identity that does not exist.'); + } + + if ($this->sraaRepository->contains($identity->nameId)) { + throw new RuntimeException('Cannot forget an identity that is currently accredited as an SRAA'); + } + + if ($this->raListingRepository->contains(new IdentityId($identity->id))) { + throw new RuntimeException('Cannot forget an identity that is currently accredited as an RA(A)'); + } + $errors = []; try { $userData = $this->deprovisionService->readUserData($collabPersonId); diff --git a/src/Surfnet/StepupMiddleware/ApiBundle/Identity/Projector/IdentityProjector.php b/src/Surfnet/StepupMiddleware/ApiBundle/Identity/Projector/IdentityProjector.php index a6574ab84..1becb7eeb 100644 --- a/src/Surfnet/StepupMiddleware/ApiBundle/Identity/Projector/IdentityProjector.php +++ b/src/Surfnet/StepupMiddleware/ApiBundle/Identity/Projector/IdentityProjector.php @@ -21,6 +21,7 @@ use Broadway\ReadModel\Projector; use Surfnet\Stepup\Identity\Event\IdentityCreatedEvent; use Surfnet\Stepup\Identity\Event\IdentityEmailChangedEvent; +use Surfnet\Stepup\Identity\Event\IdentityForgottenEvent; use Surfnet\Stepup\Identity\Event\IdentityRenamedEvent; use Surfnet\Stepup\Identity\Event\LocalePreferenceExpressedEvent; use Surfnet\Stepup\Identity\Event\SecondFactorVettedEvent; @@ -95,4 +96,9 @@ private function determinePossessionOfSelfAssertedToken(VettingType $vettingType } } } + + protected function applyIdentityForgottenEvent(IdentityForgottenEvent $event): void + { + $this->identityRepository->updateStatusByIdentityIdToForgotten($event->identityId); + } } diff --git a/src/Surfnet/StepupMiddleware/ApiBundle/Identity/Repository/IdentityRepository.php b/src/Surfnet/StepupMiddleware/ApiBundle/Identity/Repository/IdentityRepository.php index 16e84b468..eed634b59 100644 --- a/src/Surfnet/StepupMiddleware/ApiBundle/Identity/Repository/IdentityRepository.php +++ b/src/Surfnet/StepupMiddleware/ApiBundle/Identity/Repository/IdentityRepository.php @@ -22,6 +22,9 @@ use Doctrine\Common\Collections\ArrayCollection; use Doctrine\ORM\Query; use Doctrine\Persistence\ManagerRegistry; +use Surfnet\Stepup\Identity\Value\CommonName; +use Surfnet\Stepup\Identity\Value\DocumentNumber; +use Surfnet\Stepup\Identity\Value\Email; use Surfnet\Stepup\Identity\Value\IdentityId; use Surfnet\Stepup\Identity\Value\Institution; use Surfnet\Stepup\Identity\Value\NameId; @@ -140,4 +143,18 @@ public function findOneByNameId(string $nameId): ?Identity { return $this->findOneBy(['nameId' => $nameId]); } + + public function updateStatusByIdentityIdToForgotten(IdentityId $identityId): void + { + $this->getEntityManager()->createQueryBuilder() + ->update($this->getEntityName(), 'i') + ->set('i.commonName', ":name") + ->set('i.email', ":email") + ->where('i.id = :id') + ->setParameter('id', $identityId->getIdentityId()) + ->setParameter('name', CommonName::unknown()) + ->setParameter('email', Email::unknown()) + ->getQuery() + ->execute(); + } } diff --git a/src/Surfnet/StepupMiddleware/ApiBundle/Identity/Repository/RaListingRepository.php b/src/Surfnet/StepupMiddleware/ApiBundle/Identity/Repository/RaListingRepository.php index 8515f6056..940762332 100644 --- a/src/Surfnet/StepupMiddleware/ApiBundle/Identity/Repository/RaListingRepository.php +++ b/src/Surfnet/StepupMiddleware/ApiBundle/Identity/Repository/RaListingRepository.php @@ -237,4 +237,9 @@ public function removeByIdentityIdAndInstitution(IdentityId $identityId, Institu ->getQuery() ->execute(); } + + public function contains(IdentityId $identityId): bool + { + return count(parent::findBy(['identityId' => (string)$identityId])) > 0; + } } diff --git a/src/Surfnet/StepupMiddleware/ApiBundle/Identity/Repository/RaSecondFactorRepository.php b/src/Surfnet/StepupMiddleware/ApiBundle/Identity/Repository/RaSecondFactorRepository.php index 2d2b57a8d..811c0a885 100644 --- a/src/Surfnet/StepupMiddleware/ApiBundle/Identity/Repository/RaSecondFactorRepository.php +++ b/src/Surfnet/StepupMiddleware/ApiBundle/Identity/Repository/RaSecondFactorRepository.php @@ -23,6 +23,9 @@ use Doctrine\ORM\Query; use Doctrine\Persistence\ManagerRegistry; use Surfnet\Stepup\Exception\RuntimeException; +use Surfnet\Stepup\Identity\Value\CommonName; +use Surfnet\Stepup\Identity\Value\DocumentNumber; +use Surfnet\Stepup\Identity\Value\Email; use Surfnet\Stepup\Identity\Value\IdentityId; use Surfnet\StepupMiddleware\ApiBundle\Authorization\Filter\InstitutionAuthorizationRepositoryFilter; use Surfnet\StepupMiddleware\ApiBundle\Doctrine\Type\SecondFactorStatusType; @@ -31,6 +34,7 @@ use Surfnet\StepupMiddleware\ApiBundle\Identity\Value\SecondFactorStatus; /** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @extends ServiceEntityRepository */ class RaSecondFactorRepository extends ServiceEntityRepository @@ -203,9 +207,15 @@ public function updateStatusByIdentityIdToForgotten(IdentityId $identityId): voi $this->getEntityManager()->createQueryBuilder() ->update($this->getEntityName(), 'rasf') ->set('rasf.status', ":forgotten") + ->set('rasf.name', ":name") + ->set('rasf.email', ":email") + ->set('rasf.documentNumber', ":documentNumber") ->where('rasf.identityId = :identityId') ->setParameter('identityId', $identityId->getIdentityId()) ->setParameter('forgotten', 40) + ->setParameter('name', CommonName::unknown()) + ->setParameter('email', Email::unknown()) + ->setParameter('documentNumber', DocumentNumber::unknown()) ->getQuery() ->execute(); } diff --git a/src/Surfnet/StepupMiddleware/ApiBundle/Resources/config/services.yml b/src/Surfnet/StepupMiddleware/ApiBundle/Resources/config/services.yml index e7c1b9d76..77dc61586 100644 --- a/src/Surfnet/StepupMiddleware/ApiBundle/Resources/config/services.yml +++ b/src/Surfnet/StepupMiddleware/ApiBundle/Resources/config/services.yml @@ -20,6 +20,9 @@ services: arguments: $deprovisionService: '@Surfnet\StepupMiddleware\ApiBundle\Service\DeprovisionService' $formatHelper: '@Surfnet\Stepup\Helper\UserDataFormatterInterface' + $identityRepository: '@surfnet_stepup_middleware_api.repository.identity' + $sraaRepository: '@surfnet_stepup_middleware_api.repository.sraa' + $raListingRepository: '@surfnet_stepup_middleware_api.repository.ra_listing' tags: [ 'controller.service_arguments' ] # Repositories