Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can resend another confirmation email when user trying to login by not being enabled #50

Open
bastien70 opened this issue Jan 12, 2021 · 6 comments
Labels
duplicate This issue or pull request already exists enhancement New feature or request

Comments

@bastien70
Copy link

Hey! When my user tries to log in when he is not activated, I display a notification telling him to activate his account, and I add a "Resend activation email" link.

If I want to be able to manage this, I will be forced, each time a user tries to connect, to generate a new unique link allowing them to access a route that will use the bundle to send a confirmation email.

In my UserChecker.php class :

    public function checkPreAuth(UserInterface $user)
    {

        if (!$user instanceof User) {
            return;
        }
        if (!$user->getEnabled() && !$user->isVerified()) {
            // $uniqueResendEmailurl = ....
            throw new CustomUserMessageAccountStatusException("Votre compte n'est pas activé. Veuillez confirmer 
            votre inscription en cliquant sur le lien qui vous a été envoyé par email. Pensez à vérifier dans vos spams. <a href=. "$uniqueResendEmailurl" . >Renvoyer l'email de confirmation</a>");
        }
    }

The bundle should really be able to integrate this functionality directly.

To counter this, I thought about using another of your bundles. The symfonycasts/reset-password-bundle

By creating a "ResendConfirmationEmailRequest" entity which is a full clone of the "ResetPasswordRequest" entity from your other bundle. And use the same methods to generate a unique signature to allow a user to receive a confirmation email again.

What do you think ?

@jrushlow jrushlow added duplicate This issue or pull request already exists enhancement New feature or request labels Jan 12, 2021
@jrushlow
Copy link
Collaborator

Related to #35

Howdy @bastien70 - adding the ability to generate a new verification link is something that is currently planned.. I believe the functionality will be added to the templates in MakerBundle but I'm not 100% positive on that yet. Stay tuned for more information on this...

@aniskasmi
Copy link

HI do you have information for this new feature ? Date or delay because on my application i want them

@latrach
Copy link

latrach commented Nov 17, 2021

yo can add a route to request new link :

    /**
     * requestVerifyUserEmail
     */
    #[Route('/request-verify-email', name: 'app_request_verify_email')]
    public function requestVerifyUserEmail(
        Request $request,
        UserRepository $userRepository
    ): Response {

        if ($this->getUser()) {
            return $this->redirectToRoute('app_home');
        }

        $form = $this->createForm(RequestVerifyUserEmailFormType::class);
        $form->handleRequest($request);
        if ($form->isSubmitted() && $form->isValid()) {
            // generate a signed url and email it to the user
            $user =  $userRepository->findOneByEmail($form->get('email')->getData());
            if ($user) {
                $this->emailVerifier->sendEmailConfirmation(
                    'app_verify_email',
                    $user,
                    (new TemplatedEmail())
                        ->from(new Address('email@example.com', 'Sender'))
                        ->to($user->getEmail())
                        ->subject('Validation Link')
                        ->htmlTemplate('security/registration/confirmation_email.html.twig')
                );
                // do anything else you need here, like flash message
                $this->addFlash('success', 'blabla.');
                return $this->redirectToRoute('app_home');
            } else {
                $this->addFlash('error',  'Email inconnu.');
            }
        }
        return $this->render('security/registration/request.html.twig', [
            'requestForm' => $form->createView(),
        ]);
    }

and a form RequestVerifyUserEmailFormType

<?php

namespace App\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;

class RequestVerifyUserEmailFormType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options): void
    {
        $builder
            ->add('email', EmailType::class, [
                'attr' => ['autocomplete' => 'email'],
                'constraints' => [
                    new NotBlank([
                        'message' => 'Merci de saisir votre email',
                    ]),
                ],
            ])
        ;
    }

    public function configureOptions(OptionsResolver $resolver): void
    {
        $resolver->setDefaults([]);
    }
}

@arirangz
Copy link

arirangz commented Dec 7, 2021

@latrach thanks for sharing this solution

@BAD-WOLF
Copy link

BAD-WOLF commented Aug 4, 2023

Idea:
Currently, in the verifyUserEmail() method of the RegistrationController class, we handle exceptions using VerifyEmailExceptionInterface after attempting to verify the user's email. The proposal is to handle the more specific exception, ExpiredSignatureException, before the more general exception, VerifyEmailExceptionInterface.

Details:

Currently, we have the following code:

try {
    $this->emailVerifier->handleEmailConfirmation($request, $this->getUser());
} catch (VerifyEmailExceptionInterface $exception) {
    $this->addFlash('verify_email_error', $exception->getReason());
    return $this->redirectToRoute('app_register');
}

Suggestion:

My suggestion is to adjust the structure of the try and catch block as follows:

try {
    $this->emailVerifier->handleEmailConfirmation($request, $this->getUser());
} catch (ExpiredSignatureException $expiredException) {
    // Remove the user from the database, as the token has expired
    // This allows the user to re-register
    // and subsequently resend the email with the confirmation link
    // Additionally, redirect the user to the registration process again
    // The absence of the user in the database means the user can redo their registration
    return $this->redirectToRoute('app_register');
} catch (VerifyEmailExceptionInterface $genericException) {
    $this->addFlash('verify_email_error', $genericException->getReason());
    return $this->redirectToRoute('app_register');
}

Benefits:

  • Ensures that expired verification tokens are handled specifically, preventing users from lingering in the database.
  • Provides a simplified re-registration process for users who missed the verification deadline.
  • Helps maintain the integrity of the database by removing unverified records.

This approach not only enhances how we deal with expired verification tokens but also contributes to a cleaner and clearer registration flow for users.

@sovetski
Copy link

@latrach thank you! I think this solution should be integrated by default to the bundle

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
duplicate This issue or pull request already exists enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

7 participants