parent
a7e977fa94
commit
e813480de5
@ -1,177 +0,0 @@ |
||||
<?php |
||||
|
||||
namespace App\Controller; |
||||
|
||||
use App\Entity\User; |
||||
use App\Form\ChangePasswordFormType; |
||||
use App\Form\ResetPasswordRequestFormType; |
||||
use Symfony\Bridge\Twig\Mime\TemplatedEmail; |
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; |
||||
use Symfony\Component\HttpFoundation\RedirectResponse; |
||||
use Symfony\Component\HttpFoundation\Request; |
||||
use Symfony\Component\HttpFoundation\Response; |
||||
use Symfony\Component\Mailer\MailerInterface; |
||||
use Symfony\Component\Mime\Address; |
||||
use Symfony\Component\Routing\Annotation\Route; |
||||
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface; |
||||
use SymfonyCasts\Bundle\ResetPassword\Controller\ResetPasswordControllerTrait; |
||||
use SymfonyCasts\Bundle\ResetPassword\Exception\ResetPasswordExceptionInterface; |
||||
use SymfonyCasts\Bundle\ResetPassword\ResetPasswordHelperInterface; |
||||
|
||||
/** |
||||
* @Route("/reset-password") |
||||
*/ |
||||
class ResetPasswordController extends AbstractController |
||||
{ |
||||
use ResetPasswordControllerTrait; |
||||
|
||||
private $resetPasswordHelper; |
||||
|
||||
public function __construct(ResetPasswordHelperInterface $resetPasswordHelper) |
||||
{ |
||||
$this->resetPasswordHelper = $resetPasswordHelper; |
||||
} |
||||
|
||||
/** |
||||
* Display & process form to request a password reset. |
||||
* |
||||
* @Route("", name="app_forgot_password_request") |
||||
*/ |
||||
public function request(Request $request, MailerInterface $mailer): Response |
||||
{ |
||||
$form = $this->createForm(ResetPasswordRequestFormType::class); |
||||
$form->handleRequest($request); |
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) { |
||||
return $this->processSendingPasswordResetEmail( |
||||
$form->get('email')->getData(), |
||||
$mailer |
||||
); |
||||
} |
||||
|
||||
return $this->render('reset_password/request.html.twig', [ |
||||
'requestForm' => $form->createView(), |
||||
]); |
||||
} |
||||
|
||||
/** |
||||
* Confirmation page after a user has requested a password reset. |
||||
* |
||||
* @Route("/check-email", name="app_check_email") |
||||
*/ |
||||
public function checkEmail(): Response |
||||
{ |
||||
// Generate a fake token if the user does not exist or someone hit this page directly. |
||||
// This prevents exposing whether or not a user was found with the given email address or not |
||||
if (null === ($resetToken = $this->getTokenObjectFromSession())) { |
||||
$resetToken = $this->resetPasswordHelper->generateFakeResetToken(); |
||||
} |
||||
|
||||
return $this->render('reset_password/check_email.html.twig', [ |
||||
'resetToken' => $resetToken, |
||||
]); |
||||
} |
||||
|
||||
/** |
||||
* Validates and process the reset URL that the user clicked in their email. |
||||
* |
||||
* @Route("/reset/{token}", name="app_reset_password") |
||||
*/ |
||||
public function reset(Request $request, UserPasswordEncoderInterface $passwordEncoder, string $token = null): Response |
||||
{ |
||||
if ($token) { |
||||
// We store the token in session and remove it from the URL, to avoid the URL being |
||||
// loaded in a browser and potentially leaking the token to 3rd party JavaScript. |
||||
$this->storeTokenInSession($token); |
||||
|
||||
return $this->redirectToRoute('app_reset_password'); |
||||
} |
||||
|
||||
$token = $this->getTokenFromSession(); |
||||
if (null === $token) { |
||||
throw $this->createNotFoundException('No reset password token found in the URL or in the session.'); |
||||
} |
||||
|
||||
try { |
||||
$user = $this->resetPasswordHelper->validateTokenAndFetchUser($token); |
||||
} catch (ResetPasswordExceptionInterface $e) { |
||||
$this->addFlash('reset_password_error', sprintf( |
||||
'There was a problem validating your reset request - %s', |
||||
$e->getReason() |
||||
)); |
||||
|
||||
return $this->redirectToRoute('app_forgot_password_request'); |
||||
} |
||||
|
||||
// The token is valid; allow the user to change their password. |
||||
$form = $this->createForm(ChangePasswordFormType::class); |
||||
$form->handleRequest($request); |
||||
|
||||
if ($form->isSubmitted() && $form->isValid()) { |
||||
// A password reset token should be used only once, remove it. |
||||
$this->resetPasswordHelper->removeResetRequest($token); |
||||
|
||||
// Encode the plain password, and set it. |
||||
$encodedPassword = $passwordEncoder->encodePassword( |
||||
$user, |
||||
$form->get('plainPassword')->getData() |
||||
); |
||||
|
||||
$user->setPassword($encodedPassword); |
||||
$this->getDoctrine()->getManager()->flush(); |
||||
|
||||
// The session is cleaned up after the password has been changed. |
||||
$this->cleanSessionAfterReset(); |
||||
|
||||
return $this->redirectToRoute('app_home'); |
||||
} |
||||
|
||||
return $this->render('reset_password/reset.html.twig', [ |
||||
'resetForm' => $form->createView(), |
||||
]); |
||||
} |
||||
|
||||
private function processSendingPasswordResetEmail(string $emailFormData, MailerInterface $mailer): RedirectResponse |
||||
{ |
||||
$user = $this->getDoctrine()->getRepository(User::class)->findOneBy([ |
||||
'email' => $emailFormData, |
||||
]); |
||||
|
||||
// Do not reveal whether a user account was found or not. |
||||
if (!$user) { |
||||
return $this->redirectToRoute('app_check_email'); |
||||
} |
||||
|
||||
try { |
||||
$resetToken = $this->resetPasswordHelper->generateResetToken($user); |
||||
} catch (ResetPasswordExceptionInterface $e) { |
||||
// If you want to tell the user why a reset email was not sent, uncomment |
||||
// the lines below and change the redirect to 'app_forgot_password_request'. |
||||
// Caution: This may reveal if a user is registered or not. |
||||
// |
||||
// $this->addFlash('reset_password_error', sprintf( |
||||
// 'There was a problem handling your password reset request - %s', |
||||
// $e->getReason() |
||||
// )); |
||||
|
||||
return $this->redirectToRoute('app_check_email'); |
||||
} |
||||
|
||||
$email = (new TemplatedEmail()) |
||||
->from(new Address('k.jouini@tyr.local', 'SfyCAS Mail Bot')) |
||||
->to($user->getEmail()) |
||||
->subject('Your password reset request') |
||||
->htmlTemplate('reset_password/email.html.twig') |
||||
->context([ |
||||
'resetToken' => $resetToken, |
||||
]) |
||||
; |
||||
|
||||
$mailer->send($email); |
||||
|
||||
// Store the token object in session for retrieval in check-email route. |
||||
$this->setTokenObjectInSession($resetToken); |
||||
|
||||
return $this->redirectToRoute('app_check_email'); |
||||
} |
||||
} |
||||
@ -1,19 +1,86 @@ |
||||
<!DOCTYPE html> |
||||
<html> |
||||
<!doctype html> |
||||
<html lang="en"> |
||||
<head> |
||||
<meta charset="UTF-8"> |
||||
<meta charset="utf-8"> |
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> |
||||
|
||||
<title>{% block title %}Welcome!{% endblock %}</title> |
||||
{# Run `composer require symfony/webpack-encore-bundle` |
||||
and uncomment the following Encore helpers to start using Symfony UX #} |
||||
|
||||
{% block stylesheets %} |
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans:300,300i,400,400i,500,500i,600,600i&display=swap" rel="stylesheet" /> |
||||
{{ encore_entry_link_tags('app') }} |
||||
{% endblock %} |
||||
</head> |
||||
<body> |
||||
<header class="header"> |
||||
<h1 class="sr-only"> |
||||
Symfony sandbox |
||||
</h1> |
||||
|
||||
<nav class="navbar navbar-expand-xl navbar-light bg-light"> |
||||
<div class="container mt-4 mb-3"> |
||||
<a class="navbar-brand mr-4 pr-2" href="{{ path('app_home') }}"> |
||||
📙 Home |
||||
</a> |
||||
|
||||
<button class="navbar-toggler border-0" type="button" data-toggle="collapse" data-target="#header-menu" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Show/Hide navigation"> |
||||
<span class="navbar-toggler-icon"></span> |
||||
</button> |
||||
|
||||
<div class="collapse navbar-collapse" id="header-menu"> |
||||
<ul class="navbar-nav ml-auto"> |
||||
<li class="nav-item mr-3"> |
||||
<a class="nav-link" href="{{ path('app_home') }}"> |
||||
Import |
||||
</a> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
|
||||
<div class="collapse navbar-collapse" id="header-menu"> |
||||
<ul class="navbar-nav ml-auto"> |
||||
<li class="nav-item mr-3"> |
||||
<a class="nav-link" href=""> |
||||
Export |
||||
</a> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
|
||||
<div class="collapse navbar-collapse" id="header-menu"> |
||||
<ul class="navbar-nav ml-auto"> |
||||
<li class="nav-item mr-3"> |
||||
<a class="nav-link" href="{{ path('app_home') }}"> |
||||
Admin |
||||
</a> |
||||
</li> |
||||
</ul> |
||||
</div> |
||||
</div> |
||||
</nav> |
||||
|
||||
<nav class="bg-light border-bottom"> |
||||
<div class="container"> |
||||
{# render_esi(path('conference_header')) #} |
||||
</div> |
||||
</nav> |
||||
</header> |
||||
|
||||
<main role="main" class="container mt-5"> |
||||
{% block body %}{% endblock %} |
||||
</main> |
||||
|
||||
<footer class="mt-7 px-3 py-5 text-center text-muted"> |
||||
<p> |
||||
Symfony sandbox |
||||
</p> |
||||
<p> |
||||
<a href="#" class="text-white">Back to top</a> |
||||
</p> |
||||
</footer> |
||||
|
||||
{% block javascripts %} |
||||
{{ encore_entry_script_tags('app') }} |
||||
{% endblock %} |
||||
</head> |
||||
<body> |
||||
{% block body %}{% endblock %} |
||||
</body> |
||||
</html> |
||||
|
||||
Loading…
Reference in new issue