Ajout modification mail/Mot de passe

This commit is contained in:
Melaine Gérard 2025-02-22 13:07:09 +01:00
parent 9073737e36
commit 51ddf6510e
12 changed files with 268 additions and 23 deletions

View File

@ -5,21 +5,3 @@
@source '../../vendor/tales-from-a-dev/flowbite-bundle/templates/**/*.html.twig'; @source '../../vendor/tales-from-a-dev/flowbite-bundle/templates/**/*.html.twig';
@custom-variant dark (@media (prefers-color-scheme: dark)); @custom-variant dark (@media (prefers-color-scheme: dark));
/*
The default border color has changed to `currentColor` in Tailwind CSS v4,
so we've added these compatibility styles to make sure everything still
looks the same as it did with Tailwind CSS v3.
If we ever want to remove these styles, we need to add an explicit border
color utility to any element that depends on these defaults.
*/
@layer base {
*,
::after,
::before,
::backdrop,
::file-selector-button {
border-color: var(--color-gray-200, currentColor);
}
}

View File

@ -44,7 +44,7 @@
"symfony/twig-bundle": "7.2.*", "symfony/twig-bundle": "7.2.*",
"symfony/uid": "7.2.*", "symfony/uid": "7.2.*",
"symfony/ux-dropzone": "^2.23.0", "symfony/ux-dropzone": "^2.23.0",
"symfony/ux-icons": "^2.23.0", "symfony/ux-icons": "^2.23",
"symfony/ux-turbo": "^2.23.0", "symfony/ux-turbo": "^2.23.0",
"symfony/ux-twig-component": "^2.23.0", "symfony/ux-twig-component": "^2.23.0",
"symfony/validator": "7.2.*", "symfony/validator": "7.2.*",

2
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "03d94385bcbb64b3bf80357c56e137b0", "content-hash": "1d09b12a04dca26002dc08d1ee5a0f7a",
"packages": [ "packages": [
{ {
"name": "composer/semver", "name": "composer/semver",

View File

@ -4,13 +4,28 @@ declare(strict_types=1);
namespace App\Controller; namespace App\Controller;
use App\DTO\EmailDTO;
use App\DTO\PasswordDTO;
use App\Entity\User; use App\Entity\User;
use App\Form\EmailFormType;
use App\Form\PasswordFormType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Attribute\Route; use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted; use Symfony\Component\Security\Http\Attribute\IsGranted;
class ProfileController extends AbstractController class ProfileController extends AbstractController
{ {
public function __construct(
private readonly EntityManagerInterface $entityManager,
private readonly UserPasswordHasherInterface $passwordHasher,
)
{
}
#[Route('/profile', name: 'app_profile')] #[Route('/profile', name: 'app_profile')]
#[IsGranted('ROLE_USER')] #[IsGranted('ROLE_USER')]
public function index() public function index()
@ -19,8 +34,75 @@ class ProfileController extends AbstractController
* @var User $user * @var User $user
*/ */
$user = $this->getUser(); $user = $this->getUser();
return $this->render('profile/index.html.twig', [ return $this->render('profile/index.html.twig', [
'user' => $user, 'user' => $user,
]); ]);
} }
#[Route('/profile/edit/email', name: 'app_profile_email_edit')]
#[IsGranted('ROLE_USER')]
public function editEmail(Request $request): Response
{
$emailDTO = new EmailDTO();
$form = $this->createForm(EmailFormType::class, $emailDTO);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
/**
* @var User $user
*/
$user = $this->getUser();
if ($this->passwordHasher->isPasswordValid($user, $emailDTO->password)) {
$user->setEmail($emailDTO->email);
$this->entityManager->flush();
$this->addFlash('success', 'Votre adresse email a bien été modifiée.');
return $this->redirectToRoute('app_profile');
}
$this->addFlash('error', 'Le mot de passe est incorrect.');
}
return $this->render('profile/edit_email.html.twig', [
'form' => $form->createView(),
]);
}
#[Route('/profile/edit/password', name: 'app_profile_password_edit')]
#[IsGranted('ROLE_USER')]
public function editPassword(Request $request): Response
{
$passwordDTO = new PasswordDTO();
$form = $this->createForm(PasswordFormType::class, $passwordDTO);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
/**
* @var User $user
*/
$user = $this->getUser();
if ($this->passwordHasher->isPasswordValid($user, $passwordDTO->password)) {
$user->setPassword($this->passwordHasher->hashPassword($user, $passwordDTO->newPassword));
$this->entityManager->flush();
$this->addFlash('success', 'Votre mot de passe a bien été modifiée.');
return $this->redirectToRoute('app_profile');
}
$this->addFlash('error', 'Le mot de passe est incorrect.');
}
return $this->render('profile/edit_password.html.twig', [
'form' => $form->createView(),
]);
}
} }

15
src/DTO/EmailDTO.php Normal file
View File

@ -0,0 +1,15 @@
<?php
declare(strict_types=1);
namespace App\DTO;
class EmailDTO
{
public string $email;
public string $password;
public function __construct(
) {
}
}

12
src/DTO/PasswordDTO.php Normal file
View File

@ -0,0 +1,12 @@
<?php
namespace App\DTO;
class PasswordDTO
{
public string $password;
public string $newPassword;
public function __construct()
{
}
}

View File

@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
namespace App\Form;
use App\DTO\EmailDTO;
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\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class EmailFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('email', EmailType::class, [
'label' => 'Nouvelle adresse email',
'attr' => [
'placeholder' => 'Nouvelle adresse email',
'autocomplete' => 'new-email',
],
])
->add('password', PasswordType::class, [
'label' => 'Mot de passe actuel',
'attr' => [
'placeholder' => 'Mot de passe actuel',
'autocomplete' => 'new-password',
]
])
->add('submit', SubmitType::class, [
'label' => 'Enregistrer',
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => EmailDTO::class,
'attr' => [
'autocomplete' => 'off',
]
]);
}
}

View File

@ -0,0 +1,51 @@
<?php
declare(strict_types=1);
namespace App\Form;
use App\DTO\PasswordDTO;
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\SubmitType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class PasswordFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('password', PasswordType::class, [
'label' => 'Mot de passe actuel',
'attr' => [
'placeholder' => 'Mot de passe actuel',
'autocomplete' => 'old-password',
],
'required' => true,
])
->add('newPassword', RepeatedType::class, [
'type' => PasswordType::class,
'first_options' => ['label' => 'Nouveau mot de passe'],
'attr' => [
'autocomplete' => 'new-password',
],
'second_options' => ['label' => 'Confirmer le mot de passe'],
'required' => true,
'invalid_message' => 'Les mots de passe ne correspondent pas.',
])
->add('submit', SubmitType::class, [
'label' => 'Enregistrer',
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => PasswordDTO::class,
]);
}
}

15
tailwind.config.js Normal file
View File

@ -0,0 +1,15 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./vendor/tales-from-a-dev/flowbite-bundle/templates/**/*.html.twig",
"./assets/**/*.js",
"./templates/**/*.html.twig",
],
theme: {
extend: {},
},
plugins: [
require('flowbite/plugin')
],
darkMode: 'media',
}

View File

@ -0,0 +1,15 @@
{% extends 'base.html.twig' %}
{% block body %}
<div class="container mx-auto px-16 mt-4">
<div class="block p-6 bg-white border border-gray-200 rounded-lg shadow-sm dark:bg-gray-800 dark:border-gray-700">
<h3 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Modifier mon adresse email</h3>
{{ form(form) }}
</div>
</div>
{% endblock %}
{% block title %}
Modifier mon email
{% endblock %}

View File

@ -0,0 +1,15 @@
{% extends 'base.html.twig' %}
{% block body %}
<div class="container mx-auto px-16 mt-4">
<div class="block p-6 bg-white border border-gray-200 rounded-lg shadow-sm dark:bg-gray-800 dark:border-gray-700">
<h3 class="mb-2 text-2xl font-bold tracking-tight text-gray-900 dark:text-white">Modifier mon mot de passe</h3>
{{ form(form) }}
</div>
</div>
{% endblock %}
{% block title %}
Modifier mon email
{% endblock %}

View File

@ -22,10 +22,19 @@
Rôle : Rôle :
</span> {{ user.roles[0] == 'ROLE_ADMIN' ? 'Administrateur' : 'Utilisateur' }} </span> {{ user.roles[0] == 'ROLE_ADMIN' ? 'Administrateur' : 'Utilisateur' }}
</div> </div>
<div class="border-t border-gray-500 p-2 flex justify-between">
<div>
<span class="font-bold">
Rôle de dossier :
</span>
{{ user.folderRole.value }}
</div>
<a href="{{ path('app_profile_email_edit') }}" class="text-white hover:text-gray-200">
<twig:ux:icon name="line-md:pencil" class="w-6 h-6" />
</a>
</div>
<div class="border-t border-gray-500 py-2 pl-2"> <div class="border-t border-gray-500 py-2 pl-2">
<span class="font-bold"> <a href="{{ path('app_profile_password_edit') }}" class="font-medium text-blue-600 dark:text-blue-500 hover:underline">Modifier mon mot de passe</a>
Rôle de dossier :
</span> {{ user.folderRole.value }}
</div> </div>
</div> </div>