使用SonataAdminBundle编辑特定用户时,请避免使用空密码字段

时间:2014-02-06 16:54:48

标签: symfony backend sonata-admin

当我想从后端编辑现有用户时(使用SonataAdminBundle和FOSUserBundle),我遇到了问题。在我的UserAdmin类的configureFormFields方法中,密码字段显示为空,当我需要编辑保持相同用户密码的其他字段(例如lastname)时,这是一个问题。必须再次填写此字段(和密码验证字段)! (我不想修改用户密码)

在我的UserAdmin课程中,我有:

public function configureFormFields(FormMapper $formMapper)
{
        $formMapper
            ->with('User Data')
                ->add('username')

                ->add('plainPassword', 'repeated', array(
                'type' => 'password',
                'options' => array('translation_domain' => 'FOSUserBundle'),
                'first_options' => array('label' => 'form.password'),
                'second_options' => array('label' => 'form.password_confirmation'),
                'invalid_message' => 'fos_user.password.mismatch',
                )) 

                ->add('firstname')
                ->add('lastname')
                ->add('email')
                ->add('user_roles')
                ->add('enabled', 'checkbox', array(
                      'label'     => 'Enable Account',
                      'required'  => false,
                ))
            ->end()
        ;
}

我尝试在UserAdmin类中覆盖prePersist和preUpdate方法,但这些方法不起作用。密码按照FOS标准(使用salt和sha512)在数据库中输入。

任何解决方案? 非常感谢!

5 个答案:

答案 0 :(得分:2)

您可以覆盖管理类中的preUpdate功能,这就是我的工作方式

public function preUpdate($object)
    {
        $DM = $this->getConfigurationPool()->getContainer()->get('Doctrine')->getManager();
        $repository = $DM->getRepository('Namespace\YourBundle\Entity\User')->find($object->getId());

        $Password = $object->getPassword();
        if (!empty($Password)) {
            $salt = md5(time());

            $encoderservice = $this->getConfigurationPool()->getContainer()->get('security.encoder_factory');
            $encoder = $encoderservice->getEncoder($object);
            $encoded_pass = $encoder->encodePassword($object->getPassword(), $salt);
            $object->setSalt($salt);
            $object->setPassword($encoded_pass);
        } else {
            $object->setPassword($repository->getPassword());
        }
    }

我的configureFormFields功能

protected function configureFormFields(FormMapper $formMapper)
{
    $passwordoptions=array('type' => 'password','invalid_message' => 'The password fields must match.',
               'options' => array('attr' => array('class' => 'password-field')),'first_options' => array('label' => 'Password'),
        'second_options' => array('label' => 'Confirm password'),'translation_domain' => 'FOSUserBundle'
           );

    $this->record_id = $this->request->get($this->getIdParameter());
     if (!empty($this->record_id)) {
         $passwordoptions['required'] = false;
         $passwordoptions['constraints'] = array(new Assert\Length(array('min' => 10))
                             ,new Assert\Regex(array('pattern' => '/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{10,}$/','match'=>true,'message'=>'Password must contain atleast 1 special character 1 upper case letter 1 number and 1 lower case letter !'))
                             );
     } else {
        $passwordoptions['required'] = true;
        $passwordoptions['constraints'] = array(new Assert\Length(array('min' => 10))
                            ,new Assert\Regex(array('pattern' => '/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{10,}$/','match'=>true,'message'=>'Password must contain atleast 1 special character 1 upper case letter 1 number and 1 lower case letter !'))
                            );
     }
  $formMapper->add('password', 'repeated', $passwordoptions); /*you can add your other fields*/
  }

答案 1 :(得分:2)

我遇到的问题与你相同,但没有SonataAdminBundle

在经典的用户管理(Symfony3)中,这可行:

// src/AppBundle/Form/UserType.php

<?php

namespace AppBundle\Form;

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\TextType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

class UserType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        // By default, password is required (create user case)
        $passwordOptions = array(
           'type'           => PasswordType::class,
           'first_options'  => array('label' => 'Password'),
           'second_options' => array('label' => 'Repeat password'),
           'required'       => true
        );

        // If edit user : password is optional
        // User object is stored in $options['data']
        $recordId = $options['data']->getId();
        if (!empty($recordId)) {
           $passwordOptions['required'] = false;
        }

        $builder
            ->add('prenom',         TextType::class, array('label' => 'First name'))
            ->add('nom',            TextType::class, array('label' => 'Last name'))
            ->add('email',          EmailType::class)
            ->add('username',       TextType::class)
            ->add('plainPassword',  RepeatedType::class, $passwordOptions)
            ->add('roleList',          ChoiceType::class, array(
                'label'          => 'Role',
                'choices'        => array(
                  'Admin'        => 'ROLE_ADMIN',
                  'User'         => 'ROLE_USER'
                ),
            ))
            ->add('save', SubmitType::class, array(
               'attr'      => array('class' => 'button-link save'),
               'label'     => 'Validate'
            ));
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'AppBundle\Entity\User',
        ));
    }
}

不要忘记在用户实体的plainPassword上删除@Assert \ NotBlank():

/**
 * @Assert\Length(max=4096)
 */
 private $plainPassword;

我在UserController.php中的editAction():

   /**
    * @Route("/users/edit/{id}", name="user_edit")
    */
   public function editAction($id, Request $request) {
      // get user from database
      $em = $this->getDoctrine()->getManager();
      $user = $em->getRepository('AppBundle:User')->find($id);

      // user doesn't exist
      if (!$user) {
         throw $this->createNotFoundException('No user found for id '. $id);
      }

      // build the form with user data
      $originalPassword = $user->getPassword();    # encoded password
      $form = $this->createForm(UserType::class, $user);

      // form POST
      $form->handleRequest($request);
      if ($form->isSubmitted() && $form->isValid()) {

          // Encode the password if needed
          # password has changed
          if (!empty($form->get('plainPassword')->getData())) {
             $password = $this->get('security.password_encoder')
               ->encodePassword($user, $user->getPlainPassword());
             $user->setPassword($password);

          # password not changed
          } else {
             $user->setPassword($originalPassword);
          }

          $role = $form->get('roleList')->getData();
          $user->setRoles(array($role));

          // update the User
          $em->flush();

          // success message
          $this->addFlash('notice', 'User has been updated successfully !');

          // redirection
          return $this->redirectToRoute('user');
      }

      // show form
      return $this->render('users/form.html.twig', array(
         'h1_title' => 'Edit user : ' . $user->getPrenom() . " " . $user->getNom(),
         'form' => $form->createView()
      ));
   }

现在,创建新用户时需要输入密码,但编辑新用户时则不需要输入密码。

答案 2 :(得分:1)

可能为时已晚,但对其他人有用。 感谢其他帖子。 很简单。只需使用:

&#13;
&#13;
class UserAdmin extends AbstractAdmin
{
	protected $formOptions = array(
		'validation_groups' => array('Profile')
	); 
//..
}
&#13;
&#13;
&#13;

它使用以下定义的配置文件验证组:

friendsofsymfony /用户束/资源/配置/ validation.xml中

答案 3 :(得分:0)

有一些方法可以做到这一点

更改configureFormField行为

您可以在configureFormFields中获取当前对象($this->subject$this->getSubject();)并检查它是新对象还是现有对象并更改字段行为(例如验证)

使用saveHooks和FOSUser

这是一个例子

http://sonata-project.org/bundles/admin/master/doc/reference/saving_hooks.html

这将在密码字段中显示散列密码,但在输入新的密码字段时应更新密码(如果我没记错的话)

合并两者并实施自己的逻辑

在钩子里面你可以得到FOSUserManager  并使用

处理用户更新

容器:$this->getConfigurationPool()->getContainer();

fosusermanager:$userManager = $container->get('fos_user.user_manager');

https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/user_manager.md

答案 4 :(得分:-1)

如果您将SonataAdminBundle与FOSUserBundle结合使用,我强烈建议您安装SonataUserBundle。这将解决您的问题,因为它已经处理了该问题,并且它还带有标准管理类。检查安装是否很容易将其与FOSUserBundle结合使用。我知道它在用户实体中还添加了许多额外的字段,但是如果你只想要你的字段,你可以覆盖它。