Ignore password when user updates profile using FOSUserBundle

I am using FOSUserBundle and I am trying to create a page that allows the user to update his user profile. The problem I am facing is that my form does not require the user to re-enter the password if they do not want to change / update their password. Therefore, when a user submits a form with an empty password, the database will be updated with an empty string and the user will not be able to log in.

How can I get my form to ignore updating the password field if it is not set? Below is the code I'm using.

$user = $this->get('security.context')->getToken()->getUser(); //user form has email and repeating password fields $userForm = $this->createForm(new UserFormType(), $user); if ($request->getMethod() == 'POST') { $userForm->bindRequest($request); if($userForm->isValid()){ //this will be be empty string in the database if the user does not enter a password $user->setPlainPassword($userForm->getData()->getPassword()); $em->flush(); } } 

I tried several things, such as the following, but it is still empty because bindRequest sets an empty password to the user

 if($userForm->getData()->getPassword()) $user->setPlainPassword($userForm->getData()->getPassword()); 

I also tried, but this leads to a similar situation and causes an unnecessary request

 if($userForm->getData()->getPassword()) $user->setPlainPassword($userForm->getData()->getPassword()); else $user->setPlainPassword($user->getPlainPassword()); 

Are there any elegant ways to handle this use case?

+4
source share
4 answers

I think you should reconsider if this is a really good use case. Do users need to edit other user passwords? In our institution, we do not allow the administrator of the highest level to perform this task.

If the user needs to change the password, we let them handle this themselves. If they have forgotten their password, we allow them to receive it by e-mail. If they need help setting up email, we let our administrators help users. But all updates and password creation are done by the user.

I think it's great that the FOSUserBundle makes it so difficult to do otherwise, but if you must have DonCallisto seem to have gotten a good solution.

+1
source

The problem is that you are binding the form to the user object before controlling the password. Analyze your code snippet.

Do the following

 $user = $this->get('security.context')->getToken()->getUser(); 

load an existing user into a user object.
Now you "create" a form with this data and, if you receive a message, you take the published data to the previous object

 $userForm = $this->createForm(new UserFormType(), $user); if ($request->getMethod() == 'POST') { $userForm->bindRequest($request); 

So, on bindRequest you have alredy that has lost the previous password in the object (obviously not yet in the database) if it remains empty. Every control is useless from now on.

In this case, the solution is to manually check the value of the form field directly in the $request object before attaching it to the base object.
You can do this with this simple snippet of code.

 $postedValues = $request->request->get('formName'); 

You must now confirm that the password is full

 if($postedValues['plainPassword']) { ... } 

where plainPassword I believe this is the name of the field that interests us.

If you find that this field contains a value (else branch), you should not do anything.
Otherwise, you should get the original password from the User Object and set it to $request .
( update ). Otherwise, you can get the password from the User Object, but since this password is stored with a hased rating, you cannot put it in the $request object, because it will suffer from hashing again. What could you do - I suppose - array_pop directly into the $request object and remove the field that will ruin all things (plainPassword) Now that you have done this, you can link the published data to the base object.

Another solution (perhaps better because you disconnect some business logic from the controller) is to use prePersist hook, but more conceptually advanced. If you want to explore this solution, you can read it about form events.

+6
source
 <?php class User { public function setPassword($password) { if (false == empty($password)) { $this->password = $password; } } } 

This will only update the user password if it is not empty.

+1
source

I found a simple hack to get rid of the "Enter Password" form error. Manual set of dummy plainPassword in user entity. After validating the form, simply reset before you clear the object.

 <?php public function updateAction(Request $request, $id) { $em = $this->getDoctrine()->getManager(); $entity = $em->getRepository('AppBundle:User')->find($id); if (!$entity) { throw $this->createNotFoundException('Unable to find Customer entity.'); } $deleteForm = $this->createDeleteForm($id); $editForm = $this->createEditForm($entity); $postedValues = $request->request->get('appbundle_user'); /* HERE */ $entity->setPlainPassword('dummy'); // hack to avoid the "enter password" error $editForm->handleRequest($request); if ($editForm->isValid()) { /* AND HERE */ $entity->setPlainPassword(''); // hack to avoid the "enter password" error $em->flush(); return $this->redirect($this->generateUrl('customer_edit', array('id' => $id))); } return array( 'entity' => $entity, 'edit_form' => $editForm->createView(), 'delete_form' => $deleteForm->createView(), ); } 
0
source

All Articles