From a63a2f4d9f624186fb1c5849812886512868f4d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9l=C3=A8ne=20Meneuvrier?= Date: Fri, 22 Mar 2024 16:22:01 +0100 Subject: [PATCH 1/4] tag email of user or partner archived #2035 --- migrations/Version20240322123431.php | 30 ++++ .../Back/BackArchivedAccountController.php | 15 +- .../Back/BackArchivedPartnerController.php | 62 +++++++ src/Controller/Back/PartnerController.php | 7 +- src/DataFixtures/Files/Partner.yml | 6 + src/DataFixtures/Files/User.yml | 16 ++ src/DataFixtures/Loader/LoadPartnerData.php | 8 +- src/DataFixtures/Loader/LoadUserData.php | 8 +- src/Repository/PartnerRepository.php | 44 +++++ src/Repository/UserRepository.php | 13 ++ src/Service/Sanitizer.php | 5 + src/Twig/AppExtension.php | 15 ++ templates/back/account/_form.html.twig | 6 +- templates/back/account/edit.html.twig | 2 +- templates/back/account/index.html.twig | 4 +- templates/back/nav_bo.html.twig | 7 + templates/back/partner/index.html.twig | 2 +- templates/back/partner/view.html.twig | 2 +- .../back/partner_archived/index.html.twig | 162 ++++++++++++++++++ .../BackArchivedPartnerControllerTest.php | 63 +++++++ .../BackArchivedAccountControllerTest.php | 55 +++++- .../Controller/CartographieControllerTest.php | 2 +- .../Controller/PartnerControllerTest.php | 5 + .../SignalementListControllerTest.php | 2 +- .../Token/ActivationTokenGeneratorTest.php | 4 +- 25 files changed, 528 insertions(+), 17 deletions(-) create mode 100644 migrations/Version20240322123431.php create mode 100755 src/Controller/Back/BackArchivedPartnerController.php create mode 100755 templates/back/partner_archived/index.html.twig create mode 100644 tests/Functional/Controller/Back/BackArchivedPartnerControllerTest.php diff --git a/migrations/Version20240322123431.php b/migrations/Version20240322123431.php new file mode 100644 index 000000000..0bb468111 --- /dev/null +++ b/migrations/Version20240322123431.php @@ -0,0 +1,30 @@ +addSql( + "UPDATE partner SET email = CONCAT(email, '.archived@', DATE_FORMAT(NOW(), '%Y%m%d%H%i')) WHERE is_archive = 1" + ); + $this->addSql( + "UPDATE user SET email = CONCAT(email, '.archived@', DATE_FORMAT(NOW(), '%Y%m%d%H%i')) WHERE statut = 2" + ); + } + + public function down(Schema $schema): void + { + } +} diff --git a/src/Controller/Back/BackArchivedAccountController.php b/src/Controller/Back/BackArchivedAccountController.php index f950a653c..fd5239f91 100755 --- a/src/Controller/Back/BackArchivedAccountController.php +++ b/src/Controller/Back/BackArchivedAccountController.php @@ -87,6 +87,7 @@ public function reactiver( User $user, TerritoryRepository $territoryRepository, PartnerRepository $partnerRepository, + UserRepository $userRepository, EntityManagerInterface $entityManager, NotificationMailerRegistry $notificationMailerRegistry, ): Response { @@ -101,8 +102,20 @@ public function reactiver( ]); $form->handleRequest($request); - if ($form->isSubmitted() && $form->isValid()) { + $untaggedEmail = explode('.archived@', $user->getEmail())[0]; + $userExist = $userRepository->findOneBy(['email' => $untaggedEmail]); + if ($userExist && !\in_array('ROLE_USAGER', $userExist->getRoles())) { + $this->addFlash('error', 'Un utilisateur existe déjà avec cette adresse e-mail.'); + } + + $partnerExist = $partnerRepository->findOneBy(['email' => $untaggedEmail]); + if ($partnerExist) { + $this->addFlash('error', 'Un partenaire existe déjà avec cette adresse e-mail.'); + } + + if (!$userExist && !$partnerExist && $form->isSubmitted() && $form->isValid()) { $user->setStatut(User::STATUS_ACTIVE); + $user->setEmail($untaggedEmail); $entityManager->flush(); $this->addFlash('success', 'Réactivation du compte effectuée.'); diff --git a/src/Controller/Back/BackArchivedPartnerController.php b/src/Controller/Back/BackArchivedPartnerController.php new file mode 100755 index 000000000..5075b2265 --- /dev/null +++ b/src/Controller/Back/BackArchivedPartnerController.php @@ -0,0 +1,62 @@ +get('page') ?? 1; + + $isNoneTerritory = 'none' == $request->get('territory'); + $currentTerritory = $isNoneTerritory ? null : $territoryRepository->find((int) $request->get('territory')); + $partnerTerms = $request->get('partnerTerms'); + + $paginatedArchivedPartners = $partnerRepository->findAllArchivedOrWithoutTerritory( + territory: $currentTerritory, + isNoneTerritory: $isNoneTerritory, + filterTerms: $partnerTerms, + page: (int) $page + ); + + if ($request->isMethod(Request::METHOD_POST)) { + $isNoneTerritory = 'none' == $request->request->get('territory'); + $currentTerritory = $territoryRepository->find((int) $request->request->get('territory')); + $partnerTerms = $request->request->get('bo-filters-partnerterms'); + + return $this->redirect($this->generateUrl('back_archived_partner_index', [ + 'page' => 1, + 'territory' => $isNoneTerritory ? 'none' : $currentTerritory?->getId(), + 'partnerTerms' => $partnerTerms, + ])); + } + + $totalArchivedPartners = \count($paginatedArchivedPartners); + + return $this->render('back/partner_archived/index.html.twig', [ + 'isNoneTerritory' => $isNoneTerritory, + 'currentTerritory' => $currentTerritory, + 'partnerTerms' => $partnerTerms, + 'territories' => $territoryRepository->findAllList(), + 'partners' => $paginatedArchivedPartners, + 'total' => $totalArchivedPartners, + 'page' => $page, + 'pages' => (int) ceil($totalArchivedPartners / User::MAX_LIST_PAGINATION), + ]); + } +} diff --git a/src/Controller/Back/PartnerController.php b/src/Controller/Back/PartnerController.php index 6974f36f6..f4f052817 100755 --- a/src/Controller/Back/PartnerController.php +++ b/src/Controller/Back/PartnerController.php @@ -20,6 +20,7 @@ use App\Service\Mailer\NotificationMail; use App\Service\Mailer\NotificationMailerRegistry; use App\Service\Mailer\NotificationMailerType; +use App\Service\Sanitizer; use App\Service\Signalement\VisiteNotifier; use Doctrine\ORM\EntityManagerInterface; use Egulias\EmailValidator\EmailValidator; @@ -248,8 +249,12 @@ public function delete( $partner && $this->isCsrfTokenValid('partner_delete', $request->request->get('_token')) ) { + if (null !== $partner->getEmail()) { + $partner->setEmail(Sanitizer::tagArchivedEmail($partner->getEmail())); + } $partner->setIsArchive(true); foreach ($partner->getUsers() as $user) { + $user->setEmail(Sanitizer::tagArchivedEmail($user->getEmail())); $user->setStatut(User::STATUS_ARCHIVE); $entityManager->persist($user); $notificationMailerRegistry->send( @@ -490,7 +495,7 @@ public function deleteUser( /** @var User $user */ $user = $userManager->find($userId); $this->denyAccessUnlessGranted('USER_DELETE', $user); - + $user->setEmail(Sanitizer::tagArchivedEmail($user->getEmail())); $user->setStatut(User::STATUS_ARCHIVE); $userManager->save($user); $notificationMailerRegistry->send( diff --git a/src/DataFixtures/Files/Partner.yml b/src/DataFixtures/Files/Partner.yml index 14cdd81fc..9ec6bdef7 100644 --- a/src/DataFixtures/Files/Partner.yml +++ b/src/DataFixtures/Files/Partner.yml @@ -50,6 +50,12 @@ partners: is_esabora_active: 1 type: "ARS" competence: "VISITES" + - + nom: "Partenaire 13-07" + email: "partenaire-13-07@histologe.fr" + is_archive: 1 + territory: "Bouches-du-Rhône" + type: "AUTRE" - nom: "Partenaire 01-01" email: "partenaire-01-01@histologe.fr" diff --git a/src/DataFixtures/Files/User.yml b/src/DataFixtures/Files/User.yml index 4cffc31a2..d5c7a3342 100644 --- a/src/DataFixtures/Files/User.yml +++ b/src/DataFixtures/Files/User.yml @@ -193,6 +193,14 @@ users: is_generique: 0 is_mailing_active: 1 territory: "Bouches-du-Rhône" + - + email: user-13-07@histologe.fr + roles: "[\"ROLE_USER_PARTNER\"]" + partner: "Partenaire 13-07" + statut: 2 + is_generique: 0 + is_mailing_active: 1 + territory: "Bouches-du-Rhône" - email: user-2A-01@histologe.fr roles: "[\"ROLE_USER_PARTNER\"]" @@ -258,6 +266,14 @@ users: is_generique: 0 is_mailing_active: 0 territory: "Ain" + - + email: user-01-06@histologe.fr + roles: "[\"ROLE_USER_PARTNER\"]" + partner: "Partenaire 01-03-ARCHIVE" + statut: 2 + is_generique: 0 + is_mailing_active: 0 + territory: "Ain" - email: user-01-07@histologe.fr roles: "[\"ROLE_USER_PARTNER\"]" diff --git a/src/DataFixtures/Loader/LoadPartnerData.php b/src/DataFixtures/Loader/LoadPartnerData.php index 0e44a877b..47c3d392e 100644 --- a/src/DataFixtures/Loader/LoadPartnerData.php +++ b/src/DataFixtures/Loader/LoadPartnerData.php @@ -6,6 +6,7 @@ use App\Entity\Enum\Qualification; use App\Entity\Partner; use App\Repository\TerritoryRepository; +use App\Service\Sanitizer; use App\Service\Token\TokenGeneratorInterface; use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Common\DataFixtures\OrderedFixtureInterface; @@ -33,10 +34,15 @@ public function loadPartner(ObjectManager $manager, array $row): void { $partner = (new Partner()) ->setNom($row['nom']) - ->setEmail($row['email'] ?? null) ->setIsArchive($row['is_archive']) ->setIsEsaboraActive($row['is_esabora_active'] ?? false); + if ($row['is_archive'] && null !== $row['email']) { + $partner->setEmail(Sanitizer::tagArchivedEmail($row['email'])); + } else { + $partner->setEmail($row['email'] ?? null); + } + if (isset($row['insee'])) { $partner->setInsee(json_decode($row['insee'], true)); } diff --git a/src/DataFixtures/Loader/LoadUserData.php b/src/DataFixtures/Loader/LoadUserData.php index 19311c5ce..c44e9988f 100644 --- a/src/DataFixtures/Loader/LoadUserData.php +++ b/src/DataFixtures/Loader/LoadUserData.php @@ -7,6 +7,7 @@ use App\Factory\UserFactory; use App\Repository\PartnerRepository; use App\Repository\TerritoryRepository; +use App\Service\Sanitizer; use Doctrine\Bundle\FixturesBundle\Fixture; use Doctrine\Common\DataFixtures\OrderedFixtureInterface; use Doctrine\ORM\EntityManagerInterface; @@ -55,10 +56,15 @@ private function loadUsers(ObjectManager $manager, array $row): void ->setRoles(json_decode($row['roles'], true)) ->setStatut($row['statut']) ->setIsMailingActive($row['is_mailing_active']) - ->setEmail($row['email']) ->setPrenom($faker->firstName()) ->setNom($faker->lastName()); + if (User::STATUS_ARCHIVE === $row['statut']) { + $user->setEmail(Sanitizer::tagArchivedEmail($row['email'])); + } else { + $user->setEmail($row['email']); + } + if (isset($row['territory'])) { $user->setTerritory($this->territoryRepository->findOneBy(['name' => $row['territory']])); } diff --git a/src/Repository/PartnerRepository.php b/src/Repository/PartnerRepository.php index 93fda053b..c2537eab9 100755 --- a/src/Repository/PartnerRepository.php +++ b/src/Repository/PartnerRepository.php @@ -99,6 +99,50 @@ public function findAllWithoutTerritory() ->getResult(); } + public function findAllArchivedOrWithoutTerritory( + Territory|null $territory, + bool $isNoneTerritory, + ?string $filterTerms, + $page + ): Paginator { + $maxResult = Partner::MAX_LIST_PAGINATION; + $firstResult = ($page - 1) * $maxResult; + $queryBuilder = $this->createQueryBuilder('p'); + + if ($isNoneTerritory) { + if ($isNoneTerritory) { + $queryBuilder + ->where('p.territory IS NULL'); + } + } else { + $builtOrCondition = ''; + if (empty($territory)) { + $builtOrCondition .= ' OR p.territory IS NULL'; + } + + $queryBuilder + ->where('p.isArchive = 1'.$builtOrCondition); + + if (!empty($territory)) { + $queryBuilder + ->andWhere('p.territory = :territory') + ->setParameter('territory', $territory); + } + } + + if (!empty($filterTerms)) { + $queryBuilder + ->andWhere('LOWER(p.nom) LIKE :usersterms + OR LOWER(p.email) LIKE :usersterms'); + $queryBuilder + ->setParameter('usersterms', '%'.strtolower($filterTerms).'%'); + } + + $queryBuilder->setFirstResult($firstResult)->setMaxResults($maxResult); + + return new Paginator($queryBuilder->getQuery(), false); + } + public function findAutoAssignable(string $codeInsee, PartnerType $partnerType): ?array { if (empty($codeInsee)) { diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php index 46108ad64..38896a432 100755 --- a/src/Repository/UserRepository.php +++ b/src/Repository/UserRepository.php @@ -55,6 +55,19 @@ public function findActiveAdmins(): ?array ->getResult(); } + public function findArchivedUserByEmail(string $email): ?User + { + $queryBuilder = $this->createQueryBuilder('u'); + + return $queryBuilder + ->andWhere('u.email LIKE :email') + ->setParameter('email', '%'.$email.'%') + ->andWhere('u.statut LIKE :archived') + ->setParameter('archived', User::STATUS_ARCHIVE) + ->getQuery() + ->getOneOrNullResult(); + } + public function findActiveTerritoryAdmins(?Territory $territory, ?string $inseeOccupant): ?array { if (empty($territory)) { diff --git a/src/Service/Sanitizer.php b/src/Service/Sanitizer.php index 77cd7f5d5..358d3c7e6 100644 --- a/src/Service/Sanitizer.php +++ b/src/Service/Sanitizer.php @@ -10,4 +10,9 @@ public static function sanitize($text): string return str_replace('

', '
', $textSanitized); // Replace the end } + + public static function tagArchivedEmail(string $email): string + { + return $email.'.archived@'.(new \DateTimeImmutable())->format('YmdHi'); + } } diff --git a/src/Twig/AppExtension.php b/src/Twig/AppExtension.php index 2ff9f9fb4..418788afe 100644 --- a/src/Twig/AppExtension.php +++ b/src/Twig/AppExtension.php @@ -22,6 +22,7 @@ public function getFilters(): array new TwigFilter('signalement_lien_declarant_occupant', [$this, 'getLabelLienDeclarantOccupant']), new TwigFilter('image64', [ImageBase64Encoder::class, 'encode']), new TwigFilter('truncate_filename', [$this, 'getTruncatedFilename']), + new TwigFilter('clean_tagged_text', [$this, 'cleanTaggedText']), ]; } @@ -76,4 +77,18 @@ public function getFunctions(): array new TwigFunction('show_label_facultatif', [AttributeParser::class, 'showLabelAsFacultatif']), ]; } + + public function cleanTaggedText(string $taggedText, string $tag, string $direction): string + { + $parts = explode($tag, $taggedText); + + switch ($direction) { + case 'left': + return $parts[0]; + case 'right': + return $parts[1]; + default: + return $taggedText; + } + } } diff --git a/templates/back/account/_form.html.twig b/templates/back/account/_form.html.twig index e32baa7e0..e268c6d45 100755 --- a/templates/back/account/_form.html.twig +++ b/templates/back/account/_form.html.twig @@ -1,13 +1,15 @@ {{ form_start(form,{attr:{'class':'needs-validation','novalidate':true}}) }}
- Pour réactiver le compte {{ user.email }}, veuillez vérifier les champs ci-dessous et les modifier si besoin.
+ Pour réactiver le compte {{ user.email|clean_tagged_text('.archived@', 'left') }}, veuillez vérifier les champs ci-dessous et les modifier si besoin.
Tous les champs sont obligatoires.
- {{ form_widget(form.email) }} +
L'adresse email ne peut pas être modifiée
diff --git a/templates/back/account/edit.html.twig b/templates/back/account/edit.html.twig index c7b1425bf..1a3f3a8f5 100755 --- a/templates/back/account/edit.html.twig +++ b/templates/back/account/edit.html.twig @@ -4,7 +4,7 @@ {% block content %}
-

Réactivation du compte {{ user.email }}

+

Réactivation du compte {{ user.email|clean_tagged_text('.archived@', 'left') }}

{{ include('back/account/_form.html.twig') }}
diff --git a/templates/back/account/index.html.twig b/templates/back/account/index.html.twig index 3ff24816b..ba60c0616 100755 --- a/templates/back/account/index.html.twig +++ b/templates/back/account/index.html.twig @@ -82,7 +82,7 @@ {{ user.territory }} {{ user.partner ? user.partner.nom : 'aucun' }} {{ statut|upper }} - {{ user.email}} + {{ user.email|clean_tagged_text('.archived@', 'left') }} {{ user.nom}} {{ user.prenom}} @@ -92,7 +92,7 @@ {% else %} - no records found + Aucun utilisateur trouvé {% endfor %} diff --git a/templates/back/nav_bo.html.twig b/templates/back/nav_bo.html.twig index 70b711276..b51b08800 100755 --- a/templates/back/nav_bo.html.twig +++ b/templates/back/nav_bo.html.twig @@ -106,6 +106,13 @@ {% if 'back_expired_account_' in app.request.get('_route') %}aria-current="page"{% endif %}>Comptes expirés {% endif %} + {% if is_granted('ROLE_ADMIN') %} +
  • + Partenaires archivés +
  • + {% endif %} {% endif %}
    diff --git a/templates/back/partner/index.html.twig b/templates/back/partner/index.html.twig index f1c6dd17b..b9cd5800d 100755 --- a/templates/back/partner/index.html.twig +++ b/templates/back/partner/index.html.twig @@ -108,7 +108,7 @@ {% else %} - no records found + Aucun partenaire trouvé {% endfor %} diff --git a/templates/back/partner/view.html.twig b/templates/back/partner/view.html.twig index 064c4986e..a0a24c778 100755 --- a/templates/back/partner/view.html.twig +++ b/templates/back/partner/view.html.twig @@ -177,7 +177,7 @@ {% else %} - no records found + Aucun partenaire trouvé {% endfor %} diff --git a/templates/back/partner_archived/index.html.twig b/templates/back/partner_archived/index.html.twig new file mode 100755 index 000000000..6c1f40fd7 --- /dev/null +++ b/templates/back/partner_archived/index.html.twig @@ -0,0 +1,162 @@ +{% extends 'back/base_bo.html.twig' %} + +{% block title %}Partenaires archivés ou sans territoires{% endblock %} + +{% block content %} +
    +
    +
    +
    +

    Partenaires archivés

    +
    +
    +
    +
    + {% if is_granted('ROLE_ADMIN') %} +
    +
    + +
    + +
    +
    + +
    + +
    +
    + {% endif %} +
    +

    {{total}} partenaires archivés ou sans territoires trouvés

    +
    +
    + + + + + + + + + + + + {% for partner in partners %} + {% if partner is null %} + {% set classe = 'fr-badge--info' %} + {% set statut = 'aucun' %} + {% elseif partner and partner.isArchive %} + {% set classe = 'fr-badge--error' %} + {% set statut = 'archivé' %} + {% else %} + {% set classe = 'fr-badge--success' %} + {% set statut = 'actif' %} + {% endif %} + + + + + {% else %} + + + + {% endfor %} + +
    Dpt.StatutEmailNomType
    {{ partner.territory }}{{ statut|upper }}{{ partner.email|clean_tagged_text('.archived@', 'left') }} + {{ partner.nom}} + {{ partner.type.label}} +
    Aucun partenaire trouvé
    + +
    + + +{% endblock %} diff --git a/tests/Functional/Controller/Back/BackArchivedPartnerControllerTest.php b/tests/Functional/Controller/Back/BackArchivedPartnerControllerTest.php new file mode 100644 index 000000000..a9fe4c5ec --- /dev/null +++ b/tests/Functional/Controller/Back/BackArchivedPartnerControllerTest.php @@ -0,0 +1,63 @@ +get(UserRepository::class); + $user = $userRepository->findOneBy(['email' => 'admin-01@histologe.fr']); + $client->loginUser($user); + + /** @var RouterInterface $router */ + $router = self::getContainer()->get(RouterInterface::class); + + $route = $router->generate('back_archived_partner_index'); + $client->request('GET', $route); + $this->assertLessThan( + Response::HTTP_INTERNAL_SERVER_ERROR, + $client->getResponse()->getStatusCode(), + sprintf('Result value: %d', $client->getResponse()->getStatusCode()) + ); + } + + public function testAccountListWithTerritory(): void + { + $client = static::createClient(); + + /** @var UserRepository $userRepository */ + $userRepository = static::getContainer()->get(UserRepository::class); + $user = $userRepository->findOneBy(['email' => 'admin-01@histologe.fr']); + $client->loginUser($user); + + /** @var RouterInterface $router */ + $router = self::getContainer()->get(RouterInterface::class); + + /** @var TerritoryRepository $territoryRepository */ + $territoryRepository = static::getContainer()->get(TerritoryRepository::class); + $territory = $territoryRepository->findOneBy(['zip' => '01']); + + $route = $router->generate('back_archived_partner_index', [ + 'territory' => $territory->getId(), + ]); + $client->request('GET', $route); + $this->assertLessThan( + Response::HTTP_INTERNAL_SERVER_ERROR, + $client->getResponse()->getStatusCode(), + sprintf('Result value: %d', $client->getResponse()->getStatusCode()) + ); + } +} diff --git a/tests/Functional/Controller/BackArchivedAccountControllerTest.php b/tests/Functional/Controller/BackArchivedAccountControllerTest.php index 4fa89daf6..a5d1ee1f1 100644 --- a/tests/Functional/Controller/BackArchivedAccountControllerTest.php +++ b/tests/Functional/Controller/BackArchivedAccountControllerTest.php @@ -118,7 +118,7 @@ public function testAccountReactivate(): void $accountEmail = 'user-01-09@histologe.fr'; /** @var User $account */ - $account = $userRepository->findOneBy(['email' => $accountEmail]); + $account = $userRepository->findArchivedUserByEmail($accountEmail); $route = $router->generate('back_account_reactiver', [ 'id' => $account->getId(), ]); @@ -141,6 +141,55 @@ public function testAccountReactivate(): void $this->assertResponseRedirects('/bo/comptes-archives/'); } + public function testAccountReactivateDuplicateEmail(): void + { + $faker = Factory::create(); + + $client = static::createClient(); + + /** @var UserRepository $userRepository */ + $userRepository = static::getContainer()->get(UserRepository::class); + $user = $userRepository->findOneBy(['email' => 'admin-01@histologe.fr']); + $client->loginUser($user); + + /** @var RouterInterface $router */ + $router = self::getContainer()->get(RouterInterface::class); + + /** @var TerritoryRepository $territoryRepository */ + $territoryRepository = static::getContainer()->get(TerritoryRepository::class); + $territory = $territoryRepository->findOneBy(['zip' => '01']); + + /** @var PartnerRepository $partnerRepository */ + $partnerRepository = static::getContainer()->get(PartnerRepository::class); + $partner = $partnerRepository->findOneBy([ + 'territory' => $territory->getId(), + 'isArchive' => '0', + ]); + + $accountEmail = 'user-01-06@histologe.fr'; + /** @var User $account */ + $account = $userRepository->findArchivedUserByEmail($accountEmail); + $route = $router->generate('back_account_reactiver', [ + 'id' => $account->getId(), + ]); + + $crawler = $client->request('GET', $route); + + $buttonCrawlerNode = $crawler->selectButton('submit_btn_account'); + $form = $buttonCrawlerNode->form(); + + $form['user[prenom]'] = $faker->name(); + $form['user[nom]'] = $faker->lastName(); + $form['user[email]'] = (string) $account->getEmail(); + $form['user[territory]'] = (string) $territory->getId(); + $form['user[partner]'] = (string) $partner->getId(); + $client->submit($form); + + /** @var User $account */ + $account = $userRepository->findArchivedUserByEmail($accountEmail); + $this->assertEquals(USER::STATUS_ARCHIVE, $account->getStatut()); + } + public function testAccountReactivateError(): void { $faker = Factory::create(); @@ -157,7 +206,7 @@ public function testAccountReactivateError(): void $accountEmail = 'admin-02@histologe.fr'; /** @var User $account */ - $account = $userRepository->findOneBy(['email' => $accountEmail]); + $account = $userRepository->findArchivedUserByEmail($accountEmail); $route = $router->generate('back_account_reactiver', [ 'id' => $account->getId(), ]); @@ -175,7 +224,7 @@ public function testAccountReactivateError(): void $client->submit($form); /** @var User $account */ - $account = $userRepository->findOneBy(['email' => $accountEmail]); + $account = $userRepository->findArchivedUserByEmail($accountEmail); $this->assertEquals(USER::STATUS_ARCHIVE, $account->getStatut()); } } diff --git a/tests/Functional/Controller/CartographieControllerTest.php b/tests/Functional/Controller/CartographieControllerTest.php index 0eac39b5f..a709962af 100644 --- a/tests/Functional/Controller/CartographieControllerTest.php +++ b/tests/Functional/Controller/CartographieControllerTest.php @@ -47,7 +47,7 @@ public function provideUserEmail(): \Generator { /** @var UserRepository $userRepository */ $userRepository = static::getContainer()->get(UserRepository::class); - $users = $userRepository->findAll(); + $users = $userRepository->findBy(['statut' => User::STATUS_ACTIVE]); /** @var User $user */ foreach ($users as $user) { if ($user->getTerritory()) { diff --git a/tests/Functional/Controller/PartnerControllerTest.php b/tests/Functional/Controller/PartnerControllerTest.php index aa62d8ecc..c6680d155 100644 --- a/tests/Functional/Controller/PartnerControllerTest.php +++ b/tests/Functional/Controller/PartnerControllerTest.php @@ -111,6 +111,7 @@ public function testDeletePartner() /** @var Partner $partner */ $partner = $this->partnerRepository->findOneBy(['nom' => 'Partenaire 13-03']); $partnerUsers = $partner->getUsers(); + $mailBeforArchive = $partner->getEmail(); $route = $this->router->generate('back_partner_delete'); $this->client->request( @@ -124,8 +125,10 @@ public function testDeletePartner() $this->assertResponseRedirects('/bo/partenaires/'); $this->assertTrue($partner->getIsArchive()); + $this->assertStringStartsWith($mailBeforArchive.'.archived@', $partner->getEmail()); foreach ($partnerUsers as $user) { $this->assertEquals(User::STATUS_ARCHIVE, $user->getStatut()); + $this->assertStringContainsString('.archived@', $user->getEmail()); } } @@ -256,6 +259,7 @@ public function testDeleteUserAccount(): void ]); $this->assertEquals(2, $user->getStatut()); + $this->assertStringContainsString('.archived@', $user->getEmail()); } public function testDeleteUserAccountWithCsrfUnvalid(): void @@ -269,6 +273,7 @@ public function testDeleteUserAccountWithCsrfUnvalid(): void ]); $this->assertNotEquals(2, $user->getStatut()); + $this->assertStringNotContainsString('.archived@', $user->getEmail()); $this->assertResponseRedirects('/bo/partenaires/'); } } diff --git a/tests/Functional/Controller/SignalementListControllerTest.php b/tests/Functional/Controller/SignalementListControllerTest.php index 463413b18..98fe5e81a 100644 --- a/tests/Functional/Controller/SignalementListControllerTest.php +++ b/tests/Functional/Controller/SignalementListControllerTest.php @@ -45,7 +45,7 @@ public function provideUserEmail(): \Generator { /** @var UserRepository $userRepository */ $userRepository = static::getContainer()->get(UserRepository::class); - $users = $userRepository->findAll(); + $users = $userRepository->findBy(['statut' => User::STATUS_ACTIVE]); /** @var User $user */ foreach ($users as $user) { if ($user->getTerritory()) { diff --git a/tests/Functional/Service/Token/ActivationTokenGeneratorTest.php b/tests/Functional/Service/Token/ActivationTokenGeneratorTest.php index ebe8b1a25..3a0ccf03c 100644 --- a/tests/Functional/Service/Token/ActivationTokenGeneratorTest.php +++ b/tests/Functional/Service/Token/ActivationTokenGeneratorTest.php @@ -3,6 +3,7 @@ namespace App\Tests\Functional\Service\Token; use App\Entity\User; +use App\Repository\UserRepository; use App\Service\Token\ActivationTokenGenerator; use Doctrine\ORM\EntityManagerInterface; use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase; @@ -47,8 +48,9 @@ public function testValidateTokenUpdatePassword(): void public function testValidateTokenNok(): void { + /** @var UserRepository $userRepository */ $userRepository = $this->entityManager->getRepository(User::class); - $user = $userRepository->findOneBy(['email' => 'user-01-07@histologe.fr']); + $user = $userRepository->findArchivedUserByEmail('user-01-07@histologe.fr'); $container = static::getContainer(); $activationTokenGenerator = $container->get(ActivationTokenGenerator::class); From 3c4e37c1e2d20e8b1116e0a8f9c365bd18096cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=A9l=C3=A8ne=20Meneuvrier?= Date: Fri, 29 Mar 2024 11:42:59 +0100 Subject: [PATCH 2/4] changes based on comments #2035 --- migrations/Version20240322123431.php | 5 +++-- .../Back/BackArchivedAccountController.php | 12 ++++++++---- .../Back/BackArchivedPartnerController.php | 4 ++-- src/Entity/User.php | 2 ++ src/Service/Sanitizer.php | 4 +++- templates/back/account/_form.html.twig | 6 ++---- templates/back/account/edit.html.twig | 2 +- templates/back/account/index.html.twig | 4 ++-- templates/back/nav_bo.html.twig | 2 +- templates/back/partner_archived/index.html.twig | 14 +++++++------- .../Controller/PartnerControllerTest.php | 8 ++++---- 11 files changed, 35 insertions(+), 28 deletions(-) diff --git a/migrations/Version20240322123431.php b/migrations/Version20240322123431.php index 0bb468111..fe714d027 100644 --- a/migrations/Version20240322123431.php +++ b/migrations/Version20240322123431.php @@ -4,6 +4,7 @@ namespace DoctrineMigrations; +use App\Entity\User; use Doctrine\DBAL\Schema\Schema; use Doctrine\Migrations\AbstractMigration; @@ -17,10 +18,10 @@ public function getDescription(): string public function up(Schema $schema): void { $this->addSql( - "UPDATE partner SET email = CONCAT(email, '.archived@', DATE_FORMAT(NOW(), '%Y%m%d%H%i')) WHERE is_archive = 1" + "UPDATE partner SET email = CONCAT(email, '".User::SUFFIXE_ARCHIVED."', DATE_FORMAT(NOW(), '%Y%m%d%H%i')) WHERE is_archive = 1" ); $this->addSql( - "UPDATE user SET email = CONCAT(email, '.archived@', DATE_FORMAT(NOW(), '%Y%m%d%H%i')) WHERE statut = 2" + "UPDATE user SET email = CONCAT(email, '".User::SUFFIXE_ARCHIVED."', DATE_FORMAT(NOW(), '%Y%m%d%H%i')) WHERE statut = 2" ); } diff --git a/src/Controller/Back/BackArchivedAccountController.php b/src/Controller/Back/BackArchivedAccountController.php index fd5239f91..61a1f56ad 100755 --- a/src/Controller/Back/BackArchivedAccountController.php +++ b/src/Controller/Back/BackArchivedAccountController.php @@ -102,15 +102,19 @@ public function reactiver( ]); $form->handleRequest($request); - $untaggedEmail = explode('.archived@', $user->getEmail())[0]; + $untaggedEmail = explode(User::SUFFIXE_ARCHIVED, $user->getEmail())[0]; $userExist = $userRepository->findOneBy(['email' => $untaggedEmail]); - if ($userExist && !\in_array('ROLE_USAGER', $userExist->getRoles())) { - $this->addFlash('error', 'Un utilisateur existe déjà avec cette adresse e-mail.'); + if ($userExist) { + $this->addFlash('error', 'Un utilisateur existe déjà avec cette adresse e-mail. ' + .$userExist->getNomComplet().' ( id '.$userExist->getId().' ) avec le rôle ' + .$userExist->getRoleLabel()); } $partnerExist = $partnerRepository->findOneBy(['email' => $untaggedEmail]); if ($partnerExist) { - $this->addFlash('error', 'Un partenaire existe déjà avec cette adresse e-mail.'); + $this->addFlash('error', 'Un partenaire existe déjà avec cette adresse e-mail. ' + .$partnerExist->getNom().' ( id '.$partnerExist->getId().' ) dans le territoire ' + .$partnerExist->getTerritory()->getName()); } if (!$userExist && !$partnerExist && $form->isSubmitted() && $form->isValid()) { diff --git a/src/Controller/Back/BackArchivedPartnerController.php b/src/Controller/Back/BackArchivedPartnerController.php index 5075b2265..947dc352b 100755 --- a/src/Controller/Back/BackArchivedPartnerController.php +++ b/src/Controller/Back/BackArchivedPartnerController.php @@ -2,7 +2,7 @@ namespace App\Controller\Back; -use App\Entity\User; +use App\Entity\Partner; use App\Repository\PartnerRepository; use App\Repository\TerritoryRepository; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; @@ -56,7 +56,7 @@ public function index( 'partners' => $paginatedArchivedPartners, 'total' => $totalArchivedPartners, 'page' => $page, - 'pages' => (int) ceil($totalArchivedPartners / User::MAX_LIST_PAGINATION), + 'pages' => (int) ceil($totalArchivedPartners / Partner::MAX_LIST_PAGINATION), ]); } } diff --git a/src/Entity/User.php b/src/Entity/User.php index f033bd053..7a16ec0eb 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -40,6 +40,8 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface public const ROLE_ADMIN_TERRITORY = self::ROLES['Responsable Territoire']; public const ROLE_ADMIN = self::ROLES['Super Admin']; + public const SUFFIXE_ARCHIVED = '.archived@'; + public const ROLES = [ 'Usager' => 'ROLE_USAGER', 'Utilisateur' => 'ROLE_USER_PARTNER', diff --git a/src/Service/Sanitizer.php b/src/Service/Sanitizer.php index 358d3c7e6..c4e08881c 100644 --- a/src/Service/Sanitizer.php +++ b/src/Service/Sanitizer.php @@ -2,6 +2,8 @@ namespace App\Service; +use App\Entity\User; + class Sanitizer { public static function sanitize($text): string @@ -13,6 +15,6 @@ public static function sanitize($text): string public static function tagArchivedEmail(string $email): string { - return $email.'.archived@'.(new \DateTimeImmutable())->format('YmdHi'); + return $email.User::SUFFIXE_ARCHIVED.(new \DateTimeImmutable())->format('YmdHi'); } } diff --git a/templates/back/account/_form.html.twig b/templates/back/account/_form.html.twig index e268c6d45..1128ce23b 100755 --- a/templates/back/account/_form.html.twig +++ b/templates/back/account/_form.html.twig @@ -1,15 +1,13 @@ {{ form_start(form,{attr:{'class':'needs-validation','novalidate':true}}) }}
    - Pour réactiver le compte {{ user.email|clean_tagged_text('.archived@', 'left') }}, veuillez vérifier les champs ci-dessous et les modifier si besoin.
    + Pour réactiver le compte {{ user.email|clean_tagged_text(constant('App\\Entity\\User::SUFFIXE_ARCHIVED'), 'left') }}, veuillez vérifier les champs ci-dessous et les modifier si besoin.
    Tous les champs sont obligatoires.
    - + {{ form_widget(form.email, {'value': user.email|clean_tagged_text(constant('App\\Entity\\User::SUFFIXE_ARCHIVED'), 'left')}) }}
    L'adresse email ne peut pas être modifiée
    diff --git a/templates/back/account/edit.html.twig b/templates/back/account/edit.html.twig index 1a3f3a8f5..4e08fb351 100755 --- a/templates/back/account/edit.html.twig +++ b/templates/back/account/edit.html.twig @@ -4,7 +4,7 @@ {% block content %}
    -

    Réactivation du compte {{ user.email|clean_tagged_text('.archived@', 'left') }}

    +

    Réactivation du compte {{ user.email|clean_tagged_text(constant('App\\Entity\\User::SUFFIXE_ARCHIVED'), 'left') }}

    {{ include('back/account/_form.html.twig') }}
    diff --git a/templates/back/account/index.html.twig b/templates/back/account/index.html.twig index ba60c0616..0abc82437 100755 --- a/templates/back/account/index.html.twig +++ b/templates/back/account/index.html.twig @@ -82,12 +82,12 @@ {{ user.territory }} {{ user.partner ? user.partner.nom : 'aucun' }} {{ statut|upper }} - {{ user.email|clean_tagged_text('.archived@', 'left') }} + {{ user.email|clean_tagged_text(constant('App\\Entity\\User::SUFFIXE_ARCHIVED'), 'left') }} {{ user.nom}} {{ user.prenom}} + class="fr-btn fr-icon-flashlight-fill fr-btn--sm" title="Réactiver le compte {{user.email|clean_tagged_text(constant('App\\Entity\\User::SUFFIXE_ARCHIVED'), 'left')}}"> {% else %} diff --git a/templates/back/nav_bo.html.twig b/templates/back/nav_bo.html.twig index b51b08800..39180d86d 100755 --- a/templates/back/nav_bo.html.twig +++ b/templates/back/nav_bo.html.twig @@ -68,7 +68,7 @@
    {% if is_granted('ROLE_ADMIN_PARTNER') %} - {% set routesAdmin = ['back_user_report_index', 'back_situation_', 'back_partner_', 'back_account_', 'back_inactive_account_', 'back_expired_account_'] %} + {% set routesAdmin = ['back_user_report_index', 'back_situation_', 'back_partner_', 'back_account_', 'back_inactive_account_', 'back_expired_account_', 'back_archived_partner'] %}