[LiveComponent] Changing the username of a user in a live form disconnect the user before entering controllre logic
Huluti opened this issue · comments
I have a UserType form that let the user to change the email of his account.
I use dynamic fields with https://github.com/SymfonyCasts/dynamic-forms so I put the form in a Twig component to have a "live form".
The problem I have, is that when I validate the form, the user is instantly logged out even before entering the form handling part.
Here's my controller:
#[Route(path: ['fr' => '/mon-compte', 'en' => '/my-account'], name: 'dashboard')]
public function index(Request $request): Response
{
$user = $this->userService->getUser();
$currentEmail = $user->getEmail();
$form = $this->createForm(UserType::class, $user, [
'dashboard' => true,
]);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
if ($user->getEmail() !== $currentEmail) {
// If the user has changed his email, he need to re-verify it
$user->setIsVerified(false);
$locale = $this->userService->getLocale($user);
$this->emailVerifierService->sendEmailConfirmation($user, $locale);
}
$this->entityManager->flush();
$this->addFlash('success', $this->translator->trans('base.changed'));
// Redirect to refresh the page
return $this->redirectToRoute('dashboard');
}
return $this->render('dashboard/index.html.twig', [
'form' => $form->createView(),
'user' => $user,
]);
}
My dashboard.html.twig file:
{{ component('DashboardForm', {
initialFormData: user,
form: form
}) }}
My DashboardForm.php file:
<?php
declare(strict_types=1);
namespace App\Twig\Components;
use App\Entity\User;
use App\Form\UserType;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\Form\FormInterface;
use Symfony\UX\LiveComponent\Attribute\AsLiveComponent;
use Symfony\UX\LiveComponent\Attribute\LiveProp;
use Symfony\UX\LiveComponent\ComponentWithFormTrait;
use Symfony\UX\LiveComponent\DefaultActionTrait;
#[AsLiveComponent]
class DashboardForm extends AbstractController
{
use ComponentWithFormTrait;
use DefaultActionTrait;
#[LiveProp]
public ?User $initialFormData = null;
protected function instantiateForm(): FormInterface
{
return $this->createForm(UserType::class, $this->initialFormData, [
'dashboard' => true,
]);
}
}
My DashboardForm.html.twig form:
<div {{ attributes }}>
{{ form_start(form, {'attr': {'data-model': 'on(change)|*'}}) }}
{{ form_errors(form) }}
<!-- Other fields hided for the issue -->
{{ form_label(form.email) }}
{{ form_errors(form.email) }}
{{ form_widget(form.email) }}
<button class="button mb-0" type="submit">
{% trans %}base.valid_button{% endtrans %}
</button>
{{ form_end(form) }}
</div>
When I click on the submit button, the if ($form->isSubmitted() && $form->isValid()) {
part isn't reached and the user instantly logged out with the following logs:
[2024-04-05T15:30:46.252322+00:00] security.DEBUG: Stored the security token in the session. {"key":"_security_main"} []
[2024-04-05T15:30:46.305552+00:00] request.INFO: Matched route "dashboard". {"route":"dashboard","route_parameters":{"_route":"dashboard","_controller":"App\\Controller\\DashboardController::index","_locale":"fr"},"request_uri":"http://localhost/mon-compte","method":"POST"} []
[2024-04-05T15:30:46.306955+00:00] security.DEBUG: Read existing security token from the session.
[2024-04-05T15:30:46.333030+00:00] security.DEBUG: Cannot refresh token because user has changed. {"username":"*****","provider":"Symfony\\Bridge\\Doctrine\\Security\\User\\EntityUserProvider"} []
[2024-04-05T15:30:46.333117+00:00] security.DEBUG: Token was deauthenticated after trying to refresh it. [] []
[2024-04-05T15:30:46.333259+00:00] security.DEBUG: Clearing remember-me cookie. {"name":"REMEMBERME"} []
Do someone have an idea how to fix this behavior? Thanks!
It seems your user has been changed one way or another before the submit, and that forces the logout.
https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
First thing: did you try without the LiveComponent ? If you look at your profiler, do you see other requests sent to the LiveComponent and/or your controller ?
If that does not help, could you create and share a small reproducer ? It's hard to know what to investigate there :)
(Side note: using the User as LiveProp is not something i would advice. You should probably use some form of DTO here)
Without wrapping the form in a live component it works perfectly. The if ($form->isSubmitted() && $form->isValid()) {
part is reached, the user email is changed in db...
I use the User as a LiveProp as documented for any entity in the documentation. This should not be done for the user that's it?
Source: https://symfony.com/bundles/ux-live-component/current/index.html#forms
I tried to do the same with the symfony demo but I can't reproduce it outside my project... so I'll close the issue and try to find the issue in my project.
Thanks!