<?php
namespace App\Controller;
use App\Form\PasswordNewFormType;
use App\Form\PasswordResetEmailFormType;
use App\Form\PasswordResetFormType;
use Carbon\Carbon;
use Pimcore\Model\Document;
use App\Classes\Controller\AbstractFrontController as AbstractFrontController;
use App\Repository\CustomerRepository;
use App\Repository\PasswordRepository;
use App\Service\Contract\RecaptchaValidationServiceInterface;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Symfony\Contracts\Translation\TranslatorInterface;
class PasswordController extends AbstractFrontController
{
protected $customerRepository;
protected $passwordRepository;
protected $recaptchaValidationService;
private TranslatorInterface $translator;
public function __construct(
CustomerRepository $customerRepository,
PasswordRepository $passwordRepository,
RecaptchaValidationServiceInterface $recaptchaValidationService,
TranslatorInterface $translator
)
{
$this->customerRepository = $customerRepository;
$this->passwordRepository = $passwordRepository;
$this->recaptchaValidationService = $recaptchaValidationService;
$this->translator = $translator;
}
public function passwordResetRequestAction(Request $request)
{
$user = $this->getUser();
if ($user) {
return $this->redirectToRoute('account_show_password', ['division' => $request->get('division')]);
}
$form = $this->createForm(
PasswordResetEmailFormType::class
);
$form->handleRequest($request);
$registeredSuccess = false;
if ($form->isSubmitted() && $form->isValid()) {
$data = $form->getData();
if (!$this->recaptchaValidationService->isValid($data)) {
$payload = array_merge(
$request->query->all(),
$request->request->all()
);
$this->addFlash('_oldFormData', serialize($payload));
$this->addFlash('error', 'stoelting.recaptcha-failed.error');
return $this->redirectBack($request);
}
$email = $form['_email']->getData();
$customer = $this->customerRepository->getUserByEmail($email);
if (!$customer) {
$form->get('_email')->addError(new FormError($this->translator->trans('stoelting.user.not_found')));
} else {
$token = $this->passwordRepository->generateToken();
$timestamp = Carbon::now()->addDay(1)->timestamp;
$this->customerRepository->setUserPasswordToken($customer, $token);
$link = $this->generateUrl(
'password-reset',
[
'action' => 'password-reset',
'token' => $token . '-token-' . $timestamp
],
UrlGeneratorInterface::ABSOLUTE_URL
);
$division = $request->get('division');
$link = str_replace('%division', $division, $link);
$this->passwordRepository->sendResetPasswordMail(
$customer,
[
'link' => $link
]
);
$registeredSuccess = true;
}
}
$division = $request->get('division');
return $this->render(
'@App/division/auth/password-reset-request.html.twig',
[
'form' => $form->createView(),
'document' => Document::getByPath('/' . $division),
'success' => $registeredSuccess
]
);
}
public function passwordResetAction(Request $request)
{
$division = $request->get('division');
$user = $this->getUser();
if ($user) {
return $this->redirectToRoute('account_show_password', ['division' => $request->get('division')]);
}
$form = $this->createForm(PasswordResetFormType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$translator = $this->translator;
if ($form['_password']->getData() != $form['_passwordConfirmation']->getData()) {
$error = new FormError($translator->trans('stoelting.passwords-dont-match'));
$form->get('_passwordConfirmation')->addError($error);
} else {
$tokenAndTimestamp = $request->get('token');
$tokenAndTimestampExploded = explode('-token-', $tokenAndTimestamp);
$expirationTimestamp = end($tokenAndTimestampExploded);
$token = reset($tokenAndTimestampExploded);
$user = $this->customerRepository->getUserByPasswordResetToken($token);
if ($user && Carbon::now()->timestamp < $expirationTimestamp) {
$this->customerRepository->setPassword($user, $form['_password']->getData());
$this->addFlash('success', $translator->trans('stoelting.password-reset.success'));
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->container->get('security.token_storage')->setToken($token);
$this->container->get('session')->set('_security_main', serialize($token));
return new RedirectResponse('/' . $division);
}
}
}
return $this->render(
'@App/division/auth/password-reset.html.twig',
[
'form' => $form->createView(),
'document' => Document::getByPath('/' . $division)
]
);
}
public function passwordNewAction(Request $request)
{
$division = $request->get('division');
$user = $this->getUser();
if ($user) {
return $this->redirectToRoute('account_show_password', ['division' => $request->get('division')]);
}
$form = $this->createForm(PasswordNewFormType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$translator = $this->translator;
if ($form['_password']->getData() != $form['_passwordConfirmation']->getData()) {
$error = new FormError($translator->trans('stoelting.passwords-dont-match'));
$form->get('_passwordConfirmation')->addError($error);
} else {
$tokenAndTimestamp = $request->get('token');
$tokenAndTimestampExploded = explode('-token-', $tokenAndTimestamp);
$expirationTimestamp = end($tokenAndTimestampExploded);
$token = reset($tokenAndTimestampExploded);
$user = $this->customerRepository->getUserByPasswordResetToken($token);
if ($user && Carbon::now()->timestamp < $expirationTimestamp) {
$this->customerRepository->setPassword($user, $form['_password']->getData());
$this->addFlash('success', $translator->trans('stoelting.password-new.success'));
$token = new UsernamePasswordToken($user, null, 'main', $user->getRoles());
$this->container->get('security.token_storage')->setToken($token);
$this->container->get('session')->set('_security_main', serialize($token));
return new RedirectResponse('/' . $division);
}
}
}
return $this->render(
'@App/division/auth/password-new.html.twig',
[
'form' => $form->createView(),
'document' => Document::getByPath('/' . $division)
]
);
}
}