src/Controller/UserAuthenticationController.php line 96

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\User;
  4. use App\Entity\Company;
  5. use App\Entity\PersonalInfo;
  6. use App\Entity\Invitation;
  7. use App\Form\RegisterCompanyType;
  8. use App\Form\RegisterUserType;
  9. use App\Repository\UserRepository;
  10. use App\Service\MailgunService;
  11. use App\Service\UtilsService;
  12. use App\Service\LogService;
  13. use Doctrine\ORM\EntityManagerInterface;
  14. use Symfony\Component\Form\Extension\Core\Type\EmailType;
  15. use Symfony\Component\Form\Extension\Core\Type\SubmitType;
  16. use Symfony\Component\Form\Extension\Core\Type\PasswordType;
  17. use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
  18. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  19. use Symfony\Component\Routing\Annotation\Route;
  20. use Symfony\Component\HttpFoundation\Request;
  21. use Symfony\Component\HttpFoundation\Response;
  22. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  23. use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
  24. use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
  25. use Symfony\Contracts\Translation\TranslatorInterface;
  26. class UserAuthenticationController extends AbstractController
  27. {
  28.     // ## Basic Authentication ## //
  29.     #[Route(path'/login'name'login')]
  30.     public function login(AuthenticationUtils $authenticationUtils): \Symfony\Component\HttpFoundation\Response
  31.     {
  32.         // get the login error if there is one
  33.         $error $authenticationUtils->getLastAuthenticationError();
  34.         
  35.         // last username entered by the user
  36.         $lastUsername $authenticationUtils->getLastUsername();
  37.         if ($this->getUser()) {
  38.             return $this->redirectToRoute('index');
  39.         }
  40.         return $this->render('public/user-authentication/login.html.twig', array(
  41.             'last_username' => $lastUsername,
  42.             'error' => $error
  43.         ));    
  44.     }
  45.     #[Route(path'/logged'name'login_check')]
  46.     public function loginCheck() : \Symfony\Component\HttpFoundation\RedirectResponse
  47.     {
  48.         $user $this->getUser();
  49.         if (!$user) {
  50.             throw new \Exception('User not found!');
  51.         }
  52.         if(!$user->getIsActive()){
  53.             $this->addFlash(
  54.                 'danger'"Your account has been disabled"
  55.             );
  56.             return $this->redirectToRoute('login');
  57.         }
  58.         if($user->getPersonalInfo() == null){
  59.             $personal_info = new PersonalInfo();
  60.             $user->setPersonalInfo($personal_info);
  61.         }
  62.         if($user->getStatus() == null){
  63.             $user->setStatus('status.off');
  64.         }
  65.         $user->setLastLoginAt(new \DateTime());
  66.         $entityManager $this->getDoctrine()->getManager();
  67.         $entityManager->persist($user);
  68.         $entityManager->flush();
  69.         if ($this->isGranted('ROLE_OWNER') && count($user->assignedOffices()) == 0) {
  70.             return $this->redirectToRoute('add_office');
  71.         } elseif ($user->companyOwner() && count($user->assignedCompany()->getDepartments()) == 0) {
  72.             return $this->redirectToRoute('department_settings');
  73.         } elseif($user->getPersonalInfo()->profileCompletion()['completed'] <= 1) {
  74.             return $this->redirectToRoute('edit_user_profile');
  75.         }
  76.         /*
  77.                 if ($user->getLastLogin() == null) {
  78.                     return $this->redirectToRoute('complete-register');
  79.                 }*/
  80.         return $this->redirectToRoute('index');
  81.     }
  82.     #[Route(path'/logout'name'logout'methods: ['GET'])]
  83.     public function logout()
  84.     {
  85.         // controller can be blank: it will never be executed!
  86.         throw new \Exception('Don\'t forgot to activate logout in security.yaml');
  87.     }
  88.     #[Route(path'/forgot'name'forgot_password')]
  89.     public function forgotPage(Request $requestMailgunService $mailgunServiceEntityManagerInterface $entityManagerUtilsService $utilsServiceTranslatorInterface $translator): \Symfony\Component\HttpFoundation\Response
  90.     {
  91.         $form $this->createFormBuilder()
  92.             ->add('email'EmailType::class,  array(
  93.                 'label' => 'E-Mail',
  94.                 'attr' => array('maxlength' => 128'class'=> 'form-control'),
  95.             )) 
  96.             ->add('submit'SubmitType::class, array('label' => 'Send me reset password instructions'))
  97.             ->getForm();
  98.         $form->handleRequest($request);
  99.         if ($form->isSubmitted() && !$form->isValid()) {
  100.             foreach ($form->getErrors(true) as $error) {
  101.                 $this->addFlash(
  102.                     'danger'$error->getMessage()
  103.                 );
  104.             }
  105.         }
  106.         if ($form->isSubmitted() && $form->isValid()) {
  107.             $email $form["email"]->getData();
  108.             $user $entityManager->getRepository(User::class)->findOneByEmail($email);
  109.             if ($user && $user->getIsActive()) {
  110.                 $user->setForgetToken($utilsService->generateRandomString(30));
  111.                 $entityManager->persist($user);
  112.                 $entityManager->flush();
  113.                 $confirmationUrl $this->generateUrl('reset_password', array('forgotToken' => $user->getForgetToken()), UrlGeneratorInterface::ABSOLUTE_URL);
  114.                 $mailgunService->sendEmail($translator->trans('email.password_reset'),
  115.                     [$user->getEmail()],
  116.                     'email/user-authentication/reset-password.html.twig',
  117.                     ['recipientName' => $user->getPersonalInfo()->getFirstName() ? $user->getPersonalInfo()->getFirstName() : $user->getEmail(),
  118.                         'confirmationUrl' => $confirmationUrl
  119.                     ], false
  120.                 );
  121.             }
  122.             $this->addFlash(
  123.                 'success',
  124.                 'We have send an email instruction to reset your password. Please check your email.'
  125.             );
  126.         }
  127.         return $this->render(
  128.             'public/user-authentication/forgot-password.html.twig',
  129.             array('form' => $form->createView())
  130.         );
  131.     }
  132.     #[Route(path'/reset-password/{forgotToken}'name'reset_password')]
  133.     public function resetPassword(Request $requestEntityManagerInterface $entityManagerUtilsService $utilsService$forgotTokenUserPasswordHasherInterface $passwordHasher)
  134.     {
  135.         $user $entityManager->getRepository(User::class)->findOneByForgetToken($forgotToken);
  136.         if (!$user || !$user->getIsActive()) {
  137.             //throw new \Exception('User not found!');
  138.             $this->addFlash(
  139.                 'warning',
  140.                 'Link expired!'
  141.             );
  142.             return $this->redirectToRoute('login');
  143.         }
  144.         //$form = $this->createForm(ResetPasswordType::class);
  145.         $form $this->createFormBuilder()
  146.                 ->add('plainPassword'RepeatedType::class, array(
  147.                     'type' => PasswordType::class,
  148.                     'first_options'  => array('label' => 'Password'),
  149.                     'second_options' => array('label' => 'Repeat Password'),
  150.                 ))
  151.                 ->add('submit'SubmitType::class, array('label' => 'Reset password'))
  152.                 ->getForm();
  153.         $form->handleRequest($request);
  154.         if ($form->isSubmitted() && $form->isValid()) {
  155.             $user->setForgetToken(null);
  156.             $plainpassword $form['plainPassword']->getData();
  157.             $password $passwordHasher->hashPassword($user$plainpassword);
  158.             $user->setPassword($password);
  159.             $entityManager->persist($user);
  160.             $entityManager->flush();
  161.             $this->addFlash(
  162.                 'success',
  163.                 'Your password have been reset. Please login'
  164.             );
  165.              return $this->redirectToRoute('login');
  166.         }
  167.         return $this->render(
  168.             'public/user-authentication/reset-password.html.twig',
  169.             array('form' => $form->createView())
  170.         );
  171.     }
  172.     // ## User Registration Process ## //
  173.     #[Route(path'/register'name'company_registration')]
  174.     public function companyRegistration(Request $requestUserPasswordHasherInterface $passwordHasherMailgunService $mailgunServiceUtilsService $utilsServiceUserRepository $userRepositoryTranslatorInterface $translator)
  175.     { 
  176.         $user = new User();
  177.         $company = new Company();
  178.         $personal_info = new PersonalInfo();
  179.         $form $this->createForm(RegisterCompanyType::class, $user);
  180.         $form->handleRequest($request);
  181.        if ($form->isSubmitted() && !$form->isValid()) {
  182.             foreach ($form->getErrors(true) as $error) {
  183.                 $this->addFlash(
  184.                     'danger'$error->getMessage()
  185.                 );
  186.             }
  187.         }
  188.         if ($form->isSubmitted() && $form->isValid()) {
  189.             
  190.             $lowercaseEmail strtolower($user->getEmail());
  191.             $user->setCanonicalEmail($lowercaseEmail);
  192.             $existingUser $userRepository->findOneByCanonicalEmail($lowercaseEmail);
  193.             if($existingUser){
  194.                 $this->addFlash(
  195.                     'danger''Email already in use, login instead'
  196.                 );
  197.                 return $this->redirectToRoute('login');
  198.             }
  199.             $password $passwordHasher->hashPassword($user$user->getPlainPassword());
  200.             $user->setPassword($password);
  201.             $user->setConfirmationToken($utilsService->generateRandomString(30));
  202.             $user->setIsActive(false);
  203.             $user->setEmailValidated(false);
  204.             $user->setRoles(array('ROLE_HR','ROLE_MANAGEMENT''ROLE_ACCESS_ALL_OFFICE'));
  205.             $user->setCreatedAt(new \DateTime());
  206.             $user->setPersonalInfo($personal_info);
  207.             $user->setStatus('status.off');
  208.             $company->setFullname($form->get('fullName')->getData());
  209.             $user->addCompany($company);
  210.             $entityManager $this->getDoctrine()->getManager();
  211.             $entityManager->persist($user);
  212.             $entityManager->persist($company);
  213.             $entityManager->flush();
  214.             $entityManager->refresh($user);
  215.             $confirmationUrl $this->generateUrl('user_confirmation', array('confirmationToken' => $user->getConfirmationToken()), UrlGeneratorInterface::ABSOLUTE_URL);
  216.             $mailgunService->sendEmail($translator->trans('email.register_company'),
  217.                 [$user->getEmail()],
  218.                 'email/user-authentication/company-registration.html.twig',
  219.                 ['user' => $user,
  220.                     'company' => $company,
  221.                     'confirmationUrl' => $confirmationUrl
  222.                 ], false
  223.             );
  224.             $this->addFlash(
  225.                 'success'"Please check your email to finish the registration process."
  226.             );
  227.             return $this->redirect($request->getUri());
  228.             /*return $this->render(
  229.                 'public/user-authentication/register-form.html.twig',
  230.                 array('form' => $form->createView(),
  231.                     'user' => $user
  232.                 )
  233.             );*/
  234.         
  235.         return $this->render(
  236.             'public/user-authentication/register-company.html.twig',
  237.             array('form' => $form->createView())
  238.         );
  239.         
  240.     }
  241.     #[Route(path'/confirm/{confirmationToken}'name'user_confirmation')]
  242.     public function confirmUser($confirmationTokenEntityManagerInterface $entityManagerMailgunService $mailgunServiceUserRepository $userRepositoryTranslatorInterface $translator)
  243.     {
  244.         
  245.         $user $entityManager->getRepository(User::class)->findOneByConfirmationToken($confirmationToken);
  246.         $company $user->assignedCompany();
  247.         if (!$user) {
  248.             $this->addFlash(
  249.                 'warning'"User not found, please register"
  250.             );
  251.             return $this->redirectToRoute('user_registration');
  252.             //throw new NotFoundHttpException('User not found');
  253.         }
  254.         $user->setEmailValidated(true);
  255.         $user->setIsActive(true);
  256.         $entityManager->persist($user);
  257.         $entityManager->flush();
  258.         if ($user->getIsActive()) {
  259.              $mailgunService->sendEmail($translator->trans('email.registration_steps'),
  260.                 [$user->getEmail()],
  261.                 'email/user-authentication/company-registered.html.twig',
  262.                 ['user' => $user,
  263.                     'company' => $company
  264.                 ], false
  265.             );
  266.              
  267.             $this->addFlash(
  268.                 'success'"Email has been verified, please login to proceed"
  269.             );
  270.             return $this->redirectToRoute('login');
  271.         } else {
  272.             return $this->render(
  273.                 'public/user-authentication/register-status.html.twig',
  274.                 ['user' => $user]
  275.             );
  276.         }
  277.     }
  278.     #[Route(path'/invitation'name'user_invitation')]
  279.     public function invitationPage(): \Symfony\Component\HttpFoundation\RedirectResponse{
  280.         //return $this->render('public/user-authentication/invitation.html.twig', []);
  281.         return $this->redirectToRoute('login');
  282.     }
  283.     #[Route(path'/invitation/{confirmationToken}'name'user_invited')]
  284.     public function confirmInvitation(Request $request$confirmationTokenEntityManagerInterface $entityManagerUserPasswordHasherInterface $passwordHasherMailgunService $mailgunServiceUserRepository $userRepositoryTranslatorInterface $translator)
  285.     {
  286.         $invitation $entityManager->getRepository(Invitation::class)->findOneByConfirmationToken($confirmationToken);
  287.         if (!$invitation) {
  288.             $this->addFlash(
  289.                 'warning'"Invitation not found or expired, please register instead"
  290.             );
  291.             return $this->redirectToRoute('company_registration');
  292.         };
  293.         $user = new User();
  294.         $personal_info = new PersonalInfo();
  295.         
  296.         $form $this->createForm(RegisterUserType::class, $user);
  297.         $form->add('email'EmailType::class,  array(
  298.             'label' => 'E-Mail',
  299.             'disabled' => true,
  300.             'data' => $invitation->getEmail()
  301.         ));
  302.         $form->handleRequest($request);
  303.        if ($form->isSubmitted() && !$form->isValid()) {
  304.             foreach ($form->getErrors(true) as $error) {
  305.                 $this->addFlash(
  306.                     'danger'$error->getMessage()
  307.                 );
  308.             }
  309.         }
  310.         if ($form->isSubmitted() && $form->isValid()) {
  311.             $user->setEmail($invitation->getEmail());
  312.             $user->setCanonicalEmail($invitation->getCanonicalEmail());
  313.             $existingUser $userRepository->findOneByCanonicalEmail($invitation->getEmail());
  314.             if($existingUser){
  315.                 $this->addFlash(
  316.                     'danger''Email already in use, login instead'
  317.                 );
  318.                 return $this->redirectToRoute('login');
  319.             }
  320.             $invitation->setIsActive(true);
  321.             $invitation->setActivatedAt(new \DateTime());
  322.             $invitation->setConfirmationToken(null);
  323.             $password $passwordHasher->hashPassword($user$user->getPlainPassword());
  324.             $user->setPassword($password);
  325.             $user->setEmailValidated(true);
  326.             $user->setIsActive(true);
  327.             $user->setCreatedAt(new \DateTime());
  328.             $user->setOffice($invitation->getOffice());
  329.             $user->setPublicRoles($invitation->getRole());
  330.             $personal_info->setFirstName($form->get('firstName')->getData());
  331.             $personal_info->setMiddleName($form->get('middleName')->getData());
  332.             $personal_info->setLastName($form->get('lastName')->getData());
  333.             
  334.             $user->setPersonalInfo($personal_info);
  335.             $entityManager $this->getDoctrine()->getManager();
  336.             $entityManager->persist($invitation);
  337.             $entityManager->persist($user);
  338.             $entityManager->persist($personal_info);
  339.             $entityManager->flush();
  340.             $entityManager->refresh($user);
  341.             $entityManager->refresh($personal_info);
  342.             $mailgunService->sendEmail($translator->trans('email.registration_success'),
  343.                 [$invitation->getEmail()],
  344.                 'email/user-authentication/user-registered.html.twig',
  345.                 ['user' => $personal_info], false
  346.             );
  347.             $this->addFlash(
  348.                 'success'"You've been registered, please login"
  349.             );
  350.         
  351.             return $this->redirectToRoute('login');
  352.         }
  353.         return $this->render(
  354.             'public/user-authentication/register-user.html.twig',
  355.             ['form' => $form->createView(),
  356.             'user' => $user,
  357.             'invitation' => $invitation]
  358.         );
  359.     }
  360.     // ## User Account Settings ## //
  361.     #[Route(path'/settings/account'name'edit_account')]
  362.     public function editAccount(Request $requestUserPasswordHasherInterface $passwordHasherMailgunService $mailgunServiceUtilsService $utilsServiceUserRepository $userRepositoryLogService $logTranslatorInterface $translator)
  363.     {
  364.         $user $this->getUser();
  365.         
  366.         $form $this->createFormBuilder()
  367.                 ->add('plainPassword'RepeatedType::class, array(
  368.                     'type' => PasswordType::class,
  369.                     'first_options'  => array('label' => 'New password'),
  370.                     'second_options' => array('label' => 'Repeat new password'),
  371.                 ))
  372.                 ->add('submit'SubmitType::class, array('label' => 'form.save'))
  373.                 ->getForm();
  374.         $passwordSet $user->getPassword() ? true false
  375.         
  376.         if($passwordSet){
  377.             $form->add('oldPassword'PasswordType::class, array(
  378.                 'mapped' => false,
  379.                 'label' => 'Old Password'
  380.             ));
  381.             $msg_email $translator->trans('email.password_changed');
  382.             $msg_flash $translator->trans('messages.account.password_changed');
  383.         } else {
  384.             $msg_email $translator->trans('email.password_set');
  385.             $msg_flash $translator->trans('messages.account.password_set');
  386.         }
  387.         $form->handleRequest($request);
  388.         if ($form->isSubmitted() && !$form->isValid()) {
  389.             foreach ($form->getErrors(true) as $error) {
  390.                 $this->addFlash(
  391.                     'danger'$error->getMessage()
  392.                 );
  393.             }
  394.         }
  395.         if ($form->isSubmitted() && $form->isValid()) {
  396.             if($passwordSet && !$passwordHasher->isPasswordValid($user,$form->get('oldPassword')->getData())){
  397.                  $this->addFlash(
  398.                     'danger''Old password didn\'t match!'
  399.                 );
  400.                 return $this->redirect($request->getUri());
  401.             } 
  402.             $plainpassword $form['plainPassword']->getData();
  403.             $password $passwordHasher->hashPassword($user$plainpassword);
  404.             $user->setPassword($password);
  405.            
  406.             $entityManager $this->getDoctrine()->getManager();
  407.             $entityManager->persist($user);
  408.             $entityManager->flush();
  409.             $log->save($user, [
  410.                 'owner' => $user,
  411.                 'message' => 'log.password.update'
  412.                 'old_data' => null
  413.                 'new_data' => null
  414.             ]);
  415.             $mailgunService->sendEmail($msg_email,
  416.                 [$user->getEmail()],
  417.                 'email/user-notification/password-changed.html.twig',
  418.                 ['user' => $user], false
  419.             );
  420.             $this->addFlash('success'$msg_flash);
  421.             return $this->redirect($request->getUri());
  422.         }
  423.         return $this->render(
  424.             'private/settings/account.html.twig',[
  425.                 'form' => $form->createView(),
  426.                 'passwordSet' => $passwordSet
  427.             ]
  428.         );
  429.     }
  430. }