ResetPasswordController.php 3.01 KB
Newer Older
Emma's avatar
Emma committed
1 2 3 4
<?php

namespace Raddit\AppBundle\Controller;

Emma's avatar
Emma committed
5
use Doctrine\ORM\EntityManager;
Emma's avatar
Emma committed
6 7 8
use Raddit\AppBundle\Entity\User;
use Raddit\AppBundle\Form\RequestPasswordResetType;
use Raddit\AppBundle\Form\UserType;
9
use Raddit\AppBundle\Mailer\ResetPasswordMailer;
Emma's avatar
Emma committed
10
use Raddit\AppBundle\Repository\UserRepository;
11
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
Emma's avatar
Emma committed
12 13 14 15 16 17
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

final class ResetPasswordController extends Controller {
    /**
18 19 20
     * @param Request             $request
     * @param UserRepository      $ur
     * @param ResetPasswordMailer $mailer
Emma's avatar
Emma committed
21 22 23
     *
     * @return Response
     */
24
    public function requestResetAction(Request $request, UserRepository $ur, ResetPasswordMailer $mailer) {
25
        if (!$this->getParameter('env(NO_REPLY_ADDRESS)')) {
Emma's avatar
Emma committed
26 27 28 29 30 31 32 33 34 35
            throw $this->createNotFoundException();
        }

        $form = $this->createForm(RequestPasswordResetType::class);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $email = $form->getData()->getEmail();

            // TODO - this is susceptible to timing attacks.
36
            // TODO - send only one email with all the links.
Emma's avatar
Emma committed
37
            foreach ($ur->lookUpByEmail($email) as $user) {
38
                $mailer->mail($user, $request);
Emma's avatar
Emma committed
39 40
            }

41
            $this->addFlash('success', 'flash.reset_password_email_sent');
Emma's avatar
Emma committed
42

43
            return $this->redirectToRoute('front');
Emma's avatar
Emma committed
44 45
        }

46
        return $this->render('reset_password/request.html.twig', [
Emma's avatar
Emma committed
47 48 49 50 51
            'form' => $form->createView(),
        ]);
    }

    /**
52 53 54 55 56 57 58 59
     * @ParamConverter("expires", options={"format": "U"})
     *
     * @param Request             $request
     * @param EntityManager       $em
     * @param User                $user
     * @param ResetPasswordMailer $mailer
     * @param \DateTime           $expires
     * @param string              $checksum
Emma's avatar
Emma committed
60 61 62
     *
     * @return Response
     */
63 64 65 66 67
    public function resetAction(
        Request $request, EntityManager $em, User $user,
        ResetPasswordMailer $mailer, \DateTime $expires, string $checksum
    ) {
        if (!$mailer->validateChecksum($checksum, $user, $expires)) {
Emma's avatar
Emma committed
68 69 70
            throw $this->createNotFoundException('Invalid checksum');
        }

71
        if (new \DateTime('@'.time()) > $expires) {
Emma's avatar
Emma committed
72 73 74 75 76 77 78 79 80
            throw $this->createNotFoundException('The link has expired');
        }

        $form = $this->createForm(UserType::class, $user);

        try {
            $form->handleRequest($request);

            if ($form->isSubmitted() && $form->isValid()) {
Emma's avatar
Emma committed
81 82
                $em->flush();

83
                $this->addFlash('success', 'flash.user_password_updated');
Emma's avatar
Emma committed
84

85
                return $this->redirectToRoute('front');
Emma's avatar
Emma committed
86 87
            }
        } finally {
Emma's avatar
Emma committed
88
            $em->refresh($user);
Emma's avatar
Emma committed
89 90
        }

91
        return $this->render('reset_password/reset.html.twig', [
Emma's avatar
Emma committed
92 93 94 95
            'form' => $form->createView(),
        ]);
    }
}