diff --git a/.env b/.env index eb30919784bcdaddaf95d9aa8992ae45f7aeb7a8..c5270338ff8d661bf71d14bf1cf999d03080a095 100644 --- a/.env +++ b/.env @@ -27,7 +27,7 @@ MESSENGER_TRANSPORT_DSN=sync:// # DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" # DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4" # DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4" -DATABASE_URL="mysql://root:root@db_docker_symfony:3306/wishlist?serverVersion=8.0" +DATABASE_URL="mysql://root:hamma@localhost:3306/wishlist?serverVersion=8.0" ###< doctrine/doctrine-bundle ### APP_SECRET=3d9f431b0fd768e0cb2e8b139c66e9fd67ecbd49762f6a345d459e2f115f61b4 diff --git a/config/packages/security.yaml b/config/packages/security.yaml index 730a51d59c5f378a09e2851542bc18acce65cccc..e8608e366d558d2bfd380de1419fb0a6242e437c 100644 --- a/config/packages/security.yaml +++ b/config/packages/security.yaml @@ -25,8 +25,17 @@ security: secret: '%kernel.secret%' access_control: - - { path: ^/admin, allow_if: "user and user.isAdmin == true" } - - { path: ^/*, allow_if: "user and user.isLocked != true" } + # Allow access to /login without being authenticated + - { path: ^/login, allow_if: "1" } + + # Allow users who are admins to access the /admin path + - { path: ^/admin, allow_if: "user and user.isAdmin() == true" } + + # Allow users who are not locked to access other pages + - { path: ^/.*, allow_if: "user and user.isLocked() != true" } + + # Allow all authenticated users to access other routes (outside /admin or /login) + - { path: ^/, allow_if: "user" } when@test: security: diff --git a/src/Controller/HomeController.php b/src/Controller/HomeController.php index 6a27413e245f8a2b400aff981fdd99ee158e27e9..8967bd5f668ce2797499102ddae4c220248bd328 100644 --- a/src/Controller/HomeController.php +++ b/src/Controller/HomeController.php @@ -17,6 +17,8 @@ class HomeController extends AbstractController 'Login' => $this->generateUrl('login'), 'My Wishlists' => $this->generateUrl('app_wishlist_index'), 'Admin Dashboard' => $this->generateUrl('admin_dashboard'), + 'Profile' => $this->generateUrl('user_profile'), + ], ]); } diff --git a/src/Controller/RegistrationController.php b/src/Controller/RegistrationController.php index 46f72b7833b2f63c6981725a44e6c4017a8d6d27..96c886026eb60f8b33d73c21731544c9b58c09a7 100644 --- a/src/Controller/RegistrationController.php +++ b/src/Controller/RegistrationController.php @@ -22,7 +22,7 @@ class RegistrationController extends AbstractController if ($form->isSubmitted() && $form->isValid()) { // Hacher le mot de passe - $hashedPassword = $passwordHasher->hashPassword($user, $form->get('plainPassword')->getData()); + $hashedPassword = $passwordHasher->hashPassword($user, plainPassword: $form->get('plainPassword')->getData()); $user->setPassword($hashedPassword); // Sauvegarder l'utilisateur diff --git a/src/Controller/UserController.php b/src/Controller/UserController.php index a53eb97ea42b9538832991f6359a3350cc2125dc..f8088efc5d4c1a61f96b7e27c7d4dda6d1812078 100644 --- a/src/Controller/UserController.php +++ b/src/Controller/UserController.php @@ -8,6 +8,9 @@ use Symfony\Component\Routing\Attribute\Route; use Doctrine\ORM\EntityManagerInterface; use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface; use Symfony\Component\Security\Core\User\UserInterface; +use Symfony\Component\HttpFoundation\Request; + +use App\Form\UserType; final class UserController extends AbstractController { @@ -64,4 +67,40 @@ final class UserController extends AbstractController $this->addFlash('success', 'Wishlist supprimée avec succès.'); return $this->redirectToRoute('user_dashboard'); } + + #[Route('/user/profile', name: 'user_profile')] + public function profile(Request $request, EntityManagerInterface $entityManager): Response + { + // Récupérer l'utilisateur connecté + $token = $this->container->get('security.token_storage')->getToken(); + if ($token) { + $user = $token->getUser(); + dump($user); + } else { + dump('Aucun token trouvé'); + } + + if ($user==null) + { + throw $this->createAccessDeniedException('Vous devez être connecté pour accéder à cette page.'); + } + + // Créer le formulaire pour modifier les informations de l'utilisateur + $form = $this->createForm(UserType::class, $user); + $form->handleRequest($request); + + if ($form->isSubmitted() && $form->isValid()) { + // Sauvegarder les modifications + $entityManager->persist($user); + $entityManager->flush(); + + $this->addFlash('success', 'Votre profil a été mis à jour avec succès.'); + + return $this->redirectToRoute('user_profile'); + } + + return $this->render('user/profile.html.twig', [ + 'form' => $form->createView(), + ]); + } } diff --git a/src/Controller/WishlistController.php b/src/Controller/WishlistController.php index 7e1d571ad2b47914f1667103dbf12cc6a7ec0576..e7442f82f3af926c38b4f018fee36523765035f0 100644 --- a/src/Controller/WishlistController.php +++ b/src/Controller/WishlistController.php @@ -14,56 +14,54 @@ use Symfony\Component\Routing\Attribute\Route; #[Route('/wishlist')] final class WishlistController extends AbstractController { + // Method to display all wishlists for the currently logged-in user #[Route(name: 'app_wishlist_index', methods: ['GET'])] public function getWishLists(WishlistRepository $wishlistRepository): Response { - $user = $this->getUser() ; - + $user = $this->getUser(); // Get the currently authenticated user return $this->render('wishlist/index.html.twig', [ - 'wishlists' => $user->getWishlists()->toArray() + 'wishlists' => $user->getWishlists()->toArray() // Pass the user's wishlists to the template ]); } + // Method to create a new wishlist #[Route('/new', name: 'app_wishlist_new', methods: ['GET', 'POST'])] public function createWishlist(Request $request, EntityManagerInterface $entityManager): Response { - $wishlist = new Wishlist(); - $form = $this->createForm(WishlistType::class, $wishlist); - $form->handleRequest($request); + $wishlist = new Wishlist(); // Create a new Wishlist entity + $form = $this->createForm(WishlistType::class, $wishlist); // Create a form for the Wishlist entity + $form->handleRequest($request); // Handle the form submission if ($form->isSubmitted() && $form->isValid()) { - $entityManager->persist($wishlist); - $entityManager->flush(); + $entityManager->persist($wishlist); // Persist the new wishlist to the database + $entityManager->flush(); // Save changes to the database - return $this->redirectToRoute('app_wishlist_index', [], Response::HTTP_SEE_OTHER); + return $this->redirectToRoute('app_wishlist_index', [], Response::HTTP_SEE_OTHER); // Redirect to the wishlist index page } return $this->render('wishlist/new.html.twig', [ - 'wishlist' => $wishlist, - 'form' => $form, - ]); - - + 'wishlist' => $wishlist, // Pass the wishlist entity to the template + 'form' => $form, // Pass the form to the template + ]); } + // Method to display a specific wishlist #[Route('/{id}', name: 'app_wishlist_show', methods: ['GET'])] public function show(Wishlist $wishlist): Response { return $this->render('wishlist/show.html.twig', [ - 'wishlist' => $wishlist, + 'wishlist' => $wishlist, // Pass the wishlist entity to the template ]); } + // Method to edit an existing wishlist #[Route('/{id}/edit', name: 'app_wishlist_edit', methods: ['GET', 'POST'])] public function edit(Request $request, Wishlist $wishlist, EntityManagerInterface $entityManager): Response { - $wishlist->setName($request->get('name')); - $wishlist->setDeadline($request->get('deadline')) ; - $entityManager->persist($wishlist); - $entityManager->flush(); - return new Response('wishlist was modified successfully ', Response::HTTP_ACCEPTED) ; -/* $form = $this->createForm(WishlistType::class, $wishlist); + + + $form = $this->createForm(WishlistType::class, $wishlist); $form->handleRequest($request); if ($form->isSubmitted() && $form->isValid()) { @@ -75,31 +73,20 @@ final class WishlistController extends AbstractController return $this->render('wishlist/edit.html.twig', [ 'wishlist' => $wishlist, 'form' => $form, - ]); */ + ]); + } + // Method to delete a wishlist #[Route('/{id}', name: 'app_wishlist_delete', methods: ['POST'])] public function delete(Request $request, Wishlist $wishlist, EntityManagerInterface $entityManager): Response { + // Validate the CSRF token before deleting the wishlist if ($this->isCsrfTokenValid('delete'.$wishlist->getId(), $request->getPayload()->getString('_token'))) { - $entityManager->remove($wishlist); - $entityManager->flush(); + $entityManager->remove($wishlist); // Remove the wishlist from the database + $entityManager->flush(); // Save changes to the database } - return $this->redirectToRoute('app_wishlist_index', [], Response::HTTP_SEE_OTHER); + return $this->redirectToRoute('app_wishlist_index', [], Response::HTTP_SEE_OTHER); // Redirect to the wishlist index page } - - -} - - -/* - $wishlist = new Wishlist(); - $name = $request->get(key: 'name'); - $wishlist->setName(name: $name); - $deadline = $request->get('deadline') ; - $wishlist->setDeadline($deadline); - $this->getUser()->addToAuthorWhishlists($wishlist); - $entityManager->persist($wishlist); - $entityManager->persist($this->getUser()) ; - $entityManager->flush(); */ \ No newline at end of file +} \ No newline at end of file diff --git a/src/Entity/User.php b/src/Entity/User.php index 3b99380de70e1e5d2765ef69d24c94c023e4f3e1..406c8d520278523a95f205da16acde3176a2d10a 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -164,7 +164,7 @@ class User implements UserInterface, PasswordAuthenticatedUserInterface return $this->wishlists; } - public function addToAuthorWhishlists(Wishlists $wishlist){ + public function addToAuthorWhishlists(Wishlist $wishlist){ if (!$this->wishlists->contains($wishlist)) { $this->wishlists[] = $wishlist; } diff --git a/src/Entity/Wishlist.php b/src/Entity/Wishlist.php index 9c16360e90dd7fe7e5adfe93d8137a1594cb0313..60d02f6b46676bc0c8339747922d1879a7317770 100644 --- a/src/Entity/Wishlist.php +++ b/src/Entity/Wishlist.php @@ -32,6 +32,21 @@ class Wishlist #[ORM\OneToMany(targetEntity: Item::class, mappedBy: 'wishlist', orphanRemoval: true)] private Collection $items; + #[ORM\ManyToOne(targetEntity: User::class, inversedBy: 'wishlists')] + #[ORM\JoinColumn(nullable: false)] + private ?User $owner = null; + + public function getOwner(): ?User + { + return $this->owner; + } + + public function setOwner(?User $owner): static + { + $this->owner = $owner; + return $this; + } + public function __construct() { $this->items = new ArrayCollection(); diff --git a/src/Form/UserType.php b/src/Form/UserType.php new file mode 100644 index 0000000000000000000000000000000000000000..fbb140a00611683f6c38f08660de55994ced4d1d --- /dev/null +++ b/src/Form/UserType.php @@ -0,0 +1,40 @@ +<?php + +namespace App\Form; + +use App\Entity\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\TextType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\OptionsResolver\OptionsResolver; + +class UserType extends AbstractType +{ + public function buildForm(FormBuilderInterface $builder, array $options): void + { + $builder + ->add('firstName', TextType::class, [ + 'label' => 'Prénom', + ]) + ->add('lastName', TextType::class, [ + 'label' => 'Nom', + ]) + ->add('email', EmailType::class, [ + 'label' => 'Email', + ]) + ->add('image', TextType::class, [ + 'label' => 'URL de l\'image de profil', + 'required' => false, + ]); + // Note : Ne pas inclure le champ "password" ici pour des raisons de sécurité. + } + + public function configureOptions(OptionsResolver $resolver): void + { + $resolver->setDefaults([ + 'data_class' => User::class, + ]); + } +} \ No newline at end of file diff --git a/templates/user/profile.html.twig b/templates/user/profile.html.twig new file mode 100644 index 0000000000000000000000000000000000000000..ce689c9401f4aac428f341c6e9117f4e782e1dd8 --- /dev/null +++ b/templates/user/profile.html.twig @@ -0,0 +1,23 @@ +{% extends 'base.html.twig' %} + +{% block title %}Mon Profil{% endblock %} + +{% block body %} +<div class="container mt-5"> + <h1>Mon Profil</h1> + + {{ form_start(form) }} + {{ form_row(form.firstName) }} + {{ form_row(form.lastName) }} + {{ form_row(form.email) }} + {{ form_row(form.image) }} + <button type="submit" class="btn btn-primary">Mettre à jour</button> + {{ form_end(form) }} + + {% for message in app.flashes('success') %} + <div class="alert alert-success mt-3"> + {{ message }} + </div> + {% endfor %} +</div> +{% endblock %} \ No newline at end of file diff --git a/templates/wishlist/index.html.twig b/templates/wishlist/index.html.twig index 3f6757e13f54603fcee0fce0623c0a6ec7ab01cb..f08571c4e46059f76d4f5d78d8fa32345f995300 100644 --- a/templates/wishlist/index.html.twig +++ b/templates/wishlist/index.html.twig @@ -31,6 +31,6 @@ <button title="Delete wishlist">🗑</button> </div> </div> - {% end for %} + {% endfor %} </div> {% endblock %}