Partage
  • Partager sur Facebook
  • Partager sur Twitter

Comment bloquer des champs d'un formbuilder

En symfony 3

Sujet résolu
    17 septembre 2018 à 19:57:52

    Bonsoir,

    Au fait je voudrais modifier les champs d'un admin, tout en sachant qu'un admin est un user.

    Mais je veux que l'admin ne modifie que certains champs seulement et pas tous les champs que peut avoir un user. Je veux que l'admin ne modifie que son username, son password et son numéro de tel.

    Mais lors de mon affichage tous les champs apparaissent, même ceux qui ne sont pas souhaités.

    Voici mon formbuilder 

    <?php
    
    namespace Doctix\AdminBundle\Form;
    
    
    use Doctix\UserBundle\Form\UserType;
    use Doctix\UserBundle\Entity\User;
    use Symfony\Component\Form\AbstractType;
    use Symfony\Component\Form\FormBuilderInterface;
    use Symfony\Component\OptionsResolver\OptionsResolver;
    use Symfony\Component\Form\Extension\Core\Type\EmailType;
    use Symfony\Component\Form\Extension\Core\Type\PasswordType;
    use Symfony\Component\Form\Extension\Core\Type\TelType;
    class AdminType extends AbstractType
    {
        /**
         * @param FormBuilderInterface $builder
         * @param array $options
         */
        public function buildForm(FormBuilderInterface $builder, array $options)
        {
            $builder->add('user', UserType::class)
            ;
        }
        
        /**
         * @param OptionsResolver $resolver
         */
        public function configureOptions(OptionsResolver $resolver)
        {
            $resolver->setDefaults(array(
                'data_class' => 'Doctix\AdminBundle\Entity\Admin'
            ));
        }
    }
    

    Et voici ma vue

    <div class="box_general padding_bottom">
    
                       {{ form_start(form,{'attr': {'id': 'form1'}}) }}
    
    
                       {% if form.user.username is defined %}
                            <div class="form-group">
                                <label for="inputEmail" class="col-md-2 control-label">Email</label>
                                <div class="col-md-10">
                                    {{ form_widget(form.user.username, {'attr': {'class': 'form-control','placeholder':'Email'}}) }}
                                </div>
                            </div>
                            {% endif %}
                            {% if form.user.password is defined %}
                            <div class="form-group">
                                <label for="inputPassword" class="col-md-5 control-label">Mot de passe</label>
                                <div class="col-md-10">
                                    {{ form_widget(form.user.password, {'attr': {'class': 'form-control','placeholder':'Password'}}) }}
                                </div>
                            </div>
                            {% endif %}
                           {% if form.user.numTel is defined %} 
                            <div class="form-group">
                                <label for="inputPassword" class="col-md-5 control-label">N° Téléphone</label>
                                <div class="col-md-10">
                                    {{ form_widget(form.user.numTel, {'attr': {'class': 'form-control','placeholder':'N° Téléphone'}}) }}
                                </div>
                            </div>
                            {% endif %} 
    
                                  {{ form_end(form) }}
                        </div>
    
    
                         <div class="panel-footer">
                            <div class="row">
                                <div class="col-md-offset-3 col-md-3">
                                    <button class="btn btn-success btn-lg" form="form1"> Valider</button>
                                </div>
                                <div class="col-md-3">
                                    <a  href="{{ path('doctix_admin_users_parametre') }}" class=" btn btn-danger btn-lg">Annuler </a>
                                </div>
                            </div>
                        </div>

    Et voici l'image de mon affichage



    Sur l'image, je ne veux que les 3 premières lignes, et pas ce qui suit en bas. Et que la modification lors du clic valider prenne effet

    Voici mon controller:

    public function editprofilAction(Request $request){
               $user = $this->getUser();
            if($user===null){
                throw new NotFoundHttpException('Utilisateur Inexistant');
            }
    
            else {
                $em = $this->getDoctrine()->getManager();
                $repo = $em->getRepository('DoctixAdminBundle:Admin');
                $admin = $repo->findOneBy(array(
                    'user' => $user,
                ));
                $form = $this->createForm('Doctix\AdminBundle\Form\AdminType', $admin);
                $form->handleRequest($request);
                if ($form->isSubmitted() && $form->isValid()) {
    
                    $admin->getUser()->setSalt('');
                    $factory = $this->get('security.encoder_factory');
                    $encoder = $factory->getEncoder($admin->getUser());
                    $password_encoder = $encoder->encodePassword($admin->getUser()->getPassword(), $admin->getUser()->getSalt());
                    $admin->getUser()->setPassword($password_encoder);
                    $admin->getUser()->setRoles(array('ROLE_ADMIN'));
                    $em->flush();
                    // creation d'un flash bag pour une notification flash
                    $request->getSession()->getFlashBag()->add('Notice', 'Profil Modifié avec succés');
                    // redirection
                    $url = $this->generateUrl('doctix_admin_users_parametre');
                    // redirection permanente avec le status http 301 ::)))))
                    return $this->redirect($url,301);
    
                }else{
                    return $this->render('DoctixAdminBundle:User:editprofil.html.twig', array(
                        'form' => $form->createView()
                    ));
                }
    
    
            }
            
        }

    Merci beaucoup

    • Partager sur Facebook
    • Partager sur Twitter
      17 septembre 2018 à 20:57:57

      Bonjour,

      Suggestion,

      Dans le form builder tester si le user est l'admin et si c'est le cas, faire un remove des champs qui ne doivent pas être présentés.

      A+

      • Partager sur Facebook
      • Partager sur Twitter
        17 septembre 2018 à 23:59:30

        Bonjour,

        Il y a la solution proposée par Monkey3d sans doute la meilleure mais qui impose de connaître le user dans le formtype.

        Une autre solution est de faire un formType specifique pour l'admin et de faire le test dans le controler qui appelle le form

        • Partager sur Facebook
        • Partager sur Twitter
          18 septembre 2018 à 0:35:12

          Salut @Monkey3d et @CarréDas1, j'ai modifié mon form_end en cela:  {{ form_end(form, {'render_rest':false}) }} et ça a reglé mon problème d'affichage. Mais quand je clique sur le bouton valider, les modifs que j'apporte aux champs de saisies ne prennent pas effet.

          Si quelqu'un aurait une idée.

          Merci.

          • Partager sur Facebook
          • Partager sur Twitter
            18 septembre 2018 à 7:23:58

            Oui c'est normal car en enlevant le render_rest tu désactives la protection CSRF ... donc soit tu l'as mets à la main c'est indiqué comment faire dans la doc Symfony suivant ta version

            soit tu adoptes une des 2 solutions indiquées ci-dessus.

            A+

            • Partager sur Facebook
            • Partager sur Twitter
              18 septembre 2018 à 11:55:36

              Oui cela est dû au render_rest qui a été enlevé. 

              Mais @monkey3d, comment faire un test sur l'user, sachant aussi, que je declare dans le formbuilder ->add('user', UserType::class), et comment faire un remove des champs voulus sachant que le usertype ramène tous les champs.

              Merci

              • Partager sur Facebook
              • Partager sur Twitter
                18 septembre 2018 à 12:57:01

                Tu as bien un critère pour savoir que le user est administrateur.

                Donc tu passes le critère au formbuilder via les options.

                Dans ton formbuilder, tu testes l'option passée et si c'est administrateur tu remove les champs de l'entité User que tu ne veux pas ... et dans la vue d'affichage tu n'auras que les champs qui ne sont pas removés.

                Et bien-sûr tu actives la protection CSRF.

                Regarde un peu la doc Symfony correspondante à ta version c'est bien expliqué.

                C'est assez simple à faire et c'est 2 mécanismes importants à connaître voire à maîtriser dans un développement Symfony

                - savoir passer des options du contrôleur au form

                - savoir modifier un form dynamiquement.

                A+

                • Partager sur Facebook
                • Partager sur Twitter
                  18 septembre 2018 à 14:04:04

                  Salut @monkey3d, j'ai fait comme vous me l'avez suggéré, mais cela ne m'affiche aucun de mes champs.

                  Voilà mon formtype modifié:

                  <?php
                  
                  namespace Doctix\AdminBundle\Form;
                  
                  
                  use Doctix\UserBundle\Form\UserType;
                  use Doctix\UserBundle\Entity\User;
                  use Symfony\Component\Form\AbstractType;
                  use Symfony\Component\Form\FormBuilderInterface;
                  use Symfony\Component\OptionsResolver\OptionsResolver;
                  use Symfony\Component\Form\Extension\Core\Type\EmailType;
                  use Symfony\Component\Form\Extension\Core\Type\PasswordType;
                  use Symfony\Component\Form\Extension\Core\Type\TelType;
                  
                  use Symfony\Component\HttpFoundation\Request;
                  use Symfony\Component\HttpFoundation\Response;
                  use Symfony\Component\Security\Core\Security;
                  use Symfony\Component\Security\Core\Tests\Encoder;
                  
                  class AdminType extends AbstractType
                  {
                     
                  
                      /**
                       * @param FormBuilderInterface $builder
                       * @param array $options
                       */
                      public function buildForm(FormBuilderInterface $builder, array $options)
                      {
                            $user = new User();
                         // $user = $this->getUser();
                          if ($user->getRoles() == array('ROLE_ADMIN')){
                  
                      $builder->add('username',EmailType::class)
                              ->add('password',PasswordType::class)
                              ->add('numTel',TelType::class)
                              ->remove('prenom')
                              ->remove('nom')
                              ->remove('adresse');
                              
                          }
                       }    
                  
                           /**
                            * @param OptionsResolver $resolver
                           */
                      public function configureOptions(OptionsResolver $resolver)
                      {
                          $resolver->setDefaults(array(
                              'data_class' => 'Doctix\AdminBundle\Entity\Admin'
                          ));
                      }
                      
                     
                  
                  }

                  Et j'ai juste mis {{ form_end(form) }} à la fin de mon form dans ma vue

                  • Partager sur Facebook
                  • Partager sur Twitter
                    18 septembre 2018 à 21:40:55

                    Bonjour,

                    J'avais indiqué dans mon post que la méthode proposée par monkey3d nécessite de passer l'user dans le form ce que tu n'as  pas fait.

                    Tu mets un new user donc aucun risque qu'il soit admin et donc les champs ne s'enlève pas.

                    Je reviens donc à mon premier post.

                    Soit tu transferts le user et fais comme monkey propose soit tu fais le test sur user.roles is admin dans ton controler et tu renvoie pour ce cas à un form builder type qui contient uniquement les champs que tu souhaites.

                    A toi

                    • Partager sur Facebook
                    • Partager sur Twitter
                      19 septembre 2018 à 9:50:45

                      Comme le relève CarréDas1, tu n'as pas fait ce que je t'ai indiqué :

                      Tu n'as passé aucun paramètre au form ....

                      Dans le form tu fais la création d'un nouvel utilisateur, il serait bien étonnant qu'un nouvel utilisateur est le rôle d'administrateur ...

                      Donc soit tu poursuis ma manière de faire - et au delà de la solution que j'ai proposé cela te permet de comprendre 2 points importants sur l'utilisation de Symfony (cf mon post) - soit tu fais la solution de CarréDas1 qui tient la route.

                      A+

                      • Partager sur Facebook
                      • Partager sur Twitter
                        19 septembre 2018 à 13:16:25

                        CarréDas1 a écrit:

                        Bonjour,

                        J'avais indiqué dans mon post que la méthode proposée par monkey3d nécessite de passer l'user dans le form ce que tu n'as  pas fait.

                        Tu mets un new user donc aucun risque qu'il soit admin et donc les champs ne s'enlève pas.

                        Je reviens donc à mon premier post.

                        Soit tu transferts le user et fais comme monkey propose soit tu fais le test sur user.roles is admin dans ton controler et tu renvoie pour ce cas à un form builder type qui contient uniquement les champs que tu souhaites.

                        A toi


                        Bonjour, c'est ce que j'essaie en ce moment, tester l'user dans mon controller, et d'envoyer sur mon admintype, mais hélas les champs que contient mon form sont de type user, qui ne sont pas dans l'entité Admin, et l'erreur  " Neither the property username nor one of the methods... apparâit.

                        Voici mon controller modifié:

                         public function editprofilAction(Request $request){
                                   $user = $this->getUser();
                                if($user===null){
                                    throw new NotFoundHttpException('Utilisateur Inexistant');
                                }
                        
                                elseif($user->getRoles() == array('ROLE_ADMIN')){
                                    $em = $this->getDoctrine()->getManager();
                                    $repo = $em->getRepository('DoctixAdminBundle:Admin');
                                    $admin = $repo->findOneBy(array(
                                        'user' => $user,
                                    ));
                                    $form = $this->createForm('Doctix\AdminBundle\Form\AdminType', $admin);
                                    $form->handleRequest($request);
                                    if ($form->isSubmitted() && $form->isValid()) {
                        
                                        $admin->getUser()->setSalt('');
                                        $factory = $this->get('security.encoder_factory');
                                        $encoder = $factory->getEncoder($admin->getUser());
                                        $password_encoder = $encoder->encodePassword($admin->getUser()->getPassword(), $admin->getUser()->getSalt());
                                        $admin->getUser()->setPassword($password_encoder);
                                        $admin->getUser()->setRoles(array('ROLE_ADMIN'));
                                        $em->flush();
                                        // creation d'un flash bag pour une notification flash
                                        $request->getSession()->getFlashBag()->add('Notice', 'Profil Modifié avec succés');
                                        // redirection
                                        $url = $this->generateUrl('doctix_admin_users_parametre');
                                        // redirection permanente avec le status http 301 ::)))))
                                        return $this->redirect($url,301);
                        
                                    } else{
                                        return $this->render('DoctixAdminBundle:User:editprofil.html.twig', array(
                                            'form' => $form->createView()
                                        ));
                                    }
                        
                        
                                }
                                
                            }

                        et mon AdminType:

                        <?php
                        
                        namespace Doctix\AdminBundle\Form;
                        
                        
                        use Doctix\UserBundle\Form\UserType;
                        use Doctix\UserBundle\Entity\User;
                        use Symfony\Component\Form\AbstractType;
                        use Symfony\Component\Form\FormBuilderInterface;
                        use Symfony\Component\OptionsResolver\OptionsResolver;
                        use Symfony\Component\Form\Extension\Core\Type\EmailType;
                        use Symfony\Component\Form\Extension\Core\Type\PasswordType;
                        use Symfony\Component\Form\Extension\Core\Type\TelType;
                        
                        /*  use Symfony\Component\HttpFoundation\Request;
                        use Symfony\Component\HttpFoundation\Response;
                        use Symfony\Component\Security\Core\Security;
                        use Symfony\Component\Security\Core\Tests\Encoder;
                        
                        */
                        
                        class AdminType extends AbstractType
                        {
                           
                        
                            /**
                             * @param FormBuilderInterface $builder
                             * @param array $options
                             */
                            public function buildForm(FormBuilderInterface $builder, array $options)
                            {
                                  
                        
                            $builder->add('username',EmailType::class)
                                    ->add('password',PasswordType::class)
                                    ->add('numTel',TelType::class);
                                    
                             }    
                        
                                 /**
                                  * @param OptionsResolver $resolver
                                 */
                            public function configureOptions(OptionsResolver $resolver)
                            {
                                $resolver->setDefaults(array(
                                    'data_class' => 'Doctix\AdminBundle\Entity\Admin'
                                ));
                            }
                            
                           
                        
                        }
                        

                        Et excusez moi @CarréDas1 et @monkey3d de mes incompréhensions.

                        Merci.


                        • Partager sur Facebook
                        • Partager sur Twitter
                          19 septembre 2018 à 14:19:25

                          Bonjour,

                          Tout cela est tres normal. Tu passes en paramètre du forme type un $admin alors qu'il faut passer $admin->getUser() si j'ai bien compris l'organisation non présentée de ton entité admin

                          A toi

                          • Partager sur Facebook
                          • Partager sur Twitter
                            19 septembre 2018 à 15:31:08

                            Salut, voilà je l'ai ajouté mais ça m'affiche l'erreur suivante: Call to a member function getUser() on null alors que j'ai bien le getter getUser() dans mon entité admin.

                            Voici mon admin: 

                            <?php
                            
                            namespace Doctix\AdminBundle\Entity;
                            
                            use Doctrine\ORM\Mapping as ORM;
                            
                            /**
                             * Admin
                             *
                             * @ORM\Table(name="admin")
                             * @ORM\Entity(repositoryClass="Doctix\AdminBundle\Repository\AdminRepository")
                             */
                            class Admin
                            {
                                /**
                                 * @var int
                                 *
                                 * @ORM\Column(name="id", type="integer")
                                 * @ORM\Id
                                 * @ORM\GeneratedValue(strategy="AUTO")
                                 */
                                private $id;
                            
                                /**
                                 * @ORM\OneToOne(targetEntity="Doctix\UserBundle\Entity\User", cascade={"persist"})
                                 * @ORM\JoinColumn(nullable=false)
                                 */
                                private $user;
                            
                               /**
                                 * Get id
                                 *
                                 * @return int
                                 */
                                public function getId()
                                {
                                    return $this->id;
                                }
                            
                            
                            
                                /**
                                 * Set user
                                 *
                                 * @param \Doctix\UserBundle\Entity\User $user
                                 * @return Patient
                                 */
                                public function setUser(\Doctix\UserBundle\Entity\User $user)
                                {
                                    $this->user = $user;
                            
                                    return $this;
                                }
                            
                                /**
                                 * Get user
                                 *
                                 * @return \Doctix\UserBundle\Entity\User 
                                 */
                                public function getUser()
                                {
                                    return $this->user;
                                }
                            
                            }    

                            Merci beaucoup

                            • Partager sur Facebook
                            • Partager sur Twitter
                              19 septembre 2018 à 17:23:44

                              Au delà du problème actuel qui va se solutionner en suivant les indications et en faisant attention

                              pourquoi as tu fait une classe Admin spécifique ??? qui ne comporte que l'id et un lien vers User ...

                              Il manque peut-être des propriétés mais conceptuellement il me semble qu'un administrateur est un user comme un autre sur le plan des propriétés.

                              Si tu intègres une propriété rôle à un user alors un administrateur est un user qui a le rôle Admin. Alors qu'un user lambda il aura le rôle User, Blogeur, Modérateur, etc ...

                              Car comme tu l'écrivais dans ton premier post :

                              tout en sachant qu'un admin est un user.

                              A+

                              • Partager sur Facebook
                              • Partager sur Twitter
                                19 septembre 2018 à 18:02:02

                                Exactement @monkey3d, c'est d'un point de vue conception que ça coince, au début je n'avais pas d'entité Admin, je l'avais même pas faite, vu qu'un admin est un user et qu'un admin n'a pas de propriétés en plus, donc je l'avais pas mis, et je travaillais avec l'entité User et UserType, mais c'est quand j'ai rencontré une errreur, et que cela buggais, j'ai pensé que cela pouvait se resoudre en créant une entité Admin.

                                Mais si tu peux m'éclairer, sans l'entité Admin, cela m'aiderait beaucoup.

                                Merci

                                • Partager sur Facebook
                                • Partager sur Twitter
                                  19 septembre 2018 à 18:47:20

                                  Bonjour,

                                  Maintenant ca va être simple je pense. Donc tu gardes ton adminType, tu ne te soucies pas de ton entité admin et tu passes en variables dans ton adminType le $user.

                                  Si ton user a le rôle admin alors tu choisis le formType adminType autrement le formtype userType.

                                  Le code pour vérifier si un user est admin est le suivant:

                                  use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
                                  
                                  public function editprofilAction(Request $request,AuthorizationCheckerInterface $authChecker){
                                            $user = $this->getUser();
                                          if (true === $authChecker->isGranted('ROLE_ADMIN')) {
                                              //...l'user est admin
                                          }else{
                                              //......l'user n'est pas admin
                                          }
                                  //.....

                                  A toi

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                    19 septembre 2018 à 19:08:14

                                    @CarréDas1, cela m'affiche une erreur: Controller "Doctix\AdminBundle\Controller\UserController::editprofilAction" requires that you provide a value for the "$authChecker" argument. 

                                    le controller modifié :

                                    public function editprofilAction(Request $request, AuthorizationCheckerInterface $authChecker){
                                    
                                                 $user = $this->getUser();
                                            if (true === $authChecker->isGranted('ROLE_ADMIN')) {
                                                //...l'user est admin
                                    
                                                $em = $this->getDoctrine()->getManager();
                                                $repo = $em->getRepository('DoctixAdminBundle:Admin');
                                                $admin = $repo->findOneBy(array(
                                                    'user' => $user,
                                                ));
                                                $form = $this->createForm('Doctix\AdminBundle\Form\AdminType', $user);
                                                $form->handleRequest($request);
                                                if ($form->isSubmitted() && $form->isValid()) {
                                    
                                                    $admin->getUser()->setSalt('');
                                                    $factory = $this->get('security.encoder_factory');
                                                    $encoder = $factory->getEncoder($admin->getUser());
                                                    $password_encoder = $encoder->encodePassword($admin->getUser()->getPassword(), $admin->getUser()->getSalt());
                                                    $admin->getUser()->setPassword($password_encoder);
                                                    $admin->getUser()->setRoles(array('ROLE_ADMIN'));
                                                    $em->flush();
                                                    // creation d'un flash bag pour une notification flash
                                                    $request->getSession()->getFlashBag()->add('Notice', 'Profil Modifié avec succés');
                                                    // redirection
                                                    $url = $this->generateUrl('doctix_admin_users_parametre');
                                                    // redirection permanente avec le status http 301 ::)))))
                                                    return $this->redirect($url,301);
                                    
                                                }
                                    
                                            }
                                            else{
                                                //......l'user n'est pas admin
                                    
                                                return $this->render('DoctixAdminBundle:User:editprofil.html.twig', array(
                                                        'form' => $form->createView()
                                                    ));
                                                }
                                            }

                                    Et mon formtype AdminType:

                                    namespace Doctix\AdminBundle\Form;
                                    
                                    
                                    use Doctix\UserBundle\Form\UserType;
                                    use Doctix\UserBundle\Entity\User;
                                    use Symfony\Component\Form\AbstractType;
                                    use Symfony\Component\Form\FormBuilderInterface;
                                    use Symfony\Component\OptionsResolver\OptionsResolver;
                                    use Symfony\Component\Form\Extension\Core\Type\EmailType;
                                    use Symfony\Component\Form\Extension\Core\Type\PasswordType;
                                    use Symfony\Component\Form\Extension\Core\Type\TelType;
                                    
                                    /*  use Symfony\Component\HttpFoundation\Request;
                                    use Symfony\Component\HttpFoundation\Response;
                                    use Symfony\Component\Security\Core\Security;
                                    use Symfony\Component\Security\Core\Tests\Encoder;
                                    
                                    */
                                    
                                    class AdminType extends AbstractType
                                    {
                                       
                                    
                                        /**
                                         * @param FormBuilderInterface $builder
                                         * @param array $options
                                         */
                                        public function buildForm(FormBuilderInterface $builder, array $options)
                                        {
                                              
                                    
                                        $builder->add('user', UserType::class)
                                                
                                                
                                         }    
                                    
                                             /**
                                              * @param OptionsResolver $resolver
                                             */
                                        public function configureOptions(OptionsResolver $resolver)
                                        {
                                            $resolver->setDefaults(array(
                                                'data_class' => 'Doctix\UserBundle\Entity\User'
                                            ));
                                        }
                                        
                                       
                                    
                                    }

                                    Merci encore


                                    • Partager sur Facebook
                                    • Partager sur Twitter
                                      19 septembre 2018 à 19:19:59

                                      Re,

                                      1. Tu as bien mis le use en tête de ton controlleur?

                                      2. Sinon je ne vois pas où ca foire. Je te propose une autre stratégie alors. Tu enlèves tout ce qui a trait à $authchecker, y compris dans l'appel de fonction.

                                      3. tu fais le test directement sur $user comme ceci:

                                      public function editprofilAction(Request $request){
                                                $user = $this->getUser();
                                              if (in_array('ROLE_ADMIN', $user->getRoles())) {
                                                  //...l'user est admin
                                              }else{
                                                  //......l'user n'est pas admin
                                              }
                                      //.....

                                      A toi

                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        19 septembre 2018 à 19:31:23

                                        Ok j'ai compris, ,c'est fait mais je crois que le problème suivant vient de mon AdminType, car ça m'affiche l'erreur: 

                                        The form's view data is expected to be an instance of class Doctix\AdminBundle\Entity\Admin, but is an instance of class Doctix\UserBundle\Entity\User. You can avoid this error by setting the "data_class" option to null or by adding a view transformer that transforms an instance of class Doctix\UserBundle\Entity\User to an instance of Doctix\AdminBundle\Entity\Admin

                                        Merci

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                          19 septembre 2018 à 19:48:37

                                          Re,

                                          Mets user au lieu de admin dans ton forme type ligne 46 d'un de tes posts ci-dessus.

                                          <?php
                                           
                                          namespace Doctix\AdminBundle\Form;
                                           
                                           
                                          use Doctix\UserBundle\Form\UserType;
                                          use Doctix\UserBundle\Entity\User;
                                          use Symfony\Component\Form\AbstractType;
                                          use Symfony\Component\Form\FormBuilderInterface;
                                          use Symfony\Component\OptionsResolver\OptionsResolver;
                                          use Symfony\Component\Form\Extension\Core\Type\EmailType;
                                          use Symfony\Component\Form\Extension\Core\Type\PasswordType;
                                          use Symfony\Component\Form\Extension\Core\Type\TelType;
                                           
                                          /*  use Symfony\Component\HttpFoundation\Request;
                                          use Symfony\Component\HttpFoundation\Response;
                                          use Symfony\Component\Security\Core\Security;
                                          use Symfony\Component\Security\Core\Tests\Encoder;
                                           
                                          */
                                           
                                          class AdminType extends AbstractType
                                          {
                                              
                                           
                                              /**
                                               * @param FormBuilderInterface $builder
                                               * @param array $options
                                               */
                                              public function buildForm(FormBuilderInterface $builder, array $options)
                                              {
                                                     
                                           
                                              $builder->add('username',EmailType::class)
                                                      ->add('password',PasswordType::class)
                                                      ->add('numTel',TelType::class);
                                                       
                                               }   
                                           
                                                   /**
                                                    * @param OptionsResolver $resolver
                                                   */
                                              public function configureOptions(OptionsResolver $resolver)
                                              {
                                                  $resolver->setDefaults(array(
                                                      'data_class' => 'Doctix\AdminBundle\Entity\User'
                                                  ));
                                              }
                                               
                                              
                                           
                                          }


                                          -
                                          Edité par CarréDas1 19 septembre 2018 à 19:51:27

                                          • Partager sur Facebook
                                          • Partager sur Twitter
                                            19 septembre 2018 à 20:49:57

                                            @CarréDas1, donc je change mon data_class en 'Doctix\UserBundle\Entity\User', et si je fais cela cet erreur m'apparaît " Call to a member function getUser() on null ", et cela est dû à cette ligne 68 de mon controller:

                                             $admin->getUser()->setSalt(''); 

                                            Car cette variable $admin me permet une fois le form soumis de salt l'admin et de l'attribuer le rôle et de hacher le password.


                                            Voici le controller:

                                            public function editprofilAction(Request $request){
                                            
                                                         $user = $this->getUser();
                                                    if (in_array('ROLE_ADMIN', $user->getRoles())) {
                                                        //...l'user est admin
                                            
                                                        $em = $this->getDoctrine()->getManager();
                                                        $repo = $em->getRepository('DoctixAdminBundle:Admin');
                                                        $admin = $repo->findOneBy(array(
                                                            'user' => $user,
                                                        ));
                                                        $form = $this->createForm('Doctix\AdminBundle\Form\AdminType', $user);
                                                        $form->handleRequest($request);
                                                        if ($form->isSubmitted() && $form->isValid()) {
                                            
                                                            $admin->getUser()->setSalt('');
                                                            $factory = $this->get('security.encoder_factory');
                                                            $encoder = $factory->getEncoder($admin->getUser());
                                                            $password_encoder = $encoder->encodePassword($admin->getUser()->getPassword(), $admin->getUser()->getSalt());
                                                            $admin->getUser()->setPassword($password_encoder);
                                                            $admin->getUser()->setRoles(array('ROLE_ADMIN'));
                                                            $em->flush();
                                                            // creation d'un flash bag pour une notification flash
                                                            $request->getSession()->getFlashBag()->add('Notice', 'Profil Modifié avec succés');
                                                            // redirection
                                                            $url = $this->generateUrl('doctix_admin_users_parametre');
                                                            // redirection permanente avec le status http 301 ::)))))
                                                            return $this->redirect($url,301);
                                            
                                                        }
                                            
                                                    }
                                                    else{
                                                        //......l'user n'est pas admin
                                            
                                                        return $this->render('DoctixAdminBundle:User:editprofil.html.twig', array(
                                                                'form' => $form->createView()
                                                            ));
                                                        }
                                                    }

                                            Merci

                                            -
                                            Edité par msacko796 19 septembre 2018 à 20:52:12

                                            • Partager sur Facebook
                                            • Partager sur Twitter
                                              20 septembre 2018 à 4:47:40

                                              Bonjour,

                                              Je ne comprends plus ta demande!!

                                              Voila ce que tu as dit au premier post:

                                              "Mais je veux que l'admin ne modifie que certains champs seulement et pas tous les champs que peut avoir un user. Je veux que l'admin ne modifie que son username, son password et son numéro de tel."


                                              Maintenant tu parles de modifier le pwd de l'user admin, alors qu'il existe dejà. Bref, il me semble que ta représentation du fonctionnemnt de user est pas encore au top.

                                              Je te suggère donc de clore ce sujet en mettant résolu, et éventuellement d'en ouvrir un autre mais en réfléchissant bien à ce que tu souhaites faire avant de te précipiter à écrire du code.

                                              Voici quelque chose qui mérite d'être lu: https://symfony.com/doc/3.4/security.html

                                              A toi

                                              • Partager sur Facebook
                                              • Partager sur Twitter
                                                21 septembre 2018 à 17:14:02

                                                Bonjour, @CarréDas1, excusez-moi si je vous ai fait perdre votre temps, mais peut être on s'est mal compris.

                                                msacko796 a écrit:

                                                La solution que tu as proposé pour le controller me permet de modifier l'username, le password et le tel, quand je commente les codes de la ligne 16 à la ligne 21. Mais le mot de passe n'est pas haché et salté. C'est cela dont je te parle, car un mot de passe non haché, c'est pas trop sécurisant, tu conviens avec moi. Donc si avec ta solution, tu pourrais m'indiquer comment remedier à ça.

                                                Merci, et désolé encore une fois.


                                                Voici le controller:

                                                public function editprofilAction(Request $request){
                                                
                                                             $user = $this->getUser();
                                                        if (in_array('ROLE_ADMIN', $user->getRoles())) {
                                                            //...l'user est admin
                                                
                                                            $em = $this->getDoctrine()->getManager();
                                                            $repo = $em->getRepository('DoctixAdminBundle:Admin');
                                                            $admin = $repo->findOneBy(array(
                                                                'user' => $user,
                                                            ));
                                                            $form = $this->createForm('Doctix\AdminBundle\Form\AdminType', $user);
                                                            $form->handleRequest($request);
                                                            if ($form->isSubmitted() && $form->isValid()) {
                                                
                                                              /*  $admin->getUser()->setSalt('');
                                                                $factory = $this->get('security.encoder_factory');
                                                                $encoder = $factory->getEncoder($admin->getUser());
                                                                $password_encoder = $encoder->encodePassword($admin->getUser()->getPassword(), $admin->getUser()->getSalt());
                                                                $admin->getUser()->setPassword($password_encoder);
                                                                $admin->getUser()->setRoles(array('ROLE_ADMIN')); */
                                                                $em->flush();
                                                                // creation d'un flash bag pour une notification flash
                                                                $request->getSession()->getFlashBag()->add('Notice', 'Profil Modifié avec succés');
                                                                // redirection
                                                                $url = $this->generateUrl('doctix_admin_users_parametre');
                                                                // redirection permanente avec le status http 301 ::)))))
                                                                return $this->redirect($url,301);
                                                
                                                            }
                                                
                                                        }
                                                        else{
                                                            //......l'user n'est pas admin
                                                
                                                            return $this->render('DoctixAdminBundle:User:editprofil.html.twig', array(
                                                                    'form' => $form->createView()
                                                                ));
                                                            }
                                                        }

                                                Merci

                                                -
                                                Edité par msacko796 19 septembre 2018 à 20:52:12



                                                • Partager sur Facebook
                                                • Partager sur Twitter
                                                  21 septembre 2018 à 17:26:43

                                                  Je fais suite à mon post sur la conception de ton modèle :

                                                  Un User a un rôle - ou un ensemble de rôles -

                                                  Un administrateur est donc un User comme un autre sur le plan des propriétés qui a pour le rôle Administrateur.

                                                  Si tu adoptes ce modèle tu n'as plus besoin de 2 entités.

                                                  A+

                                                  • Partager sur Facebook
                                                  • Partager sur Twitter
                                                    21 septembre 2018 à 18:14:40

                                                    Salut,

                                                    @monkey3d, je suis d'accord avec toi, sur la conception, mais comment l'implémenter, c'est ce qui me fait tourner un peu en rond.

                                                    • Partager sur Facebook
                                                    • Partager sur Twitter
                                                      21 septembre 2018 à 18:39:41

                                                      Je ne vois pas bien où est ton problème d'implémentation ...

                                                      Tu as une (seule) entité User avec ses propriétés dont une des propriétés est rôles : et dedans tu vas inscrire les rôles du user.

                                                      Ce qui arrive souvent c'est que rôles est de type array car cela permet de mettre plusieurs rôles à un même user et donc de contrôler après les accès en fonction des rôles.

                                                      Pour ton problème, tu récupères donc dans ton form le User et donc ses rôles et tu en déduis ce qu'il peut modifier et tu lui interdis l'accès à ce que tu ne veux pas qu'il modifie. Je t'ai donné la possibilité par le remove pour enlever des champs mais tu peux aussi jouer dans le form sur l'attribut disabled du champs. Dans ce cas, ta vue est toujours identique quelque soit le User mais certains champs seront grisés et non modifiables suivant les rôles.

                                                      A+

                                                      -
                                                      Edité par monkey3d 21 septembre 2018 à 18:47:42

                                                      • Partager sur Facebook
                                                      • Partager sur Twitter
                                                        21 septembre 2018 à 19:08:51

                                                        @monkey3d, je comprends, mais vu que je fais appel direct à mon formbuilder, avec 
                                                        $builder->add('user',UserType::class);

                                                        et comment faire les interdictions sur des champs, dans ce type de cas avec le remove ?

                                                        Et puis une question est ce que tu crois que cette ligne de mon controller dans mon code est-elle nécessaire :

                                                         $repo = $em->getRepository('DoctixAdminBundle:Admin');
                                                                   $admin = $repo->findOneBy(array(
                                                                       'user' => $user,
                                                                   ));

                                                        Merci encore

                                                        • Partager sur Facebook
                                                        • Partager sur Twitter
                                                          21 septembre 2018 à 19:20:10

                                                          Re,

                                                          Voilà comment j'ai réglé le problème. J'ai fait une entité profileuser qui reprend les attributs que je veux changer sur laquelle s'appuie le formtype et sans table associée. Je lui ai mis comme à mon user, l'attribut password et l'astuce consiste à mettre une contrainte de sécurité sur l'entité user pour ce password.

                                                          Je mets un extrait des entités user et profileuser pour te montrer:

                                                          Entité user:

                                                          // src/Entity/User.php
                                                          namespace App\Entity;
                                                          
                                                          use Doctrine\Common\Collections\ArrayCollection;
                                                          use Doctrine\Common\Collections\Collection;
                                                          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;
                                                          use Symfony\Component\HttpFoundation\File\UploadedFile;
                                                          use App\Entity\Vuproduits;
                                                          
                                                          /**
                                                           * @ORM\Entity
                                                           * @ORM\Table(name="`user`")
                                                           * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
                                                           * @UniqueEntity(fields={"username","forename"}, message="Il existe déjà un utilisateur avec le même nom et le même prénom")
                                                           * @UniqueEntity(fields="email", message="Email déjà utilisé")
                                                           */
                                                          class User implements UserInterface, \Serializable
                                                          {
                                                              /**
                                                               * @ORM\Id
                                                               * @ORM\Column(type="integer")
                                                               * @ORM\GeneratedValue(strategy="AUTO")
                                                               */
                                                              private $id;
                                                          
                                                              /**
                                                               * @ORM\Column(type="string", length=50, unique=true)
                                                               * @Assert\NotBlank()
                                                               * @Assert\Email()
                                                               */
                                                              private $email;
                                                          
                                                              /**
                                                               * @ORM\Column(type="string", length=50)
                                                               * @Assert\NotBlank()
                                                               */
                                                              private $username;
                                                          
                                                              
                                                              /**
                                                               * @ORM\Column(type="string", length=50, nullable=true)
                                                               */
                                                              private $forename;
                                                          
                                                                  /**
                                                               * @ORM\Column(type="string", length=50, unique=true)
                                                               * @Assert\NotBlank()
                                                               */
                                                              private $fullname;
                                                          
                                                              /**
                                                               * @Assert\NotBlank()
                                                               * @Assert\Length(max=4096)
                                                               */
                                                              private $plainPassword;
                                                          
                                                              /**
                                                               * The below length depends on the "algorithm" you use for encoding
                                                               * the password, but this works well with bcrypt.
                                                               *
                                                               * @ORM\Column(type="string", length=64)
                                                               */
                                                              private $password;
                                                          
                                                              /**
                                                               * @var array
                                                               *
                                                               * @ORM\Column(type="array")
                                                               */
                                                              private $roles;
                                                          
                                                             /**
                                                             * @ORM\Column(type="string", length=20,nullable=true)
                                                             * @Assert\Regex(
                                                             *     pattern     = "/^(0|\+33)[1-9]([-. ]?[0-9]{2}){4}$/",
                                                             *     message = "Le numéro doit être de la forme 0xxxxxxxxx ou +33yyyyyyyyy"
                                                             * )
                                                             */
                                                             protected $telephone;

                                                          Et l'entité profileuser:

                                                          // src/Entity/Profileuser.php
                                                          namespace App\Entity;
                                                          
                                                          use Symfony\Component\Validator\Constraints as Assert;
                                                          use Symfony\Component\Security\Core\Validator\Constraints as SecurityAssert;
                                                          use Symfony\Component\HttpFoundation\File\UploadedFile;
                                                          
                                                          class Profileuser
                                                          {
                                                              /**
                                                              * @Assert\NotBlank()
                                                              * @Assert\Email()
                                                              */
                                                              private $email;
                                                              /**
                                                               * @Assert\NotBlank()
                                                               * 
                                                               */
                                                              private $username;
                                                              private $forename;
                                                          
                                                              /**
                                                              * @Assert\NotBlank()
                                                              */
                                                              private $fullname;
                                                          
                                                              /**
                                                               */
                                                              private $titre;
                                                          
                                                             /**
                                                             * @Assert\Regex(
                                                             *     pattern     = "/^(0|\+33)[1-9]([-. ]?[0-9]{2}){4}$/",
                                                             *     message = "Le numéro doit être de la forme 0xxxxxxxxx ou +33yyyyyyyyy"
                                                             * )
                                                             */
                                                             protected $telephone;
                                                          
                                                              /**
                                                               * @SecurityAssert\UserPassword(//ICI SE SITUE L'ASTUCE
                                                               *     message = "Vous avez indiqué un mauvais mot de passe"
                                                               * )
                                                               */
                                                              private $password;

                                                          Et donc pour instancier le fortype basé sur profileuser, je crée un new profileuser, je l'alimente avec le contenu de user (pas la peine de setpassword) et lance mon createForm avec ce profileuser alimenté par les données de user.

                                                          A tout hasard voici mon profileusertype (il s'appelle en réalité profileEditType :p)

                                                          class ProfileEditType extends AbstractType
                                                          {
                                                              public function buildForm(FormBuilderInterface $builder, array $options)
                                                              {
                                                                      $builder
                                                                      ->add('password', PasswordType::class, array(
                                                                          'mapped'=>true,
                                                                      ))
                                                                      ;
                                                                  $builder
                                                                      ->add('email', EmailType::class)
                                                                      ->add('username', TextType::class)
                                                                      ->add('forename', TextType::class, array(
                                                                          'label'=>  'Forename (not required)',
                                                                          'translation_domain' => 'messages',
                                                                          'required'=>false,
                                                                      ))
                                                                      ->add('telephone', TextType::class, array(
                                                                          'label'=>  'Phone (not required)',
                                                                          'translation_domain' => 'messages',
                                                                          'required'=>false,
                                                                      ))
                                                                  ;
                                                                      $roles = Constante::Roles;
                                                                      $builder
                                                                      ->add('roles', ChoiceType::class, array(
                                                                          'choices'  => $roles,
                                                                          'multiple' => false,
                                                                          'expanded'=>true,
                                                                          'mapped'=>true,
                                                                          'label' => 'form.roles',
                                                                          'translation_domain' => 'messages'
                                                                      ))
                                                                      ;
                                                              }
                                                          
                                                              public function configureOptions(OptionsResolver $resolver)
                                                              {
                                                          
                                                                      $resolver->setDefaults(array(
                                                          
                                                                          'parametre'=>null,
                                                                      ));
                                                          
                                                              }
                                                          
                                                          }

                                                          Une fois le form validé, je déverse dans user les nouvelles données contenues dans le profileuser issu du formulaire.


                                                          A toi

                                                          -
                                                          Edité par CarréDas1 21 septembre 2018 à 19:22:50

                                                          • Partager sur Facebook
                                                          • Partager sur Twitter
                                                            22 septembre 2018 à 7:49:18

                                                            Je pense qu'il faudrait que tu fasses un petit effort de recherche et lecture de la doc puis que tu testes ...

                                                            Par exemple :

                                                            - pour mettre un champ non modifiable dans le formbuilder il suffit d'utiliser l'attribut disabled. : la doc est claire : https://symfony.com/doc/3.4/reference/forms/types/text.html#disabled

                                                            - pour utiliser remove dans le formbuilder, il suffit de faire remove du champs selon ta logique : donc au départ ton formulaire comporte tous les add des propriétés de l'entité et en fonction de tes règles de gestion, tu removes les champs qui ne t'intéressent pas dans le formbuilder. Tu peux aussi pour ne pas faire le remove, faire un add conditionnel. Je te donne 2 liens qui doivent te donner (presque) la solution :

                                                            https://stackoverflow.com/questions/26329148/how-to-remove-a-form-field-in-embedded-forms-from-symfony-2-controller

                                                            https://ourcodeworld.com/articles/read/510/how-to-programatically-remove-a-field-from-a-symfony-3-form-form-types

                                                            - pour ta question sur le code contrôleur, tu vois bien qu'il y a un problème de conception : tu cherches dans l'entité Admin si le User existe. Avec ma solution à une seule entité la logique est de regarder si le user a le rôle admin. Ce qui me semble t-il est quand même plus logique.

                                                            A+

                                                            • Partager sur Facebook
                                                            • Partager sur Twitter
                                                              24 septembre 2018 à 12:01:40

                                                              Bonjour, 

                                                              @CarréDas1 et @monkey3d grâce à vous, j'ai pu résoudre mon problème.

                                                              J'ai suivi ta piste finalement @monkey3d, concernant l'user, avec une seule entité, et un de tes liens que tu m'a refilés a résolu le soucis avec les form.

                                                              Merci beaucoup à vous.

                                                              • Partager sur Facebook
                                                              • Partager sur Twitter

                                                              Comment bloquer des champs d'un formbuilder

                                                              × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                                              × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                                              • Editeur
                                                              • Markdown