diff --git a/sae/WEB-INF/src/controleur/Parametre.java b/sae/WEB-INF/src/controleur/Parametre.java new file mode 100644 index 0000000000000000000000000000000000000000..8da9bb591bb6f598c0e105f23dfc980de33c40d3 --- /dev/null +++ b/sae/WEB-INF/src/controleur/Parametre.java @@ -0,0 +1,58 @@ +package controleur; + +import java.io.IOException; +import jakarta.servlet.ServletException; +import jakarta.servlet.annotation.WebServlet; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import modele.AbonnementDao; +import modele.FilDeDiscussionDAO; +import modele.MessageDao; +import modele.Utilisateur; +import modele.UtilisateurDao; +import org.apache.commons.text.StringEscapeUtils; + +@WebServlet("/parametre") +public class Parametre extends HttpServlet { + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { + if (req.getSession(false) == null || req.getSession().getAttribute("email") == null) { + res.sendRedirect(req.getContextPath() + "/login"); + return; + } + req.getRequestDispatcher("/WEB-INF/vue/parametre.jsp").forward(req, res); + } + + @Override + protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { + if (req.getSession(false) == null || req.getSession().getAttribute("email") == null) { + res.sendRedirect(req.getContextPath() + "/login"); + return; + } + + String email = (String) req.getSession().getAttribute("email"); + String nom = StringEscapeUtils.escapeHtml4(req.getParameter("nom")); + String newEmail = StringEscapeUtils.escapeHtml4(req.getParameter("email")); + String motdepasse = StringEscapeUtils.escapeHtml4(req.getParameter("motdepasse")); + + UtilisateurDao udao = new UtilisateurDao(); + if (!email.equals(newEmail) && udao.emailExists(newEmail)) { + req.setAttribute("error", "Cet email est déjà utilisé."); + req.getRequestDispatcher("/WEB-INF/vue/parametre.jsp").forward(req, res); + return; + } + + Utilisateur utilisateur = udao.findUtilisateur(email); + utilisateur.setNom(nom); + utilisateur.setEmail(newEmail); + if (motdepasse != null && !motdepasse.isEmpty()) { + utilisateur.setMotDePasse(motdepasse); + } + + udao.update(utilisateur, email); + req.getSession().setAttribute("email", newEmail); + res.sendRedirect(req.getContextPath() + "/accueil"); + } +} diff --git a/sae/WEB-INF/src/modele/AbonnementDao.java b/sae/WEB-INF/src/modele/AbonnementDao.java index 151db56f829371b350e8ac9b0be21c0da1e0a84d..51021fb8679bac59f2ae01e9a092a8df659d6df5 100644 --- a/sae/WEB-INF/src/modele/AbonnementDao.java +++ b/sae/WEB-INF/src/modele/AbonnementDao.java @@ -3,6 +3,7 @@ package modele; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.sql.SQLException; import java.util.List; import java.util.ArrayList; diff --git a/sae/WEB-INF/src/modele/FilDeDiscussionDAO.java b/sae/WEB-INF/src/modele/FilDeDiscussionDAO.java index 15ca49d8a1be9c4d4306ad1782cd4d3aaeaf599b..4553a7577dadb8f09857d2528903eefad1aa5352 100644 --- a/sae/WEB-INF/src/modele/FilDeDiscussionDAO.java +++ b/sae/WEB-INF/src/modele/FilDeDiscussionDAO.java @@ -3,6 +3,7 @@ package modele; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.sql.SQLException; import java.util.ArrayList; import java.util.List; @@ -89,5 +90,4 @@ public class FilDeDiscussionDAO { System.err.println(e.getMessage()); } } - } diff --git a/sae/WEB-INF/src/modele/MessageDao.java b/sae/WEB-INF/src/modele/MessageDao.java index b1604a63607d8d720d49820df7ac01739da2681a..b95fbb2f7a7ab2748326be4a7330fd2072f0b15c 100644 --- a/sae/WEB-INF/src/modele/MessageDao.java +++ b/sae/WEB-INF/src/modele/MessageDao.java @@ -3,6 +3,7 @@ package modele; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.ResultSet; +import java.sql.SQLException; import java.util.List; import java.util.ArrayList; @@ -139,7 +140,4 @@ public class MessageDao { return false; } } - - - } diff --git a/sae/WEB-INF/src/modele/UtilisateurDao.java b/sae/WEB-INF/src/modele/UtilisateurDao.java index cb0fce656bb3582a96ad445fcb1cdb15fda75383..a13886737adcaa4cb428bf31775a4045ac1dca20 100644 --- a/sae/WEB-INF/src/modele/UtilisateurDao.java +++ b/sae/WEB-INF/src/modele/UtilisateurDao.java @@ -48,12 +48,13 @@ public class UtilisateurDao { } } - public void update(Utilisateur utilisateur) { + public void update(Utilisateur utilisateur, String oldEmail) { try(Connection con = DS.instance.getConnection()) { PreparedStatement ps = con.prepareStatement("UPDATE Utilisateur SET nom = ?, email = ?, motdepasse = ? WHERE email = ?"); ps.setString(1, utilisateur.getNom()); ps.setString(2, utilisateur.getEmail()); ps.setString(3, utilisateur.getMotDePasse()); + ps.setString(4, oldEmail); ps.executeUpdate(); } catch (Exception e) { System.out.println(e.getMessage()); diff --git a/sae/WEB-INF/vue/accueil.jsp b/sae/WEB-INF/vue/accueil.jsp index fe9569f370e2c2d70b5a722f4603078cad554984..d4a5831960f1295c3e01ec9787c95c1b9dec2385 100644 --- a/sae/WEB-INF/vue/accueil.jsp +++ b/sae/WEB-INF/vue/accueil.jsp @@ -28,6 +28,7 @@ <a href="<%= request.getContextPath() %>/accueil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Accueil</a> <a href="<%= request.getContextPath() %>/listerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Autres Fils de Discussion</a> <a href="<%= request.getContextPath() %>/creerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Créer un Fil</a> + <a href="<%= request.getContextPath() %>/parametre" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Paramètres</a> <a href="<%= request.getContextPath() %>/logout" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-red-700">Se déconnecter</a> </nav> </aside> @@ -63,7 +64,7 @@ for (FilDeDiscussion f : fddao.findAll()) { if (abonnementsIds.contains(f.getId())) { %> - <div class="mb-4 p-4 bg-gray-700 rounded-lg shadow-md"> + <div class="mb-4 p-4 bg-gray-700 rounded-lg shadow-md hover:bg-gray-600"> <a href="<%= request.getContextPath() %>/fil?id=<%= f.getId() %>" class="block"> <img src="<%= request.getContextPath() %>/images/<%= f.getLogo() %>" alt="Logo" class="w-16 h-16 mx-auto"> <h4 class="font-bold text-lg"><%= f.getNom() %></h4> diff --git a/sae/WEB-INF/vue/creerFil.jsp b/sae/WEB-INF/vue/creerFil.jsp index 9ebc55cfe3ac9920b6ebf3d9f0fa1d26667b8ce7..a74d25bbaab7389a51fdc98b25d1589c5c02139d 100644 --- a/sae/WEB-INF/vue/creerFil.jsp +++ b/sae/WEB-INF/vue/creerFil.jsp @@ -19,6 +19,7 @@ <a href="<%= request.getContextPath() %>/accueil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Accueil</a> <a href="<%= request.getContextPath() %>/listerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Autres Fils de Discussion</a> <a href="<%= request.getContextPath() %>/creerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Créer un Fil</a> + <a href="<%= request.getContextPath() %>/parametre" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Paramètres</a> <a href="<%= request.getContextPath() %>/logout" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-red-700">Se déconnecter</a> </nav> </aside> diff --git a/sae/WEB-INF/vue/fil.jsp b/sae/WEB-INF/vue/fil.jsp index 3ef1a0345ab2be035bbd399f46538198307fa27e..ce25440411fc62e2b2a82d97c5c599f3c4147df6 100644 --- a/sae/WEB-INF/vue/fil.jsp +++ b/sae/WEB-INF/vue/fil.jsp @@ -40,6 +40,7 @@ <a href="<%= request.getContextPath() %>/accueil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Accueil</a> <a href="<%= request.getContextPath() %>/listerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Autres Fils de Discussion</a> <a href="<%= request.getContextPath() %>/creerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Créer un Fil</a> + <a href="<%= request.getContextPath() %>/parametre" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Paramètres</a> <a href="<%= request.getContextPath() %>/logout" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-red-700">Se déconnecter</a> </nav> </aside> @@ -97,9 +98,9 @@ </form> </div> <% if (session.getAttribute("email").equals(m.getAuteurEmail())) { %> - <form action="<%= request.getContextPath() %>/deleteMessage" method="post" class="mt-2"> + <form action="<%= request.getContextPath() %>/deleteMessage" method="post" class="mt-2" onsubmit="return confirm('Êtes-vous sûr de vouloir supprimer ce message ?');"> <input type="hidden" name="messageId" value="<%= m.getId() %>"> - <button type="submit" class="text-red-500 hover:text-red-700">delete</button> + <button type="submit" class="text-red-500 hover:text-red-700">Supprimer</button> </form> <% } %> </div> diff --git a/sae/WEB-INF/vue/listerFil.jsp b/sae/WEB-INF/vue/listerFil.jsp index 40ce90496840bb61b6a834bd3ea0615b4c78e6f3..51f0e0629f692d12d2a7d7db7bd77bd096178bcd 100644 --- a/sae/WEB-INF/vue/listerFil.jsp +++ b/sae/WEB-INF/vue/listerFil.jsp @@ -26,6 +26,7 @@ <a href="<%= request.getContextPath() %>/accueil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Accueil</a> <a href="<%= request.getContextPath() %>/listerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Autres Fils de Discussion</a> <a href="<%= request.getContextPath() %>/creerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Créer un Fil</a> + <a href="<%= request.getContextPath() %>/parametre" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Paramètres</a> <a href="<%= request.getContextPath() %>/logout" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-red-700">Se déconnecter</a> </nav> </aside> diff --git a/sae/WEB-INF/vue/login.jsp b/sae/WEB-INF/vue/login.jsp index a81985e08faa36dfc07c239b7425891901184298..160e7b143e8b5e06ee72415f5bc1ca8235d42e2a 100644 --- a/sae/WEB-INF/vue/login.jsp +++ b/sae/WEB-INF/vue/login.jsp @@ -19,6 +19,7 @@ <a href="<%= request.getContextPath() %>/accueil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Accueil</a> <a href="<%= request.getContextPath() %>/listerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Autres Fils de Discussion</a> <a href="<%= request.getContextPath() %>/creerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Créer un Fil</a> + <a href="<%= request.getContextPath() %>/parametre" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Paramètres</a> <a href="<%= request.getContextPath() %>/logout" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-red-700">Se déconnecter</a> </nav> </aside> diff --git a/sae/WEB-INF/vue/menuFil.jsp b/sae/WEB-INF/vue/menuFil.jsp index 4cde7c2d794b0152ad5703267f85f3147f17c0fa..fbb3bffecf5cf1a07133c34e916b0abf86b6abdd 100644 --- a/sae/WEB-INF/vue/menuFil.jsp +++ b/sae/WEB-INF/vue/menuFil.jsp @@ -27,6 +27,7 @@ <a href="<%= request.getContextPath() %>/accueil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Accueil</a> <a href="<%= request.getContextPath() %>/listerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Autres Fils de Discussion</a> <a href="<%= request.getContextPath() %>/creerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Créer un Fil</a> + <a href="<%= request.getContextPath() %>/parametre" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Paramètres</a> <a href="<%= request.getContextPath() %>/logout" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-red-700">Se déconnecter</a> </nav> </aside> diff --git a/sae/WEB-INF/vue/parametre.jsp b/sae/WEB-INF/vue/parametre.jsp new file mode 100644 index 0000000000000000000000000000000000000000..e43432565f58da3adde91c7cea90fcb5af85ab1d --- /dev/null +++ b/sae/WEB-INF/vue/parametre.jsp @@ -0,0 +1,60 @@ +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> +<%@ page import="modele.Utilisateur" %> +<%@ page import="modele.UtilisateurDao" %> + +<% + String email = (String) session.getAttribute("email"); + UtilisateurDao udao = new UtilisateurDao(); + Utilisateur utilisateur = udao.findUtilisateur(email); +%> + +<!DOCTYPE html> +<html lang="fr"> +<head> + <meta charset="UTF-8"> + <meta name="viewport" content="width=device-width, initial-scale=1.0"> + <title>CampusTalk - Paramètres du Compte</title> + <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet"> + <link rel="shortcut icon" href="<%= request.getContextPath() %>/images/logo.png"> +</head> +<body class="bg-gray-900 text-white flex"> + <aside class="w-64 bg-gray-800 text-white h-screen"> + <div class="p-4 text-center"> + <img src="<%= request.getContextPath() %>/images/logo.png" alt="CampusTalk Logo" class="w-16 h-16 mx-auto"> + <h1 class="text-2xl font-bold mt-4">CampusTalk</h1> + </div> + <nav class="mt-4"> + <a href="<%= request.getContextPath() %>/accueil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Accueil</a> + <a href="<%= request.getContextPath() %>/listerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Autres Fils de Discussion</a> + <a href="<%= request.getContextPath() %>/creerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Créer un Fil</a> + <a href="<%= request.getContextPath() %>/parametre" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Paramètres</a> + <a href="<%= request.getContextPath() %>/logout" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-red-700">Se déconnecter</a> + </nav> + </aside> + <div class="flex-1 p-6"> + <div class="max-w-md mx-auto mt-12 p-6 bg-gray-800 rounded-lg shadow-md"> + <h2 class="text-2xl font-bold mb-4 text-center">Paramètres du Compte</h2> + <% if (request.getAttribute("error") != null) { %> + <div class="bg-red-100 text-red-700 p-4 rounded-lg mb-4"> + <%= request.getAttribute("error") %> + </div> + <% request.removeAttribute("error"); } %> + <form action="<%= request.getContextPath() %>/parametre" method="post"> + <div class="mb-4"> + <label for="nom" class="block text-gray-300 font-semibold">Nom</label> + <input type="text" class="w-full p-3 border border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400 bg-gray-700 text-white" name="nom" id="nom" value="<%= utilisateur.getNom() %>" required> + </div> + <div class="mb-4"> + <label for="email" class="block text-gray-300 font-semibold">Adresse e-mail</label> + <input type="email" class="w-full p-3 border border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400 bg-gray-700 text-white" name="email" id="email" value="<%= utilisateur.getEmail() %>" required> + </div> + <div class="mb-4"> + <label for="motdepasse" class="block text-gray-300 font-semibold">Nouveau mot de passe</label> + <input type="password" class="w-full p-3 border border-gray-600 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-400 bg-gray-700 text-white" name="motdepasse" id="motdepasse" placeholder="Laissez vide pour ne pas changer"> + </div> + <button type="submit" class="bg-blue-500 text-white px-4 py-2 rounded-lg shadow-md hover:bg-blue-600 transition-colors w-full">Sauvegarder</button> + </form> + </div> + </div> +</body> +</html> diff --git a/sae/WEB-INF/vue/register.jsp b/sae/WEB-INF/vue/register.jsp index 97b79baa61cec9e5094386e6f98b012cb0563841..5bbda6d4e1cb198a335d4cda22161db76eba0824 100644 --- a/sae/WEB-INF/vue/register.jsp +++ b/sae/WEB-INF/vue/register.jsp @@ -19,6 +19,7 @@ <a href="<%= request.getContextPath() %>/accueil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Accueil</a> <a href="<%= request.getContextPath() %>/listerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Autres Fils de Discussion</a> <a href="<%= request.getContextPath() %>/creerFil" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Créer un Fil</a> + <a href="<%= request.getContextPath() %>/parametre" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-gray-700">Paramètres</a> <a href="<%= request.getContextPath() %>/logout" class="block py-2.5 px-4 rounded transition duration-200 hover:bg-red-700">Se déconnecter</a> </nav> </aside> diff --git a/script.sql b/script.sql index 5d0f9ac5f4fd1f236eafdbedf5ca11cb39006dae..84686daaef244f62568e16583375f29d2190c064 100644 --- a/script.sql +++ b/script.sql @@ -20,7 +20,7 @@ CREATE TABLE FilDeDiscussion ( logo VARCHAR(255) DEFAULT 'default.png', CONSTRAINT pk_fil PRIMARY KEY (id), CONSTRAINT fk_createur FOREIGN KEY (createurEmail) REFERENCES Utilisateur(email) - ON DELETE SET NULL + ON DELETE SET NULL ON UPDATE CASCADE ); CREATE TABLE Message ( @@ -35,7 +35,7 @@ CREATE TABLE Message ( CONSTRAINT fk_fil FOREIGN KEY (filId) REFERENCES FilDeDiscussion(id) ON DELETE CASCADE, CONSTRAINT fk_auteur FOREIGN KEY (auteurEmail) REFERENCES Utilisateur(email) - ON DELETE SET NULL + ON DELETE SET NULL ON UPDATE CASCADE ); CREATE TABLE Abonnement ( @@ -44,7 +44,7 @@ CREATE TABLE Abonnement ( dateAbonnement TIMESTAMP DEFAULT CURRENT_TIMESTAMP, CONSTRAINT pk_abonnement PRIMARY KEY (utilisateurEmail, filId), CONSTRAINT fk_utilisateur FOREIGN KEY (utilisateurEmail) REFERENCES Utilisateur(email) - ON DELETE CASCADE, + ON DELETE CASCADE ON UPDATE CASCADE, CONSTRAINT fk_fil FOREIGN KEY (filId) REFERENCES FilDeDiscussion(id) ON DELETE CASCADE );