<?php
namespace App\Controller;
use DateTime;
use Sonata\UserBundle\Form\Type\ResetPasswordRequestFormType;
use Sonata\UserBundle\Form\Type\ResettingFormType;
use Sonata\UserBundle\Mailer\MailerInterface;
use Sonata\UserBundle\Model\UserManagerInterface;
use Sonata\UserBundle\Util\TokenGeneratorInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
class ResetController extends AbstractController
{
private UserManagerInterface $userManager;
private MailerInterface $mailer;
private int $retryTtl;
private int $tokenTtl;
public function __construct(
UserManagerInterface $userManager,
MailerInterface $mailer,
int $retryTtl,
int $tokenTtl
) {
$this->userManager = $userManager;
$this->mailer = $mailer;
$this->retryTtl = $retryTtl;
$this->tokenTtl = $tokenTtl;
}
/**
* @Route("/resetting/request", name="frontend_user_resetting_request")
*/
public function request(Request $request, TokenGeneratorInterface $tokenGenerator): Response
{
if ($this->isGranted('IS_AUTHENTICATED_FULLY')) {
return new RedirectResponse($this->generateUrl('index'));
}
$form = $this->createForm(ResetPasswordRequestFormType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$username = $form->get('username')->getData();
$user = $this->userManager->findUserByUsernameOrEmail($username);
if (null !== $user && $user->isEnabled() && !$user->isPasswordRequestNonExpired($this->retryTtl) && $user->isAccountNonLocked()) {
if (null === $user->getConfirmationToken()) {
$user->setConfirmationToken($tokenGenerator->generateToken());
}
$this->mailer->sendResettingEmailMessage($user);
$user->setPasswordRequestedAt(new DateTime());
$this->userManager->save($user);
}
return new RedirectResponse($this->generateUrl('frontend_user_resetting_check_email', [
'username' => $username,
]));
}
return $this->render('security/resetting/request.html.twig', [
'form' => $form->createView(),
]);
}
/**
* @Route("/resetting/check_email", name="frontend_user_resetting_check_email")
*
*/
public function checkEmail(Request $request): Response
{
$username = $request->query->get('username');
if (null === $username) {
// the user does not come from the sendEmail action
return new RedirectResponse($this->generateUrl('frontend_user_resetting_request'));
}
return $this->render('security/resetting/checkEmail.html.twig', [
'tokenLifetime' => ceil($this->tokenTtl / 3600),
'error' => null
]);
}
/**
* @Route("/resetting/reset/{token}", name="frontend_user_resetting_reset")
*/
public function reset(Request $request, string $token, TranslatorInterface $translator): Response
{
if ($this->isGranted('IS_AUTHENTICATED_FULLY')) {
return new RedirectResponse($this->generateUrl('index'));
}
$user = $this->userManager->findUserByConfirmationToken($token);
if (null === $user) {
throw new NotFoundHttpException(sprintf('The user with "confirmation token" does not exist for value "%s"', $token));
}
if (!$user->isPasswordRequestNonExpired($this->tokenTtl)) {
return new RedirectResponse($this->generateUrl('frontend_user_resetting_request'));
}
$form = $this->createForm(ResettingFormType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$user->setConfirmationToken(null);
$user->setPasswordRequestedAt(null);
$user->setEnabled(true);
$this->addFlash('success',
$translator->trans('resetting.flash.success', [], 'SonataUserBundle')
);
$response = new RedirectResponse($this->generateUrl('index'));
// Doctrine Event isn't running?
$this->userManager->updatePassword($user);
$this->userManager->save($user);
return $response;
}
return $this->render('security/resetting/reset.html.twig', [
'token' => $token,
'form' => $form->createView(),
'error' => null
]);
}
}