Skip to content

Commit

Permalink
Merge pull request #2366 from MTES-MCT/bugfix/2035-tag-mail-user-part…
Browse files Browse the repository at this point in the history
…ner-archived

[BO] Tagger les mails des comptes et partenaires archivés pour éviter les doublons
  • Loading branch information
numew committed Apr 4, 2024
2 parents 8a7afb7 + 100d96e commit 1cf68ea
Show file tree
Hide file tree
Showing 26 changed files with 539 additions and 19 deletions.
31 changes: 31 additions & 0 deletions migrations/Version20240322123431.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use App\Entity\User;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

final class Version20240322123431 extends AbstractMigration
{
public function getDescription(): string
{
return 'Add a tag to email or achived user or partner';
}

public function up(Schema $schema): void
{
$this->addSql(
"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, '".User::SUFFIXE_ARCHIVED."', DATE_FORMAT(NOW(), '%Y%m%d%H%i')) WHERE statut = 2"
);
}

public function down(Schema $schema): void
{
}
}
19 changes: 18 additions & 1 deletion src/Controller/Back/BackArchivedAccountController.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public function reactiver(
User $user,
TerritoryRepository $territoryRepository,
PartnerRepository $partnerRepository,
UserRepository $userRepository,
EntityManagerInterface $entityManager,
NotificationMailerRegistry $notificationMailerRegistry,
): Response {
Expand All @@ -101,8 +102,24 @@ public function reactiver(
]);
$form->handleRequest($request);

if ($form->isSubmitted() && $form->isValid()) {
$untaggedEmail = explode(User::SUFFIXE_ARCHIVED, $user->getEmail())[0];
$userExist = $userRepository->findOneBy(['email' => $untaggedEmail]);
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. '
.$partnerExist->getNom().' ( id '.$partnerExist->getId().' ) dans le territoire '
.$partnerExist->getTerritory()->getName());
}

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.');

Expand Down
62 changes: 62 additions & 0 deletions src/Controller/Back/BackArchivedPartnerController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace App\Controller\Back;

use App\Entity\Partner;
use App\Repository\PartnerRepository;
use App\Repository\TerritoryRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;

#[Route('/bo/partner-archives')]
class BackArchivedPartnerController extends AbstractController
{
#[Route('/', name: 'back_archived_partner_index', methods: ['GET', 'POST'])]
#[IsGranted('ROLE_ADMIN')]
public function index(
Request $request,
TerritoryRepository $territoryRepository,
PartnerRepository $partnerRepository
): Response {
$page = $request->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 / Partner::MAX_LIST_PAGINATION),
]);
}
}
7 changes: 6 additions & 1 deletion src/Controller/Back/PartnerController.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down
6 changes: 6 additions & 0 deletions src/DataFixtures/Files/Partner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
16 changes: 16 additions & 0 deletions src/DataFixtures/Files/User.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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\"]"
Expand Down Expand Up @@ -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\"]"
Expand Down
8 changes: 7 additions & 1 deletion src/DataFixtures/Loader/LoadPartnerData.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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));
}
Expand Down
8 changes: 7 additions & 1 deletion src/DataFixtures/Loader/LoadUserData.php
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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']]));
}
Expand Down
2 changes: 2 additions & 0 deletions src/Entity/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
44 changes: 44 additions & 0 deletions src/Repository/PartnerRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
13 changes: 13 additions & 0 deletions src/Repository/UserRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand Down
7 changes: 7 additions & 0 deletions src/Service/Sanitizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

namespace App\Service;

use App\Entity\User;

class Sanitizer
{
public static function sanitize($text): string
Expand All @@ -10,4 +12,9 @@ public static function sanitize($text): string

return str_replace('</p>', '<br>', $textSanitized); // Replace the end
}

public static function tagArchivedEmail(string $email): string
{
return $email.User::SUFFIXE_ARCHIVED.(new \DateTimeImmutable())->format('YmdHi');
}
}
19 changes: 19 additions & 0 deletions src/Twig/AppExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -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']),
];
}

Expand Down Expand Up @@ -76,4 +77,22 @@ public function getFunctions(): array
new TwigFunction('show_label_facultatif', [AttributeParser::class, 'showLabelAsFacultatif']),
];
}

public function cleanTaggedText(?string $taggedText, string $tag, string $direction): string
{
if (null === $taggedText) {
return '';
}

$parts = explode($tag, $taggedText);

switch ($direction) {
case 'left':
return $parts[0];
case 'right':
return $parts[1];
default:
return $taggedText;
}
}
}
4 changes: 2 additions & 2 deletions templates/back/account/_form.html.twig
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{{ form_start(form,{attr:{'class':'needs-validation','novalidate':true}}) }}
<fieldset class="fr-fieldset fr-fieldset--inline fr-mb-md-0">
<legend class="fr-fieldset__legend fr-text--regular">
<span>Pour réactiver le compte {{ user.email }}, veuillez vérifier les champs ci-dessous et les modifier si besoin.</span></br>
<span>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.</span></br>
<span>Tous les champs sont obligatoires.</span>
</legend>
<div class="fr-grid-row fr-grid-row--gutters">
<div class="fr-col-lg-6">
<label for="{{ form.email.vars.id }}" class="fr-label">Adresse email</label>
{{ form_widget(form.email) }}
{{ form_widget(form.email, {'value': user.email|clean_tagged_text(constant('App\\Entity\\User::SUFFIXE_ARCHIVED'), 'left')}) }}
</br>
<span class="fr-hint-text">L'adresse email ne peut pas être modifiée</span>
</div>
Expand Down
Loading

0 comments on commit 1cf68ea

Please sign in to comment.