Ver Fonte

gestion des comptes par l'administrateur

garthh há 1 semana atrás
pai
commit
7fd6af7828

+ 2 - 0
.env

@@ -42,5 +42,7 @@ MAILER_DSN=null://null
 
 ### Spécifiques à l'application ###
 # Adresse de courriel pour l'envoi des messages
+APP_URL=http://localhost:8000
+APP_TZ="Europe/Paris"
 CONTACT_EMAIL=no-reply@mail.com
 CONTACT_NAME=Orgasso

+ 3 - 0
config/packages/twig.yaml

@@ -1,5 +1,8 @@
 twig:
     file_name_pattern: '*.twig'
+    globals:
+        app_timezone: '%env(APP_TZ)%'
+        app_url: '%env(APP_URL)%'
 
 when@test:
     twig:

+ 31 - 0
migrations/Version20250722224212.php

@@ -0,0 +1,31 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DoctrineMigrations;
+
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\Migrations\AbstractMigration;
+
+/**
+ * Auto-generated Migration: Please modify to your needs!
+ */
+final class Version20250722224212 extends AbstractMigration
+{
+    public function getDescription(): string
+    {
+        return '';
+    }
+
+    public function up(Schema $schema): void
+    {
+        // this up() migration is auto-generated, please modify it to your needs
+        $this->addSql('ALTER TABLE user CHANGE last_update last_update DATE DEFAULT NULL, CHANGE last_login last_login DATE DEFAULT NULL, CHANGE last_action last_action DATE DEFAULT NULL');
+    }
+
+    public function down(Schema $schema): void
+    {
+        // this down() migration is auto-generated, please modify it to your needs
+        $this->addSql('ALTER TABLE user CHANGE last_update last_update DATE NOT NULL, CHANGE last_login last_login DATE NOT NULL, CHANGE last_action last_action DATE NOT NULL');
+    }
+}

+ 31 - 0
migrations/Version20250723075955.php

@@ -0,0 +1,31 @@
+<?php
+
+declare(strict_types=1);
+
+namespace DoctrineMigrations;
+
+use Doctrine\DBAL\Schema\Schema;
+use Doctrine\Migrations\AbstractMigration;
+
+/**
+ * Auto-generated Migration: Please modify to your needs!
+ */
+final class Version20250723075955 extends AbstractMigration
+{
+    public function getDescription(): string
+    {
+        return '';
+    }
+
+    public function up(Schema $schema): void
+    {
+        // this up() migration is auto-generated, please modify it to your needs
+        $this->addSql('ALTER TABLE user CHANGE last_update last_update DATETIME DEFAULT NULL, CHANGE last_login last_login DATETIME DEFAULT NULL, CHANGE last_action last_action DATETIME DEFAULT NULL');
+    }
+
+    public function down(Schema $schema): void
+    {
+        // this down() migration is auto-generated, please modify it to your needs
+        $this->addSql('ALTER TABLE user CHANGE last_update last_update DATE DEFAULT NULL, CHANGE last_login last_login DATE DEFAULT NULL, CHANGE last_action last_action DATE DEFAULT NULL');
+    }
+}

+ 174 - 0
src/Controller/Admin/UserController.php

@@ -0,0 +1,174 @@
+<?php
+
+namespace App\Controller\Admin;
+
+use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\Routing\Requirement\Requirement;
+use Symfony\Component\Routing\Attribute\Route;
+use Doctrine\ORM\EntityManagerInterface;
+use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
+use App\Security\EmailVerifier;
+use Symfony\Bridge\Twig\Mime\TemplatedEmail;
+use Symfony\Component\Mime\Address;
+use Symfony\Component\Mailer\MailerInterface;
+use Symfony\Component\Mime\Email;
+
+use App\Entity\User;
+use App\Form\UserType;
+use App\Repository\UserRepository;
+
+final class UserController extends AbstractController
+{
+    public function __construct(private EmailVerifier $emailVerifier)
+    {
+    }
+
+    /*
+     * Lister tous les utilisateurs
+     */
+    #[Route('/admin/user', name: 'app_admin_user', methods: ['GET'])]
+    public function index(UserRepository $repository): Response
+    {
+        // Extraire l'ensemble des utilisateurs
+       $users = $repository->findAll(); 
+
+        // Retourner la page
+        return $this->render('admin/user/index.html.twig', [
+            'users' => $users,
+        ]);
+    }
+
+    /*
+     * Supprimer un utilisateur
+     */
+    #[Route('/admin/user/{id}/delete', name: 'app_admin_user_delete', requirements: ['id' => Requirement::UUID_V7], methods: ['GET', 'POST'])]
+    public function delete(?User $user, Request $request, EntityManagerInterface $manager): Response
+    {
+        $form = $this->createFormBuilder(FormType::class)->getForm();
+        $form->handleRequest($request);
+
+        // Suppression de l'utilisateur si le formulaire a été soumis
+        if ($form->isSubmitted() && $form->isValid()) {
+            $manager->remove($user);
+            $manager->flush();
+            $this->addFlash('success', 'Utilisateur supprimé avec succès.');
+            return $this->redirectToRoute('app_admin_user');
+        }
+
+        // Affichage du formualaire de confirmation
+        return $this->render('admin/user/delete.html.twig', [
+            'form' => $form,
+            'user' => $user
+        ]);
+    }
+
+    /*
+     * Modifier un utilisateur
+     */
+    #[Route('/admin/user/{id}/edit', name: 'app_admin_user_edit', requirements: ['id' => Requirement::UUID_V7], methods: ['GET', 'POST'])]
+    public function edit(?User $user, Request $request, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $manager,  MailerInterface $mailer): Response
+    {
+        $form = $this->createForm(UserType::class, $user);
+
+        // Mise à jour de l'utilisateur à partir du formaulaire
+        $form->handleRequest($request);
+        if ($form->isSubmitted() && $form->isValid()) {
+            // Si un nouveau mot de passe a été proposé
+            if ($form->get('newPassword')->getData()) {
+                // Encoder le mot de passe
+                $newPassword = $form->get('newPassword')->getData();
+                $user->setPassword($userPasswordHasher->hashPassword($user, $newPassword));
+                // Prévenir l'utilisateur de la modification de son mot de passe
+                $email = (new TemplatedEmail())
+                    ->from(new Address($_ENV['CONTACT_EMAIL'], $_ENV['CONTACT_NAME']))
+                    ->to((string) $user->getEmail())
+                    ->subject('Votre mot de passe a été modifié')
+                    ->htmlTemplate('admin/user/edit.email.html.twig')
+                    ->textTemplate('admin/user/edit.email.txt.twig')
+                    ->context([
+                        'user' => $user,
+                        'clearPassword' => $newPassword,
+                    ]);
+                $mailer->send($email);
+            }
+            // Mettre à jour l'utilisateur
+            $user->setLastUpdate();
+            $manager->persist($user);
+            $manager->flush();
+            $this->addFlash('success', 'Utilisateur modifié avec succès.');
+            return $this->redirectToRoute('app_admin_user');
+        }
+
+        // Affichage du formulaire de modification
+        return $this->render('admin/user/edit.html.twig', [
+            'form' => $form,
+            'user' => $user
+        ]);
+    }
+
+    /*
+     * Ajouter un utilisateur
+     */
+    #[Route('/admin/user/add', name: 'app_admin_user_add', methods: ['GET', 'POST'])]
+    public function add(Request $request, UserPasswordHasherInterface $userPasswordHasher,EntityManagerInterface $manager,  MailerInterface $mailer): Response
+    {
+        $user = new User();
+        $form = $this->createForm(UserType::class, $user);
+
+        // Mise à jour de l'utilisateur à partir du formaulaire
+        $form->handleRequest($request);
+        if ($form->isSubmitted() && $form->isValid()) {
+            // Générer un mot de passe aléatoire et le mailler
+            if ($form->get('newPassword')->getData()) {
+                // Encoder le mot de passe
+                $newPassword = $form->get('newPassword')->getData();
+                $user->setPassword($userPasswordHasher->hashPassword($user, $newPassword));
+            } else {
+                // Générer un mot de passe aléatoire
+                $newPassword = bin2hex(random_bytes(8));
+                $user->setPassword($userPasswordHasher->hashPassword($user, $newPassword));
+            }
+            // Enregisrer ce nouvel utilisateur
+            $manager->persist($user);
+            $manager->flush();
+
+            // Prévenir l'utilisateur de la création de son compte
+            $email = (new TemplatedEmail())
+                    ->from(new Address($_ENV['CONTACT_EMAIL'], $_ENV['CONTACT_NAME']))
+                    ->to((string) $user->getEmail())
+                    ->subject('Votre mot de passe a été modifié')
+                    ->htmlTemplate('admin/user/add.email.html.twig')
+                    ->textTemplate('admin/user/add.email.txt.twig')
+                    ->context([
+                        'user' => $user,
+                        'clearPassword' => $newPassword,
+                    ]);
+            $mailer->send($email);
+
+            // Vérification de l'email, si nécessaire
+            if (!$user->isVerified()) {
+                $this->emailVerifier->sendEmailConfirmation('app_verify_email', $user,
+                   (new TemplatedEmail())
+                        ->from(new Address($_ENV['CONTACT_EMAIL'], $_ENV['CONTACT_NAME']))
+                        ->to((string) $user->getEmail())
+                        ->subject('Merci de confirmer votre adresse email')
+                        ->htmlTemplate('registration/confirmation_email.html.twig')
+                        ->textTemplate('registration/confirmation_email.txt.twig')
+                );
+            }
+
+            $this->addFlash('success', 'Utilisateur créé avec succès.');
+            return $this->redirectToRoute('app_admin_user');
+        }
+
+        // Affichage du formulaire d'ajout
+        return $this->render('admin/user/edit.html.twig', [
+            'form' => $form,
+        ]);
+    }
+
+
+
+}

+ 40 - 8
src/Controller/RegistrationController.php

@@ -3,6 +3,7 @@
 namespace App\Controller;
 
 use App\Entity\User;
+use App\Repository\UserRepository;
 use App\Form\RegistrationFormType;
 use App\Security\EmailVerifier;
 use Doctrine\ORM\EntityManagerInterface;
@@ -15,6 +16,7 @@ use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
 use Symfony\Component\Routing\Attribute\Route;
 use Symfony\Contracts\Translation\TranslatorInterface;
 use SymfonyCasts\Bundle\VerifyEmail\Exception\VerifyEmailExceptionInterface;
+use Symfony\Component\Routing\Requirement\Requirement;
 
 class RegistrationController extends AbstractController
 {
@@ -45,13 +47,15 @@ class RegistrationController extends AbstractController
                 (new TemplatedEmail())
                     ->from(new Address($_ENV['CONTACT_EMAIL'], $_ENV['CONTACT_NAME']))
                     ->to((string) $user->getEmail())
-                    ->subject('Please Confirm your Email')
+                    ->subject('Merci de confirmer votre adresse email')
                     ->htmlTemplate('registration/confirmation_email.html.twig')
+                    ->textTemplate('registration/confirmation_email.txt.twig')
             );
 
             // do anything else you need here, like send an email
 
-            return $this->redirectToRoute('app_admin');
+            $this->addFlash('success', 'Votre compte a été créé avec succès. Veuillez vérifier votre email pour confirmer votre adresse.');
+            return $this->redirectToRoute('app_main');
         }
 
         return $this->render('registration/register.html.twig', [
@@ -59,15 +63,43 @@ class RegistrationController extends AbstractController
         ]);
     }
 
+    #[Route('/verify/resend/{id}', name: 'app_resend_verification_email', requirements: ['id' => Requirement::UUID_V7], methods: ['GET'])]
+    public function resendVerificationEmail(User $user, TranslatorInterface $translator): Response
+    {
+        $this->emailVerifier->sendEmailConfirmation('app_verify_email', $user,
+            (new TemplatedEmail())
+                ->from(new Address($_ENV['CONTACT_EMAIL'], $_ENV['CONTACT_NAME']))
+                ->to((string) $user->getEmail())
+                ->subject('Merci de confirmer votre adresse email')
+                ->htmlTemplate('registration/confirmation_email.html.twig')
+                ->textTemplate('registration/confirmation_email.txt.twig')
+        );
+
+        $this->addFlash('success', 'Un nouvel email de confirmation a été envoyé à votre adresse email.');
+        return $this->redirectToRoute('app_admin_user');
+
+    }
+
     #[Route('/verify/email', name: 'app_verify_email')]
-    public function verifyUserEmail(Request $request, TranslatorInterface $translator): Response
+    public function verifyUserEmail(Request $request, UserRepository $userRepository, TranslatorInterface $translator): Response
     {
-        $this->denyAccessUnlessGranted('IS_AUTHENTICATED_FULLY');
+        $id = $request->query->get('id'); // retrieve the user id from the url
+
+        // Verify the user id exists and is not null
+        if (null === $id) {
+            return $this->redirectToRoute('app_home');
+        }
+
+        $user = $userRepository->find($id);
+
+        // Ensure the user exists in persistence
+        if (null === $user) {
+            return $this->redirectToRoute('app_home');
+        }
 
         // validate email confirmation link, sets User::isVerified=true and persists
         try {
-            /** @var User $user */
-            $user = $this->getUser();
+
             $this->emailVerifier->handleEmailConfirmation($request, $user);
         } catch (VerifyEmailExceptionInterface $exception) {
             $this->addFlash('verify_email_error', $translator->trans($exception->getReason(), [], 'VerifyEmailBundle'));
@@ -76,8 +108,8 @@ class RegistrationController extends AbstractController
         }
 
         // @TODO Change the redirect on success and handle or remove the flash message in your templates
-        $this->addFlash('success', 'Your email address has been verified.');
+        $this->addFlash('success', 'Votre adresse de courriel a été confirmée.');
 
-        return $this->redirectToRoute('app_main');
+        return $this->redirectToRoute('app_login');
     }
 }

+ 6 - 6
src/Entity/User.php

@@ -53,13 +53,13 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
     #[ORM\Column(length: 255, nullable: true)]
     private ?string $phone = null;
 
-    #[ORM\Column(type: Types::DATE_MUTABLE,nullable: true)]
+    #[ORM\Column(type: Types::DATETIME_MUTABLE,nullable: true)]
     private ?\DateTimeInterface $lastUpdate = null;
 
-    #[ORM\Column(type: Types::DATE_MUTABLE,nullable: true)]
+    #[ORM\Column(type: Types::DATETIME_MUTABLE,nullable: true)]
     private ?\DateTimeInterface $lastLogin = null;
 
-    #[ORM\Column(type: Types::DATE_MUTABLE,nullable: true)]
+    #[ORM\Column(type: Types::DATETIME_MUTABLE,nullable: true)]
     private ?\DateTimeInterface $lastAction = null;
 
     public function __construct()
@@ -195,7 +195,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
         return $this->lastUpdate;
     }
 
-    public function setLastUpdate(\DateTimeInterface $lastUpdate): static
+    public function setLastUpdate(?\DateTimeInterface $lastUpdate = null): static
     {
         // Si la date est vide, on mets à jour à la date actuelle
         if (!$lastUpdate) {
@@ -213,7 +213,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
         return $this->lastLogin;
     }
 
-    public function setLastLogin(\DateTimeInterface $lastLogin): static
+    public function setLastLogin(?\DateTimeInterface $lastLogin = null): static
     {
         // Si la date est vide, on mets à jour à la date actuelle
         if (!$lastLogin) {
@@ -231,7 +231,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface
         return $this->lastAction;
     }
 
-    public function setLastAction(\DateTimeInterface $lastAction): static
+    public function setLastAction(?\DateTimeInterface $lastAction = null): static
     {
         // Si la date est vide, on mets à jour à la date actuelle
         if (!$lastAction) {

+ 3 - 2
src/Form/ChangePasswordFormType.php

@@ -35,8 +35,9 @@ class ChangePasswordFormType extends AbstractType
                             // max length allowed by Symfony for security reasons
                             'max' => 4096,
                         ]),
-                        new PasswordStrength(),
-                        new NotCompromisedPassword(),
+                        // @todo: gérer les deux contraintes suivantes et l'activer
+//                        new PasswordStrength(),
+//                        new NotCompromisedPassword(),
                     ],
                     'label' => 'New password',
                 ],

+ 90 - 0
src/Form/UserType.php

@@ -0,0 +1,90 @@
+<?php
+
+namespace App\Form;
+
+use App\Entity\User;
+use Symfony\Component\Form\AbstractType;
+use Symfony\Component\Form\FormBuilderInterface;
+use Symfony\Component\OptionsResolver\OptionsResolver;
+use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
+use Symfony\Component\Form\Extension\Core\Type\PasswordType;
+use Symfony\Component\Validator\Constraints\Length;
+use Symfony\Component\Form\Extension\Core\Type\RepeatedType;
+
+class UserType extends AbstractType
+{
+    public function buildForm(FormBuilderInterface $builder, array $options): void
+    {
+        $builder
+            ->add('firstName', null, [
+                'label' => 'Prénom',
+                'required' => true,
+                'help' => 'Entrez le prénom de l\'utilisateur.'
+            ])
+            ->add('lastName', null, [
+                'label' => 'Nom',
+                'required' => true,
+                'help' => 'Entrez le nom de l\'utilisateur.'
+            ])
+            ->add('email', null, [
+                'label' => 'eMail',
+                'required' => true,
+                'help' => 'Entrez une adresse email.'
+            ])
+            ->add('isVerified', null, [
+                'label' => 'email vérifié',
+                'help' => 'Cochez si l\'adresse email est vérifiée. La connexion est impossible si l\'email n\'est pas vérifié.',
+            ])
+            ->add('phone', null, [
+                'label' => 'Téléphone',
+                'required' => false,
+                'help' => 'Entrez un numéro de téléphone (optionnel).'
+            ])
+            ->add('roles', ChoiceType::class, [
+                'label' => 'Rôles',
+                'help' => 'Sélectionnez les rôles de l\'utilisateur.',
+                'choices' => [
+                    'Participant' => 'ROLE_USER',
+                    'Equipe' => 'ROLE_STAFF',
+                    'Gestionnaire' => 'ROLE_MANAGER',
+                    'Administrateur' => 'ROLE_ADMIN',
+                ],
+                'expanded' => true,
+                'multiple' => true,
+            ])
+            ->add('newPassword', RepeatedType::class, [
+                'mapped' => false,
+                'required' => false,
+                'invalid_message' => 'Les mots de passe ne sont pas identiques.',
+                'type' => PasswordType::class,
+                'first_options' => [
+                    'label' => 'Mot de passe (laissez vide pour ne pas changer)',
+                    'toggle' => true,
+                    'attr' => ['autocomplete' => 'new-password'],
+                    'constraints' => [
+                        new Length([
+                            'min' => 6,
+                            'minMessage' => 'Your password should be at least {{ limit }} characters',
+                            // max length allowed by Symfony for security reasons
+                            'max' => 4096,
+                        ]),
+                    ]],
+                'second_options' => [
+                    'label' => 'Répétez le mot de passe',
+                    'toggle' => true,
+                    'attr' => ['autocomplete' => 'new-password'],
+                    ],
+            ])
+            /*->add('lastUpdate')
+            ->add('lastLogin')
+            ->add('lastAction') */
+        ;
+    }
+
+    public function configureOptions(OptionsResolver $resolver): void
+    {
+        $resolver->setDefaults([
+            'data_class' => User::class,
+        ]);
+    }
+}

+ 2 - 1
src/Security/EmailVerifier.php

@@ -24,7 +24,8 @@ class EmailVerifier
         $signatureComponents = $this->verifyEmailHelper->generateSignature(
             $verifyEmailRouteName,
             (string) $user->getId(),
-            (string) $user->getEmail()
+            (string) $user->getEmail(),
+            ['id' => $user->getId()]
         );
 
         $context = $email->getContext();

+ 38 - 0
templates/admin/user/add.email.html.twig

@@ -0,0 +1,38 @@
+{% extends 'base.email.html.twig' %}
+
+{% block title %}Votre compte utilisateur{% endblock %}
+{% block content %}
+                    <tr>
+                        <td style="padding: 0 20px 10px 20px; font-size: 16px;">
+                            <p style="margin: 0;">Bonjour {{ user.firstname }},</p>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td style="padding: 0 20px 20px 20px; font-size: 16px;">
+                            <p style="margin: 0;">Voici les informations pour vous connecter :</p>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td style="padding: 0 20px 20px 20px;">
+                            <table width="100%" cellpadding="0" cellspacing="0" border="0" style="font-size: 15px; line-height: 1.6;">
+                                <tr>
+                                    <td><strong>Identifiant :</strong></td>
+                                    <td>{{ user.email }}</td>
+                                </tr>
+                                <tr>
+                                    <td><strong>Mot de passe :</strong></td>
+                                    <td>{{ clearPassword }}</td>
+                                </tr>
+                                <tr>
+                                    <td><strong>Adresse de connexion :</strong></td>
+                                    <td>{{ app_url }}/login</td>
+                                </tr>
+                            </table>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td style="padding: 0 20px 20px 20px;">
+                            <p style="margin: 0;">La vérfication de l'adresse de courriel est indispensable avant de pouvoir se connecter. Un second courriel contient le lien de vérification.</p>
+                        </td>
+                    </tr>
+{% endblock %}

+ 9 - 0
templates/admin/user/add.email.txt.twig

@@ -0,0 +1,9 @@
+Bonjour {{ user.firstname }},
+
+Voici les informations pour vous connecter :
+
+Identifiant : {{ user.email }}
+Mot de passe : {{ clearPassword }}
+Adresse de connexion : {{ app_url }}/login
+
+La vérfication de l'adresse de courriel est indispensable avant de pouvoir se connecter. Un second courriel contient le lien de vérification.

+ 16 - 0
templates/admin/user/delete.html.twig

@@ -0,0 +1,16 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}Hello Admin/UserController!{% endblock %}
+
+{% block content %}
+            
+            {{ form_start(form) }}
+            {{ form_widget(form) }}
+            <button type="submit">Supprimer l'utilisateur</button>
+            <a href="{{ path('app_admin_user') }}">Annuler</a>
+            {{ form_end(form) }}
+        </div>
+    </div>
+</div>
+
+{% endblock %}

+ 33 - 0
templates/admin/user/edit.email.html.twig

@@ -0,0 +1,33 @@
+{% extends 'base.email.html.twig' %}
+
+{% block title %}Mise à jour de votre mot de passe{% endblock %}
+{% block content %}
+                    <tr>
+                        <td style="padding: 0 20px 10px 20px; font-size: 16px;">
+                            <p style="margin: 0;">Bonjour {{ user.firstname }},</p>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td style="padding: 0 20px 20px 20px; font-size: 16px;">
+                            <p style="margin: 0;">Votre mot de passe a été mis à jour :</p>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td style="padding: 0 20px 20px 20px;">
+                            <table width="100%" cellpadding="0" cellspacing="0" border="0" style="font-size: 15px; line-height: 1.6;">
+                                <tr>
+                                    <td><strong>Identifiant :</strong></td>
+                                    <td>{{ user.email }}</td>
+                                </tr>
+                                <tr>
+                                    <td><strong>Mot de passe :</strong></td>
+                                    <td>{{ clearPassword }}</td>
+                                </tr>
+                                <tr>
+                                    <td><strong>Adresse de connexion :</strong></td>
+                                    <td>{{ app_url }}/login</td>
+                                </tr>
+                            </table>
+                        </td>
+                    </tr>
+{% endblock %}

+ 7 - 0
templates/admin/user/edit.email.txt.twig

@@ -0,0 +1,7 @@
+Bonjour {{ user.firstname }},
+
+Votre mot de passe a été mis à jour :
+
+Identifiant : {{ user.email }}
+Mot de passe : {{ clearPassword }}
+Adresse de connexion : {{ app_url }}/login

+ 13 - 0
templates/admin/user/edit.html.twig

@@ -0,0 +1,13 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}Hello Admin/UserController!{% endblock %}
+
+{% block content %}
+
+    {{ form_errors(form) }}
+    {{ form_start(form) }}
+        {{ form_widget(form) }}
+        <button type="submit">Envoyer</button>
+    {{ form_end(form) }}
+
+{% endblock %}

+ 22 - 0
templates/admin/user/index.html.twig

@@ -0,0 +1,22 @@
+{% extends 'base.html.twig' %}
+
+{% block title %}Hello Admin/UserController!{% endblock %}
+
+{% block content %}
+
+{% for user in users %}
+    <div class="user">
+        <p>Identitié : {{ user.firstname }} {{ user.lastname }}</p>
+        <p>Email: {{ user.email }}</p>
+        <p>Roles: {{ user.roles|join(', ') }}</p>
+        <p>Last Login: {{ user.lastLogin ? user.lastLogin|date('d/m/Y H:i:s', app_timezone) : 'Never' }}</p>
+        <p>Last update: {{ user.lastUpdate ? user.lastUpdate|date('d/m/Y H:i:s', app_timezone) : 'Never' }}</p>
+        <a href="{{ path('app_admin_user_edit', {id: user.id}) }}">Edit</a> |
+        <a href="{{ path('app_admin_user_delete', {id: user.id}) }}">Delete</a> |
+        {% if not user.isVerified %}<a href="{{ path('app_resend_verification_email', {id: user.id}) }}">Resend Verification Email</a>{% endif %}
+    </div>
+
+
+{% endfor %}
+
+{% endblock %}

+ 59 - 0
templates/base.email.html.twig

@@ -0,0 +1,59 @@
+<!DOCTYPE html>
+<html lang="fr">
+<head>
+    <meta charset="UTF-8">
+</head>
+<body style="margin:0; padding:0; background-color:#f4f1e9;">
+    <table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color:#f4f1e9; padding: 20px 0;">
+        <tr>
+            <td align="center">
+                <table width="600" cellpadding="0" cellspacing="0" border="0" style="background-color:#fffef9; border: 1px solid #c2b280; border-radius: 8px; font-family: Georgia, serif; color:#2c2c2c;">
+                    <tr>
+                        <td style="padding: 30px 20px 10px 20px; text-align: center;">
+                            <h1 style="margin: 0; color: #5e3c00; font-size: 24px;">⚔️ {% block title %}Votre réservation{% endblock %} 🛡️</h1>
+                        </td>
+                    </tr>
+                    {% block content %}
+                    <tr>
+                        <td style="padding: 0 20px 10px 20px; font-size: 16px;">
+                            <p style="margin: 0;">Bonjour,</p>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td style="padding: 0 20px 20px 20px; font-size: 16px;">
+                            <p style="margin: 0;">Voici les informations pour vous connecter :</p>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td style="padding: 0 20px 20px 20px;">
+                            <table width="100%" cellpadding="0" cellspacing="0" border="0" style="font-size: 15px; line-height: 1.6;">
+                                <tr>
+                                    <td><strong>Identifiant :</strong></td>
+                                    <td>{{ user.username }}</td>
+                                </tr>
+                                <tr>
+                                    <td><strong>Mot de passe :</strong></td>
+                                    <td>{{ password }}</td>
+                                </tr>
+                                <tr>
+                                    <td><strong>Adresse de connexion :</strong></td>
+                                    <td>{{ url }}/login</td>
+                                </tr>
+                            </table>
+                        </td>
+                    </tr>
+                    {% endblock %}
+                </table>
+            </td>
+        </tr>
+    </table>
+    <br/>
+    <table width="100%" cellpadding="0" cellspacing="0" border="0" style="background-color:#f4f1e9; padding: 20px 0;">
+        <tr>
+            <td align="center" style="font-size: 10px; color: #999999;">
+                <p style="margin: 0;">Vous recevez ce courriel de notification en réponse à une action de votre part sur notre application.</p>
+                <p style="margin: 0;">Vous pouvez consulter les <a href="{{ app_url }}/cgu">conditions d'utilisation</a> ou nous <a href="{{ app_url }}/contact">contacter</a> pour plus d'informations.</p>
+            </td>
+        </tr>
+</body>
+</html>

+ 25 - 9
templates/registration/confirmation_email.html.twig

@@ -1,11 +1,27 @@
-<h1>Hi! Please confirm your email!</h1>
+{% extends 'base.email.html.twig' %}
 
-<p>
-    Please confirm your email address by clicking the following link: <br><br>
-    <a href="{{ signedUrl|raw }}">Confirm my Email</a>.
-    This link will expire in {{ expiresAtMessageKey|trans(expiresAtMessageData, 'VerifyEmailBundle') }}.
-</p>
+{% block title %}Confirmez votre adresse de courriel{% endblock %}
 
-<p>
-    Cheers!
-</p>
+{% block content %}
+    <tr>
+        <td style="padding: 0 20px 10px 20px; font-size: 16px;">
+            <p>Bonjour,</p>
+        </td>
+    </tr>
+                    <tr>
+                        <td style="padding: 0 20px 20px 20px; font-size: 16px;">
+                            <p style="margin: 0;">Merci de confirmer votre adresse de courriel en cliquant sur ce lien :</p>
+                        </td>
+                    </tr>
+                                        <tr>
+                        <td style="padding: 0 20px 20px 20px; font-size: 16px;">
+                            <p style="margin: 0;"><a href="{{ signedUrl|raw }}">{{ signedUrl|raw }}</a></p>
+                        </td>
+                    </tr>
+                    <tr>
+                        <td style="padding: 0 20px 20px 20px; font-size: 16px;">
+                            <p style="margin: 0;">Ce lien expirera dans {{ expiresAtMessageKey|trans(expiresAtMessageData, 'VerifyEmailBundle') }}.</p>
+                            <p>Vous pouvez également le copier/coller dans votre navigateur.</p>
+
+                    </tr>
+{% endblock %}

+ 8 - 0
templates/registration/confirmation_email.txt.twig

@@ -0,0 +1,8 @@
+Bonjour,
+
+Merci de confirmer votre adresse de courriel en cliquant sur ce lien :
+
+{{ signedUrl|raw }}
+
+Ce lien expirera dans {{ expiresAtMessageKey|trans(expiresAtMessageData, 'VerifyEmailBundle') }}.
+Vous pouvez également le copier/coller dans votre navigateur.