Symfony3 Form to change the password Error @SecurityAssert \ UserPassword

0

I have a problem with the typical form to change the password in which I first put you to enter your current password.

The theory is very simple and it is explained in the symfony doc but it gives me an error like the current password is incorrect

in my entity I have

/**
 * @SecurityAssert\UserPassword(
 *     message = "Error al poner la contraseña actual"
 * )
 */
private $oldPassword;

/**
 * @var string
 * @Assert\NotBlank(message = "No puedes dejar el password vacio")
 * @Assert\Length(min = 6)
 */
private $password;

the fomType I have put

->add('oldPassword', PasswordType::class, array(
                'label' => 'Ponga su password actual',
                'mapped' => false,
                ))
->add('password', RepeatedType::class, array(
                "required" => "required",
                'type' => PasswordType::class,
                'invalid_message' => 'Los dos password deben coincidir',
                'first_options' => array('label' => 'Password nuevo', "attr" 
=> array("class" => "form-password form-control")),
                'second_options' => array('label' => 'Repita el Password nuevo', "attr" => array("class" => "form-password form-control"))
                    )
            )

And little else must be done (I think) in addition to the controler create the view with the form and then collect the data of the new password, etc, but as I say, I sent error of not valid field that checks the password and I do not know if it's because the password I keep it encrypted in my security.yml I have it as

security:
    encoders:
        BackendBundle\Entity\Users:
            algorithm: bcrypt
            cost: 4

I edit to add the action

public function passAction(Request $request) {


    $userId = $this->getUser(); //metemos  id  del usuario sacado de su sesión
    $em = $this->getDoctrine()->getManager();
    $user_repo = $em->getRepository("BackendBundle:Users");
    $user = $user_repo->find($userId); // buscamos este usuario


    $form = $this->createForm(UsersPassType::class, $user);
    $form->handleRequest($request);

    if ($form->isSubmitted()) {
        if ($form->isValid()) {

            $factory = $this->get("security.encoder_factory"); // llamamos al servicio para usar el mismo tipo de encriptación
            $encoder = $factory->getEncoder($user); // llamamos al objeto user
            $password = $encoder->encodePassword($form->get("password")->getData(), $user->getSalt()); //codifciamos la password que ha llegado por el formulario

            $user->setPassword($password);

            $em->persist($user);
            $flush = $em->flush();
            if ($flush === null) {
                $this->session->getFlashBag()->add('success', 'El usuario se ha editado correctamente');
                return $this->redirectToRoute("demokratian_index_user"); //redirigimos la pagina si se incluido correctamete
            } else {
                $this->session->getFlashBag()->add('warning', 'Error al editar el passwordo');
            }
        } else {
            $this->session->getFlashBag()->add('warning', 'El password no se ha editado por un error en el formulario !');
        }
    }

    return $this->render("BackendBundle:Others:editPass.html.twig", array(
                "form" => $form->createView()));
}

Well, can anyone help me? Do I have to indicate in any way to the SecurityAssert to check the encrypted password? Am I making any other mistake? Thank you very much for your help

I add by suggestion in the comment of Jakala (thank you very much) the dump ($ form-> getErrors ()) in the else of the $ form-> isValid () to see if it gives any clue

-children: OrderedHashMap {#680 ▼
  -elements: array:2 [▼
    "oldPassword" => Form {#687 ▼
      -config: FormBuilder {#681 ▶}
      -parent: Form {#688}
      -children: OrderedHashMap {#682 ▶}
      -errors: array:1 [▼
        0 => FormError {#746 ▼
          #messageTemplate: "Error al poner la contraseña actual"
          #messageParameters: []
          #messagePluralization: null
          -message: "Error al poner la contraseña actual"
          -cause: ConstraintViolation {#994 ▼
            -message: "Error al poner la contraseña actual"
            -messageTemplate: "Error al poner la contraseña actual"
            -parameters: []
            -plural: null
            -root: Form {#688}
            -propertyPath: "data.oldPassword"
            -invalidValue: null
            -constraint: UserPassword {#934 ▶}
            -code: null
            -cause: null
          }
          -origin: Form {#687}
        }
      ]
      -submitted: true
      -clickedButton: null
      -modelData: "00004311"
      -normData: "00004311"
      -viewData: "00004311"
      -extraData: []
      -transformationFailure: null
      -defaultDataSet: true
      -lockSetData: false
    }
    
asked by Carlos Salgado 22.01.2018 в 13:13
source

1 answer

0

After many laps and thanks to the help of @Spunc in the stackoverflow in English, I managed to make it work. I put the complete code by its some other user has problems and needs it

passControler

namespace BackendBundle\Controller;

use BackendBundle\Entity\Users;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;

class PassController extends Controller {
public function passAction(Request $request) {
    $changePasswordModel = new ChangePassword();
    $form = $this->createForm(ChangePasswordType::class, $changePasswordModel);

    $form->handleRequest($request);

    if ($form->isSubmitted()) {

        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $user = $this->getUser(); //metemos como id la del usuario sacado de su sesion
            $encoder = $this->container->get('security.encoder_factory')->getEncoder($user);
            $password = $encoder->encodePassword($changePasswordModel->getPassword(), $user->getSalt());
            $user->setPassword($password);
            $em->persist($user);
            $flush = $em->flush();
            if ($flush === null) {
                $this->session->getFlashBag()->add('success', 'El usuario se ha editado correctamente');
                return $this->redirectToRoute("others_show"); //redirigimos la pagina si se incluido correctamete
            } else {
                $this->session->getFlashBag()->add('warning', 'Error al editar el password');
            }
        } else {
           // dump($form->getErrors());
            $this->session->getFlashBag()->add('warning', 'El password no se ha editado por un error en el formulario !');
        }
    }

    return $this->render('BackendBundle:Others:editPass.html.twig', array(
                'form' => $form->createView(),
    ));
}
}

model ChangePassword

namespace BackendBundle\Form\Model;

use Symfony\Component\Security\Core\Validator\Constraints as SecurityAssert;
use Symfony\Component\Validator\Constraints as Assert;

class ChangePassword {

/**
 * @SecurityAssert\UserPassword(
 *     message = "Error al poner la contraseña actual"
 * )
 */
protected $oldPassword;

/**
 * @Assert\Length(
 *     min = 6,
 *     minMessage = "El password tiene que tener al menos 6 caracteres"
 * )
 */
protected $password;


public function getOldPassword() {
    return $this->oldPassword;
}

public function setOldPassword($oldPassword) {
    $this->oldPassword = $oldPassword;
    return $this;
}


public function getPassword() {
    return $this->password;
}

public function setPassword($password) {
    $this->password = $password;
    return $this;
}

}

ChangePasswordType

namespace BackendBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;

class ChangePasswordType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{

    $builder
                ->add('oldPassword', PasswordType::class, array(
                'label' => 'Ponga su password actual',
                ))
            ->add('password', RepeatedType::class, array(
                "required" => "required",
                'type' => PasswordType::class,
                'invalid_message' => 'Los dos password deben coincidir',
                'first_options' => array('label' => 'Password nuevo', "attr" => array("class" => "form-password form-control")),
                'second_options' => array('label' => 'Repita el Password nuevo', "attr" => array("class" => "form-password form-control"))
                    )
            )
    ;
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'Acme\UserBundle\Form\Model\ChangePassword',
    ));
}

public function getName()
{
    return 'change_passwd';
}
}
    
answered by 10.02.2018 в 14:51