Question

I have an application running on Symfony2.0 with FOSUSerBundle. Every 3 months a user who connect the application have to change its password, it's in place and it's working.

Today every 3 months if the user write as new password the same as the previous one there is no verification and he can use it 3 more months.

I would like to add a constraints on the password reset and force the user to give a different password from the previous one. I have no idea how to do this. I tried to create a validator but i don't have my user ID in the validator...

Any clue?

Was it helpful?

Solution

I found a solution, It's working but I still have a small issue : when i submit my new password, if i try to put the same password as the previous one, my form is not valid (that's great !), but the error message is not shown by my twig whereas I'm using :

{{ form_widget(edit_form) }}

Any idea why?

Anyway here is my solution :

I added a validator on the class level to verify the password. To do so, i added a validator on my User class :

// \src\Acme\UserBundle\Resources\config\validation.xml
<class name="Acme\UserBundle\Entity\User">
    <constraint name="Acme\UserBundle\Validator\Constraints\IsDifferentPassword">
        <option name="message">Password has to be different from the previous one</option>
    </constraint>
    <property name="plainPassword">
        <constraint name="NotBlank">
            <option name="message">fos_user.password.blank</option>
        </constraint>
    </property>
</class>

And i created a validator on the class level :

// \src\Acme\UserBundle\Validator\Constraints\IsDifferentPassword.php

namespace Acme\UserBundle\Validator\Constraints;

use Symfony\Component\Validator\Constraint;

/**
 * @Annotation
 */
class IsDifferentPassword extends Constraint
{
    public $message = 'Password has to be different from the previous one';

    public function getTargets()
    {
        return Constraint::CLASS_CONSTRAINT;
    }
}

And :

// \src\Acme\UserBundle\Validator\Constraints\IsDifferentPasswordValidator.php

namespace Acme\UserBundle\Validator\Constraints;
use Symfony\Component\Validator\Constraint;
use Symfony\Component\Validator\ConstraintValidator;
use Symfony\Component\Security\Core\Encoder\MessageDigestPasswordEncoder;

class IsDifferentPasswordValidator extends ConstraintValidator
{
    public function isValid($value, Constraint $constraint)
    {
        $encoder = new MessageDigestPasswordEncoder();
        $password = $encoder->encodePassword($value->getPlainPassword(), $value->getSalt());
        $oldPassword = $value->getPassword();
        if($password == $oldPassword){
            return false;
        }
        return true;
    }
}

OTHER TIPS

I had the same problem with symfony 3.4. I solved (symfony doc) replacing your "return false" with this:

    if ($password == $oldPassword) {
        $this->context->buildViolation($constraint->message)
            ->atPath('current_password')
            ->addViolation();
    }

where

The atPath() method defines the property which the validation error is associated to. Use any valid PropertyAccess syntax to define that property.

and cutting the "return true;" row at the end of your isValid function.

Another difference is that I used validate() function instead of your isValid()

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top