<?php
namespace AppBundle\Controller\Customer;
use AppBundle\Email\ResetConfirmMail;
use AppBundle\Email\ResetMail;
use AppBundle\Form\Customer\ResetConfirmType;
use AppBundle\Form\Customer\ResetType;
use AppBundle\Repository\CustomerRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Annotation\Route;
class PasswordResetController extends AbstractController
{
public function __construct(
private string $passwordResetTokenTimespan,
private EntityManagerInterface $entityManager,
private CustomerRepository $customerRepository
) {
}
#[Route(path: '/password/reset', name: 'reset')]
public function editAction(Request $request, ResetMail $resetMail)
{
$form = $this->createForm(ResetType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$customer = $this->customerRepository->findOneBy(['email' => $form->get('email')->getData()]);
if ($customer) {
// reset token if invalid
if (
null != $customer->getPasswordResetTokenValidDate() &&
(new \DateTime(date('Y-m-d H:i:s')))->format('Y-m-d H:i:s') > $customer->getPasswordResetTokenValidDate()->format('Y-m-d H:i:s')) {
$customer->setPasswordResetToken(null);
$customer->setPasswordResetTokenValidDate(null);
}
// send reset mail if no valid token is set
if (
null == $customer->getPasswordResetToken() &&
null == $customer->getPasswordResetTokenValidDate()
) {
// token is only 30 minutes valid
$customer->setPasswordResetToken(bin2hex(random_bytes(20)));
$customer->setPasswordResetTokenValidDate(
(new \DateTime(date('Y-m-d H:i:s')))
->add(\DateInterval::createFromDateString('+'.$this->passwordResetTokenTimespan.' minutes'))
);
// dont update the timestamps
// these changes are only technical and not explicitlly done by the user
$customer->disableUpdateTimestamps();
// save user
$this->entityManager->persist($customer);
$this->entityManager->flush();
// send reset mail
$resetMail
->setTo([$customer->getEmail() => $customer->getEmail()])
->addMessage(
'Gericke Buchungsassistent - Passwort ändern / zurücksetzen',
['customer' => $customer]
)
->send();
}
}
// show the success page, always
// we don't want the customer to know which email addresses exist at this point
$this->addFlash('info', 'security.password.reset_send');
return new RedirectResponse($this->generateUrl('login'));
}
return $this->render('Customer/reset.html.twig', [
'form' => $form->createView(),
]);
}
#[Route(path: '/password/reset/confirm', name: 'reset.confirm')]
public function saveAction(
Request $request,
ResetConfirmMail $resetConfirmMail,
UserPasswordHasherInterface $userPasswordEncoder
) {
$customer = null;
if (
$this->isGranted('IS_AUTHENTICATED_FULLY') ||
$this->isGranted('ROLE_USER')
) {
$customer = $this->getUser();
} else {
// if a customer submits a valid token -> use this user
if ($request->query->has('token')) {
$customer = $this->customerRepository->findOneBy(['passwordResetToken' => $request->query->get('token')]);
if ($customer) {
if (
null != $customer->getPasswordResetTokenValidDate() &&
(new \DateTime(date('Y-m-d H:i:s')))->format('Y-m-d H:i:s') > $customer->getPasswordResetTokenValidDate()->format('Y-m-d H:i:s')
) {
$customer->setPasswordResetToken(null);
$customer->setPasswordResetTokenValidDate(null);
$this->entityManager->persist($customer);
$this->entityManager->flush();
$customer = null;
}
} else {
$customer = null;
}
}
}
// customer could be found
if ($customer) {
$form = $this->createForm(ResetConfirmType::class, $customer);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// change password
$password = $userPasswordEncoder
->hashPassword(
$customer,
$form->get('plainPassword')->getData()
);
$customer->setPassword($password);
// reset password_reset
$customer->setPasswordResetToken(null);
$customer->setPasswordResetTokenValidDate(null);
// save customer
$this->entityManager->persist($customer);
$this->entityManager->flush();
// send confirm mail
$resetConfirmMail
->setTo([$customer->getEmail() => $customer->getEmail()])
->addMessage(
'Gericke Buchungsassistenten - Passwort erfolgreich geändert',
['customer' => $customer]
)
->send();
$this->addFlash('success', 'security.password.reset_success');
if (
$this->isGranted('IS_AUTHENTICATED_FULLY') ||
$this->isGranted('ROLE_USER')
) {
return new RedirectResponse($this->generateUrl('dashboard'));
}
return new RedirectResponse($this->generateUrl('login'));
}
return $this->render('Customer/resetConfirm.html.twig', [
'form' => $form->createView(),
]);
}
// show error page
$this->addFlash('error', 'Es ist ein Fehler aufgetreten.');
return new RedirectResponse($this->generateUrl('dashboard'));
}
}