I have a problem when I want to edit an existing user from the Backend (using SonataAdminBundle and FOSUserBundle). In configureFormFields method of my UserAdmin class, the password field appears empty and this is a problem when I need to edit another fields (for example the lastname) keeping the same user password. This field (and the password verification field) must be filled again! (I do not want modify the user password)
In my UserAdmin class, I have:
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()
;
}
I tried to overwrite prePersist and preUpdate methods in my UserAdmin class, but these do not work. The password is encripted in the database following the FOS standard (with salt and sha512).
Any solution? Many thanks!
You can override your the preUpdate
function in your admin class this is how i have done
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());
}
}
And my configureFormFields
function
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*/
}
I have the same problem than you but without SonataAdminBundle.
In a classic user admin management (Symfony3), this works :
// 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',
));
}
}
Don't forget to remove @Assert\NotBlank() on plainPassword in your User Entity :
/**
* @Assert\Length(max=4096)
*/
private $plainPassword;
My editAction() in UserController.php :
/**
* @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()
));
}
Now, password is required when you create a new user, but it isn't when you edit one.
Maybe too late but useful for others. With thanks to other posts. So simple. Just use :
class UserAdmin extends AbstractAdmin
{
protected $formOptions = array(
'validation_groups' => array('Profile')
);
//..
}
It uses the profile validation group defined in:
friendsofsymfony/user-bundle/Resources/config/validation.xml
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With