Im trying to use a specific validator in a form.
That form is for an user to redefine his password, he must also enter his current password. For that I use a built in validator from symfony
in my form:
use Symfony\Component\Security\Core\Validator\Constraints\UserPassword;
and the form type looks like that:
/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('currentpassword', 'password', array('label'=>'Current password',
'mapped' => false,
'constraints' => new UserPassword(array('message' => 'you wot m8?')),
'required' => true
))
->add('password', 'repeated', array(
'first_name' => 'new',
'second_name' => 'confirm',
'type' => 'password',
'required' => true
))
;
}
I know in my controller I could just get the data form, get the currentpassword value, call the security.encoder_factory, etc but that validator looked handy.
my problem is that the form always return an error (here: 'you wot m8?') just like I had entered the wrong current password.
Any idea what I am doing wrong?
I know this answer is coming a few years late, but as I was stumbleing ybout the same Problem I want to present my solution:
The problem is that there was a connection in my case between the
$user
Entity I used for FormMapping and theUser
that comes form thesecurity.context
.See following: (PasswordChange - Controller)
The
isValid()
function is triggering the UserPassword Constraint Validator:The line of interest is:
if (!$encoder->isPasswordValid($user->getPassword(), $password, $user->getSalt()))
In my case the
$user->getPassword()
was giving back the new Password I just entered in the form as my new Password. Thats why the test allways failed! I did not understand why there could be a connection between the User in the tokenStorage and the one that I loaded from my Database. It feels like both Objects (MyDatabase one and the tokenStorage one) share the same processor address and are actually the same...Weird!
My solution was to also decouple the (new)password field in ChangePasswordType from the EntityMapping: See
The line of interest is
'mapped' => false,
By this, the new password entered in the form will not be automatically mapped to the given
$user
Entity. Instead you now need to grab it from theform
. SeeA bit of a workaround for problem what I could not fully understand. If anyone can explain the connection between the Database Object and the security.context Object I'd be glad to hear it!
I had the same problem and, after lot of research and practical tests, this is the solution I used:
(NB: if you dont define this entity as model, then you can not map it, later in the form, unless you create it throw Doctrine, and that is not our purpose)
Define the form 'ChangePasswordType' for these fields (newPasword could be RepeatedType for password confirmation). The mapping as 'true' MUST be maintained for automatic validation of oldPassword, throw SecurityAssert defined above, and for catching these fields later in the controller
In the controller (changeCurrentUserPasswordAction,... or whatever Action), declare a new ChangePassword Entity and associate it with the form to create ('ChangePasswordType)
I hope this can help someone...