<?php
namespace Umimeweby\UWLoginUserBundle\Controller\UserResetPass;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
use Umimeweby\EmailerBundle\Contract\Service\MailMessages\MessageBuilderInterface;
use Umimeweby\EmailerBundle\Service\Mailer\EMailer;
use Umimeweby\UWHelpersBundle\Helper\FlashTypes;
use Umimeweby\UWLoginUserBundle\Contracts\Repository\BasicORMUserRepositoryInterface;
use Umimeweby\UWLoginUserBundle\Contracts\Service\Security\ResetPasswordViewProviderInterface;
use Umimeweby\UWLoginUserBundle\Contracts\Service\Security\RouteProviderInterface;
use Umimeweby\UWLoginUserBundle\DataHolder\ResetPassDetails;
use Umimeweby\UWLoginUserBundle\Entity\RsToken\RsToken;
use Umimeweby\UWLoginUserBundle\Form\ResetPassType;
use Umimeweby\UWLoginUserBundle\Repository\RsToken\RsTokenRepository;
use Umimeweby\UWLoginUserBundle\Service\Security\ResetPassword\RSTokenCleaner;
use Umimeweby\UWLoginUserBundle\Service\Security\ResetPassword\RSTokenGenerator;
use Umimeweby\UWLoginUserBundle\Service\Security\ResetPassword\RsTokenVerifier;
use Umimeweby\UWLoginUserBundle\Service\Security\RouteProvider\BasicRouteProvider;
class ResetPasswordController extends AbstractController
{
private $userRepo;
private $emailer;
private $newResetPassTokenMsgBuilder;
private $routeProvider;
private $rpViewProvider;
private $rstgen;
private $rstRepo;
private $rstCleaner;
private $rstVerifier;
private $encoder;
public function __construct(
BasicORMUserRepositoryInterface $userRepo,
MessageBuilderInterface $nrptmBuilder,
RouteProviderInterface $routeprovider,
ResetPasswordViewProviderInterface $rpViewProvider,
EMailer $emailer,
RSTokenGenerator $rstgen,
RsTokenRepository $rstRepo,
RSTokenCleaner $rstCleaner,
RsTokenVerifier $rstVerifier,
UserPasswordEncoderInterface $encoder
) {
$this->userRepo = $userRepo;
$this->emailer = $emailer;
$this->newResetPassTokenMsgBuilder = $nrptmBuilder;
$this->routeProvider = $routeprovider;
$this->rpViewProvider = $rpViewProvider;
$this->rstgen = $rstgen;
$this->rstRepo = $rstRepo;
$this->rstCleaner = $rstCleaner;
$this->rstVerifier = $rstVerifier;
$this->encoder = $encoder;
}
public function stepOneEmail(Request $request)
{
/** @var \Symfony\Component\Form\FormInterface */
$form = $this->createFormBuilder()
->add('email', EmailType::class, [
'label' => 'Váš email',
])
->getForm();
$form->handleRequest($request);
if ($form->isSubmitted() and $form->isValid()) {
$email = $form->get('email')->getData();
if ($this->userRepo->activeEmailExists($email)) {
$tokenString = $this->rstgen->generateResetPasswordToken($email);
$data = [];
$data['token'] = $tokenString;
$data['emailTo'] = $email;
$emailMessage = $this->newResetPassTokenMsgBuilder->buildMessage($data);
$this->emailer->sendMessage($emailMessage);
$this->addFlash(FlashTypes::FL_SUCCESS, 'Během chvilky by vám měl přijít email s instrukcemi jak postupovat dále');
return $this->redirectToRoute($this->routeProvider->getRouteToRedirectAfterRSTokenSend());
} else {
$this->addFlash(FlashTypes::FL_WARNING, 'Uživatel s emailem '.$email.' neexistuje nebo není aktivovaný');
}
}
return $this->render($this->rpViewProvider->getResetPasswordFormViewtemplatePath(), [
'form' => $form->createView(),
]);
}
public function stepTwoRp($token = '')
{
if ('' == $token) {
return $this->redirectToRoute($this->routeProvider->getRouteTokenCheckError());
}
$selector = substr($token, 0, 30);
$this->rstCleaner->removeExpiredTokens(RsToken::RESETPASS_DAYS_TO_EXPIRE);
/** @var RsToken */
$rsToken = $this->rstRepo->findToken($selector);
if ($rsToken) {
$verifier = substr($token, 30);
if (!$this->rstVerifier->verifyOrDelete($verifier, $rsToken)) {
$this->addFlash(FlashTypes::FL_ERROR, 'Token nemohl být ověřen');
return $this->redirectToRoute($this->routeProvider->getRouteTokenCheckError());
}
$rpData = new ResetPassDetails($rsToken->getEmail());
$form = $this->createForm(ResetPassType::class, $rpData, [
'action' => $this->generateUrl(BasicRouteProvider::DEFAULT_RESETPASSWORD_NEWPASSHANDLE_ROUTE),
]);
$this->rstVerifier->removeToken($rsToken);
return $this->render($this->rpViewProvider->getNewPasswordFormViewtemplatePath(), [
'form' => $form->createView(),
]);
}
$this->addFlash(FlashTypes::FL_ERROR, 'Token nenalezen - možná již expiroval?');
return $this->redirectToRoute($this->routeProvider->getRouteTokenCheckError());
}
/**
* Step 3 in reset-password-process, this method handles Posting of Form with new password.
*
* @param Request $request
*
* @throws UsernameNotFoundException
*
* @return \Symfony\Component\HttpFoundation\RedirectResponse
*/
public function stepThree(Request $request)
{
$rpDetails = new ResetPassDetails();
$form = $this->createForm(ResetPassType::class, $rpDetails);
$form->handleRequest($request);
if (!($form->isSubmitted() and $form->isValid())) {
$formErrors = $form->getErrors(true);
if (count($formErrors) > 0) {
$message = $formErrors[0]->getMessage();
} else {
$message = 'Problem s formularem';
}
$this->addFlash(FlashTypes::FL_ERROR, $message);
//show again reset pass form to show errors and possibility to provide new password again
return $this->render($this->rpViewProvider->getNewPasswordFormViewtemplatePath(), [
'form' => $form->createView(),
]);
}
$email = $form->get('email')->getData();
$plainPass = $form->get('plainPassword')->getData();
$em = $this->getDoctrine()->getManager();
$user = $this->userRepo->findOneBy(['email' => $email]);
if (!$user) {
throw new UsernameNotFoundException();
}
$password = $this->encoder->encodePassword($user, $plainPass);
$user->changeEncodedPassword($password);
$em->flush();
$this->addFlash(FlashTypes::FL_SUCCESS, 'Vaše heslo bylo změněno. Můžete se přihlásit');
return $this->redirectToRoute($this->routeProvider->getLoginFormRoute());
}
}