9

I am trying to build a form that resets user password. I am using FOSUserBundle to manage users, but I don't want to override FOSUser resetting controller due to some architecture reasons

So I decided to build my own type and controller to reset password

PasswordResettingType.php

public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder->add('plainPassword', RepeatedType::class, array(
        'type' => PasswordType::class,
        'attr' => ['class' => 'form-group has-feedback'],
        'first_options' => array('label' => false,
            'attr' => ['placeholder' => 'New Password']
            ),
        'second_options' => array('label' => false,
            'attr' => ['placeholder' => 'Repeat Password']),
        'invalid_message' => 'Passwords don't match',
    ));
}

public function configureOptions(OptionsResolver $resolver)
{
    $resolver->setDefaults(array(
        'data_class' => 'CoreBundle\Entity\User',
        'csrf_token_id' => 'resetting'
    ));
}

Resetting controller

/**
 * @Route("/reset/{token}", name="api_resetting_reset")
 */
public function resetAction(Request $request, $token)
{
    $userManager = $this->get('fos_user.user_manager');

    $user = $userManager->findUserByConfirmationToken($token);

    if (null === $user) {
        return $this->render('APIBundle:Resetting:error.html.twig');
    }

    $form = $this->createForm(PasswordResettingType::class, $user);

    $form->handleRequest($request);

    if ($form->isValid()) {
        $user->setConfirmationToken(null);
        $user->setPasswordRequestedAt(null);
        $user->setPlainPassword($form["plainPassword"]->getData());
        $userManager->updateUser($user);

        return $this->redirectToRoute('api_resetting_success');
    }

    return $this->render('APIBundle:Resetting:reset.html.twig', array(
        'token' => $token,
        'form' => $form->createView()
    ));
}

reset.html.twig

{{ form_start(form) }}

        {% for passwordField in form.plainPassword %}
            <div class="form-group has-feedback">
                {{ form_widget(passwordField, { 'attr': {'class': 'form-control'} }) }}
                <span class="show">show</span>
                {{ form_errors(passwordField) }}
            </div>
        {% endfor %}

    <input type="submit" class="btn" value="Submit" />
{{ form_end(form) }}

But when I submit form, new password is not set, ConfirmationToken and PasswordRequestedAt are not set to null.

5
  • I should ask a stupid question, because personally I could stack on the issue like this: Are you sure that you $form->isValid() = true? No other reason for this code not to work. Commented Oct 17, 2016 at 8:07
  • No, that's not stupid question :) and yes, I checked that and I'm puzzled that code still doesn't work. Commented Oct 17, 2016 at 8:34
  • Have you try to look in your log file what is happening ? Commented Oct 17, 2016 at 17:54
  • 1
    Another stupid question: have you check that your route isn't in conflict with another route? (FOSUserBundle has a /reset/{token} route for example). I think you would have notice if that was the case, but like everyone here, I can't see why this wouldn't work. Commented Oct 18, 2016 at 8:44
  • Try printing and exit the result before returning the success. See what results you get from $user and $userManager. Do you get redirected to api_resetting_success after submit ? Commented Oct 20, 2016 at 8:36

2 Answers 2

6
+50

I think you are doing it the wrong way. If you take a look to FOS User and read with detail the documentation, you will see that they are doing this using EventListeners.

That means you can hook on them and do your stuff. Or if you don't want to do it you can override it and make your own. Doing this half way like you are doing is not going to work properly. For example you are not checking the onResettingResetInitialize event that checks if the password request expired.

About last answer I think you don't really need to do this:

$encoder = $this->container->get('security.password_encoder');
$user->setPassword($encoder->encodePassword($user, $user->getPlainPassword()));

Since that is the job of the UserManager->UpdateUser()

By the way: Can't you debug from there and put a dump($user);exit(); and check what's the output and if it's being called properly.

Also Boulzy comment is right: /reset/{token} is the same route of FOS. If you debug the UpdateUser using echo debug_backtrace(); you can also see from where is being called the UpdateUser.

Sign up to request clarification or add additional context in comments.

Comments

0

You have to set the new password like this:

$encoder = $this->container->get('security.password_encoder');
$user->setPassword($encoder->encodePassword($user, $user->getPlainPassword()));

after you can clear some data:

$user->setConfirmationToken(NULL);
$user->setPasswordRequestedAt(NULL);
$user->setPlainPassword(NULL);

1 Comment

Thanks, but it didn't help

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.