From 145584a28a444bb367201ae25b8fac148dca712c Mon Sep 17 00:00:00 2001
From: Paul <paul.cancel.etu@univ-lille.fr>
Date: Sat, 18 Jan 2025 13:02:40 +0100
Subject: [PATCH] Application sans le calendrier

---
 pom.xml                                       |   8 +-
 .../MeetingPlannr/MeetingController.java      | 252 ++++++++++--
 .../MeetingPlannrApplication.java             |   2 +-
 .../infoetu/MeetingPlannr/pojo/Meeting.java   |   5 +-
 .../infoetu/MeetingPlannr/pojo/Request.java   |  13 +-
 .../but/infoetu/MeetingPlannr/pojo/User.java  |  73 +++-
 .../repository/MeetingRepository.java         |   8 +-
 .../repository/RequestRepository.java         |   4 +-
 .../repository/UserRepository.java            |   6 +-
 .../MeetingPlannr/security/Security.java      |  93 +++++
 .../MeetingPlannr/service/UserService.java    |  22 ++
 src/main/resources/application.properties     |  22 +-
 src/main/resources/import.sql                 |  44 ++-
 src/main/resources/static/styles/main.css     | 361 ++++++++++++++++++
 src/main/webapp/WEB-INF/jsp/common/footer.jsp |   6 +
 src/main/webapp/WEB-INF/jsp/common/header.jsp |  13 +
 src/main/webapp/WEB-INF/jsp/listeAction.jsp   |  81 ----
 src/main/webapp/WEB-INF/jsp/login.jsp         |  88 -----
 src/main/webapp/WEB-INF/jsp/public/login.jsp  |  45 +++
 .../WEB-INF/jsp/{ => public}/register.jsp     |  59 +--
 .../WEB-INF/jsp/user/detailRendezVous.jsp     |  31 ++
 .../webapp/WEB-INF/jsp/user/editMeeting.jsp   |  45 +++
 .../webapp/WEB-INF/jsp/user/editProfile.jsp   |  40 ++
 .../webapp/WEB-INF/jsp/user/listeAction.jsp   |  38 ++
 src/main/webapp/WEB-INF/jsp/user/profile.jsp  |  29 ++
 .../webapp/WEB-INF/jsp/user/rendezVous.jsp    |  46 +++
 .../MeetingPlannrApplicationTests.java        |   2 +-
 27 files changed, 1143 insertions(+), 293 deletions(-)
 create mode 100644 src/main/java/fr/but/infoetu/MeetingPlannr/security/Security.java
 create mode 100644 src/main/java/fr/but/infoetu/MeetingPlannr/service/UserService.java
 create mode 100644 src/main/resources/static/styles/main.css
 create mode 100644 src/main/webapp/WEB-INF/jsp/common/footer.jsp
 create mode 100644 src/main/webapp/WEB-INF/jsp/common/header.jsp
 delete mode 100644 src/main/webapp/WEB-INF/jsp/listeAction.jsp
 delete mode 100644 src/main/webapp/WEB-INF/jsp/login.jsp
 create mode 100644 src/main/webapp/WEB-INF/jsp/public/login.jsp
 rename src/main/webapp/WEB-INF/jsp/{ => public}/register.jsp (54%)
 create mode 100644 src/main/webapp/WEB-INF/jsp/user/detailRendezVous.jsp
 create mode 100644 src/main/webapp/WEB-INF/jsp/user/editMeeting.jsp
 create mode 100644 src/main/webapp/WEB-INF/jsp/user/editProfile.jsp
 create mode 100644 src/main/webapp/WEB-INF/jsp/user/listeAction.jsp
 create mode 100644 src/main/webapp/WEB-INF/jsp/user/profile.jsp
 create mode 100644 src/main/webapp/WEB-INF/jsp/user/rendezVous.jsp

diff --git a/pom.xml b/pom.xml
index 17b76ca..4a6eede 100644
--- a/pom.xml
+++ b/pom.xml
@@ -9,9 +9,9 @@
 		<relativePath/> <!-- lookup parent from repository -->
 	</parent>
 	<groupId>fr.but.infoetu</groupId>
-	<artifactId>MeetingPlannr</artifactId>
+	<artifactId>meetingplannr</artifactId>
 	<version>0.0.1-SNAPSHOT</version>
-	<name>MeetingPlannr</name>
+	<name>meetingplannr</name>
 	<description>Demo project for Spring Boot</description>
 	<url/>
 	<licenses>
@@ -69,6 +69,10 @@
 			<artifactId>tomcat-embed-jasper</artifactId>
 			<scope>compile</scope>
 		</dependency>
+		<dependency>
+			<groupId>org.springframework.boot</groupId>
+			<artifactId>spring-boot-starter-security</artifactId>
+		</dependency>
 	</dependencies>
 
 	<build>
diff --git a/src/main/java/fr/but/infoetu/MeetingPlannr/MeetingController.java b/src/main/java/fr/but/infoetu/MeetingPlannr/MeetingController.java
index 5437580..0a4606e 100644
--- a/src/main/java/fr/but/infoetu/MeetingPlannr/MeetingController.java
+++ b/src/main/java/fr/but/infoetu/MeetingPlannr/MeetingController.java
@@ -1,19 +1,29 @@
-package fr.but.infoetu.MeetingPlannr;
+package fr.but.infoetu.meetingplannr;
 
+import java.util.List;
 import java.util.Optional;
 
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.AnonymousAuthenticationToken;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.annotation.AuthenticationPrincipal;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.Model;
 import org.springframework.validation.BindingResult;
 import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.PathVariable;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
 
-import fr.but.infoetu.MeetingPlannr.pojo.User;
-import fr.but.infoetu.MeetingPlannr.repository.MeetingRepository;
-import fr.but.infoetu.MeetingPlannr.repository.RequestRepository;
-import fr.but.infoetu.MeetingPlannr.repository.UserRepository;
+import fr.but.infoetu.meetingplannr.pojo.Meeting;
+import fr.but.infoetu.meetingplannr.pojo.User;
+import fr.but.infoetu.meetingplannr.repository.MeetingRepository;
+import fr.but.infoetu.meetingplannr.repository.RequestRepository;
+import fr.but.infoetu.meetingplannr.repository.UserRepository;
+import fr.but.infoetu.meetingplannr.service.UserService;
 import jakarta.servlet.http.HttpSession;
 import jakarta.validation.Valid;
 
@@ -27,48 +37,220 @@ public class MeetingController {
     @Autowired
     RequestRepository rr;
 
-    @RequestMapping(value = "login", method = RequestMethod.GET)
-    private String loginForm(){
-        return "login";
+    @Autowired
+    UserService userService;
+
+    @RequestMapping
+    private String redirectHome(HttpSession session) {
+        if (session.getAttribute("currentUser") == null) {
+            return "public/login";
+        }
+        return "user/listeAction";
     }
 
-    @RequestMapping(value = "login", method = RequestMethod.POST)
-    private String loginFormPost(String email, String password, HttpSession session){
-        Optional<User> userOpt = ur.findByEmail(email);
-        if(userOpt.isPresent()){
-            User user = userOpt.get();
-            if(user.getPassword().equals(password)){
-                session.setAttribute("currentUser", user);
-                System.out.println("Bienvenue " + user.getSurname());
-                return "listeAction";
-            }
-        }
-        return "login";
+    @RequestMapping(value = "public/login", method = RequestMethod.GET)
+    private String loginForm(){
+        System.out.println("Is authenticated : " + isAuthenticated());
+        if (isAuthenticated()) {
+            return "redirect:/user/listeAction";
+        }
+        return "public/login";
     }
 
-    @RequestMapping(value = "register", method = RequestMethod.GET)
+    @RequestMapping(value = "public/register", method = RequestMethod.GET)
     private String registerForm(){
-        return "register";
+        if (isAuthenticated()) {
+            return "redirect:/user/listeAction";
+        }
+        return "public/register";
     }
 
-    @RequestMapping(value = "register", method = RequestMethod.POST)
-    private String registerFormPost(@Valid User user, BindingResult res, Model model, HttpSession session){
-        System.out.println(user);
-        if(res.hasErrors()){
-            return "register";
+    @RequestMapping(value = "public/register", method = RequestMethod.POST)
+    private String registerFormPost(@Valid User user, BindingResult res, Model model, HttpSession session) {
+        if (res.hasErrors()) {
+            StringBuilder errorMessage = new StringBuilder("Veuillez corriger les erreurs suivantes :<br>");
+            res.getFieldErrors().forEach(error -> errorMessage.append(error.getField()).append(": ").append(error.getDefaultMessage()).append("<br>"));
+            model.addAttribute("errorMessage", errorMessage.toString());
+            return "public/register";
         }
-        Optional<User> userOpt = ur.findByEmail(user.getEmail());
-        if(userOpt.isPresent()){
-            return "login";
+        Optional<User> userOpt = ur.findByUsername(user.getUsername());
+        if (userOpt.isPresent()) {
+            model.addAttribute("errorMessage", "Cet email est déjà utilisé.");
+            return "public/register";
         }
-        ur.save(user);
+        userService.createUser(user);
         session.setAttribute("currentUser", user);
 
-        return "listeAction";
+        // Automatically log in the user
+        UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword(), user.getAuthorities());
+        SecurityContextHolder.getContext().setAuthentication(authToken);
+
+        return "redirect:/user/listeAction";
+    }
+
+    @RequestMapping(value = "user/listeAction", method = RequestMethod.GET)
+    private String listeAction(@AuthenticationPrincipal UserDetails details, Model model){ 
+        if (details == null) {
+            return "redirect:/public/login";
+        }
+        User user = ur.findByUsername(details.getUsername()).get();
+        model.addAttribute("currentUser", user);
+        return "user/listeAction";
+    }
+
+    @RequestMapping(value = "user/profile", method = RequestMethod.GET)
+    private String profile(@AuthenticationPrincipal UserDetails details, Model model) {
+        if (details == null) {
+            return "redirect:/public/login";
+        }
+        User user = ur.findByUsername(details.getUsername()).get();
+        model.addAttribute("currentUser", user);
+        return "user/profile";
+    }
+
+    @RequestMapping(value = "user/editProfile", method = RequestMethod.GET)
+    private String editProfile(@AuthenticationPrincipal UserDetails details, Model model) {
+        if (details == null) {
+            return "redirect:/public/login";
+        }
+        User user = ur.findByUsername(details.getUsername()).get();
+        model.addAttribute("currentUser", user);
+        return "user/editProfile";
+    }
+
+
+    @RequestMapping(value = "user/updateProfile", method = RequestMethod.POST)
+    private String updateProfile(User user, BindingResult res, Model model, @AuthenticationPrincipal UserDetails details) {
+        System.out.println(user);
+        
+        if (res.hasErrors()) {
+            StringBuilder errorMessage = new StringBuilder("Veuillez corriger les erreurs suivantes :<br>");
+            res.getFieldErrors().forEach(error -> errorMessage.append(error.getField()).append(": ").append(error.getDefaultMessage()).append("<br>"));
+            model.addAttribute("errorMessage", errorMessage.toString());
+            return "user/editProfile"; 
+        }
+
+        if (details == null) {
+            model.addAttribute("errorMessage", "Utilisateur non connecté.");
+            return "public/login";
+        }
+
+        User currentUser = ur.findByUsername(details.getUsername()).get();
+        Optional<User> existingUser = ur.findByUsername(user.getUsername());
+        if (existingUser.isPresent() && existingUser.get().getUno() != (currentUser.getUno())) {
+            model.addAttribute("errorMessage", "Cet email est déjà utilisé.");
+            return "user/editProfile";
+        }
+
+        currentUser.setName(user.getName());
+        currentUser.setSurname(user.getSurname());
+
+        ur.save(currentUser);
+
+        return "redirect:/user/profile";
+    }
+
+    @RequestMapping(value = "user/meetings", method = RequestMethod.GET)
+    private String meetings(@AuthenticationPrincipal UserDetails details, Model model) {
+        if (details == null) {
+            return "redirect:/public/login";
+        }
+        User user = ur.findByUsername(details.getUsername()).get();
+        List<Meeting> meetings = mr.findByUserOrderByDateAsc(user);
+        model.addAttribute("meetings", meetings);
+        model.addAttribute("currentUser", user);
+        return "user/rendezVous";
+    }
+
+    @RequestMapping(value = "user/meetings/detail/{mno}", method = RequestMethod.GET)
+    private String appointmentDetail(@PathVariable int mno, @AuthenticationPrincipal UserDetails details, Model model) {
+        if (details == null) {
+            return "redirect:/public/login";
+        }
+        
+        Optional<Meeting> meetingOpt = mr.findById(mno);
+        if (!meetingOpt.isPresent()) {
+            return "redirect:/user/meetings";
+        }
+        
+        Meeting meeting = meetingOpt.get();
+        User currentUser = ur.findByUsername(details.getUsername()).get();
+        
+        model.addAttribute("meeting", meeting);
+        model.addAttribute("isOwner", meeting.getUser().getUno() == currentUser.getUno());
+        
+        return "user/detailRendezVous";
+    }
+
+    @RequestMapping(value = "user/meetings/edit/{mno}", method = RequestMethod.GET)
+    private String editMeeting(@PathVariable int mno, @AuthenticationPrincipal UserDetails details, Model model) {
+        Optional<Meeting> meetingOpt = mr.findById(mno);
+        if (!meetingOpt.isPresent()) {
+            return "redirect:/user/meetings";
+        }
+
+        Meeting meeting = meetingOpt.get();
+        User currentUser = ur.findByUsername(details.getUsername()).get();
+
+        if (meeting.getUser().getUno() != currentUser.getUno()) {
+            return "redirect:/user/meetings";
+        }
+
+        model.addAttribute("meeting", meeting);
+        return "user/editMeeting";
+    }
+
+    @RequestMapping(value = "user/meetings/update/{mno}", method = RequestMethod.POST)
+    private String updateMeeting(@PathVariable int mno, Meeting updatedMeeting, 
+                               BindingResult result, @AuthenticationPrincipal UserDetails details, 
+                               Model model) {
+        if (result.hasErrors()) {
+            model.addAttribute("errorMessage", "Veuillez corriger les erreurs du formulaire.");
+            return "user/editMeeting";
+        }
+
+        Optional<Meeting> meetingOpt = mr.findById(mno);
+        if (!meetingOpt.isPresent()) {
+            return "redirect:/user/meetings";
+        }
+
+        Meeting existingMeeting = meetingOpt.get();
+        User currentUser = ur.findByUsername(details.getUsername()).get();
+
+        if (existingMeeting.getUser().getUno() != currentUser.getUno()) {
+            return "redirect:/user/meetings";
+        }
+
+        existingMeeting.getRequest().setReason(updatedMeeting.getRequest().getReason());
+        existingMeeting.getRequest().setDescription(updatedMeeting.getRequest().getDescription());
+
+        mr.save(existingMeeting);
+        rr.save(existingMeeting.getRequest());
+
+        return "redirect:/user/meetings/detail/" + mno;
+    }
+
+    @RequestMapping(value = "user/meetings/delete/{mno}", method = RequestMethod.GET)
+    private String deleteMeeting(@PathVariable int mno, @AuthenticationPrincipal UserDetails details) {
+        Optional<Meeting> meetingOpt = mr.findById(mno);
+        if (!meetingOpt.isPresent()) {
+            return "redirect:/user/meetings";
+        }
+
+        Meeting meeting = meetingOpt.get();
+        User currentUser = ur.findByUsername(details.getUsername()).get();
+
+        if (meeting.getUser().getUno() == currentUser.getUno()) {
+            mr.delete(meeting);
+        }
+
+        return "redirect:/user/meetings";
     }
 
-    @RequestMapping(value = "listeAction", method = RequestMethod.GET)
-    private String listeAction(){
-        return "listeAction";
+    private boolean isAuthenticated() {
+        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        return authentication != null && 
+               authentication.isAuthenticated() && 
+               !(authentication instanceof AnonymousAuthenticationToken);
     }
 }
diff --git a/src/main/java/fr/but/infoetu/MeetingPlannr/MeetingPlannrApplication.java b/src/main/java/fr/but/infoetu/MeetingPlannr/MeetingPlannrApplication.java
index b9e07c7..502e6a9 100644
--- a/src/main/java/fr/but/infoetu/MeetingPlannr/MeetingPlannrApplication.java
+++ b/src/main/java/fr/but/infoetu/MeetingPlannr/MeetingPlannrApplication.java
@@ -1,4 +1,4 @@
-package fr.but.infoetu.MeetingPlannr;
+package fr.but.infoetu.meetingplannr;
 
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
diff --git a/src/main/java/fr/but/infoetu/MeetingPlannr/pojo/Meeting.java b/src/main/java/fr/but/infoetu/MeetingPlannr/pojo/Meeting.java
index 4c391dd..430fdb2 100644
--- a/src/main/java/fr/but/infoetu/MeetingPlannr/pojo/Meeting.java
+++ b/src/main/java/fr/but/infoetu/MeetingPlannr/pojo/Meeting.java
@@ -1,4 +1,4 @@
-package fr.but.infoetu.MeetingPlannr.pojo;
+package fr.but.infoetu.meetingplannr.pojo;
 
 import java.time.LocalDate;
 
@@ -10,10 +10,12 @@ import jakarta.persistence.JoinColumn;
 import jakarta.persistence.ManyToOne;
 import jakarta.validation.constraints.NotNull;
 import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
 @Entity
+@Builder
 @AllArgsConstructor
 @Data
 @NoArgsConstructor
@@ -25,6 +27,7 @@ public class Meeting {
     private int mno;
 
     @ManyToOne
+    @NotNull
     @JoinColumn(name = "rno")
     private Request request;
 
diff --git a/src/main/java/fr/but/infoetu/MeetingPlannr/pojo/Request.java b/src/main/java/fr/but/infoetu/MeetingPlannr/pojo/Request.java
index 002d7ab..e025d12 100644
--- a/src/main/java/fr/but/infoetu/MeetingPlannr/pojo/Request.java
+++ b/src/main/java/fr/but/infoetu/MeetingPlannr/pojo/Request.java
@@ -1,18 +1,24 @@
-package fr.but.infoetu.MeetingPlannr.pojo;
+package fr.but.infoetu.meetingplannr.pojo;
 
 import jakarta.persistence.Entity;
 import jakarta.persistence.GeneratedValue;
 import jakarta.persistence.GenerationType;
 import jakarta.persistence.Id;
+import jakarta.persistence.Table;
+import jakarta.persistence.ManyToOne;
+import jakarta.persistence.JoinColumn;
 import jakarta.validation.constraints.NotNull;
 import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 
 @Entity
+@Builder
 @AllArgsConstructor
 @Data
 @NoArgsConstructor
+@Table(name = "requests")
 public class Request {
     private static final String REQUIRED = "is required";
 
@@ -25,4 +31,9 @@ public class Request {
 
     @NotNull(message = REQUIRED)
     private String description;
+
+    @ManyToOne
+    @JoinColumn(name = "uno")
+    @NotNull(message = REQUIRED)
+    private User user;
 }
diff --git a/src/main/java/fr/but/infoetu/MeetingPlannr/pojo/User.java b/src/main/java/fr/but/infoetu/MeetingPlannr/pojo/User.java
index 9c7a610..4734efd 100644
--- a/src/main/java/fr/but/infoetu/MeetingPlannr/pojo/User.java
+++ b/src/main/java/fr/but/infoetu/MeetingPlannr/pojo/User.java
@@ -1,63 +1,98 @@
-package fr.but.infoetu.MeetingPlannr.pojo;
+package fr.but.infoetu.meetingplannr.pojo;
 
 import java.time.LocalDate;
 
-import org.springframework.boot.context.properties.bind.DefaultValue;
-
 import jakarta.persistence.Column;
 import jakarta.persistence.Entity;
 import jakarta.persistence.GeneratedValue;
 import jakarta.persistence.GenerationType;
 import jakarta.persistence.Id;
+import jakarta.persistence.SequenceGenerator;
 import jakarta.persistence.Table;
 import jakarta.validation.constraints.Email;
+import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotNull;
 import jakarta.validation.constraints.PastOrPresent;
 import jakarta.validation.constraints.Pattern;
 import jakarta.validation.constraints.Size;
 import lombok.AllArgsConstructor;
+import lombok.Builder;
 import lombok.Data;
 import lombok.NoArgsConstructor;
 import lombok.Builder.Default;
 
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+
+import java.util.Collection;
+import java.util.Collections;
+
 @Entity
+@Builder
 @AllArgsConstructor
 @Data
 @NoArgsConstructor
 @Table(name = "users")
-public class User {
-    private static final String REQUIRED = "is required";
+public class User implements UserDetails {
+    private static final String REQUIRED = "est obligatoire";
 
     @Id
-    @GeneratedValue(strategy = GenerationType.IDENTITY)
+    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "users_uno_seq")
+    @SequenceGenerator(name = "users_uno_seq", sequenceName = "users_uno_seq", allocationSize = 1)
     private int uno;
 
-    @NotNull(message = REQUIRED)
-    @Email(message = "email not valid")
-    private String email;
+    @NotBlank(message = REQUIRED)
+    @Email(message = "L'email n'est pas valide")
+    private String username;
 
-    @NotNull(message = REQUIRED)
+    @NotBlank(message = REQUIRED)
     private String name;
 
-    @NotNull(message = REQUIRED)
+    @NotBlank(message = REQUIRED)
     private String surname;
 
-    @NotNull(message = REQUIRED)
     @Pattern(
         regexp = "^0[1-9]([-. ]?[0-9]{2}){4}$", 
-        message = "invalid phone number"
+        message = "Numéro de téléphone invalide"
     )
     private String phoneNumber;
 
     @NotNull(message = REQUIRED)
-    @PastOrPresent(message = "date must be within the past")
+    @PastOrPresent(message = "La date doit être dans le passé")
     private LocalDate birthdate;
 
-    @NotNull(message = REQUIRED)
-    @Size(min = 8, message = "password too short")
+    @Size(min = 8, message = "Le mot de passe est trop court")
     private String password;
 
-    @Column(columnDefinition = "BOOLEAN DEFAULT FALSE")
-    private boolean isAdmin = false;
-    
+    @Column(name = "authority", columnDefinition = "VARCHAR(50)")
+    private String authority = "ROLE_USER";  
+
+    @Column(columnDefinition = "BOOLEAN DEFAULT TRUE")
+    private boolean enabled = true;
+
+    @Override
+    public Collection<? extends GrantedAuthority> getAuthorities() {
+        return Collections.singletonList(new SimpleGrantedAuthority(authority));
+    }
+
+    @Override
+    public boolean isAccountNonExpired() {
+        return true;
+    }
+
+    @Override
+    public boolean isAccountNonLocked() {
+        return true;
+    }
+
+    @Override
+    public boolean isCredentialsNonExpired() {
+        return true;
+    }
+
+    @Override
+    public boolean isEnabled() {
+        return enabled;
+    }
 }
diff --git a/src/main/java/fr/but/infoetu/MeetingPlannr/repository/MeetingRepository.java b/src/main/java/fr/but/infoetu/MeetingPlannr/repository/MeetingRepository.java
index bc4f7cb..900111b 100644
--- a/src/main/java/fr/but/infoetu/MeetingPlannr/repository/MeetingRepository.java
+++ b/src/main/java/fr/but/infoetu/MeetingPlannr/repository/MeetingRepository.java
@@ -1,10 +1,14 @@
-package fr.but.infoetu.MeetingPlannr.repository;
+package fr.but.infoetu.meetingplannr.repository;
+
+import java.util.List;
 
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.repository.CrudRepository;
 
-import fr.but.infoetu.MeetingPlannr.pojo.Meeting;
+import fr.but.infoetu.meetingplannr.pojo.Meeting;
+import fr.but.infoetu.meetingplannr.pojo.User;
 
 public interface MeetingRepository extends JpaRepository<Meeting, Integer>{
     
+    List<Meeting> findByUserOrderByDateAsc(User user);
 }
diff --git a/src/main/java/fr/but/infoetu/MeetingPlannr/repository/RequestRepository.java b/src/main/java/fr/but/infoetu/MeetingPlannr/repository/RequestRepository.java
index 21e8ca7..bba52ce 100644
--- a/src/main/java/fr/but/infoetu/MeetingPlannr/repository/RequestRepository.java
+++ b/src/main/java/fr/but/infoetu/MeetingPlannr/repository/RequestRepository.java
@@ -1,9 +1,9 @@
-package fr.but.infoetu.MeetingPlannr.repository;
+package fr.but.infoetu.meetingplannr.repository;
 
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.repository.CrudRepository;
 
-import fr.but.infoetu.MeetingPlannr.pojo.Request;
+import fr.but.infoetu.meetingplannr.pojo.Request;
 
 public interface RequestRepository extends JpaRepository<Request, Integer>{
     
diff --git a/src/main/java/fr/but/infoetu/MeetingPlannr/repository/UserRepository.java b/src/main/java/fr/but/infoetu/MeetingPlannr/repository/UserRepository.java
index 32e9bdf..628df46 100644
--- a/src/main/java/fr/but/infoetu/MeetingPlannr/repository/UserRepository.java
+++ b/src/main/java/fr/but/infoetu/MeetingPlannr/repository/UserRepository.java
@@ -1,12 +1,12 @@
-package fr.but.infoetu.MeetingPlannr.repository;
+package fr.but.infoetu.meetingplannr.repository;
 
 import java.util.Optional;
 
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.repository.CrudRepository;
 
-import fr.but.infoetu.MeetingPlannr.pojo.User;
+import fr.but.infoetu.meetingplannr.pojo.User;
 
 public interface UserRepository extends JpaRepository<User, Integer>{
-    Optional<User> findByEmail(String email);
+    Optional<User> findByUsername(String email);
 }
diff --git a/src/main/java/fr/but/infoetu/MeetingPlannr/security/Security.java b/src/main/java/fr/but/infoetu/MeetingPlannr/security/Security.java
new file mode 100644
index 0000000..2b4046b
--- /dev/null
+++ b/src/main/java/fr/but/infoetu/MeetingPlannr/security/Security.java
@@ -0,0 +1,93 @@
+package fr.but.infoetu.meetingplannr.security;
+
+import javax.sql.DataSource;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.security.provisioning.JdbcUserDetailsManager;
+import org.springframework.security.provisioning.UserDetailsManager;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
+import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher;
+import org.springframework.web.servlet.handler.HandlerMappingIntrospector;
+
+import com.zaxxer.hikari.HikariDataSource;
+
+import jakarta.servlet.DispatcherType;
+
+@Configuration
+@EnableWebSecurity
+public class Security {
+
+    @Autowired
+    private DataSource dataSource;
+
+    @Bean
+    public PasswordEncoder passwordEncoder() {
+        return new BCryptPasswordEncoder();
+    }
+
+    @Bean
+    public UserDetailsManager userDetailsManager() {
+        String usersByUsernameQuery = "select username, password, enabled from users where username = ?";
+        String authoritiesByUsernameQuery = "select username, authority from users where username = ?";
+
+        JdbcUserDetailsManager users = new JdbcUserDetailsManager(dataSource);
+
+        users.setUsersByUsernameQuery(usersByUsernameQuery);
+        users.setAuthoritiesByUsernameQuery(authoritiesByUsernameQuery);
+
+        return users;
+    }
+
+    @Bean
+    public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception {
+        return config.getAuthenticationManager();
+    }
+
+    @Bean
+    public AuthenticationSuccessHandler authenticationSuccessHandler() {
+        return (request, response, authentication) -> {
+            System.out.println("User authenticated: " + authentication.getName());
+            response.sendRedirect("/user/listeAction");
+        };
+    }
+
+    @Bean
+    public SecurityFilterChain authorization(HttpSecurity http, HandlerMappingIntrospector intro) throws Exception {
+        MvcRequestMatcher.Builder mvc = new MvcRequestMatcher.Builder(intro);
+        return http
+            .csrf().disable()
+            .authorizeHttpRequests((authorize) -> authorize
+                .dispatcherTypeMatchers(DispatcherType.FORWARD).permitAll()
+                .requestMatchers(mvc.pattern("/public/**"),mvc.pattern("styles/**")).permitAll()
+                .requestMatchers(mvc.pattern("/perform_login")).permitAll()
+                .requestMatchers(mvc.pattern("/user/**")).authenticated()
+                .requestMatchers(mvc.pattern("/admin/**")).hasRole("ADMIN")
+                .anyRequest().authenticated()
+            )
+            .formLogin(configurer ->
+                configurer.loginPage("/public/login")
+                .loginProcessingUrl("/public/perform_login")
+                .defaultSuccessUrl("/user/listeAction", true)
+                .failureUrl("/public/login?error")
+                .permitAll()
+            )
+            .logout(configurer -> 
+                configurer.logoutUrl("/perform_logout")
+                .deleteCookies("JSESSIONID")
+                .logoutSuccessUrl("/public/login?logout")
+            )
+            .userDetailsService(userDetailsManager())
+            .build();
+    }
+}
diff --git a/src/main/java/fr/but/infoetu/MeetingPlannr/service/UserService.java b/src/main/java/fr/but/infoetu/MeetingPlannr/service/UserService.java
new file mode 100644
index 0000000..99d03f6
--- /dev/null
+++ b/src/main/java/fr/but/infoetu/MeetingPlannr/service/UserService.java
@@ -0,0 +1,22 @@
+package fr.but.infoetu.meetingplannr.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+
+import fr.but.infoetu.meetingplannr.pojo.User;
+import fr.but.infoetu.meetingplannr.repository.UserRepository;
+
+@Service
+public class UserService {
+    @Autowired
+    private PasswordEncoder passwordEncoder;
+    @Autowired
+    private UserRepository userRepository;
+    
+    public void createUser(User user) {
+        user.setPassword(passwordEncoder.encode(user.getPassword()));
+        user.setAuthority(user.getAuthority());
+        userRepository.save(user);
+    }
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 553839b..aa87288 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1,15 +1,27 @@
-spring.application.name=MeetingPlannr
+spring.application.name=meetingplannr
 spring.mvc.view.prefix=/WEB-INF/jsp/
 spring.mvc.view.suffix=.jsp
 
 spring.datasource.driverClassName=org.postgresql.Driver
-spring.datasource.url=jdbc:postgresql://psqlserv/but3
-spring.datasource.username=paulcanceletu
-spring.datasource.password=moi
+spring.datasource.url=jdbc:postgresql://localhost:5432/but3
+spring.datasource.username=postgres
+spring.datasource.password=admin
 
 spring.jpa.hibernate.ddl-auto=create-drop
 
 spring.jpa.show-sql=true
 spring.jpa.properties.hibernate.format_sql=true
+spring.jpa.open-in-view=false
 
-server.servlet.contextPath=/meetingplannr
\ No newline at end of file
+server.servlet.contextPath=/meetingplannr
+
+logging.level.org.hibernate.type=TRACE
+logging.level.org.hibernate.SQL=DEBUG
+logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
+logging.level.org.springframework.transaction=TRACE
+
+logging.level.org.springframework.security=DEBUG
+logging.level.org.springframework.jdbc=TRACE
+
+spring.security.filter.order=10
+server.servlet.session.timeout=30m
\ No newline at end of file
diff --git a/src/main/resources/import.sql b/src/main/resources/import.sql
index 7f7073e..d66ef5a 100644
--- a/src/main/resources/import.sql
+++ b/src/main/resources/import.sql
@@ -1,7 +1,37 @@
-INSERT INTO users (email, name, surname, phone_number, birthdate, password) VALUES ('john.doe@example.com', 'John', 'Doe', '0612345678', '1990-05-15', 'password123');
-INSERT INTO users (email, name, surname, phone_number, birthdate, password) VALUES ('jane.smith@example.com', 'Jane', 'Smith', '0698765432', '1985-08-22', 'securepwd');
-INSERT INTO users (email, name, surname, phone_number, birthdate, password) VALUES ('robert.brown@example.com', 'Robert', 'Brown', '0711121314', '1992-03-12', 'robert2024');
-INSERT INTO users (email, name, surname, phone_number, birthdate, password) VALUES ('emily.jones@example.com', 'Emily', 'Jones', '0645678901', '2000-11-09', 'emily!secure');
-INSERT INTO users (email, name, surname, phone_number, birthdate, password) VALUES ('william.davis@example.com', 'William', 'Davis', '0623456789', '1988-07-30', 'password789');
-INSERT INTO users (email, name, surname, phone_number, birthdate, password, is_admin) VALUES ('paul.cancel@net.fr', 'Paul', 'Cancel', '0682015653', '2004-12-26', 'maywennjuliagoat', true);
-INSERT INTO users (email, name, surname, phone_number, birthdate, password, is_admin) VALUES ('theo.vienne@net.fr', 'Theo', 'Vienne', '0619515793', '2000-08-31', 'noemiegoat', true);
+DROP SEQUENCE IF EXISTS users_uno_seq;
+CREATE SEQUENCE users_uno_seq START WITH 1;
+
+-- password: password123
+INSERT INTO users (uno, username, name, surname, phone_number, birthdate, password, authority, enabled) VALUES (nextval('users_uno_seq'), 'john.doe@example.com', 'John', 'Doe', '0612345678', '1990-05-15', '$2a$12$o0C1lgpgzoxPrE64DHda6O0DEDqQznVxqXb5y6gzWne3BP4nZMWrC', 'ROLE_USER', true);
+
+-- password: securepwd
+INSERT INTO users (uno, username, name, surname, phone_number, birthdate, password, authority, enabled) VALUES (nextval('users_uno_seq'), 'jane.smith@example.com', 'Jane', 'Smith', '0698765432', '1985-08-22', '$2a$12$9DmwZZv31epkRx6kUOCeueYRCrlAUyV1J0iB6eienUWRKT3ozpLGu', 'ROLE_USER', true);
+
+-- password: robert2024
+INSERT INTO users (uno, username, name, surname, phone_number, birthdate, password, authority, enabled) VALUES (nextval('users_uno_seq'), 'robert.brown@example.com', 'Robert', 'Brown', '0711121314', '1992-03-12', '$2a$12$bTyqZfn.UGxEXThkvSeU2uKUgO1o6rRadIqg8yYeo9WFLIcnVgGpq', 'ROLE_USER', true);
+
+-- password: emily!secure
+INSERT INTO users (uno, username, name, surname, phone_number, birthdate, password, authority, enabled) VALUES (nextval('users_uno_seq'), 'emily.jones@example.com', 'Emily', 'Jones', '0645678901', '2000-11-09', '$2a$12$MDEm7.8TV90OrE1PhuDfCeJlrLlZAtIj0H5uNEybKVO.cGru3qUD6', 'ROLE_USER', true);
+
+-- password: password789
+INSERT INTO users (uno, username, name, surname, phone_number, birthdate, password, authority, enabled) VALUES (nextval('users_uno_seq'), 'william.davis@example.com', 'William', 'Davis', '0623456789', '1988-07-30', '$2a$12$/T572UEV.ptFg0.KEeSLnev8tj75Ubxm1xAsHZx2/kyneBdDTGbuu', 'ROLE_USER', true);
+
+-- password: testgoat
+INSERT INTO users (uno, username, name, surname, phone_number, birthdate, password, authority, enabled) VALUES (nextval('users_uno_seq'), 'paul.cancel@net.fr', 'Paul', 'Cancel', '0682015653', '2004-12-26', '$2a$12$4agvRLzb.KKGSKLjDi4bZelLWCAQKI15xwFMEI4mpYYgfeo4DyThW', 'ROLE_ADMIN', true);
+
+-- password: noemiegoat
+INSERT INTO users (uno, username, name, surname, phone_number, birthdate, password, authority, enabled) VALUES (nextval('users_uno_seq'), 'theo.vienne@net.fr', 'Theo', 'Vienne', '0619515793', '2000-08-31', '$2a$12$XWqr1MGt9oSxRm2YfEMQle4QWq9r9QcpSXDcOgsEzEQTqtLRdBgcC', 'ROLE_ADMIN', true);
+
+
+INSERT INTO requests (reason, description, uno) VALUES ('Rendez-vous pour discussion projet', 'Discussion des objectifs du projet', 6);
+INSERT INTO requests (reason, description, uno) VALUES ('Point d''avancement mensuel', 'Revue mensuelle des progrès', 6);
+INSERT INTO requests (reason, description, uno) VALUES ('Réunion de planification', 'Planification des prochaines étapes', 6);
+INSERT INTO requests (reason, description, uno) VALUES ('Bilan trimestriel', 'Evaluation des résultats du trimestre', 6);
+INSERT INTO requests (reason, description, uno) VALUES ('Session de développement', 'Session de codage en équipe', 6);
+
+-- Création des meetings liés aux requests
+INSERT INTO meeting (date, uno, rno) VALUES ('2024-03-20', 6, (SELECT rno FROM requests WHERE reason = 'Rendez-vous pour discussion projet'));
+INSERT INTO meeting (date, uno, rno) VALUES ('2024-03-25', 6, (SELECT rno FROM requests WHERE reason = 'Point d''avancement mensuel'));
+INSERT INTO meeting (date, uno, rno) VALUES ('2024-04-01', 6, (SELECT rno FROM requests WHERE reason = 'Réunion de planification'));
+INSERT INTO meeting (date, uno, rno) VALUES ('2024-04-15', 6, (SELECT rno FROM requests WHERE reason = 'Bilan trimestriel'));
+INSERT INTO meeting (date, uno, rno) VALUES ('2024-05-02', 6, (SELECT rno FROM requests WHERE reason = 'Session de développement'));
\ No newline at end of file
diff --git a/src/main/resources/static/styles/main.css b/src/main/resources/static/styles/main.css
new file mode 100644
index 0000000..947458f
--- /dev/null
+++ b/src/main/resources/static/styles/main.css
@@ -0,0 +1,361 @@
+/* Style de base */
+body {
+    font-family: Arial, sans-serif;
+    margin: 0;
+    padding: 0;
+    background-color: #f4f4f9;
+}
+h1, h2 {
+    text-align: center;
+    color: #333;
+}
+.container {
+    max-width: 800px;
+    margin: 90px auto 80px auto; /* Réduit la marge du haut */
+    padding: 0 30px 30px 30px; /* Supprime le padding du haut */
+    background-color: #fff;
+    border-radius: 15px;
+    box-shadow: 0 5px 15px rgba(0,0,0,0.08);
+    min-height: calc(100vh - 140px); /* Ajout d'une hauteur minimale */
+    display: flex;
+    flex-direction: column;
+}
+.error {
+    color: red;
+    font-size: 0.9em;
+}
+
+/* Boutons */
+button {
+    padding: 12px 24px;
+    font-size: 16px;
+    color: white;
+    border: none;
+    border-radius: 8px;
+    cursor: pointer;
+    transition: all 0.3s ease;
+    font-weight: 600;
+    text-transform: uppercase;
+    letter-spacing: 0.5px;
+    box-shadow: 0 2px 4px rgba(0,0,0,0.1);
+}
+button:hover {
+    transform: translateY(-1px);
+    box-shadow: 0 4px 8px rgba(0,0,0,0.2);
+}
+button.logout {
+    background-color: #dc3545;
+}
+button.logout:hover {
+    background-color: #c82333;
+}
+button.submit {
+    background: #28a745;
+}
+button.submit:hover {
+    background-color: #218838;
+}
+button.back {
+    background-color: #007bff;
+}
+button.back:hover {
+    background-color: #0056b3;
+}
+
+
+/* Formulaires */
+.form-container, .container {
+    max-width: 500px;
+    margin: 50px auto;
+    padding: 20px;
+    border: 1px solid #ccc;
+    border-radius: 5px;
+    background-color: #fff;
+}
+.form-group {
+    margin-bottom: 15px;
+}
+.form-group label {
+    display: block;
+    margin-bottom: 5px;
+    font-weight: bold;
+    color: #555;
+}
+.form-group input {
+    width: 100%;
+    padding: 12px;
+    box-sizing: border-box;
+    border: 2px solid #e1e1e1;
+    border-radius: 8px;
+    font-size: 16px;
+    transition: border-color 0.3s ease;
+}
+.form-group input:focus, .form-group textarea:focus {
+    border-color: #007bff;
+    outline: none;
+    box-shadow: 0 0 0 3px rgba(0,123,255,0.1);
+}
+
+/* Style pour le formulaire d'édition */
+.form-group textarea {
+    width: 100%;
+    padding: 12px;
+    box-sizing: border-box;
+    border: 2px solid #e1e1e1;
+    border-radius: 8px;
+    font-size: 16px;
+    resize: vertical;
+    min-height: 100px;
+    transition: border-color 0.3s ease;
+}
+
+.form-group input[type="date"] {
+    width: 100%;
+    padding: 8px;
+    box-sizing: border-box;
+    border: 1px solid #ccc;
+    border-radius: 5px;
+    font-size: 14px;
+}
+
+/* Profil */
+.profile-info {
+    background: #f8f9fa;
+    padding: 25px;
+    border-radius: 10px;
+    margin-top: 30px;
+}
+.profile-info p {
+    margin: 15px 0;
+    padding: 10px;
+    background: white;
+    border-radius: 8px;
+    box-shadow: 0 2px 4px rgba(0,0,0,0.05);
+}
+.actions {
+    margin-top: 30px;
+    text-align: center;
+}
+.actions button {
+    margin: 10px 0;
+}
+
+/* Bannière */
+.banner {
+    background: linear-gradient(135deg, #0056b3, #007bff);
+    color: white;
+    padding: 20px;
+    text-align: center;
+    font-size: 18px;
+    margin: 50px -30px 30px -30px; 
+    border-radius: 15px 15px 15px 15px;
+    box-shadow: 0 4px 6px rgba(0,0,0,0.1);
+    position: relative;
+}
+
+.meeting-detail {
+    padding: 20px;
+    margin-bottom: 30px;
+}
+
+.detail-section {
+    background-color: #f8f9fa;
+    border-radius: 8px;
+    padding: 20px;
+    margin-bottom: 20px;
+}
+
+.detail-section h2 {
+    color: #007bff;
+    font-size: 1.2em;
+    margin-bottom: 15px;
+    text-align: left;
+}
+
+.detail-section p {
+    margin: 10px 0;
+    line-height: 1.5;
+}
+
+.detail-section strong {
+    color: #495057;
+    margin-right: 10px;
+}
+
+.actions {
+    display: flex;
+    gap: 10px;
+    justify-content: center;
+}
+
+/* Nouveau conteneur pour le contenu principal */
+.main-content {
+    flex: 1;
+    display: flex;
+    flex-direction: column;
+    justify-content: center;
+}
+
+.liste-actions {
+    display: flex;
+    flex-direction: column;
+    gap: 15px;
+    justify-content: center;
+    align-items: center;
+    padding: 20px 0;
+}
+
+.liste-actions form {
+    width: 250px; 
+}
+
+.liste-actions button {
+    width: 100%; 
+}
+
+.meeting-item {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding: 20px;
+    background: white;
+    border-radius: 10px;
+    margin-bottom: 20px;
+    box-shadow: 0 4px 6px rgba(0,0,0,0.1);
+    transition: transform 0.2s, box-shadow 0.2s;
+}
+
+.meeting-item:hover {
+    transform: translateY(-2px);
+    box-shadow: 0 6px 12px rgba(0,0,0,0.15);
+}
+
+.meeting-item button {
+    margin-left: 10px;
+}
+
+.meeting-content {
+    display: flex;
+    flex-direction: column;
+    gap: 10px;
+}
+
+.meeting-info {
+    flex-grow: 1;
+}
+
+.meeting-info p {
+    margin: 5px 0;
+    color: #333;
+}
+
+.meeting-actions {
+    display: flex;
+    justify-content: flex-end;
+}
+
+.meeting-actions button {
+    width: 100%;
+}
+
+.meeting-info {
+    flex-grow: 1;
+}
+
+.meeting-info p {
+    margin: 5px 0;
+}
+
+.meeting-actions {
+    margin-left: 20px;
+    flex-shrink: 0;
+}
+
+/* Header Styles - Updated */
+.app-header {
+    background: linear-gradient(135deg, #0056b3, #007bff);
+    color: white;
+    padding: 1rem; /* Réduit légèrement le padding */
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    z-index: 1000;
+    box-shadow: 0 2px 10px rgba(0,0,0,0.1);
+}
+
+.header-content {
+    max-width: 1200px;
+    margin: 0 auto;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+}
+
+.logo {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+}
+
+.logo a {
+    text-decoration: none;
+    color: white;
+    display: flex;
+    align-items: center;
+    gap: 15px;
+}
+
+.logo-icon {
+    font-size: 2rem;
+}
+
+.logo h1 {
+    margin: 0;
+    font-size: 2.2rem;
+    font-weight: 700;
+    letter-spacing: 1px;
+}
+
+.header-subtitle {
+    font-size: 1.1rem;
+    margin-top: 0.5rem;
+    opacity: 0.9;
+}
+
+/* Footer - Updated */
+.app-footer {
+    background: linear-gradient(135deg, #333, #222);
+    color: white;
+    padding: 1.5rem;
+    position: fixed;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    text-align: center;
+    box-shadow: 0 -2px 10px rgba(0,0,0,0.1);
+}
+
+.footer-content {
+    max-width: 1200px;
+    margin: 0 auto;
+    font-size: 0.9rem;
+    opacity: 0.9;
+}
+
+/* Cards Style */
+.meeting-item {
+    background: white;
+    border-radius: 10px;
+    padding: 20px;
+    margin-bottom: 20px;
+    box-shadow: 0 4px 6px rgba(0,0,0,0.1);
+    transition: transform 0.2s, box-shadow 0.2s;
+}
+
+.meeting-item:hover {
+    transform: translateY(-2px);
+    box-shadow: 0 6px 12px rgba(0,0,0,0.15);
+}
+
+/* ...existing code... */
diff --git a/src/main/webapp/WEB-INF/jsp/common/footer.jsp b/src/main/webapp/WEB-INF/jsp/common/footer.jsp
new file mode 100644
index 0000000..9642d63
--- /dev/null
+++ b/src/main/webapp/WEB-INF/jsp/common/footer.jsp
@@ -0,0 +1,6 @@
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<footer class="app-footer">
+    <div class="footer-content">
+        <p>&copy; 2024 MeetingPlannr - Tous droits réservés</p>
+    </div>
+</footer>
diff --git a/src/main/webapp/WEB-INF/jsp/common/header.jsp b/src/main/webapp/WEB-INF/jsp/common/header.jsp
new file mode 100644
index 0000000..246a409
--- /dev/null
+++ b/src/main/webapp/WEB-INF/jsp/common/header.jsp
@@ -0,0 +1,13 @@
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<header class="app-header">
+    <div class="header-content">
+        <div class="logo">
+            <a href="${pageContext.request.contextPath}/user/listeAction">
+                <h1>MeetingPlannr</h1>
+            </a>
+        </div>
+        <div class="header-subtitle">
+            Gestionnaire de rendez-vous
+        </div>
+    </div>
+</header>
diff --git a/src/main/webapp/WEB-INF/jsp/listeAction.jsp b/src/main/webapp/WEB-INF/jsp/listeAction.jsp
deleted file mode 100644
index 325f434..0000000
--- a/src/main/webapp/WEB-INF/jsp/listeAction.jsp
+++ /dev/null
@@ -1,81 +0,0 @@
-<%@ page contentType="text/html;charset=UTF-8" language="java" %>
-<%@ page import="fr.but.infoetu.MeetingPlannr.pojo.User" %>
-<!DOCTYPE html>
-<html>
-<head>
-    <title>Liste des Actions</title>
-    <style>
-        body {
-            font-family: Arial, sans-serif;
-            margin: 0;
-            padding: 0;
-            background-color: #f4f4f9;
-        }
-        .container {
-            max-width: 800px;
-            margin: 50px auto;
-            padding: 20px;
-            background-color: #fff;
-            border-radius: 8px;
-            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
-        }
-        h1 {
-            text-align: center;
-            color: #333;
-        }
-        .actions {
-            display: flex;
-            flex-direction: column;
-            gap: 15px;
-        }
-        .actions button {
-            padding: 10px 20px;
-            font-size: 16px;
-            color: #fff;
-            background-color: #007bff;
-            border: none;
-            border-radius: 4px;
-            cursor: pointer;
-            transition: background-color 0.3s;
-        }
-        .actions button:hover {
-            background-color: #0056b3;
-        }
-        .actions button.logout {
-            background-color: #dc3545;
-        }
-        .actions button.logout:hover {
-            background-color: #c82333;
-        }
-    </style>
-</head>
-<body>
-    <% 
-        User currentUser = (User) request.getSession().getAttribute("currentUser")
-    %>
-    <div class="container">
-        <h1>Actions Disponibles</h1>
-        <div class="actions">
-            <!-- Bouton pour voir le calendrier et poser des requêtes -->
-            <form action="/calendar" method="get">
-                <button type="submit">Voir le Calendrier</button>
-            </form>
-
-            <!-- Bouton pour accéder à ses rendez-vous -->
-            <form action="/appointments" method="get">
-                <button type="submit">Mes Rendez-Vous</button>
-            </form>
-
-            <!-- Bouton pour voir les détails de son profil -->
-            <form action="/profile" method="get">
-                <button type="submit">Mon Profil</button>
-            </form>
-
-            <!-- Bouton pour se déconnecter -->
-            <form action="/logout" method="post">
-                <button type="submit" class="logout">Se Déconnecter</button>
-            </form>
-        </div>
-    </div>
-</body>
-</html>
diff --git a/src/main/webapp/WEB-INF/jsp/login.jsp b/src/main/webapp/WEB-INF/jsp/login.jsp
deleted file mode 100644
index bf259c3..0000000
--- a/src/main/webapp/WEB-INF/jsp/login.jsp
+++ /dev/null
@@ -1,88 +0,0 @@
-<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
-<!DOCTYPE html>
-<html>
-<head>
-    <title>Login</title>
-    <style>
-        body {
-            font-family: Arial, sans-serif;
-            margin: 0;
-            padding: 0;
-            background-color: #f4f4f9;
-        }
-        .container {
-            max-width: 400px;
-            margin: 100px auto;
-            padding: 20px;
-            background: #ffffff;
-            border: 1px solid #ddd;
-            box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
-        }
-        h2 {
-            text-align: center;
-            color: #333;
-        }
-        .form-group {
-            margin-bottom: 15px;
-        }
-        label {
-            display: block;
-            margin-bottom: 5px;
-            color: #555;
-        }
-        input[type="email"],
-        input[type="password"] {
-            width: 100%;
-            padding: 10px;
-            border: 1px solid #ccc;
-            border-radius: 5px;
-            font-size: 14px;
-        }
-        button {
-            width: 100%;
-            padding: 10px;
-            background: #007bff;
-            border: none;
-            color: white;
-            font-size: 16px;
-            border-radius: 5px;
-            cursor: pointer;
-            margin: 10px;
-        }
-        button:hover {
-            background: #0056b3;
-        }
-        .error {
-            color: red;
-            font-size: 14px;
-        }
-    </style>
-</head>
-<body>
-    <div class="container">
-        <h2>Login</h2>
-        <form action="login" method="POST">
-            <div class="form-group">
-                <label for="email">Email :</label>
-                <input type="email" id="email" name="email" placeholder="Entrez votre email">
-            </div>
-            <div class="form-group">
-                <label for="password">Mot de passe :</label>
-                <input type="password" id="password" name="password" placeholder="Entrez votre mot de passe">
-            </div>
-            <button type="submit">Se connecter</button>
-            <a href="/register">
-                Créer un nouveau compte
-            </a>
-        </form>
-        <%
-            String errorMessage = (String) request.getAttribute("errorMessage");
-            if (errorMessage != null) {
-        %>
-            <div class="error"><%= errorMessage %></div>
-        <%
-            }
-        %>
-    </div>
-</body>
-</html>
diff --git a/src/main/webapp/WEB-INF/jsp/public/login.jsp b/src/main/webapp/WEB-INF/jsp/public/login.jsp
new file mode 100644
index 0000000..0b5499d
--- /dev/null
+++ b/src/main/webapp/WEB-INF/jsp/public/login.jsp
@@ -0,0 +1,45 @@
+<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Login</title>
+    <link rel="stylesheet" href="${pageContext.request.contextPath}/styles/main.css">
+</head>
+<body>
+    <div class="container">
+        <h2>Login</h2>
+        <form action="${pageContext.request.contextPath}/public/perform_login" method="POST">
+            <div class="form-group">
+                <label for="username">Email :</label>
+                <input type="email" id="username" name="username" placeholder="Entrez votre email">
+            </div>
+            <div class="form-group">
+                <label for="password">Mot de passe :</label>
+                <input type="password" id="password" name="password" placeholder="Entrez votre mot de passe">
+            </div>
+            <button type="submit">Se connecter</button>
+            <a href="register">
+                Créer un nouveau compte
+            </a>
+        </form>
+        <%
+            String errorMessage = (String) request.getAttribute("errorMessage");
+            if (errorMessage != null) {
+        %>
+            <div class="error"><%= errorMessage %></div>
+        <%
+            }
+        %>
+        <br>
+        <%
+            String error = request.getParameter("error");
+            if (error != null) {
+        %>
+            <div class="error">Email ou mot de passe incorrect</div>
+        <%
+            }
+        %>
+    </div>
+    
+</body>
+</html>
diff --git a/src/main/webapp/WEB-INF/jsp/register.jsp b/src/main/webapp/WEB-INF/jsp/public/register.jsp
similarity index 54%
rename from src/main/webapp/WEB-INF/jsp/register.jsp
rename to src/main/webapp/WEB-INF/jsp/public/register.jsp
index 9c697cc..33d5488 100644
--- a/src/main/webapp/WEB-INF/jsp/register.jsp
+++ b/src/main/webapp/WEB-INF/jsp/public/register.jsp
@@ -3,57 +3,15 @@
 <html>
 <head>
     <title>Register</title>
-    <style>
-        body {
-            font-family: Arial, sans-serif;
-        }
-        .form-container {
-            max-width: 500px;
-            margin: 50px auto;
-            padding: 20px;
-            border: 1px solid #ccc;
-            border-radius: 5px;
-        }
-        .form-container h1 {
-            text-align: center;
-        }
-        .form-group {
-            margin-bottom: 15px;
-        }
-        .form-group label {
-            display: block;
-            font-weight: bold;
-        }
-        .form-group input {
-            width: 100%;
-            padding: 8px;
-            box-sizing: border-box;
-        }
-        .error {
-            color: red;
-            font-size: 0.9em;
-        }
-        .form-group button {
-            width: 100%;
-            padding: 10px;
-            background-color: #28a745;
-            color: white;
-            border: none;
-            border-radius: 5px;
-            font-size: 1em;
-        }
-        .form-group button:hover {
-            background-color: #218838;
-        }
-    </style>
+    <link rel="stylesheet" href="${pageContext.request.contextPath}/styles/main.css">
 </head>
 <body>
     <div class="form-container">
         <h1>Register</h1>
         <form action="register" method="post">
             <div class="form-group">
-                <label for="email">Email:</label>
-                <input type="email" id="email" name="email">
+                <label for="username">Email:</label>
+                <input type="email" id="username" name="username">
             </div>
             <div class="form-group">
                 <label for="name">Name:</label>
@@ -77,8 +35,19 @@
             </div>
             <div class="form-group">
                 <button type="submit">Register</button>
+                <a href="login">
+                    Se connecter
+                </a>
             </div>
         </form>
+        <% 
+            String errorMessage = (String) request.getAttribute("errorMessage");
+            if (errorMessage != null) {
+        %>
+            <div class="error"><%= errorMessage %></div>
+        <% 
+            }
+        %>
     </div>
 </body>
 </html>
diff --git a/src/main/webapp/WEB-INF/jsp/user/detailRendezVous.jsp b/src/main/webapp/WEB-INF/jsp/user/detailRendezVous.jsp
new file mode 100644
index 0000000..b8c9e1a
--- /dev/null
+++ b/src/main/webapp/WEB-INF/jsp/user/detailRendezVous.jsp
@@ -0,0 +1,31 @@
+<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <title>Détail du rendez-vous</title>
+    <link rel="stylesheet" href="${pageContext.request.contextPath}/styles/main.css">
+</head>
+<body>
+    <div class="container">
+        <div class="banner">
+            <h1>Détail du rendez-vous</h1>
+        </div>
+        
+        <div class="meeting-detail">
+            <div class="detail-section">
+                <h2>Informations générales</h2>
+                <p><strong>Motif:</strong> ${meeting.getRequest().getReason()}</p>
+                <p><strong>Description:</strong> ${meeting.getRequest().getDescription()}</p>
+                <p><strong>Date:</strong> ${meeting.date}</p>
+            </div>
+        </div>
+
+        <div class="actions">
+            <button onclick="window.location.href='${pageContext.request.contextPath}/user/meetings'" class="back">Retour à la liste</button>
+                <button class="submit" onclick="window.location.href='${pageContext.request.contextPath}/user/meetings/edit/${meeting.mno}'">Modifier</button>
+                <button class="logout" onclick="if(confirm('Êtes-vous sûr de vouloir supprimer ce rendez-vous?')) window.location.href='${pageContext.request.contextPath}/user/meetings/delete/${meeting.mno}'">Supprimer</button>
+        </div>
+    </div>
+</body>
+</html>
diff --git a/src/main/webapp/WEB-INF/jsp/user/editMeeting.jsp b/src/main/webapp/WEB-INF/jsp/user/editMeeting.jsp
new file mode 100644
index 0000000..7e2c819
--- /dev/null
+++ b/src/main/webapp/WEB-INF/jsp/user/editMeeting.jsp
@@ -0,0 +1,45 @@
+<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
+<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
+<!DOCTYPE html>
+<html>
+<head>
+    <meta charset="UTF-8">
+    <title>Modifier le rendez-vous</title>
+    <link rel="stylesheet" href="${pageContext.request.contextPath}/styles/main.css">
+</head>
+<body>
+    <div class="container">
+        <div class="banner">
+            <h1>Modifier le rendez-vous</h1>
+        </div>
+
+        <form:form action="${pageContext.request.contextPath}/user/meetings/update/${meeting.mno}" 
+                   method="POST" 
+                   modelAttribute="meeting" 
+                   class="form-container">
+            
+            <div class="form-group">
+                <label for="request.reason">Motif :</label>
+                <form:input path="request.reason" required="true" />
+                <form:errors path="request.reason" cssClass="error" />
+            </div>
+
+            <div class="form-group">
+                <label for="request.description">Description :</label>
+                <form:textarea path="request.description" required="true" rows="4" />
+                <form:errors path="request.description" cssClass="error" />
+            </div>
+
+
+            <div class="actions">
+                <button type="submit" class="submit">Enregistrer</button>
+                <button type="button" onclick="window.location.href='${pageContext.request.contextPath}/user/meetings/detail/${meeting.mno}'" class="logout">Annuler</button>
+            </div>
+
+                <div class="error">
+                    ${errorMessage}
+                </div>
+        </form:form>
+    </div>
+</body>
+</html>
diff --git a/src/main/webapp/WEB-INF/jsp/user/editProfile.jsp b/src/main/webapp/WEB-INF/jsp/user/editProfile.jsp
new file mode 100644
index 0000000..353581a
--- /dev/null
+++ b/src/main/webapp/WEB-INF/jsp/user/editProfile.jsp
@@ -0,0 +1,40 @@
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ page import="fr.but.infoetu.meetingplannr.pojo.User" %>
+<!DOCTYPE html>
+<html lang="fr">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>Modifier le Profil</title>
+    <link rel="stylesheet" href="${pageContext.request.contextPath}/styles/main.css">
+</head>
+<body>
+    <div class="container">
+        <h1>Modifier le Profil</h1>
+        <div class="form-container">
+            <form action="${pageContext.request.contextPath}/user/updateProfile" method="post">
+                <div class="form-group">
+                    <label for="name">Prénom :</label>
+                    <input type="text" id="name" name="name" value="${currentUser.getName()}" required>
+                </div>
+                <div class="form-group">
+                    <label for="surname">Nom :</label>
+                    <input type="text" id="surname" name="surname" value="${currentUser.getSurname()}" required>
+                </div>
+                <div class="actions">
+                    <button type="submit" class="submit">Enregistrer les modifications</button>
+                    <button type="button" class="logout" onclick="window.location.href='${pageContext.request.contextPath}/user/profile'">Annuler</button>
+                </div>
+            </form>
+            <% 
+                String errorMessage = (String) request.getAttribute("errorMessage");
+                if (errorMessage != null) {
+            %>
+                <div class="error"><%= errorMessage %></div>
+            <% 
+                }
+            %>
+        </div>
+    </div>
+</body>
+</html>
diff --git a/src/main/webapp/WEB-INF/jsp/user/listeAction.jsp b/src/main/webapp/WEB-INF/jsp/user/listeAction.jsp
new file mode 100644
index 0000000..5c5aba4
--- /dev/null
+++ b/src/main/webapp/WEB-INF/jsp/user/listeAction.jsp
@@ -0,0 +1,38 @@
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ page import="fr.but.infoetu.meetingplannr.pojo.User" %>
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Liste des Actions - MeetingPlannr</title>
+    <link rel="stylesheet" href="${pageContext.request.contextPath}/styles/main.css">
+</head>
+<body>
+    <%@ include file="../common/header.jsp" %>
+    <div class="container">
+        <div class="banner">
+            Bonjour, ${currentUser.name} ${currentUser.surname} (${currentUser.username})
+        </div>
+        <div class="main-content">
+            <h1>Actions Disponibles</h1>
+            <div class="liste-actions">
+                <form action="${pageContext.request.contextPath}/user/calendar" method="get">
+                    <button type="submit" class="submit">Voir le Calendrier</button>
+                </form>
+
+                <form action="${pageContext.request.contextPath}/user/meetings" method="get">
+                    <button type="submit" class="submit">Mes Rendez-Vous</button>
+                </form>
+
+                <form action="${pageContext.request.contextPath}/user/profile" method="get">
+                    <button type="submit" class="submit">Mon Profil</button>
+                </form>
+
+                <form action="${pageContext.request.contextPath}/perform_logout" method="post">
+                    <button type="submit" class="logout">Se Déconnecter</button>
+                </form>
+            </div>
+        </div>
+    </div>
+    <%@ include file="../common/footer.jsp" %>
+</body>
+</html>
diff --git a/src/main/webapp/WEB-INF/jsp/user/profile.jsp b/src/main/webapp/WEB-INF/jsp/user/profile.jsp
new file mode 100644
index 0000000..8b7dd22
--- /dev/null
+++ b/src/main/webapp/WEB-INF/jsp/user/profile.jsp
@@ -0,0 +1,29 @@
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ page import="fr.but.infoetu.meetingplannr.pojo.User" %>
+<%@ page import="org.springframework.security.core.context.SecurityContextHolder" %>
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Mon Profil</title>
+    <link rel="stylesheet" href="${pageContext.request.contextPath}/styles/main.css">
+</head>
+<body>
+    <%@ include file="../common/header.jsp" %>
+    <div class="container">
+        <h1>Mon Profil</h1>
+        <div class="profile-info">
+            <p><strong>Nom :</strong> ${currentUser.surname}</p>
+            <p><strong>Prénom :</strong> ${currentUser.name}</p>
+            <p><strong>Email :</strong> ${currentUser.username}</p>
+        </div>
+        <div class="actions">
+            <form action="${pageContext.request.contextPath}/user/editProfile" method="get">
+                <button type="submit"  class="submit">Modifier mon Profil</button>
+            </form>
+            <form action="${pageContext.request.contextPath}/user/listeAction" method="get">
+                <button type="submit" class="back">Retour aux Actions</button>
+            </form>
+        </div>
+    </div>
+</body>
+</html>
\ No newline at end of file
diff --git a/src/main/webapp/WEB-INF/jsp/user/rendezVous.jsp b/src/main/webapp/WEB-INF/jsp/user/rendezVous.jsp
new file mode 100644
index 0000000..e43f5f5
--- /dev/null
+++ b/src/main/webapp/WEB-INF/jsp/user/rendezVous.jsp
@@ -0,0 +1,46 @@
+<%@ page contentType="text/html;charset=UTF-8" language="java" %>
+<%@ page import="fr.but.infoetu.meetingplannr.pojo.User" %>
+<%@ page import="fr.but.infoetu.meetingplannr.pojo.Meeting" %>
+<%@ page import="java.util.List" %>
+<%@ page import="java.time.format.DateTimeFormatter" %>
+<!DOCTYPE html>
+<html>
+<head>
+    <title>Mes Rendez-vous</title>
+    <link rel="stylesheet" href="${pageContext.request.contextPath}/styles/main.css">
+</head>
+<body>
+    <div class="container">
+        <h1>Mes Rendez-vous</h1>
+        <div class="meetings-list">
+            <% 
+            List<Meeting> meetings = (List<Meeting>) request.getAttribute("meetings");
+            if (meetings != null && !meetings.isEmpty()) {
+                for (Meeting meeting : meetings) {
+            %>
+                <div class="meeting-item">
+                    <div class="meeting-content">
+                        <div class="meeting-info">
+                            <p>Date: <%= meeting.getDate().format(DateTimeFormatter.ofPattern("dd/MM/yyyy")) %></p>
+                            <p>Motif: <%= meeting.getRequest().getReason() %></p>
+                        </div>
+                        <div class="meeting-actions">
+                            <button onclick="window.location.href='${pageContext.request.contextPath}/user/meetings/detail/<%= meeting.getMno() %>'" class="submit">Voir détails</button>
+                        </div>
+                    </div>
+                </div>
+            <% 
+                }
+            } else {
+            %>
+                <p>Aucun rendez-vous programmé.</p>
+            <% 
+            }
+            %>
+        </div>
+        <div class="actions">
+            <button onclick="window.location.href='${pageContext.request.contextPath}/user/listeAction'" class="back">Retour</button>
+        </div>
+    </div>
+</body>
+</html>
diff --git a/src/test/java/fr/but/infoetu/MeetingPlannr/MeetingPlannrApplicationTests.java b/src/test/java/fr/but/infoetu/MeetingPlannr/MeetingPlannrApplicationTests.java
index 37ced39..ee1f890 100644
--- a/src/test/java/fr/but/infoetu/MeetingPlannr/MeetingPlannrApplicationTests.java
+++ b/src/test/java/fr/but/infoetu/MeetingPlannr/MeetingPlannrApplicationTests.java
@@ -1,4 +1,4 @@
-package fr.but.infoetu.MeetingPlannr;
+package fr.but.infoetu.meetingplannr;
 
 import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.context.SpringBootTest;
-- 
GitLab