mirror of
https://github.com/kmitresse/Cards-Rush.git
synced 2026-07-09 13:27:45 +00:00
feat: devWeb - update forgotten-password
This commit is contained in:
@@ -0,0 +1,115 @@
|
|||||||
|
package uppa.project.bean;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.UUID;
|
||||||
|
import javax.mail.Authenticator;
|
||||||
|
import javax.mail.Message;
|
||||||
|
import javax.mail.MessagingException;
|
||||||
|
import javax.mail.PasswordAuthentication;
|
||||||
|
import javax.mail.Session;
|
||||||
|
import javax.mail.Transport;
|
||||||
|
import javax.mail.internet.InternetAddress;
|
||||||
|
import javax.mail.internet.MimeMessage;
|
||||||
|
import uppa.project.Global;
|
||||||
|
import uppa.project.database.dao.DAO;
|
||||||
|
import uppa.project.database.dao.DAOException;
|
||||||
|
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
|
||||||
|
import uppa.project.database.pojo.RecoveryPasswordToken;
|
||||||
|
import uppa.project.database.pojo.User;
|
||||||
|
|
||||||
|
import static uppa.project.web.servlet.ForgottenPasswordServlet.CreateToken;
|
||||||
|
|
||||||
|
public class ForgottenPasswordBean implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String email;
|
||||||
|
|
||||||
|
public ForgottenPasswordBean() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public ForgottenPasswordBean(String username, String password) {
|
||||||
|
this.email = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean validate(String requestPath) {
|
||||||
|
Game_JPA_DAO_Factory factory = new Game_JPA_DAO_Factory();
|
||||||
|
|
||||||
|
try {
|
||||||
|
DAO<User> userDao = factory.getDAOUser();
|
||||||
|
User[] user = userDao.findByField("email", email);
|
||||||
|
|
||||||
|
for (User u : user) {
|
||||||
|
if (u.getEmail().equals(email)) {
|
||||||
|
sendTokenEmail(u, requestPath);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (DAOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public ForgottenPasswordBean setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendTokenEmail(User user, String requestPath) {
|
||||||
|
|
||||||
|
String token = UUID.randomUUID().toString();
|
||||||
|
RecoveryPasswordToken recoveryPasswordToken = new RecoveryPasswordToken(token, user);
|
||||||
|
CreateToken(recoveryPasswordToken);
|
||||||
|
sendRecoveryEmail(user.getEmail(), token, requestPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Envoi d'un e-mail de réinitialisation de mot de passe
|
||||||
|
*
|
||||||
|
* @param email
|
||||||
|
* @param token
|
||||||
|
*/
|
||||||
|
public void sendRecoveryEmail(String email, String token, String requestPath){
|
||||||
|
String host = Global.MAIL_HOST;
|
||||||
|
String port = Global.MAIL_PORT;
|
||||||
|
String username = Global.MAIL_USERNAME;
|
||||||
|
String password = Global.MAIL_PASSWORD;
|
||||||
|
|
||||||
|
Properties props = new Properties();
|
||||||
|
props.put("mail.smtp.auth", "true");
|
||||||
|
props.put("mail.smtp.starttls.enable", "true");
|
||||||
|
props.put("mail.smtp.host", host);
|
||||||
|
props.put("mail.smtp.port", port);
|
||||||
|
|
||||||
|
Session session = Session.getInstance(props, new Authenticator() {
|
||||||
|
@Override
|
||||||
|
protected PasswordAuthentication getPasswordAuthentication() {
|
||||||
|
return new PasswordAuthentication(username, password);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Création du message
|
||||||
|
Message message = new MimeMessage(session);
|
||||||
|
message.setFrom(new InternetAddress(username));
|
||||||
|
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(email));
|
||||||
|
message.setSubject("Réinitialisation de votre mot de passe");
|
||||||
|
message.setText("Bonjour,\n\n" +
|
||||||
|
"Vous avez demandé la réinitialisation de votre mot de passe.\n" +
|
||||||
|
"Pour cela, veuillez cliquer sur le lien suivant :"+ requestPath +"/reset-password?token=" + token + "\n\n" +
|
||||||
|
"Cordialement,\n" +
|
||||||
|
"L'équipe CardRush");
|
||||||
|
// Envoi du message
|
||||||
|
Transport.send(message);
|
||||||
|
|
||||||
|
System.out.println("E-mail envoyé avec succès à : " + email);
|
||||||
|
} catch (MessagingException e) {
|
||||||
|
throw new RuntimeException("Erreur lors de l'envoi de l'e-mail", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
-61
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
package uppa.project.web.servlet;
|
package uppa.project.web.servlet;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
import jakarta.persistence.EntityManager;
|
import jakarta.persistence.EntityManager;
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
import jakarta.servlet.annotation.WebServlet;
|
import jakarta.servlet.annotation.WebServlet;
|
||||||
@@ -13,20 +14,17 @@ import jakarta.servlet.http.HttpServlet;
|
|||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.UUID;
|
import java.io.PrintWriter;
|
||||||
import javax.mail.Message;
|
import uppa.project.bean.ForgottenPasswordBean;
|
||||||
import uppa.project.Global;
|
|
||||||
import uppa.project.database.dao.DAO;
|
import uppa.project.database.dao.DAO;
|
||||||
import uppa.project.database.dao.DAOException;
|
import uppa.project.database.dao.DAOException;
|
||||||
import uppa.project.database.dao.jpa.DAO_JPA_User;
|
import uppa.project.database.dao.jpa.DAO_JPA_User;
|
||||||
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
|
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
|
||||||
import uppa.project.database.pojo.RecoveryPasswordToken;
|
import uppa.project.database.pojo.RecoveryPasswordToken;
|
||||||
import uppa.project.database.pojo.User;
|
import uppa.project.database.pojo.User;
|
||||||
import java.util.Properties;
|
|
||||||
import javax.mail.*;
|
|
||||||
import javax.mail.internet.*;
|
|
||||||
import uppa.project.database.dao.EntityManagerProvider;
|
import uppa.project.database.dao.EntityManagerProvider;
|
||||||
|
import uppa.project.json.HttpResponse;
|
||||||
|
import uppa.project.json.HttpResponseCode;
|
||||||
|
|
||||||
@WebServlet(name = "forgottenPasswordServlet", value = "/forgotten-password")
|
@WebServlet(name = "forgottenPasswordServlet", value = "/forgotten-password")
|
||||||
public class ForgottenPasswordServlet extends HttpServlet {
|
public class ForgottenPasswordServlet extends HttpServlet {
|
||||||
@@ -36,7 +34,7 @@ public class ForgottenPasswordServlet extends HttpServlet {
|
|||||||
|
|
||||||
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||||
request.setAttribute("current", "forgotten-password");
|
request.setAttribute("current", "forgotten-password");
|
||||||
request.getRequestDispatcher("/WEB-INF/views/forgotten-password.jsp").forward(request, response);
|
request.getRequestDispatcher("/WEB-INF/pages/forgotten-password.jsp").forward(request, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -47,62 +45,27 @@ public class ForgottenPasswordServlet extends HttpServlet {
|
|||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||||
String email = request.getParameter("email");
|
response.setContentType("application/json");
|
||||||
User user = getUserByEmail(email);
|
response.setCharacterEncoding("UTF-8");
|
||||||
if (user == null) {
|
PrintWriter out = response.getWriter();
|
||||||
response.sendRedirect(request.getContextPath() + "/forgotten-password?error=1");
|
|
||||||
|
ForgottenPasswordBean forgottenPasswordBean = new ForgottenPasswordBean()
|
||||||
|
.setEmail(request.getParameter("email"));
|
||||||
|
|
||||||
|
Gson gson = new Gson();
|
||||||
|
HttpResponse httpResponse;
|
||||||
|
String url = request.getRequestURL().toString();
|
||||||
|
//retirer le dernier segment de l'url pour avoir le contextPath
|
||||||
|
String uri = url.substring(0, url.lastIndexOf("/"));
|
||||||
|
System.out.println(uri);
|
||||||
|
if (forgottenPasswordBean.validate(uri)) {
|
||||||
|
httpResponse = new HttpResponse(HttpResponseCode.OK, "Mail sent");
|
||||||
} else {
|
} else {
|
||||||
String token = UUID.randomUUID().toString();
|
httpResponse = new HttpResponse(HttpResponseCode.NOT_FOUND, "<strong>Erreur:</strong> L'email renseigné est inconnu de nos services.");
|
||||||
RecoveryPasswordToken recoveryPasswordToken = new RecoveryPasswordToken(token, user);
|
|
||||||
CreateToken(recoveryPasswordToken);
|
|
||||||
sendRecoveryEmail(email, token, request);
|
|
||||||
response.sendRedirect(request.getContextPath() + "/forgotten-password?success=200");
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
out.println(gson.toJson(httpResponse));
|
||||||
* Envoi d'un e-mail de réinitialisation de mot de passe
|
out.flush();
|
||||||
*
|
|
||||||
* @param email
|
|
||||||
* @param token
|
|
||||||
*/
|
|
||||||
public void sendRecoveryEmail(String email, String token, HttpServletRequest request){
|
|
||||||
String host = Global.MAIL_HOST;
|
|
||||||
String port = Global.MAIL_PORT;
|
|
||||||
String username = Global.MAIL_USERNAME;
|
|
||||||
String password = Global.MAIL_PASSWORD;
|
|
||||||
|
|
||||||
Properties props = new Properties();
|
|
||||||
props.put("mail.smtp.auth", "true");
|
|
||||||
props.put("mail.smtp.starttls.enable", "true");
|
|
||||||
props.put("mail.smtp.host", host);
|
|
||||||
props.put("mail.smtp.port", port);
|
|
||||||
|
|
||||||
Session session = Session.getInstance(props, new Authenticator() {
|
|
||||||
@Override
|
|
||||||
protected PasswordAuthentication getPasswordAuthentication() {
|
|
||||||
return new PasswordAuthentication(username, password);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Création du message
|
|
||||||
Message message = new MimeMessage(session);
|
|
||||||
message.setFrom(new InternetAddress(username));
|
|
||||||
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(email));
|
|
||||||
message.setSubject("Réinitialisation de votre mot de passe");
|
|
||||||
message.setText("Bonjour,\n\n" +
|
|
||||||
"Vous avez demandé la réinitialisation de votre mot de passe.\n" +
|
|
||||||
"Pour cela, veuillez cliquer sur le lien suivant :"+ request.getContextPath() +"/project_war_exploded/reset-password?token=" + token + "\n\n" +
|
|
||||||
"Cordialement,\n" +
|
|
||||||
"L'équipe CardRush");
|
|
||||||
// Envoi du message
|
|
||||||
Transport.send(message);
|
|
||||||
|
|
||||||
System.out.println("E-mail envoyé avec succès à : " + email);
|
|
||||||
} catch (MessagingException e) {
|
|
||||||
throw new RuntimeException("Erreur lors de l'envoi de l'e-mail", e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static User getUserByEmail(String email){
|
public static User getUserByEmail(String email){
|
||||||
|
|||||||
@@ -1,33 +1,52 @@
|
|||||||
<%--
|
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
|
||||||
Created by IntelliJ IDEA.
|
<%@taglib prefix="layout" tagdir="/WEB-INF/tags/layouts" %>
|
||||||
User: lucas
|
<%@taglib prefix="component" tagdir="/WEB-INF/tags/components" %>
|
||||||
Date: 20/03/2024
|
<%@taglib prefix="form" tagdir="/WEB-INF/tags/forms" %>
|
||||||
Time: 16:47
|
|
||||||
To change this template use File | Settings | File Templates.
|
<layout:base>
|
||||||
--%>
|
<jsp:attribute name="title">CardRush - Mot de passe oublié</jsp:attribute>
|
||||||
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
|
<jsp:body>
|
||||||
<html>
|
<div class="hero is-light is-fullheight-with-navbar">
|
||||||
<head>
|
<div class="hero-body">
|
||||||
<title>Forgotten Password</title>
|
<div class="container">
|
||||||
<meta charset="UTF-8">
|
<div class="columns is-centered">
|
||||||
<%-- <link href="${pageContext.request.contextPath}/static/css/forgotten-password.css" rel="stylesheet">--%>
|
<div class="column is-5-tablet is-5-desktop is-5-widescreen">
|
||||||
<script src="${pageContext.request.contextPath}/static/js/forgotten-password.js" defer></script>
|
<div class="box">
|
||||||
</head>
|
<h1 class="title has-text-centered">Mot de passe oublié ?</h1>
|
||||||
<body>
|
<p class="content"> Veuillez entrer votre email pour obtenir un lien de récupération</p>
|
||||||
<%@include file="../components/navbar.jsp"%>
|
<form:forgotten-password/>
|
||||||
<main>
|
</div>
|
||||||
<h1>Mot de passe oublié</h1>
|
</div>
|
||||||
<p>Entrer votre email pour recevoir un lien de récupération</p>
|
</div>
|
||||||
<form id="forgottenPasswordForm" action="forgotten-password" method="post">
|
</div>
|
||||||
<label for="email">Email</label>
|
</div>
|
||||||
<input type="email" id="email" name="email" required>
|
</div>
|
||||||
<button type="submit">Send</button>
|
</jsp:body>
|
||||||
</form>
|
</layout:base>
|
||||||
<%if(request.getParameter("error") != null && request.getParameter("error").equals("1")){%>
|
|
||||||
<p>L'adresse mail insérée est incorrecte</p>
|
<%--<%@ page contentType="text/html;charset=UTF-8" language="java" %>--%>
|
||||||
<%} else if (request.getParameter("success") != null) {%>
|
<%--<html>--%>
|
||||||
<p>Un email vous a été envoyé</p>
|
<%--<head>--%>
|
||||||
<%}%>
|
<%-- <title>Forgotten Password</title>--%>
|
||||||
</main>
|
<%-- <meta charset="UTF-8">--%>
|
||||||
</body>
|
<%--<%– <link href="${pageContext.request.contextPath}/static/css/forgotten-password.css" rel="stylesheet">–%>--%>
|
||||||
</html>
|
<%-- <script src="${pageContext.request.contextPath}/static/js/forgotten-password.js" defer></script>--%>
|
||||||
|
<%--</head>--%>
|
||||||
|
<%--<body>--%>
|
||||||
|
<%-- <%@include file="../components/navbar.jsp"%>--%>
|
||||||
|
<%-- <main>--%>
|
||||||
|
<%-- <h1>Mot de passe oublié</h1>--%>
|
||||||
|
<%-- <p>Entrer votre email pour recevoir un lien de récupération</p>--%>
|
||||||
|
<%-- <form id="forgottenPasswordForm" action="forgotten-password" method="post">--%>
|
||||||
|
<%-- <label for="email">Email</label>--%>
|
||||||
|
<%-- <input type="email" id="email" name="email" required>--%>
|
||||||
|
<%-- <button type="submit">Send</button>--%>
|
||||||
|
<%-- </form>--%>
|
||||||
|
<%-- <%if(request.getParameter("error") != null && request.getParameter("error").equals("1")){%>--%>
|
||||||
|
<%-- <p>L'adresse mail insérée est incorrecte</p>--%>
|
||||||
|
<%-- <%} else if (request.getParameter("success") != null) {%>--%>
|
||||||
|
<%-- <p>Un email vous a été envoyé</p>--%>
|
||||||
|
<%-- <%}%>--%>
|
||||||
|
<%-- </main>--%>
|
||||||
|
<%--</body>--%>
|
||||||
|
<%--</html>--%>
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
<%@tag description="form/forgotten-password" pageEncoding="UTF-8" %>
|
||||||
|
|
||||||
|
<form id="forgotten-password-form" action="${pageContext.request.contextPath}/forgotten-password" method="post">
|
||||||
|
<div class="field"> <!-- Field Username -->
|
||||||
|
<label class="label" for="email">Email</label>
|
||||||
|
<input id="email" placeholder="johndoe@exemple.com" class="input is-fullwidth" required/>
|
||||||
|
</div>
|
||||||
|
<input type="submit" class="button is-primary is-fullwidth" value="Envoyer">
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.notification {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
|
margin: 1em !important;
|
||||||
|
|
||||||
|
transform: translateY(100%);
|
||||||
|
opacity: 0;
|
||||||
|
animation: toast 5s ease forwards;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes toast {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(100%);
|
||||||
|
}
|
||||||
|
5% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
95% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes shake {
|
||||||
|
0%, 100% {
|
||||||
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
10%, 30%, 50%, 70%, 90% {
|
||||||
|
transform: translateX(-5px);
|
||||||
|
}
|
||||||
|
20%, 40%, 60%, 80% {
|
||||||
|
transform: translateX(5px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script defer type="module">
|
||||||
|
const forgottenPasswordForm = document.querySelector("form#forgotten-password-form");
|
||||||
|
|
||||||
|
// Form fields
|
||||||
|
const emailInput = document.querySelector("input#email");
|
||||||
|
|
||||||
|
// Add event listener to the form submission
|
||||||
|
forgottenPasswordForm.addEventListener("submit", onSubmit)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the form submission with Ajax request
|
||||||
|
* @param event {Event} - Event of the form submission
|
||||||
|
*/
|
||||||
|
function onSubmit(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
const {action, method} = forgottenPasswordForm;
|
||||||
|
|
||||||
|
const url = new URL(action);
|
||||||
|
url.searchParams.append("email", emailInput.value);
|
||||||
|
|
||||||
|
fetch(url, {headers: {"Content-Type": "application/json"}, method})
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.code !== 200) throw new Error(data.message);
|
||||||
|
})
|
||||||
|
.then(() => window.location.href = "${pageContext.request.contextPath}/login")
|
||||||
|
.catch(onError);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the error of the form submission
|
||||||
|
* @param error {Error} - Error of the form submission
|
||||||
|
*/
|
||||||
|
function onError(error) {
|
||||||
|
console.error("Error:", error)
|
||||||
|
|
||||||
|
// Input fields in red
|
||||||
|
emailInput.classList.add("is-danger");
|
||||||
|
|
||||||
|
// Shake the inputs
|
||||||
|
emailInput.style.animation = "shake 0.5s ease-in-out";
|
||||||
|
|
||||||
|
// Notification
|
||||||
|
const notification = document.createElement("div");
|
||||||
|
notification.classList.add("notification", "is-danger");
|
||||||
|
notification.innerHTML = error.message;
|
||||||
|
document.body.appendChild(notification);
|
||||||
|
setTimeout(() => notification.remove(), 5010);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the shake animation at the end of animation
|
||||||
|
emailInput.addEventListener("animationend", () => emailInput.style.animation = "");
|
||||||
|
</script>
|
||||||
|
|
||||||
Reference in New Issue
Block a user