Giter VIP home page Giter VIP logo

Comments (6)

jrushlow avatar jrushlow commented on August 13, 2024

Sure! Contributions are always welcome! But first, I would suggest reading Symfony's Contributing Guide.

Second, let's make sure you're in the right repository. Using a simple project as an example, any files that are in vendor/symfonycasts/reset-password-bundle belong to the SymfonyCasts/reset-password-bundle Github Repository (The one you're in now).

Any files that were created as a result of bin/console make:reset-password - Symfony's Maker Bundle is responsible for those. E.,g. src/Controller/ResetPasswordController.php or tempates/reset_password/check_email.html.twig.

Having said that, if you have some code you are unsure which repository it belongs in, feel free to post it below and I'll do my best to get you moving in the right direction.

from reset-password-bundle.

dd2424 avatar dd2424 commented on August 13, 2024

OK thanks for your answer. I pasted my modified controller below, I deleted a method and modified some lines. Compare my controller and tell me what you think. Less code, same use, 1 file view less.

<?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(),
        ]);
    }

    /**
     * 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('danger', sprintf(
                'Un problème est survenu lors de votre demande de réinitialisation - %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();

            $this->addFlash(
                'success',
                'Votre mot de passe vient d\'être réinitialisé avec succés.'
            );

            return $this->redirectToRoute('app_login');
        }

        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,
        ]);

        // Marks that you are allowed to see the app_check_email page.
        $this->setCanCheckEmailInSession(); // now I think this line is useless ?

        // Do not reveal whether a user account was found or not.
        if ($user) { // change: a user is found then we enter the condition.
            try {
                $resetToken = $this->resetPasswordHelper->generateResetToken($user);
            } catch (ResetPasswordExceptionInterface $e) {
                $this->addFlash('danger', sprintf(
                    'There was a problem handling your password reset request - %s',
                    $e->getReason()
                ));

                return $this->redirectToRoute('app_forgot_password_request');
            }

            $email = (new TemplatedEmail())
                ->from(new Address('[email protected]', 'Acme Mail Bot'))
                ->to($user->getEmail())
                ->subject('Your password reset request')
                ->htmlTemplate('reset_password/email.html.twig')
                ->context([
                    'resetToken' => $resetToken,
                    'tokenLifetime' => $this->resetPasswordHelper->getTokenLifetime(),
                ]);

            $mailer->send($email);
        }

        $this->addFlash(
            'info',
            'C’est dans la boite ! Vous avez reçu un email contenant un lien pour reinitialiser votre mot de passe. Ce lien expirera dans 2 heures.'
        );

        return $this->redirectToRoute('app_forgot_password_request');
    }
}

from reset-password-bundle.

jrushlow avatar jrushlow commented on August 13, 2024

Your concept is not a bad idea, I'm a huge fan of reducing complexity. I have not attempted to run the code you suggest but just off the top of my head, here are a couple thoughts -

  • The code within the if ($user) { block adds an extra level of indentation within the if statement. While there is no hard fast rule on this, in-versing if ($user) to if (!$user) may be a better solution for readability. (Think exit/return early strategy)

  • I'm not sure how I feel about the flash message for the "check your email" message. First thought that comes to mind is how would this affect caching as opposed to having a template. This may be an invalid point of my own.

  • If you use a flash message instead of the check_email route w/ template. In general, what happens when someone doesn't want to use flashes in their UI and the traditional templates.

  • How does this affect the DX for translations. For a translation example - see the pending PR for the Symfony Demo app. e.g. symfony/demo#1100

There may be more that I am missing to this that would affect the UX (positively / negatively). Later tonight I'll spin up a demo of this and mess around with it.

None the less, if you were to submit these changes - you would have to do so in the Maker Bundle repository. @weaverryan Thoughts?

https://github.com/symfony/maker-bundle/blob/master/src/Resources/skeleton/resetPassword/ResetPasswordController.tpl.php

from reset-password-bundle.

dd2424 avatar dd2424 commented on August 13, 2024

thank you for your opinion. Yes, try the code. It works very well.
Question: I do not understand, why want to prohibit access to the view check_email? this is an unnecessary method. If a visitor wants to write, in his browser, the route to access check_email, he will see the message but it is not dangerous, it does not matter. The visitor has nothing else to do with his life. This condition is not necessary, I think. Sorry for my English, I use the translation to write, I'm sorry. I take note of your points, thank you.

from reset-password-bundle.

chaleto avatar chaleto commented on August 13, 2024

Hello!
I use the same function on Symfony ,but i have got a little issue:
When i submit the form it does everything by the way it must be , but i do not receive email.
Do you know where can be the problem?
Thank you!

from reset-password-bundle.

weaverryan avatar weaverryan commented on August 13, 2024

Hey @chaleto!

That could be a problem with the delivery of your email - like mailer config, or it's going to spam. A good way to see if Symfony actually "sent" the mail is to use the profiler. After completing the form, you can click the web debug toolbar to go into the profiler. You won't see it inside THIS profiler, because this is the profiler for the redirected request. But if you click the "Last 10" link and find the 2nd from the top - we should an example on this video https://symfonycasts.com/screencast/symfony-uploads/dropzone - it should be a POST request, then you can go into the Email section to see if the mail was delivered.

Cheers!

from reset-password-bundle.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.