src/Controller/Auth/App/AccountManagementController.php line 143

Open in your IDE?
  1. <?php
  2. namespace App\Controller\Auth\App;
  3. use App\Entity\App\User;
  4. use App\Event\Auth\UserCreatedEvent;
  5. use App\Event\Auth\UserResetEvent;
  6. use App\Form\App\Security\RegistrationFormType;
  7. use App\Service\Auth\UserResetNotifier;
  8. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  9. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  10. use Symfony\Component\Form\Extension\Core\Type\EmailType;
  11. use Symfony\Component\Form\Extension\Core\Type\PasswordType;
  12. use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
  13. use Symfony\Component\Form\FormError;
  14. use Symfony\Component\Form\FormInterface;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Symfony\Component\HttpFoundation\Response;
  17. use Symfony\Component\Routing\Annotation\Route;
  18. use Symfony\Component\Validator\Constraints\NotBlank;
  19. use Symfony\Component\Validator\Constraints\Email;
  20. use Symfony\Contracts\Translation\TranslatorInterface;
  21. /**
  22. * Class RegistrationController
  23. *
  24. * @package App\Controller
  25. *
  26. * @Route("/")
  27. */
  28. class AccountManagementController extends AbstractController
  29. {
  30. /**
  31. * @Route("/register", name="register")
  32. * @Route("/{_locale}/register", name="register", requirements={"_locale": "\w{2}"}, methods={"GET", "POST"})
  33. */
  34. public function register(
  35. Request $request,
  36. EventDispatcherInterface $dispatcher,
  37. UserResetNotifier $notifier
  38. ): Response
  39. {
  40. if (!$request->attributes->get('_locale')) {
  41. return $this->redirectToRoute('register', ['_locale' => $request->getDefaultLocale()]);
  42. }
  43. $user = new User();
  44. $form = $this->createForm(RegistrationFormType::class, $user)->handleRequest($request);
  45. if (!$form->isSubmitted() || !$form->isValid()) {
  46. return $this->render('Auth/Registration/register.html.twig', [
  47. 'form' => $form->createView(),
  48. ]);
  49. }
  50. $dispatcher->dispatch(new UserCreatedEvent($user, $notifier));
  51. $entityManager = $this->getDoctrine()->getManager();
  52. $entityManager->persist($user);
  53. $entityManager->flush();
  54. return $this->redirectToRoute('login');
  55. }
  56. /**
  57. * @Route("/{_locale}/verify_email/{token}", name="verify_email", requirements={"_locale": "\w{2}"}, methods={"GET"})
  58. */
  59. public function verifyEmail(string $token, TranslatorInterface $translator): Response
  60. {
  61. $user = $this->getDoctrine()->getRepository(User::class)->findByToken($token);
  62. if (!$user) {
  63. $this->addFlash('error', $translator->trans(
  64. 'registration.invalid_token',
  65. [],
  66. 'Auth'
  67. ));
  68. return $this->redirectToRoute('login');
  69. }
  70. $user->setEnabled(true)->setConfirmationToken();
  71. $em = $this->getDoctrine()->getManager();
  72. $em->persist($user);
  73. $em->flush();
  74. $this->addFlash('success', $translator->trans(
  75. 'registration.confirmed',
  76. ['%username%' => $user->getFullName()],
  77. 'Auth'
  78. ));
  79. return $this->redirectToRoute('login');
  80. }
  81. /**
  82. *
  83. * @Route("/reset_password", name="reset_password")
  84. * @Route("/{_locale}/reset_password", name="reset_password", requirements={"_locale": "\w{2}"}, methods={"GET", "POST"})
  85. */
  86. public function resetPassword(
  87. Request $request,
  88. EventDispatcherInterface $dispatcher,
  89. TranslatorInterface $translator,
  90. UserResetNotifier $notifier
  91. ): Response {
  92. if (!$request->attributes->get('_locale')) {
  93. return $this->redirectToRoute('reset_password', ['_locale' => $request->getDefaultLocale()]);
  94. }
  95. $form = $this->createResetPasswordForm($request)->handleRequest($request);
  96. $tokenLifetime = $this->getParameter('tokenLifetime');
  97. if ($form->isSubmitted() && $form->isValid()) {
  98. $user = $this->getDoctrine()->getRepository(User::class)->findByEmail($form->getData()['email']);
  99. if (!$user instanceof User){
  100. $form->addError(new FormError($translator->trans('resetting.reset.error', [], 'Auth')));
  101. } elseif ($user->isPasswordRequestNonExpired($tokenLifetime * 3600)) {
  102. $form->addError(
  103. new FormError(
  104. $translator->trans(
  105. 'resetting.reset.not_expired_error',
  106. ['%tokenLifetime%' => $tokenLifetime],
  107. 'Auth'
  108. )
  109. )
  110. );
  111. } else {
  112. $dispatcher->dispatch(new UserResetEvent($user, $notifier));
  113. $em = $this->getDoctrine()->getManager();
  114. $em->persist($user);
  115. $em->flush();
  116. }
  117. }
  118. return $this->render(
  119. 'Auth/Resetting/reset.html.twig',
  120. [
  121. 'tokenLifetime' => $tokenLifetime,
  122. 'user' => $user ?? null,
  123. 'form' => $form->createView(),
  124. ]
  125. );
  126. }
  127. /**
  128. * Create Reset Password Form
  129. *
  130. * @param Request $request
  131. *
  132. * @return FormInterface
  133. */
  134. protected function createResetPasswordForm(Request $request): FormInterface
  135. {
  136. return $this->createFormBuilder(
  137. ['email' => ''],
  138. [
  139. 'method' => 'POST',
  140. 'action' => $this->generateUrl('reset_password', ['_locale' => $request->getLocale()])
  141. ]
  142. )
  143. ->add('email', EmailType::class, [
  144. 'constraints' => [
  145. new NotBlank(),
  146. new Email()
  147. ]
  148. ])
  149. ->getForm();
  150. }
  151. /**
  152. * @Route("/reset_password/{token}", name="reset_password_submit")
  153. * @Route("/{_locale}/reset_password/{token}", name="reset_password_submit", requirements={"_locale": "\w{2}"}, methods={"GET", "POST"})
  154. */
  155. public function newPassword(
  156. Request $request,
  157. TranslatorInterface $translator,
  158. string $token
  159. ): Response {
  160. if (!$request->attributes->get('_locale')) {
  161. return $this->redirectToRoute('reset_password', ['_locale' => $request->getDefaultLocale()]);
  162. }
  163. $form = $this->createNewPasswordForm($request)->handleRequest($request);
  164. $tokenLifetime = $this->getParameter('tokenLifetime');
  165. if ($form->isSubmitted() && $form->isValid()) {
  166. $user = $this->getDoctrine()->getRepository(User::class)->findByToken($token);
  167. if (!$user instanceof User) {
  168. $form->addError(new FormError($translator->trans('resetting.reset.error', [], 'Auth')));
  169. } elseif (!$user->isPasswordRequestNonExpired($tokenLifetime * 3600)) {
  170. $form->addError(new FormError($translator->trans('resetting.reset.expired_error', [], 'Auth')));
  171. } else {
  172. $user->setConfirmationToken()->setPasswordRequestedAt();
  173. $em = $this->getDoctrine()->getManager();
  174. $em->persist($user);
  175. $em->flush();
  176. $this->addFlash('success', $translator->trans('resetting.flash.success', [], 'Auth'));
  177. return $this->redirectToRoute('login', ['_locale' => $request->getLocale()]);
  178. }
  179. }
  180. return new Response(
  181. $this->renderView(
  182. 'Auth/Resetting/reset.html.twig',
  183. [
  184. 'tokenLifetime' => $tokenLifetime,
  185. 'form' => $form->createView(),
  186. ]
  187. ),
  188. $form->getErrors()->count() < 1 ? Response::HTTP_OK : Response::HTTP_BAD_REQUEST
  189. );
  190. }
  191. /**
  192. * Create Reset Password Form
  193. *
  194. * @param Request $request
  195. *
  196. * @return FormInterface
  197. */
  198. protected function createNewPasswordForm(Request $request): FormInterface
  199. {
  200. return $this->createFormBuilder(
  201. ['password' => ''],
  202. [
  203. 'method' => 'POST',
  204. 'action' => $this->generateUrl(
  205. 'reset_password_submit',
  206. [
  207. '_locale' => $request->getLocale(),
  208. 'token' => $request->get('token'),
  209. ]
  210. )
  211. ]
  212. )
  213. ->add('password', RepeatedType::class, [
  214. 'type' => PasswordType::class,
  215. 'constraints' => [
  216. new NotBlank(),
  217. ]
  218. ])
  219. ->getForm();
  220. }
  221. }