<?php
namespace App\Controller\Back;
use App\Entity\BackUser;
use App\Entity\BackUserLog;
use App\Form\ForgotPasswordType;
use App\Form\Model\ForgotPassword;
use App\Form\Model\ResetPassword;
use App\Form\ResetPasswordType;
use App\Repository\BackUserRepository;
use App\Service\MailService;
use App\Utils\FormHelper;
use DateInterval;
use DateTime;
use Doctrine\ORM\NonUniqueResultException;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;
#[Route('/back')]
class SecurityController extends AbstractController
{
/**
* SecurityController constructor.
*/
public function __construct(
protected MailService $mailer,
protected UserPasswordHasherInterface $passwordEncoder,
protected ManagerRegistry $registry
) {
}
/**
* @throws \Exception
*/
#[Route('/login', name: 'back_security_login')]
public function login(Request $request, AuthenticationUtils $helper): Response
{
$session = $request->getSession();
$date = new DateTime();
$date->sub(new DateInterval('P5M'));
$locked = $session->get('locked', false);
if ($locked && $locked < $date->format('YmdHis')) {
$session->set('locked', false);
}
return $this->render('back/security/login.html.twig', [
'last_username' => $helper->getLastUsername(),
'error' => $helper->getLastAuthenticationError(),
'locked' => $session->get('locked', false),
]);
}
/**
* @throws NonUniqueResultException
* @throws LoaderError
* @throws RuntimeError
* @throws SyntaxError
*/
#[Route('/forgot-password', name: 'back_security_forgotPassword')]
public function forgotPassword(Request $request): Response
{
$forgotPassword = new ForgotPassword();
$form = $this->createForm(ForgotPasswordType::class, $forgotPassword);
if ('POST' == $request->getMethod()) {
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$mail = $forgotPassword->getEmail();
/** @var BackUserRepository $repository */
$repository = $this->registry->getRepository(BackUser::class);
/** @var BackUser $user */
$user = $repository->findOneByMail($mail);
if (null !== $user) {
$user->generateResetPasswordHash();
$em = $this->registry->getManager();
$em->persist($user);
$em->flush();
$this->mailer->resetPassword($user);
}
return $this->render('back/security/forgot-password-success.html.twig');
}
$errors = FormHelper::getErrorMessages($form);
}
$form = FormHelper::getData($form);
return $this->render('back/security/forgot-password.html.twig', [
'form' => $form['forgot_password']['children'],
'errors' => $errors ?? null,
]);
}
/**
* @throws \Exception
*/
#[Route('/reset-password/{resetPasswordHash}', name: 'back_security_resetPassword')]
public function resetPassword(Request $request, BackUser $user): Response
{
$resetPassword = new ResetPassword();
$form = $this->createForm(ResetPasswordType::class, $resetPassword);
if ('POST' == $request->getMethod()) {
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$em = $this->registry->getManager();
$user->setPassword($this->passwordEncoder->hashPassword($user, $resetPassword->getPassword()));
$user->setResetPasswordHash();
$em->persist($user);
$userLog = new BackUserLog();
$userLog->setType(BackUserLog::TYPE_RESET_PASSWORD);
$userLog->setUser($user);
$userLog->setIp($user->getLastIp());
$userLog->setDate(new DateTime());
$em->persist($userLog);
$em->flush();
return new RedirectResponse($this->generateUrl('back_security_login'));
}
$errors = FormHelper::getErrorMessages($form);
}
$form = FormHelper::getData($form);
return $this->render('back/security/reset-password.html.twig', [
'form' => $form['reset_password']['children'],
'errors' => $errors ?? null,
'hash' => $user->getResetPasswordHash(),
]);
}
/**
* @throws \Exception
*/
#[Route('/unlock-account/{unlockingHash}', name: 'back_security_unlockAccount')]
public function unlockAccount(BackUser $user): Response
{
$em = $this->registry->getManager();
$user->setEnabled(true);
$user->setUnlockingHash();
$em->persist($user);
$userLog = new BackUserLog();
$userLog->setType(BackUserLog::TYPE_UNLOCK);
$userLog->setUser($user);
$userLog->setIp($user->getLastIp());
$userLog->setDate(new DateTime());
$em->persist($userLog);
$em->flush();
return new RedirectResponse($this->generateUrl('back_security_login'));
}
/**
* @throws \Exception
*/
#[Route('/logout', name: 'back_security_logout')]
public function logout(): never
{
throw new \Exception('This should never be reached!');
}
}