src/Controller/Security/RegisterController.php line 85

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Security;
  3. use App\Entity\ChangePasswordDTO;
  4. use App\Entity\Region;
  5. use App\Form\ChangePasswordType;
  6. use App\Repository\CountryRepository;
  7. use App\Repository\RegionRepository;
  8. use App\Repository\RoleRepository;
  9. use App\Repository\UserRepository;
  10. use App\Services\EmailService;
  11. use Doctrine\ORM\EntityManagerInterface;
  12. use Psr\EventDispatcher\EventDispatcherInterface;
  13. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  14. use Symfony\Bundle\FrameworkBundle\Controller\Controller;
  15. use Symfony\Component\Form\FormError;
  16. use Symfony\Component\HttpFoundation\RedirectResponse;
  17. use Symfony\Component\HttpFoundation\Request;
  18. use Symfony\Component\HttpFoundation\RequestStack;
  19. use Symfony\Component\HttpFoundation\Response;
  20. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  21. use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
  22. use Symfony\Component\Routing\Annotation\Route;
  23. use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
  24. use Symfony\Component\Security\Csrf\TokenStorage\TokenStorageInterface;
  25. use Symfony\Component\Security\Http\Authentication\UserAuthenticatorInterface;
  26. use Symfony\Component\Security\Http\Authenticator\FormLoginAuthenticator;
  27. use Symfony\Component\Security\Http\Event\InteractiveLoginEvent;
  28. use App\Entity\Role;
  29. use App\Entity\User;
  30. use App\Form\UserType;
  31. use App\Tools\Utils;
  32. use Symfony\Contracts\Translation\TranslatorInterface;
  33. class RegisterController extends AbstractController {
  34.     private EntityManagerInterface $em;
  35.     private CountryRepository $countryRepository;
  36.     private RegionRepository $regionRepository;
  37.     private UserRepository $userRepository;
  38.     private UserPasswordHasherInterface $hasher;
  39.     private RoleRepository $roleRepository;
  40.     private TokenStorageInterface $tokenStorage;
  41.     private RequestStack $requestStack;
  42.     private EventDispatcherInterface $dispatcher;
  43.     private EmailService $emailService;
  44.     private UserAuthenticatorInterface $authenticator;
  45.     private UserAuthenticatorInterface $userAuthenticator;
  46.     private FormLoginAuthenticator $formLoginAuthenticator;
  47.     private TranslatorInterface $translator;
  48.     public function __construct(
  49.         EntityManagerInterface $em,
  50.         CountryRepository $countryRepository,
  51.         RegionRepository $regionRepository,
  52.         UserRepository $userRepository,
  53.         UserPasswordHasherInterface $hasher,
  54.         RoleRepository $roleRepository,
  55.         TokenStorageInterface $tokenStorage,
  56.         RequestStack $requestStack,
  57.         EventDispatcherInterface $dispatcher,
  58.         EmailService $emailService,
  59.         UserAuthenticatorInterface $authenticator,
  60.         UserAuthenticatorInterface $userAuthenticator,
  61.         FormLoginAuthenticator $formLoginAuthenticator,
  62.         TranslatorInterface $translator
  63.     ) {
  64.         $this->em $em;
  65.         $this->countryRepository $countryRepository;
  66.         $this->regionRepository $regionRepository;
  67.         $this->userRepository $userRepository;
  68.         $this->hasher $hasher;
  69.         $this->roleRepository $roleRepository;
  70.         $this->tokenStorage $tokenStorage;
  71.         $this->requestStack $requestStack;
  72.         $this->dispatcher $dispatcher;
  73.         $this->emailService $emailService;
  74.         $this->authenticator $authenticator;
  75.         $this->userAuthenticator $userAuthenticator;
  76.         $this->formLoginAuthenticator $formLoginAuthenticator;
  77.         $this->translator $translator;
  78.     }
  79.     #[Route(path'/createAccount'name'register_create_account'methods: ['GET''POST'])]
  80.     public function createAccountAction(Request $request): RedirectResponse|Response {
  81.         $user = new User();
  82.         $form $this->createForm(UserType::class, $user);
  83.         $countries $this->countryRepository->findByValid(true);
  84.         $allCountries $this->countryRepository->findAll();
  85.         //Adaptation for DBTA
  86.         if($_ENV['STRUCT_PROVINCE_COUNTRY_CITY'] == 'true') {
  87.             $form $this->createForm(UserType::class, $user);
  88.             $countries $this->regionRepository->findByValid(true);
  89.             $allCountries $this->regionRepository->findAll();
  90.         }
  91.         $form->handleRequest($request);
  92.         $isValidPhone false;
  93.         if ($form->isSubmitted() && $form->isValid()) {
  94.             $existUser $this->userRepository->findOneByPhone($user->getPhone());
  95.             $typePerson $request->get('userbundle_user')['typePerson'];
  96.             $country $user->getCountry();
  97.             $residenceCountry null;
  98.             //Adaptation for DBTA
  99.             if($_ENV['STRUCT_PROVINCE_COUNTRY_CITY'] == 'true') {
  100.                 $country $user->getRegion()->getCountry();
  101.                 $country->setPhoneCode($user->getRegion()->getPhoneCode());
  102.                 $country->setPhoneDigit($user->getRegion()->getPhoneDigit());
  103.                 $user->setCountry($user->getRegion()->getCountry());
  104.             }
  105.             if ($typePerson != Role::ROLE_ADMIN && !$country) {
  106.                 $this->addFlash('danger'$this->translator->trans('flashbag.the_country_field_is_mandatory'));
  107.                 return $this->render('user/register.html.twig', [
  108.                     'user' => $user,
  109.                     'form' => $form->createView(),
  110.                     'countries' => $countries,
  111.                     'allCountries' => $allCountries
  112.                 ]);
  113.             }
  114.             if (isset ($request->get('userbundle_user')['diaspora'])) {
  115.                 // $residenceCountryStr = null;
  116.                 if($_ENV['STRUCT_PROVINCE_COUNTRY_CITY'] == 'true') {
  117.                     $residenceCountryStr $request->get('userbundle_user')['residenceRegion'];
  118.                 } else {
  119.                     $residenceCountryStr $request->get('userbundle_user')['residenceCountry'];
  120.                 }
  121.                 if( ! $residenceCountryStr) {
  122.                     $this->addFlash('danger'$this->translator->trans('flashbag.the_country_of_residence_field_is_mandatory'));
  123.                     return $this->render('user/register.html.twig', [
  124.                         'user' => $user,
  125.                         'form' => $form->createView(),
  126.                         'countries' => $countries,
  127.                         'allCountries' => $allCountries
  128.                     ]);
  129.                 //Récupération du pays de résidence
  130.                 } else {
  131.                     $residenceCountry $this->countryRepository->find($residenceCountryStr);
  132.                     if($_ENV['STRUCT_PROVINCE_COUNTRY_CITY'] == 'true') {
  133.                         $residenceCountry $this->regionRepository->find($residenceCountryStr);
  134.                     }
  135.                 }
  136.             }
  137.             //verification de l'indicatif pays
  138.             $phoneCode '+' $country->getPhoneCode();
  139.             if($residenceCountry) {
  140.                 $phoneCode '+' $residenceCountry->getPhoneCode();
  141.             }
  142.             $nationalPhone "";
  143.             //verification du nombre de digits téléphonique du pays
  144.             $phoneDigit '+' $country->getPhoneDigit();
  145.             if($residenceCountry) {
  146.                 $phoneDigit '+' $residenceCountry->getPhoneDigit();
  147.             }
  148.             if (strncmp($phoneCode$user->getPhone(), strlen($phoneCode)) === 0) {
  149.                 $nationalPhone substr($user->getPhone(), strlen($phoneCode));
  150.                 $isValidPhone true;
  151.             } else {
  152.                 $errorMessage $this->translator->trans('flashbag.the_number_must_start_with_number', ['{number}' => $phoneCode]);
  153.                 $this->addFlash('danger'$errorMessage);
  154.             }
  155.             if ($isValidPhone && strlen($nationalPhone) > 0) {
  156.                 // suppression du 0 pour le national
  157.                 if ($nationalPhone[0] == '0') {
  158.                     $nationalPhone substr($nationalPhone1);
  159.                 }
  160.                 // reconstruit le numéro de téléphone sans le 0 national
  161.                 $validPhone $phoneCode $nationalPhone;
  162.                 if ($validPhone !== $user->getPhone()) {
  163.                     $user->setPhone($validPhone);
  164.                     $mesgWarn $this->translator->trans('flashbag.your_login_account_is_renamed_to_name', ['{name}' => $validPhone]);
  165.                     $this->addFlash('warning'$mesgWarn);
  166.                 }
  167.             }
  168.             // vérification de la conformité du numéro de téléphone
  169.             if ($isValidPhone) {
  170.                 if (strlen($nationalPhone) != $phoneDigit) {
  171.                     $isValidPhone false;
  172.                     $errorMessage $this->translator->trans('flashbag.the_number_without_the_country_code_must_have_number_digits', ['{number}' => (int)$phoneDigit]);
  173.                     $this->addFlash('danger'$errorMessage);
  174.                 }
  175.                 if (!ctype_digit($nationalPhone)) {
  176.                     $isValidPhone false;
  177.                     $errorMessage $this->translator->trans('flashbag.wrong_phone_number_syntax');
  178.                     $this->addFlash('danger'$errorMessage);
  179.                 }
  180.             }
  181.             // vérification de l'intégrité du mot de passe :
  182.             if ($isValidPhone) {
  183.                 if (strlen($user->getPlainPassword()) < 6) {
  184.                     $isValidPhone false;
  185.                     $errorMessage $this->translator->trans('flashbag.the_password_must_have_at_least_6_characters');
  186.                     $this->addFlash('danger'$errorMessage);
  187.                 }
  188.             }
  189.             // ecriture en base
  190.             if ($isValidPhone) {
  191.                 if ($existUser == null) {
  192.                     $typePerson $request->get('userbundle_user')['typePerson'];
  193.                     $redirection $this->addRoleAndGererateRedirection($user$typePerson);
  194.                     // Supprime les espaces du numéro de téléphone
  195.                     $user->setPhone(preg_replace('/\s/'''$user->getPhone()));
  196.                     // Encode le password
  197.                     $user->setPassword($this->hasher->hashPassword($user$user->getPlainPassword()));
  198.                     // synchronise le username avec le phone
  199.                     $user->setUsername($user->getPhone());
  200.                     // créé l'adresse mail fictive
  201.                     $user->setEmail($user->getPhone() . "@domaine.extension");
  202.                     // si établissement , alors création de la clé API
  203.                     if ($typePerson == 'ROLE_ETABLISSEMENT') {
  204.                         $user->setApiToken(bin2hex(random_bytes(32)));
  205.                     }
  206.                     $this->em->persist($user);
  207.                     $this->em->flush();
  208.                     // Authentification de l'utilisateur
  209.                     $this->authenticator->authenticateUser(
  210.                         $user,
  211.                         $this->formLoginAuthenticator,
  212.                         $request
  213.                     );
  214.                     return $redirection;
  215.                 } else {
  216.                     $errorMessage $this->translator->trans('flashbag.this_phone_number_is_already_in_use');
  217.                     $this->addFlash('danger'$errorMessage);
  218.                 }
  219.             }
  220.         }
  221.         return $this->render('user/register.html.twig', [
  222.             'user' => $user,
  223.             'form' => $form->createView(),
  224.             'countries' => $countries,
  225.             'allCountries' => $allCountries
  226.         ]);
  227.     }
  228.     private function addRoleAndGererateRedirection(User &$user$typePerson): RedirectResponse {
  229.         switch ($typePerson) {
  230.             case Utils::COMPANY:
  231.                 {
  232.                     $user->addProfil($this->createRole(Utils::COMPANY));
  233.                     $flashBag $this->translator->trans('flashbag.welcome_before_answering_the_satisfaction_questionnaire_please_complete_your_profile_below');
  234.                     $redirect $this->redirectToRoute('front_company_new');
  235.                 }
  236.                 break;
  237.             case Utils::PERSON_DEGREE:
  238.                 {
  239.                     $user->addProfil($this->createRole(Utils::PERSON_DEGREE));
  240.                     $flashBag $this->translator->trans('flashbag.Welcome_please_complete_your_profile_below');
  241.                     $redirect $this->redirectToRoute('front_persondegree_new');
  242.                 }
  243.                 break;
  244.             case Utils::SCHOOL:
  245.                 {
  246.                     $user->addProfil($this->createRole(Utils::SCHOOL));
  247.                     $flashBag $this->translator->trans('flashbag.welcome_please_complete_your_profile_below');
  248.                     $redirect $this->redirectToRoute('front_school_new');
  249.                 }
  250.                 break;
  251.             default:
  252.                 throw new NotFoundHttpException($this->translator->trans('flashbag.unable_to_create_an_account'));
  253.         }
  254.         $this->addFlash(Utils::OFB_SUCCESS$flashBag);
  255.         return $redirect;
  256.     }
  257.     private function createRole(string $roleName): ?Role {
  258.         $role $this->roleRepository
  259.             ->findOneBy(['role' => $roleName]);
  260.         return ($role) ?: new Role($roleName);
  261.     }
  262.     /**
  263.      * @param Request $request
  264.      * @param User $user
  265.      */
  266.     private function authenticateUser(Request $requestUser $user) {
  267.         $token = new UsernamePasswordToken($user'main');
  268.         $this->tokenStorage->setToken($token);
  269.         $this->requestStack->getSession()->set('_security_main'serialize($token));
  270.         // Déclencher l'événement de connexion manuellement
  271.         $event = new InteractiveLoginEvent($request$token);
  272.         $this->dispatcher->dispatch($event'security.interactive_login');
  273.     }
  274.     /**
  275.      * Ask to change password.
  276.      */
  277.     #[Route(path'/askNewPassword'name'register_ask_new_password'methods: ['GET''POST'])]
  278.     public function askNewPasswordAction(Request $request): RedirectResponse|Response {
  279.         $user = new User();
  280.         $form $this->createForm(UserType::class, $user);
  281.         $form->handleRequest($request);
  282.         $submitPhone $request->get('userbundle_user')['phone'] ?? null;
  283.         $submitEmail $request->get('userbundle_user')['email'] ?? null;
  284.         $submitCode $request->get('userbundle_user')['validCode'] ?? null;
  285.         if ($form->isSubmitted() && $form->isValid()) {
  286.             $isValidEmail false;
  287.             $existUser $this->userRepository->findOneByPhone($submitPhone);
  288.             if ($existUser) {
  289.                 // si user est diplômé
  290.                 if ($existUser->getPersonDegree()) {
  291.                     $personDegree $existUser->getPersonDegree();
  292.                     $existEmail $personDegree->getEmail();
  293.                     if ($existEmail == $submitEmail) {
  294.                         $isValidEmail true;
  295.                     }
  296.                     // si user est établissement
  297.                 } elseif ($existUser->getSchool()) {
  298.                     $school $existUser->getSchool();
  299.                     $existEmail $school->getEmail();
  300.                     if ($existEmail == $submitEmail) {
  301.                         $isValidEmail true;
  302.                     }
  303.                     // si user est entreprise
  304.                 } elseif ($existUser->getCompany()) {
  305.                     $company $existUser->getCompany();
  306.                     $existEmail $company->getEmail();
  307.                     if ($existEmail == $submitEmail) {
  308.                         $isValidEmail true;
  309.                     }
  310.                     // si user est admin ou législateur
  311.                 } else {
  312.                     $existEmail $existUser->getEmail();
  313.                     if ($existEmail == $submitEmail) {
  314.                         $isValidEmail true;
  315.                     }
  316.                 }
  317.             }
  318.             // envoie du message email
  319.             if (strlen($submitCode) == 0) {
  320.                 if ($isValidEmail) {
  321.                     // creation du code d'activation
  322.                     $code rand(10028902);
  323.                     $this->requestStack->getSession()->set('code'$code);
  324.                     $this->requestStack->getSession()->set('refu'$existUser->getId());
  325.                     $this->emailService->sendCodeChangePassword($submitEmail$code);
  326.                     $this->addFlash('success'$this->translator->trans('flashbag.your_code_is_sent_by_email'));
  327.                 } elseif (strlen($submitEmail) == 0) {
  328.                     $this->addFlash('danger'$this->translator->trans('flashbag.sending_the_code_by_sms_is_not_yet_authorized_please_enter_a_valid_email_address'));
  329.                 } else {
  330.                     $this->addFlash('danger'$this->translator->trans('flashbag.your_email_does_not_match_your_profile'));
  331.                 }
  332.             } elseif ((strlen($submitCode) == 4) && (is_numeric($submitCode))) {
  333.                 if ($submitCode == $this->requestStack->getSession()->get('code')) {
  334.                     $this->addFlash('success'$this->translator->trans('flashbag.enter_your_new_password'));
  335.                     return $this->redirectToRoute('register_change_password', array('user' => $existUser));
  336.                 } else {
  337.                     $this->addFlash('danger'$this->translator->trans('flashbag.your_code_is_invalid'));
  338.                 }
  339.             } else {
  340.                 $this->addFlash('danger'$this->translator->trans('flashbag.the_code_must_have_4_digits'));
  341.             }
  342.         }
  343.         return $this->render('user/ask_password.html.twig', [
  344.             'user' => $user,
  345.             'form' => $form->createView(),
  346.             'userphone' => $submitPhone,
  347.             'useremail' => $submitEmail,
  348.         ]);
  349.     }
  350.     #[Route(path'/change_password'name'register_change_password'methods: ['POST''GET'])]
  351.     public function changePasswordAction(Request $request): RedirectResponse|Response {
  352.         $user $this->userRepository->findOneById($this->requestStack->getSession()->get('refu'));
  353.         $changePasswordDTO = new ChangePasswordDTO();
  354.         $form $this->createForm(ChangePasswordType::class, $changePasswordDTO);
  355.         $form->handleRequest($request);
  356.         if ($form->isSubmitted() && $form->isValid()) {
  357.             $firstPassword $request->get('userbundle_user')['plainPassword']['first'];
  358.             $secondPassword $request->get('userbundle_user')['plainPassword']['second'];
  359.             if ($firstPassword === $secondPassword) {
  360.                 $plainPassword $changePasswordDTO->getPlainPassword();
  361.                 if (strlen($plainPassword) < 6) {
  362.                     $errorMessage 'Le mot de passe doit avoir au minimum 6 caractères ';
  363.                     $this->addFlash('danger'$errorMessage);
  364.                 } else {
  365.                     $user->setPassword($this->hasher->hashPassword($user$plainPassword));
  366.                     $this->em->persist($user);
  367.                     $this->em->flush();
  368.                     $this->addFlash('success'$this->translator->trans('flashbag.your_password_has_been_changed'));
  369.                     return $this->redirectToRoute('logout');
  370.                 }
  371.             }
  372.         }
  373.         return $this->render('user/change_password.html.twig', [
  374.             'user' => $user,
  375.             'form' => $form->createView()
  376.         ]);
  377.     }
  378. }