src/Controller/UserProfileController.php line 58

  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\User;
  4. use App\Entity\UserProfile;
  5. use App\Form\UserProfileType;
  6. use App\Form\ChangePwsdFormType;
  7. use App\Message\SendEmailMessage;
  8. use App\Repository\EventRequestRepository;
  9. use App\Repository\RegistrationCertificateRepository;
  10. use App\Repository\UserRepository;
  11. use App\Controller\UtilsController;
  12. use Doctrine\ORM\EntityManagerInterface;
  13. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  14. use Symfony\Component\HttpFoundation\Request;
  15. use Symfony\Component\Routing\Annotation\Route;
  16. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  17. use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
  18. use Symfony\Component\Security\Http\Attribute\IsGranted;
  19. use Symfony\Contracts\Translation\TranslatorInterface;
  20. use Symfony\Component\Messenger\MessageBusInterface;
  21. use Symfony\Component\Form\FormInterface;
  22. #[Route('/alumno')]
  23. class UserProfileController extends AbstractController
  24. {
  25.     private function denyUnlessSelfOrAdmin(): void
  26.     {
  27.         if (!$this->getUser()) {
  28.             throw $this->createAccessDeniedException();
  29.         }
  30.         if (
  31.             !$this->isGranted('ROLE_ADMIN')
  32.             && !$this->isGranted('ROLE_SUPERUSER')
  33.             && !$this->isGranted('ROLE_ALUMNO')
  34.             && !$this->isGranted('ROLE_COURSE')
  35.         ) {
  36.             throw $this->createAccessDeniedException();
  37.         }
  38.     }
  39.    #[Route('/alta'name'alumno_alta')]
  40.     public function alta(
  41.         Request $request,
  42.         EntityManagerInterface $em,
  43.         UserPasswordHasherInterface $passwordHasher,
  44.         UtilsController $utilsController,
  45.         UserRepository $userRepository,
  46.         MessageBusInterface $bus
  47.     ) {
  48.         $user = new User();
  49.         $profile = new UserProfile();
  50.         $form $this->createForm(UserProfileType::class, $profile, [
  51.             'mode' => 'alta',
  52.             'profile_context' => 'public_signup',
  53.             'validation_groups' => static function (FormInterface $form): array {
  54.                 return ['Default''public_signup''public_internal'];
  55.             },
  56.         ]);
  57.         $form->handleRequest($request);
  58.         if ($form->isSubmitted()) {
  59.             $recaptchaResponse $request->request->get('g-recaptcha-response');
  60.             if (!$utilsController->isRecaptchaValid($recaptchaResponse)) {
  61.                 $this->addFlash('error''Verifique el captcha');
  62.                 return $this->render('public/new_student.html.twig', [
  63.                     'form' => $form->createView(),
  64.                     'recaptcha_site_key' => $_ENV['GOOGLE_RECAPTCHA_SITE_KEY'],
  65.                 ]);
  66.             }
  67.         }
  68.         if ($form->isSubmitted() && $form->isValid()) {
  69.             $dni $form->get('dni')->getData();
  70.             if ($dni && $userRepository->findOneBy(['dni' => $dni])) {
  71.                 $this->addFlash('error''Ese DNI ya se encuentra dado de alta.');
  72.                 return $this->render('public/new_student.html.twig', [
  73.                     'form' => $form->createView(),
  74.                     'recaptcha_site_key' => $_ENV['GOOGLE_RECAPTCHA_SITE_KEY'],
  75.                 ]);
  76.             }
  77.             $email $form->get('email')->getData();
  78.             if ($email && $userRepository->findOneBy(['email' => $email])) {
  79.                 $this->addFlash('error''Ese correo electrónico ya se encuentra dado de alta.');
  80.                 return $this->render('public/new_student.html.twig', [
  81.                     'form' => $form->createView(),
  82.                     'recaptcha_site_key' => $_ENV['GOOGLE_RECAPTCHA_SITE_KEY'],
  83.                 ]);
  84.             }
  85.             $user->setDni($dni);
  86.             $user->setUsername($email);
  87.             $user->setEmail($email);
  88.             $user->setNomComplet($profile->getNombre());
  89.             $user->setSurname($profile->getApellido1().' '.$profile->getApellido2());
  90.             $user->setPhone($profile->getTelefono());
  91.             $user->setRoles(['ROLE_ALUMNO']);
  92.             $user->setValid(true);
  93.             $user->setDeleted(false);
  94.             $user->setAdmin(false);
  95.             // password temporal
  96.             $plainPassword bin2hex(random_bytes(4));
  97.             $user->setPassword(
  98.                 $passwordHasher->hashPassword($user$plainPassword)
  99.             );
  100.             $profile->setUser($user);
  101.             // activación
  102.             $token bin2hex(random_bytes(32));
  103.             $user->setActivationToken($token);
  104.             $user->setActive(false);
  105.             $em->persist($user);
  106.             $em->persist($profile);
  107.             $em->flush();
  108.             $activationUrl $this->generateUrl(
  109.                 'alumno_activate_account',
  110.                 ['token' => $token],
  111.                 UrlGeneratorInterface::ABSOLUTE_URL
  112.             );
  113.             $bus->dispatch(new SendEmailMessage(
  114.                 $user->getEmail(),
  115.                 'notifications/student_account_activation.html.twig',
  116.                 'Activación de la cuenta necesaria',
  117.                 $user->getNomComplet(),
  118.                 [
  119.                     'activationUrl' => $activationUrl,
  120.                     'gender' => $profile->getSexo()]
  121.             ));
  122.             $this->addFlash('success''Revise su correo para activar la cuenta');
  123.             return $this->redirectToRoute('app_login');
  124.         }
  125.         return $this->render('public/new_student.html.twig', [
  126.             'form' => $form->createView(),
  127.             'recaptcha_site_key' => $_ENV['GOOGLE_RECAPTCHA_SITE_KEY'],
  128.         ]);
  129.     }
  130.       #[Route('/activar/{token}'name'alumno_activate_account')]
  131.         public function activate(
  132.             string $token,
  133.             Request $request,
  134.             EntityManagerInterface $em,
  135.             UserPasswordHasherInterface $hasher,
  136.             MessageBusInterface $bus
  137.         ) {
  138.         $user $em->getRepository(User::class)
  139.             ->findOneBy(['activationToken' => $token]);
  140.         if (!$user) {
  141.             throw $this->createNotFoundException();
  142.         }
  143.         $isPasswordSetupOnly $user->isActive();
  144.         if ($request->isMethod('POST')) {
  145.             if (!$this->isCsrfTokenValid('activate_account'$request->request->get('_token'))) {
  146.                 throw $this->createAccessDeniedException();
  147.             }
  148.             $password = (string) $request->request->get('password');
  149.             $repeat   = (string) $request->request->get('password_repeat');
  150.             if ($password === '' || $repeat === '') {
  151.                 $this->addFlash('error''Debe introducir ambos campos');
  152.             } elseif ($password !== $repeat) {
  153.                 $this->addFlash('error''Las contraseñas no coinciden');
  154.             } else {
  155.                 $user->setPassword(
  156.                     $hasher->hashPassword($user$password)
  157.                 );
  158.                 $user->setActivationToken(null);
  159.                 if (!$isPasswordSetupOnly) {
  160.                     $user->setActive(true);
  161.                 }
  162.                 $em->flush();
  163.                 if ($isPasswordSetupOnly) {
  164.                     $this->addFlash('success''La contraseña se ha establecido correctamente. Ya puede acceder a la plataforma con su correo electrónico y la contraseña definida.');
  165.                 } else {
  166.                     $bus->dispatch(new SendEmailMessage(
  167.                         $user->getEmail(),
  168.                         'notifications/student_account_activated.html.twig',
  169.                         'Cuenta activada',
  170.                         $user->getNomComplet(),
  171.                         [
  172.                             'loginUrl' => $this->generateUrl(
  173.                                 'app_login',
  174.                                 [],
  175.                                 UrlGeneratorInterface::ABSOLUTE_URL
  176.                             )
  177.                         ]
  178.                     ));
  179.                     $this->addFlash('success''Su cuenta ha sido activada correctamente. Ya puede acceder a la plataforma con su dirección de correo y la contraseña establecida');
  180.                 }
  181.                 return $this->redirectToRoute('app_login');
  182.             }
  183.         }
  184.         return $this->render('public/activate_account.html.twig', [
  185.             'token' => $token,
  186.             'isPasswordSetupOnly' => $isPasswordSetupOnly,
  187.         ]);
  188.     }
  189.     #[Route(path'/cambioPassword'name'alumno_change_password')]
  190.     public function changePswd(
  191.         Request $request
  192.         TranslatorInterface $translator,
  193.         EntityManagerInterface $em,
  194.         UserPasswordHasherInterface $passwordHasher)
  195.     {
  196.         $this->denyUnlessSelfOrAdmin();
  197.         $user $this->getUser();
  198.         $form $this->createForm(ChangePwsdFormType::class, $user, ['translator' => $translator]);
  199.         $form->handleRequest($request);
  200.         if ($form->isSubmitted() && $form->isValid()) {
  201.             $password $form['justpassword']->getData();
  202.             $newPassword $form['newpassword']->getData();
  203.             if ($passwordHasher->isPasswordValid($user$password)) {
  204.                 $user->setPassword($passwordHasher->hashPassword($user$newPassword));
  205.                 
  206.             } else {
  207.                 $this->addFlash('error''backend.user.new_passwod_must_be');
  208.                 return $this->render('public/profile/cambio_password_student.html.twig', ['passwordForm' => $form]);
  209.             }
  210.             $em->persist($user);
  211.             $em->flush();
  212.             $this->addFlash('success'$translator->trans('backend.user.changed_password'));
  213.             return $this->redirectToRoute('public_events');
  214.         }
  215.         return $this->render('public/profile/cambio_password_student.html.twig', ['passwordForm' => $form]);
  216.     }
  217.     #[Route('/perfil'name'alumno_perfil')]
  218.     public function editar(
  219.         Request $request,
  220.         EntityManagerInterface $em
  221.     ) {
  222.         $this->denyUnlessSelfOrAdmin();
  223.         $user $this->getUser();
  224.         $profile $user->getProfile();
  225.         if (!$profile) {
  226.             $this->addFlash('error''Perfil no encontrado');
  227.             return $this->redirectToRoute('public_events');
  228.         }
  229.         $mode $request->query->getBoolean('edit') ? 'edit' 'view';
  230.         $form $this->createForm(UserProfileType::class, $profile, [
  231.             'mode' => $mode,
  232.             'profile_context' => 'public_profile',
  233.         ]);
  234.         $form->get('dni')->setData($user->getDni());
  235.         $form->get('email')->setData($user->getEmail());
  236.         $form->handleRequest($request);
  237.         if ($mode && $form->isSubmitted() && $form->isValid()) {
  238.             $em->flush();
  239.             $this->addFlash('success''Perfil actualizado');
  240.             return $this->redirectToRoute('alumno_perfil');
  241.         }
  242.         return $this->render('public/profile/edit_profile_student.html.twig', [
  243.             'form' => $form->createView(),
  244.             'mode' => $mode,
  245.         ]);
  246.     }
  247.      #[Route('/cursos'name'alumno_cursos')]
  248.     public function cursos(
  249.         EventRequestRepository $repo,
  250.         RegistrationCertificateRepository $registrationCertificateRepository
  251.     ) {
  252.         $this->denyUnlessSelfOrAdmin();
  253.         $certificatesByEvent = [];
  254.         foreach ($registrationCertificateRepository->findActiveByUser($this->getUser()) as $certificate) {
  255.             $eventId $certificate->getEvent()?->getId();
  256.             if ($eventId === null) {
  257.                 continue;
  258.             }
  259.             $certificatesByEvent[$eventId][] = $certificate;
  260.         }
  261.         return $this->render('public/profile/course_history_student.html.twig', [
  262.             'requests' => $repo->findByUser($this->getUser()),
  263.             'certificatesByEvent' => $certificatesByEvent,
  264.         ]);
  265.     }
  266.     
  267.     #[Route('/baja'name'alumno_baja')]
  268.     public function baja(EntityManagerInterface $em)
  269.     {
  270.         $this->denyUnlessSelfOrAdmin();
  271.         /** @var \App\Entity\User $user */
  272.         $user $this->getUser();
  273.         $user->setDeleted(true);
  274.         $user->setValid(false);
  275.         $em->flush();
  276.         return $this->redirectToRoute('app_logout');
  277.     }
  278. }