IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Symfony PHP Discussion :

Utilisation d'une classe user custom et encodage [3.x]


Sujet :

Symfony PHP

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2017
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Septembre 2017
    Messages : 4
    Points : 8
    Points
    8
    Par défaut Utilisation d'une classe user custom et encodage
    Bonjour à tous,

    J'ai voulu m’entraîner sur du symfony3 en créant une classe user custom. La classe fonctionne bien, je peux créer mes users sans problème.
    Je suis passé à l'étape suivante à savoir un CRUD pour les users en utilisant Sonata. L'installation de sonata est ok le listing des users et leurs suppressions aussi mais pas la création. En effet je n'arrive pas à utilise la fonction d'encodage proposé dans la doc de symfony.

    mon entité user

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    <?php
     
    namespace AppBundle\Entity;
     
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Component\Validator\Constraints as Assert;
    use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
    use Symfony\Component\Security\Core\User\UserInterface;
     
    /* implémentation manuel d'un user selon la doc sf3.3
     * utilisation des champs email et username en unique pour ne pas avoir de doublon
     */
     
    /**
     * @ORM\Table(name="users")
     * @ORM\Entity(repositoryClass="AppBundle\Repository\UserRepository")
     * @UniqueEntity(fields="email", message="Email already taken")
     * @UniqueEntity(fields="username", message="Username already taken")
     */
    class User implements UserInterface, \Serializable
    {
        /**
         * @ORM\Column(type="integer")
         * @ORM\Id
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        private $id;
     
        /**
         * @ORM\Column(type="string", length=25, unique=true)
         */
        private $username;
     
        /**
         * @ORM\Column(type="string", length=25)
         */
        private $firstname;
     
         /**
         * @ORM\Column(type="string", length=25)
         */
        private $lastname;
     
        /**
         * @ORM\Column(type="string", length=64)
         */
        private $password;
     
        // A noter l'absence de @ORM\Column plainPassword n'est pas enregistré en bdd
        //sert juste pour vérifier le mdp du user
     
         /**
         * @Assert\NotBlank()
         * @Assert\Length(max=4096)
         */
        private $plainPassword;
     
        /**
         * @ORM\Column(type="string", length=60, unique=true)
         */
        private $email;
     
        /**
         * @ORM\Column(type="array")
         */
        private $roles;
     
        /**
         * @ORM\Column(name="is_active", type="boolean")
         */
        private $isActive;
     
        public function __construct()
        {
            $this->isActive = true;
            // may not be needed, see section on salt below
            // $this->salt = md5(uniqid(null, true));
        }
     
        public function getSalt()
        {
            // you *may* need a real salt depending on your encoder
            // see section on salt below
            return null;
        }    
     
        public function getRoles()
        {
            return $this->roles;
        }
     
         public function setRoles($role)
        {
            $this->roles = $role;
        } 
     
        public function eraseCredentials()
        {
     
        }
     
        public function getId() {
            return $this->id;
        }
     
        public function getUsername() {
            return $this->username;
        }
     
        public function getPassword() {
            return $this->password;
        }
     
        public function getEmail() {
            return $this->email;
        }
     
        public function getIsActive() {
            return $this->isActive;
        }
     
        public function setId($id) {
            $this->id = $id;
        }
     
        public function setUsername($username) {
            $this->username = $username;
        }
     
        public function setPassword($password) {
            $this->password = $password;
        }
     
        public function setEmail($email) {
            $this->email = $email;
        }
     
        public function getFirstname() {
            return $this->firstname;
        }
     
        public function getLastname() {
            return $this->lastname;
        }
     
        public function setFirstname($firstname) {
            $this->firstname = $firstname;
        }
     
        public function setLastname($lastname) {
            $this->lastname = $lastname;
        }
     
     
        public function setIsActive($isActive) {
            $this->isActive = $isActive;
        }
     
        public function getPlainPassword() {
            return $this->plainPassword;
        }
     
        public function setPlainPassword($plainPassword) {
            $this->plainPassword = $plainPassword;
        }
     
     
        /** @see \Serializable::serialize() */
        public function serialize()
        {
            return serialize(array(
                $this->id,
                $this->username,
                $this->password,
                // see section on salt below
                // $this->salt,
            ));
        }
     
        /** @see \Serializable::unserialize() */
        public function unserialize($serialized)
        {
            list (
                $this->id,
                $this->username,
                $this->password,
                // see section on salt below
                // $this->salt
            ) = unserialize($serialized);
        }
     
    }

    le code du registration (avec le encode password qui fonctionne bien dans ce cas la )

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    <?php
     
    namespace AppBundle\Controller;
     
    use AppBundle\Form\UserType;
    use AppBundle\Entity\User;
    use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
    use Symfony\Bundle\FrameworkBundle\Controller\Controller;
    use Symfony\Component\HttpFoundation\Request;
    use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
    use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
     
    class RegistrationController extends Controller
    {
        /**
         * @Route("/register", name="user_registration")
         */
        public function registerAction(Request $request, UserPasswordEncoderInterface $passwordEncoder, \Swift_Mailer $mailer)
        {
     
            $user = new User();
            $form = $this->createForm(UserType::class, $user);
            $form->handleRequest($request);
            if ($form->isSubmitted() && $form->isValid()) {
     
                // utilisation de PlainPassword mais seul le password encodé est enregistré
                $password = $passwordEncoder->encodePassword($user, $user->getPlainPassword());
                $user->setPassword($password);
     
                // sauvegarde du user
                $em = $this->getDoctrine()->getManager();
                $em->persist($user);
                $em->flush();
        }
     
     
    }
    Par contre je n'arrive pas à utilise le encodePassword dans ma classe spécifique à sonata.
    En commentaire j'ai indiqué mes tentatives.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
     
    <?php
     
    namespace AppBundle\Admin;
     
    use Sonata\AdminBundle\Admin\AbstractAdmin;
    use Sonata\AdminBundle\Show\ShowMapper;
    use Sonata\AdminBundle\Form\FormMapper;
    use Sonata\AdminBundle\Datagrid\ListMapper;
    use Sonata\AdminBundle\Datagrid\DatagridMapper;
    use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;
    use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
    use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
    use Symfony\Component\Security\Core\Encoder\UserPasswordEncoder;
    use AppBundle\Entity\User;
     
    class UserAdmin extends AbstractAdmin 
    {
     
        //https://sonata-project.org/bundles/admin/master/doc/reference/getting_started.html
        // champs visible pour create/edit forms
        protected function configureFormFields(FormMapper $formMapper)
        {
            $formMapper
                //lecture de l'ensemble des propriétés de l'entité de la classe user
                ->add('username')
                ->add('firstname')
                ->add('lastname')
                ->add('email')
                ->add('plainPassword', 'password')
                ->add('roles', 'choice', array('choices' => array(
                      'ROLE_ADMIN' => 'ROLE_ADMIN',
                      'ROLE_MANAGER' => 'ROLE_MANAGER',
                      'ROLE_USER' => 'ROLE_USER'),
                      'multiple' => true,))
               ->add('isActive')
           ;
        }
        // Fields to be shown on filter forms
        protected function configureDatagridFilters(DatagridMapper $datagridMapper)
        {
           $datagridMapper
                ->add('username')
                ->add('firstname')
                ->add('lastname')
                ->add('email')
                ->add('isActive')
     
           ;
        }
     
        // Fields to be shown on lists
        protected function configureListFields(ListMapper $listMapper)
        {
            $listMapper
                ->add('username')
                ->add('firstname')
                ->add('lastname')
                ->add('email')
                ->add('isActive')
           ;
        }
     
        // Fields to be shown on show action
        protected function configureShowFields(ShowMapper $showMapper)
        {
            $showMapper
                ->add('username')
                ->add('firstname')
                ->add('lastname')
                ->add('email')
                ->add('isActive')
           ;
        }
     
     
        //avant d'enregistrer les infos en bdd
        // verification que c'est bien un objet user
        // sur le password prendre celui du plain text et l'encoder dans la proprieté password
        public function prePersist($object) {
            if($object instanceof User != TRUE){
                return false;
            }else{
                $textPassword = $object->getPlainPassword();
                //check au cas si le password n'est pas vide
                if(!empty($textPassword)){
    //                $logger = $this->container->get('security.password_encoder'); => n'etendant pas un BaseControlleur $this->container n'est pas disponible
                    $logger = $this->get('EncodePassword');
    //                $encodePassword = $logger->encodePassword($object, $textPassword, $toto); => ne fonctionne pas
                    var_dump($encodePassword);die;
                }else{
                    return FALSE;
                }
            }
            var_dump($object);die;
        }
    }
    Si quelqu'un à une astuce je suis preneur.
    En vous remerciant.

  2. #2
    Membre émérite

    Profil pro
    Inscrit en
    Mai 2008
    Messages
    1 576
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 1 576
    Points : 2 440
    Points
    2 440
    Par défaut
    Il faut que tu injectes un object UserPasswordEncoderInterface dans le constructeur de ta classe pour pouvoir l'utiliser ensuite. N'oublie pas de le configurer dans tes services si tu n'as pas l'autowiring activé.

  3. #3
    Membre émérite

    Profil pro
    Inscrit en
    Mai 2008
    Messages
    1 576
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2008
    Messages : 1 576
    Points : 2 440
    Points
    2 440
    Par défaut
    Par ailleurs, la présence de la contrainte "Not Blank" pour $plainPassword va entraîner une erreur lorsque l'utilisateur modifie son nom ou son email seulement: symfony ne va pas accepter que le champ $plainPassword reste vide.

  4. #4
    Futur Membre du Club
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2017
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine et Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Septembre 2017
    Messages : 4
    Points : 8
    Points
    8
    Par défaut
    Merci Tsilefy pour ta réponse et désolé pour le temps de réponse qui à été assez long de ma part.

    Avec tes indications en regardant la doc de symfony http://symfony.com/doc/current/servi...ion_types.html je m'en suis inspiré pour mon cas. De plus en regardant http://symfony.com/doc/current/servi...i-changes.html et mon services.yml
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    services:
        # default configuration for services in *this* file
        _defaults:
            # automatically injects dependencies in your services
            autowire: true
            # automatically registers your services as commands, event subscribers, etc.
            autoconfigure: true
            # this means you cannot fetch services directly from the container via $container->get()
            # if you need to do this, you can override this setting on individual services
            public: false
    je me suis c'est bon j'ai juste à injecté dans le controlleur une variable typé selon la classe userPasswordEncoder et c'est bon

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        private $encodePassword;
     
        public function __construct($code, $class, $baseControllerName, UserPasswordEncoder $encodePassword) {
            parent::__construct($code, $class, $baseControllerName);
            $this->encodePassword =  $encodePassword;
        }
    Cependant ça me met une erreur

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Catchable Fatal Error: Argument 4 passed to AppBundle\Admin\UserAdmin::__construct() must be an instance of AppBundle\Admin\UserPasswordEncoder, none given,
    Bon qu'a cela ne tienne je rajoute dans la déclaration du service l'argument comme tu me l'a indiqué

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    #creation du fichier qui liste l'ensemble des admin que l'on va creer avec sonata
    services:
        app.admin.user:
            class: AppBundle\Admin\UserAdmin
            tags:
                - { name: sonata.admin, manager_type: orm, group: "Content", label: "User" }
            arguments:
                #1er et 3eme argument optionnel (code du service et controlleur à utiliser (par défaut celui de sonata crud)  
                # seul le second déclaration de la classe sur laquelle le service doit agir (mappage)
                # le 4 argument permet de passer des services par exemple (a implementer dans le constructeur de userAdmin du coup)
                - ~
                - AppBundle\Entity\User
                - ~
                - security.user_password_encoder.generic  => appelle du service
            calls:
                - [ setTranslationDomain, [AppBundle]]
    ce qui me met une erreur comme quoi j'appelle une string et non une classe.

    Dans mon terminal en lançant la commande qui permet d'avoir des infos sur les services de symfony (pour le userPassword) j'obtiens

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
     
    php bin/console debug:container password
     
     Select one of the following services to display its information:
      [0] form.type.password
      [1] security.user_password_encoder.generic
      [2] security.validator.user_password
      [3] security.console.user_password_encoder_command
      [4] security.password_encoder
      [5] console.command.symfony_bundle_securitybundle_command_userpasswordencodercommand
     > 4
     
     
     // This service is an alias for the service security.user_password_encoder.generic                                     
     
    Information for Service "security.user_password_encoder.generic"
    ================================================================
     
     ---------------- ------------------------------------------------------------- 
      Option           Value                                                        
     ---------------- ------------------------------------------------------------- 
      Service ID       security.user_password_encoder.generic                       
      Class            Symfony\Component\Security\Core\Encoder\UserPasswordEncoder  
      Tags             -                                                            
      Public           no                                                           
      Synthetic        no                                                           
      Lazy             no                                                           
      Shared           yes                                                          
      Abstract         no                                                           
      Autowired        no                                                           
      Autoconfigured   no                                                           
     ---------------- -------------------------------------------------------------
    et comme on peut le voir l'Autowired n'est pas activé pour ce service. Pourtant au vu du services.yml ça ne devrait pas être ok ?

    Comment puis-je faire ?
    Merci d'avance.

    EDIT : j'ai trouvé
    Il suffisait de mettre au niveau du 4éme argument de ma classe
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    '@security.user_password_encoder.generic'
    et la je peux instancier le userPasswordEncoder dans mon userAdmin

    code du construct du userAdmin
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
        private $encodingPassword;
     
        public function __construct($code, $class, $baseControllerName, UserPasswordEncoder $encodePassword) {
            parent::__construct($code, $class, $baseControllerName);
            $this->encodingPassword =  $encodePassword;
        }
    Voila et merci encore Tsilefy

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Utilisation d'une classe User
    Par Jenojen dans le forum Langage
    Réponses: 6
    Dernier message: 07/04/2011, 11h49
  2. Réponses: 4
    Dernier message: 08/11/2005, 15h10
  3. ou mettre une structure utilisée par une classe
    Par grand's dans le forum C++
    Réponses: 10
    Dernier message: 28/07/2005, 18h53
  4. Réponses: 8
    Dernier message: 22/12/2004, 22h57
  5. Réponses: 2
    Dernier message: 18/05/2004, 14h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo