Email confirmation on FOSUserBundle Profile Edit
Using new FOSUserBundle's events (FOS 2.0 feature), you can create a ChangeProfileListener
that handle email changes.
The idea : use the same logic as a registration process : disable our user, send him a token (and logging-him out for our case).
There is two things to do :
- create an event suscriber
- overwrite the mail.txt.twig to replace the "registration" message by a neutral "email confirmation" message.
Here is my listener, don't forget to replace namespace.
EventListener/ChangeProfileListener.php:
<?php// src/Fuz/HomeBundle/EventListener/ChangeProfileListener.phpnamespace Fuz\HomeBundle\EventListener;use FOS\UserBundle\FOSUserEvents;use FOS\UserBundle\Event\GetResponseUserEvent;use FOS\UserBundle\Event\FormEvent;use FOS\UserBundle\Mailer\MailerInterface;use FOS\UserBundle\Util\TokenGeneratorInterface;use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;use Symfony\Component\EventDispatcher\EventSubscriberInterface;use Symfony\Component\HttpFoundation\RedirectResponse;use Symfony\Component\HttpFoundation\Session\SessionInterface;use Symfony\Component\Routing\Generator\UrlGeneratorInterface;class ChangeProfileListener implements EventSubscriberInterface{ private $mailer; private $tokenGenerator; private $router; private $session; private $tokenStorage; public function __construct(MailerInterface $mailer, TokenGeneratorInterface $tokenGenerator, UrlGeneratorInterface $router, SessionInterface $session, TokenStorageInterface $tokenStorage) { $this->mailer = $mailer; $this->tokenGenerator = $tokenGenerator; $this->router = $router; $this->session = $session; $this->tokenStorage = $tokenStorage; } public static function getSubscribedEvents() { return array( FOSUserEvents::PROFILE_EDIT_INITIALIZE => 'onProfileEditInitialize', FOSUserEvents::PROFILE_EDIT_SUCCESS => 'onProfileEditSuccess', ); } public function onProfileEditInitialize(GetResponseUserEvent $event) { // required, because when Success's event is called, session already contains new email $this->email = $event->getUser()->getEmail(); } public function onProfileEditSuccess(FormEvent $event) { $user = $event->getForm()->getData(); if ($user->getEmail() !== $this->email) { // disable user $user->setEnabled(false); // send confirmation token to new email $user->setConfirmationToken($this->tokenGenerator->generateToken()); $this->mailer->sendConfirmationEmailMessage($user); // force user to log-out $this->tokenStorage->setToken(); // redirect user to check email page $this->session->set('fos_user_send_confirmation_email/email', $user->getEmail()); $url = $this->router->generate('fos_user_registration_check_email'); $event->setResponse(new RedirectResponse($url)); } }}
services.yml :
parameters: fuz_home.email_change.listener.class: Fuz\HomeBundle\EventListener\ChangeProfileListenerservices: fuz_home.email_change.listener: class: %fuz_home.email_change.listener.class% arguments: ['@fos_user.mailer', '@fos_user.util.token_generator', '@router', '@session', '@security.token_storage'] tags: - { name: kernel.event_subscriber }
About overwritting email template, that's just creating app/Resources/FOSUserBundle/views/Registration/email.txt.twig and put, for example :
{% block subject %}Email Confirmation{% endblock %}{% block body_text %}Welcome to example.com, {{ user.username }}! To confirm your email, please follow this link: {{ confirmationUrl }}You will be able to log-in using the username or email you given: Username : {{ user.username }} Email : {{ user.email }} If you received this e-mail in error just ignore this message. No further actions are required from you. ***** See you soon!{% endblock %}
The functionality to send a confirmation email only exists in
RegistrationFormHandler->onSucces
where that configuration variable is passed and checked. Similar functionality doesn't exist in the profile/edit:
ProfileFormHandler->onSuccess.
You would therefore need to override the FOS ProfileFormHandler
and add this functionality yourself. This is covered in the FOSUserBundle documentation: Overriding Forms.