Admin des utilisateurs avec EasyAdmin

Publié le 21/10/2019
Admin des utilisateurs avec EasyAdmin

EasyAdmin est un bundle symfony très pratique qui permet d'administrer ses entités. Son principal avantage, face à une machine de guerre comme le bundle Sonata Admin, est qu'il est très simple à paramétrer. Toute la configuration est faite grâce à des fichiers Yaml.

Sauf que dans certains cas, on est bien obligé de mettre les mains dans le cambouis!

Le composant Security de Symfony 4 étant très complet, l'usage de FOSUserBundle n'est plus nécessaire. Sauf que ce dernier apportait une couche intéressante, la gestion simple des utilisateurs. J'ai donc tout naturellement pensé à EasyAdmin pour gérer mes utilisateurs, après tout, dans Symfony, un User se matérialise (entre autres) par une entité.

Mais je me suis retrouvé face à un problème: comment modifier le mot de passe d'un utilisateur? En effet, celui-ci est encodé en base de données, par mesure de sécurité.

Heureusement, tout est prévu dans EasyAdmin pour palier à ce genre de cas :)

Tout d'abord, nous allons ajouter une propriété à notre entité User, qui ne sera pas mappée avec la base de données. Cette propriété, que nous allons nommer plainPassword, sera le mot de passe saisi dans l'interface d'administration pour modifier le mot de passe d'un utilisateur. Nous n'allons donc surtout pas l'enregistrer en base de données.

class User implements UserInterface
{
    // ......
    /**
     * @var string
     */
    private $plainPassword;
     
    // ......

     /**
     * @return string
     */
    public function getPlainPassword(): ?string
    {
        return $this->plainPassword;
    }

    /**
     * @param string $plainPassword
     * @return User
     */
    public function setPlainPassword(string $plainPassword): User
    {
        $this->plainPassword = $plainPassword;
        return $this;
    }

C'est cette propriété plainPassword que nous utiliserons dans EasyAdmin pour la modification du mot de passe.

Il est possible d'étendre le controlleur de base d'EasyAdmin, afin de réaliser des traitements particuliers.
Pour cela, il faut déclarer le controlleur à EasyAdmin dans la configuration yaml de EasyAdmin :

easy_admin:
    entities:
        User:
            class: App\Entity\User\User
            # Notre controller spécifique
            controller: App\Controller\Admin\User\UserAdminController
            form:
                fields:
                    # Fomulaire de création / modification d'un utilisateur
                    - { property: 'email'}
                    # Ici on retrouve notre propriété plainPassword pour la modification du mot de passe 
                    - { property: 'plainPassword', type: 'password', type_options: { required: false }}

Ici, on va utiliser un UserAdminController que nous allons créer. Ce controller devra simplement étendre le controller de base EasyAdmin. Nous allons charger le UserPasswordEncoder qui va nous permettre d'encoder le mot de passe modifié, en l'appelant dans le constructeur de notre controller. Merci à l'autowiring de Symfony!


namespace App\Controller\Admin\User;

use App\Entity\User\User;
use EasyCorp\Bundle\EasyAdminBundle\Controller\EasyAdminController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;

class UserAdminController extends EasyAdminController
{
    /**
     * @var UserPasswordEncoderInterface
     */
    private $passwordEncoder;

    public function __construct(UserPasswordEncoderInterface $passwordEncoder)
    {
        $this->passwordEncoder = $passwordEncoder;
    }

    public function persistUserEntity($user)
    {
        // Avec FOSUserBundle, on faisait comme ça :
        // $this->get('fos_user.user_manager')->updateUser($user, false);
        $this->updatePassword($user);
        parent::persistEntity($user);
    }

    public function updateUserEntity($user)
    {
        // Avec FOSUserBundle, on faisait comme ça :
        //$this->get('fos_user.user_manager')->updateUser($user, false);
        $this->updatePassword($user);
        parent::updateEntity($user);
    }

    public function updatePassword(User $user)
    {
        if (!empty($user->getPlainPassword())) {
            $user->setPassword($this->passwordEncoder->encodePassword($user, $user->getPlainPassword()));
        }
    }
}

Qu'avons-nous fait? Nous sommes intervenus au niveau de l'ajout et de la modification d'une entité Utilisateur (dans notre interface d'admin) pour simplement encoder notre mot de passe avant enregistrement par Doctrine...

Simple et efficace, non ?

Commentaires
Merci, bonnes bases pour démarrer
Ajoutez votre commentaire