src/Controller/PasswordChangeController.php line 54

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Form\EventListener\ReCaptchaValidatorListener;
  4. use App\Service\PasswordChecker;
  5. use App\Service\UserManager;
  6. use Psr\Log\LoggerInterface;
  7. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  8. use Symfony\Component\Form\Extension\Core\Type\EmailType;
  9. use Symfony\Component\Form\Extension\Core\Type\FormType;
  10. use Symfony\Component\Form\Extension\Core\Type\PasswordType;
  11. use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
  12. use Symfony\Component\Form\Extension\Core\Type\SubmitType;
  13. use Symfony\Component\Form\FormError;
  14. use Symfony\Component\HttpFoundation\JsonResponse;
  15. use Symfony\Component\HttpFoundation\Request;
  16. use Symfony\Component\Routing\Annotation\Route;
  17. use Symfony\Component\HttpFoundation\Response;
  18. use Symfony\Component\Validator\Constraints\Email;
  19. use Symfony\Component\Validator\Constraints\Length;
  20. use Symfony\Component\Validator\Constraints\NotBlank;
  21. use Symfony\Contracts\Translation\TranslatorInterface;
  22. /**
  23.  * @Route("/cambiar", name="password_change_", 
  24.  *  requirements={"_locale":"%app.supported_locales%"},
  25.  *  defaults={"_locale" = "es", "_title"="Pasarela cambia clave de la Universidad de Murcia"})
  26.  */
  27. class PasswordChangeController extends AbstractController
  28. {
  29.     const PANEL_STEPS 4;
  30.     const PASSWORD_MIN_LEN 12;
  31.     const DEFAULT_ERRORS = [
  32.         500 => 'error.default.500'// Se ha producido un error inesperado, vuelva a intentarlo más tarde.
  33.     ];
  34.     /**
  35.      * @Route("/validatepasswd/{_locale}", name="check", requirements={"_locale"="[a-zA-Z]+"}, methods="POST")
  36.      */
  37.     public function checkPassword(Request $requestPasswordChecker $passwordCheckerUserManager $userManager) : JsonResponse
  38.     {
  39.         // REVIEW no se puede hacer autowire del UserManager en PasswordChecker, por que el primero usa al primero en el constructor para log fortaleza
  40.         $passwordChecker->setUserManager($userManager);
  41.         return new JsonResponse($passwordChecker->validate(
  42.             $request->get('password'''),
  43.             $request->get('username')
  44.         ));
  45.     }
  46.     /**
  47.      * @Route("/{_locale}", name="index", requirements={"_locale"="[a-zA-Z]+"})
  48.      */
  49.     public function index(Request $requestReCaptchaValidatorListener $recaptchaValidatorUserManager $userManagerTranslatorInterface $translatorLoggerInterface $logger): Response
  50.     {
  51.         // Si se pasa GET['pose'] se ocultará el iframe y se inyectará el correo
  52.         // Si se pasa GET['email'] se inyectará el correo
  53.         $pose_email $request->get('pose'null);
  54.         $myaccount_email $request->get('micuenta'null);
  55.         $iframe false;
  56.         $email null;
  57.         if (filter_var($pose_emailFILTER_VALIDATE_EMAIL) !== false) {
  58.             $iframe true;
  59.             $email $pose_email;
  60.         }
  61.         elseif (filter_var($myaccount_emailFILTER_VALIDATE_EMAIL) !== false) {
  62.             $email $myaccount_email;
  63.         }
  64.         $passwdForm $this->createPasswdForm($recaptchaValidator$email);
  65.         $passwdForm->handleRequest($request);
  66.         if ($passwdForm->isSubmitted() && $passwdForm->isValid()) {
  67.             $data $passwdForm->getData();
  68.             $logger->info('[cambiar] solicitud cambio clave para '.$data['username']);
  69.             try {
  70.                 // Validar usuario haciendo login y comprobando que la cuenta no esté bloqueada
  71.                 $userManager->infoAccount($data['username'], true);
  72.                 $userManager->login($data['username'], $data['password'], UserManager::ALLOW_PPOLICY_EXPIRED);
  73.                 $userManager->changePassword($data['username'], $data['newpassword']);
  74.                 $logger->info('[cambiar] cambio de clave realizado para '.$data['username']);
  75.                 return $this->render('success.html.twig', [ 
  76.                     'iframe' => $iframe,
  77.                     'show_chpwd_help' => true
  78.                 ]);
  79.             } catch (\Throwable $th) {
  80.                 // Nueva clave no válida
  81.                 if (400 == $th->getCode() || 406 == $th->getCode()) {
  82.                     $passwdForm->get('newpassword')['first']->addError(new FormError($th->getMessage()));
  83.                 // Usuario no vaĺido
  84.                 } else if (404 == $th->getCode()) {
  85.                     if ($iframe)
  86.                         $passwdForm->get('password')->addError(new FormError($th->getMessage()));
  87.                     else
  88.                         $passwdForm->get('username')->addError(new FormError($th->getMessage()));
  89.                 // Enviar a pantalla de error
  90.                 } else
  91.                     return $this->render('error.html.twig', [
  92.                         'error_code' => $th->getCode(),
  93.                         'error_body' => $th->getMessage(),
  94.                         'iframe' => $iframe
  95.                     ]);
  96.             }
  97.         }
  98.         
  99.         // Establecer token del formulario y renderizar
  100.         return $this->renderForm('password_change.html.twig', [
  101.             'passwd_form' => $passwdForm,
  102.             'iframe' => $iframe,
  103.         ]);
  104.     }
  105.     /**
  106.      * Crea un formulario de restauración de clave.
  107.      */
  108.     private function createPasswdForm(ReCaptchaValidatorListener $recaptchaValidator, ?string $username ''string $name 'passwdForm'string $formid 'changePassword') {
  109.         //return $this->get('form.factory')->createNamedBuilder($name, FormType::class, [ 'formid' => $formid ])
  110.         return $this->createFormBuilder()->getFormFactory()->createNamedBuilder($nameFormType::class, [ 'formid' => $formid ])
  111.             ->add('username'EmailType::class, [
  112.                 'required' => true,
  113.                 'constraints' => [ 
  114.                     new NotBlank(),
  115.                     new Email() 
  116.                 ],
  117.                 'label' => 'Correo electrónico',
  118.                 'attr' => [ 
  119.                     'autofocus' => empty($username) ? 'autofocus' false,
  120.                     'readonly' => ! empty($username),
  121.                     'value' => $username
  122.                 ],
  123.                 'row_attr' => [ 'class' => 'form-floating'],
  124.             ])->add('password'PasswordType::class, [
  125.                 'required' => true,
  126.                 'constraints' => [ new NotBlank() ],
  127.                 'label' => 'Clave actual',
  128.                 'attr' => [
  129.                     'autofocus' => empty($username) ? false 'autofocus',
  130.                 ],
  131.                 'row_attr' => [ 'class' => 'form-floating form-caps-lock'],
  132.             ])->add('newpassword'RepeatedType::class, [
  133.                 'required' => true,
  134.                 'type' => PasswordType::class,
  135.                 'constraints' => [
  136.                     new NotBlank(),
  137.                     new Length([ 'min' => self::PASSWORD_MIN_LEN ]), 
  138.                 ],
  139.                 'options' => [ 
  140.                     'attr' => [ 'minglength' => 12 ],
  141.                     'row_attr' => [ 'class' => 'form-floating form-caps-lock'],
  142.                 ],
  143.                 'first_options' => [ 'label' => 'Nueva clave' ],
  144.                 'second_options' => [ 'label' => 'Repita la clave' ],
  145.                 'invalid_message' => 'Las claves deben coincidir.',
  146.                 'error_bubbling'  => false,
  147.             ])->add('next'SubmitType::class, [
  148.                 'label' => 'Cambiar clave',
  149.             ])->addEventSubscriber($recaptchaValidator)
  150.             ->getForm();
  151.     }
  152. }
  153. ?>