<?php
/**
* Reset Password Controller
*
* @author Gideon Oudhuis <g.oudhuis@visualmedia.nl>
*/
namespace VisualMedia\UserBundle\Controller;
use DateTime;
use Swift_Mailer;
use Swift_Message;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use VisualMedia\LisaBundle\Helper\Helper;
use VisualMedia\LisaBundle\Component\ManagerData;
use VisualMedia\LisaBundle\Controller\BaseController;
use VisualMedia\LisaBundle\Service\SettingProvider;
use VisualMedia\UserBundle\Entity\BaseUser;
use VisualMedia\UserBundle\Form\Type\ResetPasswordRequestType;
use VisualMedia\UserBundle\Form\Type\ResetPasswordType;
use VisualMedia\UserBundle\Manager\BaseUserManager;
/**
* Reset Password Controller
*/
class ResetPasswordController extends BaseController
{
// Route template mapping
const TEMPLATE_MAPPING = array(
'manage_reset_password_request' => '@VisualMediaUser/ResetPassword/reset_password_request.html.twig',
'manage_reset_password' => '@VisualMediaUser/ResetPassword/reset_password.html.twig',
'frontend_reset_password_request' => '@VisualMediaUser/ResetPassword/frontend_reset_password_request.html.twig',
'frontend_reset_password' => '@VisualMediaUser/ResetPassword/frontend_reset_password.html.twig'
);
/**
* Reset Password Request Action
*
* @param Request $request
*
* @return Response
*/
public function resetPasswordRequestAction(Request $request): Response
{
$route = $request->get('_route');
$firewall = explode('_', $route)[0] ?? null;
$translator = $this->get('translator');
$userManager = $this->container->get(BaseUserManager::class);
$form = $this->createForm(ResetPasswordRequestType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$email = $form->get('email')->getData();
if (null !== $user = $userManager->getFirst(new ManagerData(array($userManager::OPTION_EMAIL => $email)))) {
$encoderToken = openssl_random_pseudo_bytes(64);
$token = bin2hex($encoderToken);
$resetExpired = new DateTime();
$resetExpired->modify('+30 minutes');
$user->setResetToken($token);
$user->setResetExpired($resetExpired);
$userManager->persist($user);
$userManager->flush();
$this->sendResetPasswordMail($request, $user, sprintf('%s_reset_password', $firewall));
return $this->redirectToRoute(sprintf('%s_login', $firewall));
}
else {
$request->getSession()->getFlashBag()->set('danger', $translator->trans('reset_password.user_not_found', array('%email%' => $email), 'flashmessage'));
}
}
return $this->render(static::TEMPLATE_MAPPING[$route], array(
'form' => $form->createView(),
));
}
/**
* Reset Password Action
*
* @param Request $request
* @param string $token
*
* @return Response
* @throws Exception
*/
public function resetPasswordAction(Request $request, $token): Response
{
$route = $request->get('_route');
$firewall = explode('_', $route)[0] ?? null;
$now = new DateTime();
$translator = $this->get('translator');
$encoder = $this->container->get(UserPasswordEncoderInterface::class);
$userManager = $this->container->get('VisualMedia\UserBundle\Manager\BaseUserManager');
$user = $userManager->getFirst(new ManagerData(array(
$userManager::OPTION_TOKEN => $token,
$userManager::OPTION_EXPIRED => $now->format('Y-m-d:H-i-s'),
)));
if ($user === null) {
throw new \Exception($translator->trans('reset_password.token_expired', [], 'exception'));
}
$form = $this->createForm(ResetPasswordType::class);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$plainPassword = $form->get('plainPassword')->getData();
$password = $encoder->encodePassword($user, $plainPassword);
$user->setPassword($password);
$userManager->persist($user);
$userManager->flush();
$request->getSession()->getFlashBag()->set('success', $translator->trans('reset_password.success', [], 'flashmessage'));
return $this->redirectToRoute(sprintf('%s_login', $firewall));
}
return $this->render(static::TEMPLATE_MAPPING[$route] , array(
'form' => $form->createView(),
));
}
/**
* Send Reset Password Mail
*
* @param Request $request
* @param BaseUser $user
* @param string $route
*
* @return void
*/
protected function sendResetPasswordMail(Request $request, BaseUser $user, $route): void
{
$translator = $this->get('translator');
$settingProvider = $this->get(SettingProvider::class);
$mailer = $this->container->get('swiftmailer.mailer.default');
$resetUrl = $this->generateUrl($route, array('token' => $user->getResetToken()), UrlGeneratorInterface::ABSOLUTE_URL);
$mailerSenderName = $settingProvider->getValue($reference = 'mailer_sender_name', $domain = 'system') ?? Helper::settingPlaceholder($reference, $domain);
$mailerSenderEmail = $settingProvider->getValue($reference = 'mailer_sender_email', $domain = 'system') ?? Helper::settingPlaceholder($reference, $domain);
$message = new Swift_Message($translator->trans('reset_password.subject', [], 'email'));
$message->setFrom($mailerSenderEmail, $mailerSenderName);
$message->setTo($user->getEmail(), $user->getUsername());
$message->setBody($this->renderView('@VisualMediaUser/Email/reset_password.html.twig', array(
'user' => $user,
'resetUrl' => $resetUrl,
'mailer_sender_name' => $mailerSenderName,
)), 'text/html');
$mailer->send($message);
$request->getSession()->getFlashBag()->set('success', $translator->trans('reset_password.email_send', [], 'flashmessage'));
}
}