I've been trying to add a edit-user page where they can change username, email address and password.
One thing I am trying to implement is they have to type in the old password to be able to change it to a new one.
I've been reading these pages:
but I'm really struggling on the implementation side.
Here's my Controller for the form:
<?php
namespace App\Controller\User;
use App\Entity\User;
use App\Form\User\EditUserType;
use App\Repository\UserRepository;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class EditController extends Controller
{
public function edit(Request $request, UserPasswordEncoderInterface $encoder)
{
$userInfo = ['username' => null, 'plainPassword' => null, 'password' => null, 'email' => null];
$form = $this->createForm(EditUserType::class, $userInfo);
$form->handleRequest($request);
$user = new User();
$oldPassword = $user->getPassword();
if ($form->isSubmitted() && $form->isValid()) {
$userInfo = $form->getData();
$username = $userInfo['username'];
$email = $userInfo['email'];
$newPass = $userInfo['plainPassword'];
$oldPass = $userInfo['password'];
$encryptOldPass = $encoder->encodePassword($user, $oldPass);
if ($oldPassword === $encryptOldPass) {
$this->addFlash('danger', $oldPass. ' ' .$encryptOldPass. ' ' .$oldPassword);
return $this->redirectToRoute('user_edit');
} else {
$this->addFlash('success', $oldPassword. '-' .$encryptOldPass);
return $this->redirectToRoute('user_edit');
}
$pass = $encoder->encodePassword($user, $newPass);
$user->setPassword($pass);
$user->setEmail($email);
$user->setUsername($username);
echo 'trey was here';
$this->addFlash('success', 'User Details Edited');
return $this->redirectToRoute('user_edit');
}
return $this->render('user/edit.html.twig', array('form' => $form->createView()));
}
}
my EditUserType file:
<?php
namespace App\Form\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\EmailType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
use Symfony\Component\Form\Extension\Core\Type\TextType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class EditUserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('email', EmailType::class)
->add('username', TextType::class)
->add('password', PasswordType::class, array())
->add('plainPassword', RepeatedType::class, array(
'type' => PasswordType::class,
'first_options' => array('label' => 'New Password'),
'second_options' => array('label' => 'New Repeat Password')
));
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults(array());
}
}
my validation (file: config/validator/validation.yaml)
App\Form\User\EditUserType:
properties:
oldPassword:
- Symfony\Component\Security\Core\Validator\Constraints\UserPassword:
message: 'Invalid Password'
my template file:
{% include 'builder/header.html.twig' %}
<div class="user-container" id="user-content">
{% block body %}
{% include 'builder/notices.html.twig' %}
<div class="user-container">
<i class="fas fa-user-edit fa-5x"></i>
</div>
<hr />
{{ form_start(form) }}
{{ form_row(form.username, { 'attr': {'class': 'form-control', 'value': app.user.username} }) }}
{{ form_row(form.email, { 'attr': {'class': 'form-control', 'value': app.user.email} }) }}
{{ form_row(form.password, { 'attr': {'class': 'form-control'} }) }}
{{ form_row(form.plainPassword.first, { 'attr': {'class': 'form-control'} }) }}
{{ form_row(form.plainPassword.second, { 'attr': {'class': 'form-control'} }) }}
<div class="register-btn-container">
<button class="btn btn-danger" id="return-to-dash-btn" type="button">Cancel!</button>
<button class="btn btn-primary" type="submit">Update!</button>
</div>
{{ form_end(form) }}
{% endblock %}
</div>
{% include 'builder/footer.html.twig' %}
Typing in any old password for the old password fields seems to get by and not update the password to the newly typed value.. so how do I validate the old password against the database so the user can update it to a new password?
Thanks
Found the solution, using cerad comment on previous (now removed) answer:
updated controller:
<?php
namespace App\Controller\User;
use App\Form\User\EditUserType;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Encoder\UserPasswordEncoderInterface;
class EditController extends Controller
{
public function edit(Request $request, UserPasswordEncoderInterface $encoder)
{
$userInfo = ['username' => null, 'plainPassword' => null, 'password' => null, 'email' => null];
$form = $this->createForm(EditUserType::class, $userInfo);
$form->handleRequest($request);
$user = $this->getUser();
$entityManager = $this->getDoctrine()->getManager();
if ($form->isSubmitted() && $form->isValid()) {
$userInfo = $form->getData();
$username = $userInfo['username'];
$email = $userInfo['email'];
$newPass = $userInfo['plainPassword'];
$oldPass = $userInfo['password'];
if (!$encoder->isPasswordValid($user, $oldPass)) {
$this->addFlash('danger', 'Old password is invalid. Please try again');
return $this->redirectToRoute('user_edit');
}
$pass = $encoder->encodePassword($user, $newPass);
$user->setPassword($pass);
$user->setEmail($email);
$user->setUsername($username);
$entityManager->persist($user);
$entityManager->flush();
$this->addFlash('success', 'User Details Edited - Please Login Again');
return $this->redirectToRoute('login');
}
return $this->render('user/edit.html.twig', array('form' => $form->createView()));
}
}
the issue was, I wasn't checking the logged in user details, and I thought persist meant insert, not insert/update - so lack of knowledge on this one.