src/Controller/FrontSecurityController.php line 60

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use Symfony\Component\HttpFoundation\RedirectResponse;
  4. use LogicException;
  5. use App\Entity\Usuario;
  6. use App\Form\CambiarPasswordType;
  7. use App\Form\FrontRegistroType;
  8. use App\Service\Mails;
  9. use DateTime;
  10. use Doctrine\ORM\EntityManagerInterface;
  11. use Exception;
  12. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  13. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  14. use Symfony\Component\Form\Extension\Core\Type\TextType;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Symfony\Component\HttpFoundation\Response;
  17. use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
  18. use Symfony\Component\Routing\Annotation\Route;
  19. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  20. use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
  21. use Symfony\Component\Validator\Constraints\Length;
  22. use Symfony\Component\Validator\Constraints\NotBlank;
  23. use Symfony\Contracts\Translation\TranslatorInterface;
  24. class FrontSecurityController extends AbstractController
  25. {
  26. private $uploadsPath;
  27. public function __construct(
  28. private readonly EntityManagerInterface $em,
  29. private readonly TranslatorInterface $translator,
  30. private readonly Mails $mails,
  31. private readonly UserPasswordHasherInterface $encoder,
  32. private readonly ParameterBagInterface $params)
  33. {
  34. $this->uploadsPath = $this->params->get('uploadsPath').'/usuarios';
  35. }
  36. #[Route(path: '/login', name: 'front_app_login')]
  37. public function login(AuthenticationUtils $authenticationUtils): RedirectResponse|Response
  38. {
  39. if ($this->isGranted('IS_AUTHENTICATED_FULLY')) {
  40. return $this->redirectToRoute('front_inicio');
  41. }
  42. // get the login error if there is one
  43. $error = $authenticationUtils->getLastAuthenticationError();
  44. // last username entered by the user
  45. $lastUsername = $authenticationUtils->getLastUsername();
  46. return $this->render('front-security/login.html.twig', [
  47. 'last_username' => $lastUsername,
  48. 'error' => $error
  49. ]);
  50. }
  51. #[Route(path: '/registro', name: 'front_registro', options: ['sitemap' => true])]
  52. public function registro(Request $request): Response
  53. {
  54. $confirmarRegistro = $this->getParameter('confirmarRegistro');
  55. $msgError = $this->translator->trans('notificaciones.operacion.error', [], 'app');
  56. $usuario = new Usuario();
  57. $form = $this->createForm(FrontRegistroType::class, $usuario);
  58. $form->handleRequest($request);
  59. if ($form->isSubmitted() && $form->isValid()) {
  60. try {
  61. //Codificación de la contraseña
  62. $passForm = $form->get('plainPassword')->getData();
  63. if ($passForm) {
  64. $pass = $this->encoder->hashPassword($usuario, $passForm);
  65. $usuario->setPassword($pass);
  66. }
  67. $usuario->setActivo(!$confirmarRegistro);
  68. $this->em->persist($usuario);
  69. $this->em->flush();
  70. // $emailsAdmins = $this->em->getRepository(Usuario::class)->obtenerEmailsAdmins();
  71. // if (count($emailsAdmins) > 0) {
  72. // $this->mails->sendNotification(
  73. // "Nuevo proveedor registrado - {$proveedor->getNombreFiscal()}",
  74. // "<p>Se acaba de registrar un nuevo proveedor.</p>
  75. // <br>
  76. // <p>Estos son los detalles:</p>
  77. // <p><strong>Proveedor:</strong> {$proveedor->getNombreFiscal()}</p>
  78. // <p><strong>Email:</strong> {$proveedor->getEmail()}</p>
  79. // <p><strong>Persona contacto:</strong> {$proveedor->getPersonaContacto()}</p>
  80. // <p><strong>Teléfono:</strong> {$proveedor->getTelefonoPersonaContacto()}</p>",
  81. // $emailsAdmins,
  82. // null,
  83. // true
  84. // );
  85. // }
  86. if ($confirmarRegistro) {
  87. $usuario->setTokenConfirmacion(sha1(uniqid(mt_rand(), true)));
  88. $urlConfirmacionRegistro = $this->generateUrl('front_confirmar_registro', ['tokenConfirmacion' => $usuario->getTokenConfirmacion()], UrlGeneratorInterface::ABSOLUTE_URL);
  89. $this->mails->sendNotification(
  90. 'Confirmación de su registro',
  91. "<p>Hola ".$usuario->getUsuario().": </p>
  92. <p>Para acceder al sistema es necesario confirmar su registro. Para confirmarlo acceda <u><a class='btn btn-sm btn-primary' href='".$urlConfirmacionRegistro."'>aquí</a></u>.</p>",
  93. $usuario->getEmail(),
  94. null,
  95. true
  96. );
  97. $this->em->flush();
  98. }
  99. return $this->render('front-security/registro-finalizado.html.twig');
  100. } catch (Exception $e) {
  101. $this->addFlash('error', $msgError);
  102. }
  103. }
  104. return $this->render('front-security/registro.html.twig', [
  105. 'usuario' => $usuario,
  106. 'form' => $form->createView(),
  107. 'error' => $msgError
  108. ]);
  109. }
  110. #[Route(path: '/cambiar-contrasena', name: 'front_cambiar_contrasena')]
  111. public function cambiarContrasena(Request $request): Response
  112. {
  113. $msgError = $this->translator->trans('notificaciones.operacion.error', [], 'app');
  114. $form = $this->createFormBuilder()
  115. ->add('usuarioEmail', TextType::class, [
  116. 'label' => false,
  117. 'attr' => [
  118. 'class' => 'manual-placeholder',
  119. 'autocomplete' => 'Off',
  120. 'placeholder' => 'Introduzca nombre de usuario o email'
  121. ],
  122. 'constraints' => [
  123. new NotBlank(),
  124. new Length([
  125. 'max' => 100
  126. ])
  127. ]
  128. ])
  129. ->getForm();
  130. $form->handleRequest($request);
  131. if ($form->isSubmitted() && $form->isValid()) {
  132. try {
  133. $usuarioEmailForm = $form->get('usuarioEmail')->getData();
  134. // Buscamos el usuario introducido y validamos que exista y esté activo
  135. $usuario = $this->em->getRepository(Usuario::class)
  136. ->createQueryBuilder('u')
  137. ->andWhere('u.activo = true AND u.borrado = false AND (u.usuario = :u OR u.email = :u)')
  138. ->setParameters([
  139. ':u' => $usuarioEmailForm
  140. ])
  141. ->setMaxResults(1)
  142. ->getQuery()
  143. ->getResult();
  144. $usuario = count($usuario) > 0 ? $usuario[0] : null;
  145. if(!$usuario){
  146. $msgError = 'El nombre de usuario o email indicado no existe.';
  147. throw new Exception();
  148. }
  149. if(!$usuario->getEmail()){
  150. $msgError = 'No ha sido posible restablecer la contraseña ya que el usuario no tiene un email asociado. Contacte con un responsable.';
  151. throw new Exception();
  152. }
  153. if ($usuario->getFechaSolicitudPassword() !== null) {
  154. $now = new DateTime();
  155. $fechaSolicitudPassword = $usuario->getFechaSolicitudPassword();
  156. $minutos = abs($now->getTimestamp() - $fechaSolicitudPassword->getTimestamp()) / 60 ;
  157. // Si no han pasado dos horas entre solicitud y solicitud, no hacemos nada
  158. if ($minutos < 120) {
  159. $msgError = 'Debe esperar dos horas para poder volver a solicitar un cambio de contraseña.';
  160. throw new Exception();
  161. }
  162. }
  163. $usuario
  164. ->setFechaSolicitudPassword(new DateTime())
  165. ->setTokenConfirmacion(sha1(uniqid(mt_rand(), true)));
  166. $urlCambiarPassword = $this->generateUrl('front_confirmar_cambio_contrasena', ['tokenConfirmacion' => $usuario->getTokenConfirmacion()], UrlGeneratorInterface::ABSOLUTE_URL);
  167. $this->mails->sendNotification(
  168. 'Solicitud de nueva contraseña',
  169. "<p>Hola ".$usuario->getUsername().": </p>
  170. <p>Para restablecer tu contraseña - por favor pincha <u><a class='btn btn-sm btn-primary' href='".$urlCambiarPassword."'>aquí</a></u>.</p>",
  171. $usuario->getEmail(),
  172. null,
  173. true
  174. );
  175. $this->em->flush();
  176. return $this->render('front-security/comprobar-email-cambiar-contrasena.html.twig');
  177. } catch (Exception) {
  178. $this->addFlash('error', $msgError);
  179. }
  180. }
  181. return $this->render('front-security/cambiar-contrasena.html.twig', [
  182. 'form' => $form->createView(),
  183. 'error' => $msgError
  184. ]);
  185. }
  186. #[Route(path: '/confirmar-cambio-contrasena/{tokenConfirmacion}', name: 'front_confirmar_cambio_contrasena')]
  187. public function confirmarCambioContrasena(Request $request, Usuario $usuario = null): RedirectResponse|Response
  188. {
  189. if (!$usuario instanceof Usuario) {
  190. return $this->redirectToRoute('front_app_login');
  191. }
  192. if ($usuario->getFechaSolicitudPassword() < (new DateTime())->modify('-1 days')) {
  193. $this->addFlash('error', 'El enlace a caducado. Debe solicitar nuevamente la renovación de contraseña.');
  194. return $this->redirectToRoute('front_app_login');
  195. }
  196. $this->translator->trans('notificaciones.operacion.ok', [], 'app');
  197. $msgError = $this->translator->trans('notificaciones.operacion.error', [], 'app');
  198. $form = $this->createForm(CambiarPasswordType::class, $usuario);
  199. $form->handleRequest($request);
  200. if ($form->isSubmitted() && $form->isValid()) {
  201. try {
  202. //Codificación de la contraseña
  203. $passForm = $form->get('password')->getData();
  204. if ($passForm) {
  205. $pass = $this->encoder->hashPassword($usuario, $passForm);
  206. $usuario
  207. ->setPassword($pass)
  208. ->setTokenConfirmacion(null)
  209. ->setFechaSolicitudPassword(null);
  210. }
  211. $this->em->flush();
  212. return $this->render('front-security/contrasena-cambiada.html.twig');
  213. } catch (Exception) {
  214. $this->addFlash('error', $msgError);
  215. }
  216. }
  217. return $this->render('front-security/confirmar-cambio-contrasena.html.twig', [
  218. 'form' => $form->createView(),
  219. 'error' => $msgError
  220. ]);
  221. }
  222. #[Route(path: '/confirmar-registro/{tokenConfirmacion}', name: 'front_confirmar_registro')]
  223. public function confirmarRegistro(Usuario $usuario = null): RedirectResponse|Response
  224. {
  225. if (!$usuario instanceof Usuario) {
  226. return $this->redirectToRoute('front_app_login');
  227. }
  228. $usuario
  229. ->setActivo(true)
  230. ->setTokenConfirmacion(null);
  231. $this->em->flush();
  232. return $this->render('front-security/registro-confirmado.html.twig');
  233. }
  234. #[Route(path: '/logout', name: 'front_app_logout')]
  235. public function logout(): never
  236. {
  237. throw new LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
  238. }
  239. }