FOSUserBundle – login, change password, reset password – PHP5 – Symfony 2

Cet article explique comment surcharger les contrôleurs et les templates de FOSUserBundle.

fosuser bundle

Login

SecurityController extends FOS\UserBundle\Controller\SecurityController
-> loginAction (Resources/views/Security/login.html.twig)

exemple de surcharge de la fonction :

public function loginAction(Request $request)
{
    if($this->container->get('security.context')->isGranted('IS_AUTHENTICATED_FULLY')) {
         return new RedirectResponse($this->container->get('router')->generate('homepage', array(), UrlGeneratorInterface::ABSOLUTE_PATH), 302);
     }    
     return parent::loginAction($request);
}

Change password

ChangePasswordController extends FOS\UserBundle\Controller\ChangePasswordController
-> changePasswordAction (Resources/views/ChangePassword/changePassword.html.twig)

Le ChangePasswordFormType par défaut de FOSUserBundle contient trois champs :

  • mot de passe actuel ;
  • nouveau mot de passe ;
  • seconde saisie du nouveau mot de passe.

L'utilisateur peut ainsi changer son mot de passe en saisissant le mot de passe actuel.

Il est possible de surcharger ces éléments afin de permettre à un utilisateur Administrateur de changer les mots de passe des utilisateurs sans avoir à connaître les mots de passe.

Pour cela on déclare une route dans le UserController et on reprend le formulaire du FOSUserBundle en enlevant le champ "current_password" :

/**
     * Displays a form to change password of an existing User entity.
     * @Route("/{id}/password/", name="admin_user_password")
     * @Method({"GET", "POST"})
     * @Template()
*/
public function changePasswordAction(Request $request, $id)
{
     $em = $this->getDoctrine()->getManager();
     $entity = $em->getRepository('LizeoUserBundle:User')->find($id);

        if (!$entity) {
            throw $this->createNotFoundException('Unable to find User entity.');
        }

        $formFactory = $this->container->get('fos_user.change_password.form.factory');

        $form = $formFactory->createForm();
        $form->remove('current_password');
        $form->setData($entity);

        if ($request->isMethod('POST')) {
            $form->bind($request);
            if ($form->isValid()) {
	            $userManager = $this->container->get('fos_user.user_manager');
	            $userManager->updateUser($entity);

	            return $this->redirect($this->generateUrl('admin_user'));
            }
        }

        return array(
            'entity'      => $entity,
            'form'   => $form->createView(),
        );
}	

 

Il faut redéfinir le FormType en déclarant la classe :

Me\UserBundle\Form\Type\ChangePasswordFormType.php extends \FOS\UserBundle\Form\Type\ChangePasswordFormType :

public function buildForm(FormBuilderInterface $builder, array $options)
{
    parent::buildForm($builder, $options);

    $builder->add('change', 'submit', array(
           'label' => 'password.update.Mettre à jour',
           'translation_domain' => 'FOSUserBundle',
           'attr' => array(
                 'class' => 'btn btn-primary'
            )
     ));
}

public function getName()
{
    return 'me_user_change_password';
}

Déclaration du FormType dans le fichier config.yml :

fos_user:
   db_driver: orm
   firewall_name: main
   user_class: Me\UserBundle\Entity\User
   change_password:
      form:
          type: me_user_change_password

 

Déclaration du FormType dans le fichier services.xml :

<service id="me.change_password.form.type" class="Me\UserBundle\Form\Type\ChangePasswordFormType">
     <tag name="form.type" alias = "me_user_change_password" />
     <argument>%fos_user.model.user.class%</argument>
</service>

 

Reset password

En cas d'oubli de son mot de passe, l'utilisateur peut cliquer sur un lien sur la page de connexion pour demander à ré-initialiser son mot de passe : "Mot de passe oublié ?".

Il lui suffit de renseigner son email ou son identifiant, et un email avec un lien de réinitialisation lui est envoyé.

Le contenu de ce mail sera à définir dans un template ".email.twig" (Email/password_resetting.email.twig ; dossier app/Resources/views).

{% block subject %
    [... subject ...]
{% endblock %}

{% block body_html %}
    [... content ...]
{% endblock %}

Il y a un temps d'attente entre chaque demande de reset du mot de passe. Si les demandes sont trop rapprochées dans le temps, le template  resetting/password_already_requested est affiché. Par défaut : "Un nouveau mot de passe a déjà été demandé pour cet utilisateur dans les dernières 24 heures".

Ce temps entre chaque demande est paramétrable (fichier config.yml) :

fos_user:
    resetting:
       email:
           token_ttl: 43200

Par défaut, le token_ttl est à 86400 (secondes soit 24h).

Fichier config.yml complet :

fos_user:
   db_driver: orm
   firewall_name: main
   user_class: Me\UserBundle\Entity\User
   from_email:
      address: %fos_user_from_email_address%
      sender_name: %fos_user_from_email_sender_name%
   change_password:
      form:
          type: me_user_change_password
    service:
       mailer: fos_user.mailer.twig_swift
    resetting:
       email:
           template: Email/password_resetting.email.twig
           token_ttl: 43200

 

Les formulaires de FOSUserBundle pour :

  • obtenir un lien de réinitialisation de mot de passe (views/Resetting/request_content.html.twig)
  • réinitialiser le mot de passe ;
  • ...

sont tous re-définissables à condition de les créer dans la même hiérachie de dossier que le FOSUserBundle, donc dans "views/Resetting/" (ou dans "views/Security" pour le template de login).

On peut aussi surcharger le contrôleur et ainsi les différentes étapes du processus du reset de mot de passe.

 

ResettingController extends FOS\UserBundle\Controller\ResettingController

-> requestAction() : demande pour un lien de réinitialisation

-> sendEmailAction() : vérification  que le "username"  (si saisi) existe

-> checkEmailAction() : vérifie que l'email (si saisi) existe ; si toutes les vérifications passent, alors un mail est envoyé.

-> resetAction() : le lien présent dans le mail permet de fournir le token qui va permettre de ré-initialiser / changer le mot de passe du user. NB : l'utilisateur peut redemander un reset du mot de passe dès à présent, sans attendre les "24h" (champ "password_requested_at" remis à NULL).

2 commentaires

  1. Bonjour,

    Merci pour ce super article, il y a très peu de ressources sur la manière de surcharger les contrôleurs de FOSUserBundle.

    Cependant, lorsque j’essaye de surcharger la méthode de changement de mot de passe de Symfony, j’obtiens une erreur du type « Could not load type : me_user_change_password »

    Pourriez-vous m’aider sur ce point ?
    Je suis sous Symfony 3.

    Merci par avance.

    Michael

  2. Bonjour,
    Merci pour le tuto, mais j’ai exactement le même problème que Michael et suis aussi sous Symfony 3, le 3.4 exactement.
    Je ne comprends pas le message, j’ai vérifié et fait vérifier les nomenclatures, et elles sont correctes.

    De l’aide ne serait pas de refus 😉

    Merci

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.