0
votes

I am using my own entity that extend fos_user.

I'm extending the User entity actually in 2 distinct tables (investor that extend the table user). Some data such as password and email are stored in user. Investor can access therefor to the Fos_user methods.

I have a form populated with the users's data. I need to be able to update the user with or without the password.

This is how it is done :

if(!empty($form->get('password')->getData())){
    $investor->setPlainPassword($form->get('password')->getData());
}

The update is perfectly working except if the password input is empty.

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'password' cannot be null

This is how i declare the input in my form $builder :

->add('password', 'repeated',
            array(
                'type' => 'password',
                'invalid_message' => 'The password fields have to be the same',
                'required' => false,
                'first_options'  => array('label' => 'New password'),
                'second_options' => array('label' => 'Confirm the new password')
            )
        )

And this is my Controller :

public function updateInvestorAction(Request $request)
{
    $user = $this->container->get('security.context')->getToken()->getUser();

    $investor = $this->getDoctrine()->getRepository('AppBundle:Investor')->findOneBy(array('id' => $user->getId()));

    $form = $this->createForm(new UpdateInvestorType(), $investor);

    $form->handleRequest($request);

    if ($form->isValid()) {

        if(!empty($form->get('password')->getData())){
            $investor->setPlainPassword($form->get('password')->getData());
        }

        $em = $this->getDoctrine()->getManager();
        $em->persist($investor);
        $em->flush();

        $session = $this->getRequest()->getSession();
        $session->getFlashBag()->add('message', 'Votre profil a été correctement modifié');

        return $this->redirect($this->generateUrl('home'));

    }

    return array(
        'form' => $form->createView(),
    );
}

How can i update my user without giving a new or the previous password?

1
Ether in the Database and/or in the Entity the password is set to nullable = false, thats why you can't update it without setting the password. To allow what you want you must change that behavior, but I think that this is a real big security holeKhorneHoly
I couldn't find it in the FOSUserBundle either, but it is set in the database, just look after it in your user table. That's the only way I know how it could work without submitting the password. But you really shouldn't do that because it's pretty dangerous to allow users to have no password. In fact it's unacceptable, data from people could be hijacked just by simply loggin in if the password is nullKhorneHoly
But the FOS User Bundle has a function how to edit the user. Maybe you can look up how they do it and adapt it to your code!KhorneHoly
Yes you are right but i'm extending the User entity actually in 2 distinct tables (investor that extend the table user). Some data such as password and email are stored in user. Investor can access therefor to the Fos user methods. So if i update the fos user i still need to persist my investor data and i will get the same error.Brieuc

1 Answers

0
votes

I finally found a solution :

It is possible to set Unhashed/Unsalted password with setPassword();

Therefor if the password is empty i will set the password with the previous hashed password so it will not be hashed again. If it is not empty i will use setPlainPassword() method.

Here the new controller :

public function updateInvestorAction(Request $request)
{
    $user = $this->container->get('security.context')->getToken()->getUser();

    $investor = $this->getDoctrine()->getRepository('AppBundle:Investor')->findOneBy(array('id' => $user->getId()));

    $password = $investor->getPassword();

    $form = $this->createForm(new UpdateInvestorType(), $investor);

    $form->handleRequest($request);

    if ($form->isValid()) {

        if(!empty($form->get('password')->getData())){
            $investor->setPlainPassword($form->get('password')->getData());
        }
        else{
            $investor->setPassword($password);
        }

        $em = $this->getDoctrine()->getManager();
        $em->persist($investor);
        $em->flush();

        $session = $this->getRequest()->getSession();
        $session->getFlashBag()->add('message', 'Votre profil a été correctement modifié');

        return $this->redirect($this->generateUrl('home'));

    }

    return array(
        'form' => $form->createView(),
    );
}