feat!(DevWeb): Add BulmaCSS, refacto, handle error on login pages, use bean, filters and tags

This commit is contained in:
Lucàs
2024-04-17 13:59:16 +02:00
parent 109ffd334e
commit 469b037232
81 changed files with 1315 additions and 691 deletions
+8
View File
@@ -46,6 +46,14 @@
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<dependency>
<groupId>javax.servlet.jsp</groupId>
<artifactId>javax.servlet.jsp-api</artifactId>
<version>2.3.3</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
@@ -1,12 +1,8 @@
package uppa.project;
import java.util.Calendar;
import uppa.project.dao.DAO;
import uppa.project.dao.DAOException;
import uppa.project.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.pojo.Card;
import uppa.project.pojo.Deck;
import uppa.project.pojo.User;
import uppa.project.database.dao.DAOException;
import uppa.project.database.pojo.Card;
import uppa.project.database.pojo.Deck;
public class Main {
@@ -0,0 +1,58 @@
package uppa.project.bean;
import java.io.Serializable;
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.User;
public class LoginBean implements Serializable {
private static final long serialVersionUID = 1L;
private String username;
private String password;
private User user;
public LoginBean() {
}
public LoginBean(String username, String password) {
this.username = username;
this.password = password;
}
public boolean validate() {
Game_JPA_DAO_Factory factory = new Game_JPA_DAO_Factory();
try {
DAO<User> userDao = factory.getDAOUser();
User[] user = userDao.findByField("username", username);
for (User u : user) {
if (u.getUsername().equals(username)) {
this.user = u;
return true;
}
}
} catch (DAOException e) {
throw new RuntimeException(e);
}
return false;
}
public User getUser() {
return user;
}
public LoginBean setUsername(String username) {
this.username = username;
return this;
}
public LoginBean setPassword(String password) {
this.password = password;
return this;
}
}
@@ -0,0 +1,127 @@
package uppa.project.bean;
import jakarta.persistence.EntityManager;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import uppa.project.database.dao.DAO;
import uppa.project.database.dao.DAOException;
import uppa.project.database.dao.EntityManagerProvider;
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.pojo.User;
public class RegisterBean implements Serializable {
private static final long serialVersionUID = 1L;
private String username;
private String email;
private String password;
private String birth;
private String gender;
private String errorMessage;
public RegisterBean() {
}
public RegisterBean(String username, String email, String password, String birth, String gender) {
this.username = username;
this.email = email;
this.password = password;
this.birth = birth;
this.gender = gender;
}
public boolean validate() {
Game_JPA_DAO_Factory jpaDaoFactory = new Game_JPA_DAO_Factory();
DAO<User> userDAO;
// Check if the user is valid
try {
userDAO = jpaDaoFactory.getDAOUser();
// Check if the username is already taken
User[] users = userDAO.findByField("username", username);
if (users.length > 0) {
errorMessage = "Ce nom d'utilisateur est déjà pris";
return false;
}
// Check if the email is already taken
users = userDAO.findByField("email", email);
if (users.length > 0) {
errorMessage = "Cet email est déjà utilisé";
return false;
}
} catch(DAOException e) {
errorMessage = "Une erreur est survenue (DB_CONNECTION_ERROR)";
return false;
}
// Create a new User
User user = new User();
user.setUsername(username);
user.setPassword(password);
user.setEmail(email);
try {
user.setGender(User.Gender.valueOf(gender));
} catch (IllegalArgumentException e) {
errorMessage = "Le genre n'est pas valide";
return false;
}
// convert the birthdate from String as YYYY-MM-DD to Date object
try {
LocalDate localDate = LocalDate.parse(birth);
ZoneId defaultZoneId = ZoneId.systemDefault();
Date date = Date.from(localDate.atStartOfDay(defaultZoneId).toInstant());
user.setBirth(date);
} catch (Exception e) {
errorMessage = "La date de naissance n'est pas valide";
return false;
}
// Send the user to the database
EntityManager entityManager = EntityManagerProvider.getInstance();
entityManager.getTransaction().begin();
try {
userDAO = jpaDaoFactory.getDAOUser();
userDAO.create(user);
entityManager.getTransaction().commit();
return true;
} catch(DAOException e) {
entityManager.getTransaction().rollback();
}
return false;
}
public RegisterBean setUsername(String username) {
this.username = username;
return this;
}
public RegisterBean setPassword(String password) {
this.password = password;
return this;
}
public RegisterBean setEmail(String email) {
this.email = email;
return this;
}
public RegisterBean setBirth(String birth) {
this.birth = birth;
return this;
}
public RegisterBean setGender(String gender) {
this.gender = gender;
return this;
}
public String getErrorMessage() {
return errorMessage;
}
}
@@ -4,9 +4,9 @@
* Pas de copyright, aucun droits
*/
package uppa.project.dao;
package uppa.project.database.dao;
import uppa.project.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
/**
* Factory renvoyant une factory de DAO en fonction du support de persistance choisi
@@ -4,7 +4,7 @@
* Pas de copyright, aucun droits
*/
package uppa.project.dao;
package uppa.project.database.dao;
/**
* DAO abstrait et générique pour tout type de données
@@ -4,7 +4,7 @@
* Pas de copyright, aucun droits
*/
package uppa.project.dao;
package uppa.project.database.dao;
/**
* Exception spécifique aux problèmes d'accès aux données via un DAO
@@ -4,7 +4,7 @@
* Pas de copyright, aucun droits
*/
package uppa.project.provider;
package uppa.project.database.dao;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityManagerFactory;
@@ -4,12 +4,12 @@
* Pas de copyright, aucun droits
*/
package uppa.project.dao;
package uppa.project.database.dao;
import uppa.project.pojo.Game;
import uppa.project.pojo.Player;
import uppa.project.pojo.RecoveryPasswordToken;
import uppa.project.pojo.User;
import uppa.project.database.pojo.Game;
import uppa.project.database.pojo.Player;
import uppa.project.database.pojo.RecoveryPasswordToken;
import uppa.project.database.pojo.User;
/**
* Fabrique abstraite de DAO pour le schéma du jeu
@@ -4,7 +4,7 @@
* Pas de copyright, aucun droits
*/
package uppa.project.dao;
package uppa.project.database.dao;
/**
* Type de support de persistance pour les données
@@ -4,17 +4,16 @@
* Pas de copyright, aucun droits
*/
package uppa.project.dao.jpa;
package uppa.project.database.dao.jpa;
import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import java.math.BigDecimal;
import java.util.List;
import java.util.Objects;
import uppa.project.dao.DAO;
import uppa.project.dao.DAOException;
import uppa.project.pojo.Game;
import uppa.project.provider.EntityManagerProvider;
import uppa.project.database.dao.DAO;
import uppa.project.database.dao.DAOException;
import uppa.project.database.pojo.Game;
import uppa.project.database.dao.EntityManagerProvider;
/**
* DAO pour les parties de jeu
@@ -4,16 +4,16 @@
* Pas de copyright, aucun droits
*/
package uppa.project.dao.jpa;
package uppa.project.database.dao.jpa;
import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import java.math.BigDecimal;
import java.util.List;
import uppa.project.dao.DAO;
import uppa.project.dao.DAOException;
import uppa.project.pojo.Player;
import uppa.project.provider.EntityManagerProvider;
import uppa.project.database.dao.DAO;
import uppa.project.database.dao.DAOException;
import uppa.project.database.dao.EntityManagerProvider;
import uppa.project.database.pojo.Player;
/**
* DAO pour les joueurs
@@ -4,16 +4,16 @@
* Pas de copyright, aucun droits
*/
package uppa.project.dao.jpa;
package uppa.project.database.dao.jpa;
import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import java.math.BigDecimal;
import java.util.List;
import uppa.project.dao.DAO;
import uppa.project.dao.DAOException;
import uppa.project.pojo.RecoveryPasswordToken;
import uppa.project.provider.EntityManagerProvider;
import uppa.project.database.dao.DAO;
import uppa.project.database.dao.DAOException;
import uppa.project.database.dao.EntityManagerProvider;
import uppa.project.database.pojo.RecoveryPasswordToken;
/**
* DAO pour les tokens de récupération de mot de passe
@@ -4,16 +4,16 @@
* Pas de copyright, aucun droits
*/
package uppa.project.dao.jpa;
package uppa.project.database.dao.jpa;
import jakarta.persistence.EntityManager;
import jakarta.persistence.TypedQuery;
import java.math.BigDecimal;
import java.util.List;
import uppa.project.dao.DAO;
import uppa.project.dao.DAOException;
import uppa.project.pojo.User;
import uppa.project.provider.EntityManagerProvider;
import uppa.project.database.dao.DAO;
import uppa.project.database.dao.DAOException;
import uppa.project.database.pojo.User;
import uppa.project.database.dao.EntityManagerProvider;
/**
* DAO pour les utilisateurs
@@ -4,12 +4,15 @@
* Pas de copyright, aucun droits
*/
package uppa.project.dao.jpa;
package uppa.project.database.dao.jpa;
import uppa.project.dao.DAO;
import uppa.project.pojo.*;
import uppa.project.dao.DAOException;
import uppa.project.dao.GameDAOFactory;
import uppa.project.database.dao.DAO;
import uppa.project.database.dao.GameDAOFactory;
import uppa.project.database.pojo.Game;
import uppa.project.database.pojo.Player;
import uppa.project.database.pojo.RecoveryPasswordToken;
import uppa.project.database.pojo.User;
import uppa.project.database.dao.DAOException;
/**
* Fabrique concrète de DAO pour le schéma relationnel sports avec une implémentation en JDBC.
@@ -4,7 +4,7 @@
* Pas de copyright, aucun droits
*/
package uppa.project.pojo;
package uppa.project.database.pojo;
import jakarta.persistence.Transient;
@@ -4,9 +4,8 @@
* Pas de copyright, aucun droits
*/
package uppa.project.pojo;
package uppa.project.database.pojo;
import jakarta.persistence.Transient;
import java.util.ArrayList;
import java.util.Collections;
@@ -4,7 +4,7 @@
* Pas de copyright, aucun droits
*/
package uppa.project.pojo;
package uppa.project.database.pojo;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
@@ -25,8 +25,6 @@ import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.Objects;
import java.util.Timer;
import java.util.TimerTask;
/**
* Représentation d'une partie de jeu
@@ -4,7 +4,7 @@
* Pas de copyright, aucun droits
*/
package uppa.project.pojo;
package uppa.project.database.pojo;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
@@ -1,4 +1,4 @@
package uppa.project.pojo;
package uppa.project.database.pojo;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
@@ -4,7 +4,7 @@
* Pas de copyright, aucun droits
*/
package uppa.project.pojo;
package uppa.project.database.pojo;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
@@ -23,8 +23,6 @@ import java.io.Serializable;
import java.math.BigDecimal;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDate;
import java.time.Period;
import java.util.ArrayList;
import java.util.Date;
import java.util.Objects;
@@ -195,6 +193,7 @@ public class User implements Serializable {
/**
* Modifie le mot de passe de l'utilisateur
* Le mot de passe est hashé avant d'être stocké
*
* @param password le nouveau mot de passe
*/
@@ -0,0 +1,37 @@
/*
* HttpResponse.java, 20/03/2024
* UPPA M1 TI 2023-2024
* Pas de copyright, aucun droits
*/
package uppa.project.json;
/**
* Classe représentant une réponse HTTP
*
* @author Kevin Mitresse
* @author Lucàs Vabre
*/
public class HttpResponse {
/**
* Défini si la réponse est un succès
*/
protected final int code;
/**
* Message de la réponse
*/
protected final String message;
/**
* Constructeur
*
* @param code code HTTP de l'erreur
* @param message message d'erreur
*/
public HttpResponse(HttpResponseCode code, String message) {
this.code = code.getCode();
this.message = message;
}
}
@@ -0,0 +1,23 @@
package uppa.project.json;
public enum HttpResponseCode {
OK(200),
CREATED(201),
NO_CONTENT(204),
BAD_REQUEST(400),
UNAUTHORIZED(401),
FORBIDDEN(403),
NOT_FOUND(404),
CONFLICT(409),
INTERNAL_SERVER_ERROR(500);
private final int code;
HttpResponseCode(int code) {
this.code = code;
}
public int getCode() {
return code;
}
}
@@ -1,4 +1,4 @@
package uppa.project.pojo.json.websocket;
package uppa.project.json.websocket;
public class Message {
private final String type;
@@ -1,53 +0,0 @@
/*
* ErrorResponse.java, 20/03/2024
* UPPA M1 TI 2023-2024
* Pas de copyright, aucun droits
*/
package uppa.project.pojo.json;
/**
* Classe représentant une erreur
*
* @author Kevin Mitresse
* @author Lucàs Vabre
*/
public class ErrorResponse extends HttpResponse{
/**
* Type de l'erreur
*/
private final String error;
/**
* Message d'erreur
*/
private final String message;
/**
* Constructeur
*
* @param status code HTTP de l'erreur
* @param error type de l'erreur
* @param message message d'erreur
*/
public ErrorResponse(int status, String error, String message) {
super(status);
this.error = error;
this.message = message;
}
/**
* @return le type de l'erreur
*/
public String getError() {
return error;
}
/**
* @return le message d'erreur
*/
public String getMessage() {
return message;
}
}
@@ -1,37 +0,0 @@
/*
* HttpResponse.java, 20/03/2024
* UPPA M1 TI 2023-2024
* Pas de copyright, aucun droits
*/
package uppa.project.pojo.json;
/**
* Classe représentant une réponse HTTP
*
* @author Kevin Mitresse
* @author Lucàs Vabre
*/
public abstract class HttpResponse {
/**
* Code HTTP de la réponse
*/
protected final int status;
/**
* Constructeur
*
* @param status code HTTP de l'erreur
*/
public HttpResponse(int status) {
this.status = status;
}
/**
* @return le code HTTP de la réponse
*/
public int getStatus() {
return status;
}
}
@@ -1,33 +0,0 @@
/*
* LoginServlet.java, 20/03/2024
* UPPA M1 TI 2023-2024
* Pas de copyright, aucun droits
*/
package uppa.project.servlet;
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 java.io.IOException;
@WebServlet(name = "loginServlet", value = "/login")
public class LoginServlet extends HttpServlet {
public void init() {
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
if (request.getSession().getAttribute("user") != null) {
response.sendRedirect(request.getContextPath() + "/main-menu");
return;
}
request.setAttribute("current", "login");
request.getRequestDispatcher("/WEB-INF/views/login.jsp").forward(request, response);
}
public void destroy() {
}
}
@@ -1,34 +0,0 @@
/*
* RegisterServlet.java, 20/03/2024
* UPPA M1 TI 2023-2024
* Pas de copyright, aucun droits
*/
package uppa.project.servlet;
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 java.io.IOException;
@WebServlet(name = "registerServlet", value = "/register")
public class RegisterServlet extends HttpServlet {
public void init() {
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
if (request.getSession().getAttribute("user") != null) {
response.sendRedirect(request.getContextPath() + "/main-menu");
return;
}
request.setAttribute("current", "register");
request.getRequestDispatcher("/WEB-INF/views/register.jsp").forward(request, response);
}
public void destroy() {
}
}
@@ -1,82 +0,0 @@
/*
* LoginServlet.java, 20/03/2024
* UPPA M1 TI 2023-2024
* Pas de copyright, aucun droits
*/
package uppa.project.servlet.api.auth;
import com.google.gson.Gson;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import uppa.project.dao.DAO;
import uppa.project.dao.DAOException;
import uppa.project.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.listener.SessionServletContextListener;
import uppa.project.pojo.User;
@WebServlet(name = "authLoginServlet", value = "/api/auth/login")
public class AuthLoginServlet extends HttpServlet {
private static class JsonRequest {
private String username;
private String password;
}
private final Gson gson = new Gson();
public void init() {
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
// Get the json in the request body
StringBuilder sb = new StringBuilder();
BufferedReader reader = request.getReader();
String line;
while((line = reader.readLine()) != null) {
sb.append(line);
}
String requestBody = sb.toString();
JsonRequest jsonRequest = gson.fromJson(requestBody, JsonRequest.class);
// Login User
User user = loginUser(jsonRequest);
// Set user in session
request.getSession().setAttribute("user", user);
SessionServletContextListener.addSession(request.getSession());
out.println(gson.toJson(user));
out.flush();
}
private static User loginUser(JsonRequest jsonRequest) {
String username = jsonRequest.username;
String password = jsonRequest.password;
Game_JPA_DAO_Factory factory = new Game_JPA_DAO_Factory();
try {
DAO<User> userDao = factory.getDAOUser();
User[] users = userDao.findByField("username", username);
for (User user : users) {
if (user.verifyPassword(password)) return user;
}
} catch (DAOException e) {
throw new RuntimeException(e);
}
return null;
}
public void destroy() {
}
}
@@ -1,103 +0,0 @@
/*
* RegisterApiServlet.java, 03/04/2024
* UPPA M1 TI 2023-2024
* Pas de copyright, aucun droits
*/
package uppa.project.servlet.api.auth;
import com.google.gson.Gson;
import jakarta.persistence.EntityManager;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
import uppa.project.dao.DAO;
import uppa.project.dao.DAOException;
import uppa.project.pojo.User;
import uppa.project.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.provider.EntityManagerProvider;
@WebServlet(name = "authRegisterServlet", value = "/api/auth/register")
public class AuthRegisterServlet extends HttpServlet {
private class JsonRequest {
private String username;
private String password;
private String email;
private String birthdate;
private String gender;
}
private final Gson gson = new Gson();
public void init() {}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
// Get the json in the request body
StringBuilder sb = new StringBuilder();
BufferedReader reader = request.getReader();
String line;
while((line = reader.readLine()) != null) {
sb.append(line);
}
String requestBody = sb.toString();
JsonRequest jsonRequest = gson.fromJson(requestBody, JsonRequest.class);
// Create the user
User user = this.createUser(jsonRequest);
if (user == null) {
// TODO send error
return;
}
out.println(gson.toJson(user));
out.flush();
}
private User createUser(JsonRequest jsonRequest) {
// Create a new User
User user = new User();
user.setUsername(jsonRequest.username);
user.setPassword(jsonRequest.password);
user.setEmail(jsonRequest.email);
user.setGender(User.Gender.valueOf(jsonRequest.gender));
// convert the birthdate from String as YYYY-MM-DD to Date object)
LocalDate localDate = LocalDate.parse(jsonRequest.birthdate);
ZoneId defaultZoneId = ZoneId.systemDefault();
Date date = Date.from(localDate.atStartOfDay(defaultZoneId).toInstant());
user.setBirth(date);
// Send the user to the database
EntityManager entityManager = EntityManagerProvider.getInstance();
entityManager.getTransaction().begin();
try {
Game_JPA_DAO_Factory jpaDaoFactory = new Game_JPA_DAO_Factory();
DAO<User> userDAO = jpaDaoFactory.getDAOUser();
User newUser = userDAO.create(user);
entityManager.getTransaction().commit();
return newUser;
} catch(DAOException e) {
entityManager.getTransaction().rollback();
return null;
}
}
public void destroy() {
}
}
@@ -0,0 +1,31 @@
package uppa.project.web.filter;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
public class AlreadyLoggedFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpSession session = httpRequest.getSession(false);
// Vérifier si l'utilisateur est connecté en vérifiant la présence d'une session
boolean isLoggedIn = (session != null && session.getAttribute("user") != null);
// Si l'utilisateur n'est pas connecté, laisser passer la requête
if (!isLoggedIn) {
chain.doFilter(request, response);
} else {
// Sinon, rediriger vers la page du menu principal
httpResponse.sendRedirect(httpRequest.getContextPath() + "/main-menu");
}
}
}
@@ -0,0 +1,32 @@
package uppa.project.web.filter;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import java.io.IOException;
public class AuthenticationFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
HttpServletResponse httpResponse = (HttpServletResponse) response;
HttpSession session = httpRequest.getSession(false);
// Vérifier si l'utilisateur est connecté en vérifiant la présence d'une session
boolean isLoggedIn = (session != null && session.getAttribute("user") != null);
// Si l'utilisateur est connecté, laisser passer la requête
if (isLoggedIn) {
chain.doFilter(request, response);
} else {
// Sinon, rediriger vers la page de connexion
httpResponse.sendRedirect(httpRequest.getContextPath() + "/login");
}
}
}
@@ -4,7 +4,7 @@
* Pas de copyright, aucun droits
*/
package uppa.project.servlet;
package uppa.project.web.servlet;
import jakarta.persistence.EntityManager;
import jakarta.servlet.ServletException;
@@ -16,16 +16,16 @@ import java.io.IOException;
import java.util.UUID;
import javax.mail.Message;
import uppa.project.Global;
import uppa.project.dao.DAO;
import uppa.project.dao.DAOException;
import uppa.project.dao.jpa.DAO_JPA_User;
import uppa.project.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.pojo.RecoveryPasswordToken;
import uppa.project.pojo.User;
import uppa.project.database.dao.DAO;
import uppa.project.database.dao.DAOException;
import uppa.project.database.dao.jpa.DAO_JPA_User;
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.pojo.RecoveryPasswordToken;
import uppa.project.database.pojo.User;
import java.util.Properties;
import javax.mail.*;
import javax.mail.internet.*;
import uppa.project.provider.EntityManagerProvider;
import uppa.project.database.dao.EntityManagerProvider;
@WebServlet(name = "forgottenPasswordServlet", value = "/forgotten-password")
@@ -4,7 +4,7 @@
* Pas de copyright, aucun droits
*/
package uppa.project.servlet;
package uppa.project.web.servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
@@ -20,13 +20,8 @@ public class IndexServlet extends HttpServlet {
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
if (request.getSession().getAttribute("user") != null) {
response.sendRedirect(request.getContextPath() + "/main-menu");
return;
}
request.setAttribute("current", "index");
request.getRequestDispatcher("/WEB-INF/views/index.jsp").forward(request, response);
request.getRequestDispatcher("/WEB-INF/pages/index.jsp").forward(request, response);
}
public void destroy() {
@@ -0,0 +1,59 @@
/*
* LoginServlet.java, 20/03/2024
* UPPA M1 TI 2023-2024
* Pas de copyright, aucun droits
*/
package uppa.project.web.servlet;
import com.google.gson.Gson;
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 java.io.IOException;
import java.io.PrintWriter;
import uppa.project.bean.LoginBean;
import uppa.project.json.HttpResponse;
import uppa.project.json.HttpResponseCode;
@WebServlet(name = "loginServlet", value = "/login")
public class LoginServlet extends HttpServlet {
public void init() {
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
request.setAttribute("current", "login");
request.getRequestDispatcher("/WEB-INF/pages/login.jsp").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
LoginBean loginBean = new LoginBean()
.setUsername(request.getParameter("username"))
.setPassword(request.getParameter("password"))
;
Gson gson = new Gson();
HttpResponse httpResponse;
if (loginBean.validate()) {
request.getSession().setAttribute("user", loginBean.getUser());
httpResponse = new HttpResponse(HttpResponseCode.OK, "Login success");
} else {
httpResponse = new HttpResponse(HttpResponseCode.UNAUTHORIZED, "<strong>Erreur de connexion:</strong> Le nom d'utilisateur ou le " +
"mot de passe est incorrect.");
}
out.println(gson.toJson(httpResponse));
out.flush();
}
public void destroy() {
}
}
@@ -4,7 +4,7 @@
* Pas de copyright, aucun droits
*/
package uppa.project.servlet;
package uppa.project.web.servlet;
import com.google.gson.Gson;
import jakarta.servlet.annotation.WebServlet;
@@ -23,11 +23,8 @@ public class LogoutServlet extends HttpServlet {
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
if (request.getSession().getAttribute("user") != null) {
SessionServletContextListener.removeSession(request.getSession());
request.getSession().removeAttribute("user");
}
SessionServletContextListener.removeSession(request.getSession());
request.getSession().removeAttribute("user");
response.sendRedirect(request.getContextPath() + "/login");
}
@@ -4,7 +4,7 @@
* Pas de copyright, aucun droits
*/
package uppa.project.servlet;
package uppa.project.web.servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
@@ -16,9 +16,9 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import uppa.project.pojo.Game;
import uppa.project.pojo.Player;
import uppa.project.pojo.User;
import uppa.project.database.pojo.Game;
import uppa.project.database.pojo.Player;
import uppa.project.database.pojo.User;
@WebServlet(name = "mainMenuServlet", value = "/main-menu")
public class MainMenuServlet extends HttpServlet {
@@ -34,8 +34,8 @@ public class MainMenuServlet extends HttpServlet {
// }
request.setAttribute("current", "main-menu");
manageNewGame(request, response, user);
manageStatistiques(request, response, user);
request.getRequestDispatcher("/WEB-INF/views/main-menu.jsp").forward(request, response);
manageStatistics(request, response, user);
request.getRequestDispatcher("/WEB-INF/pages/main-menu.jsp").forward(request, response);
}
public void destroy() {
@@ -44,6 +44,7 @@ public class MainMenuServlet extends HttpServlet {
private void manageNewGame(HttpServletRequest request, HttpServletResponse response, User sessionUser) throws IOException, ServletException {
List<User> connectedUsers = new ArrayList<>();
Set<HttpSession> loginsSessions = (Set<HttpSession>) request.getServletContext().getAttribute("loginSession");
if (loginsSessions == null) {
throw new RuntimeException("No login sessions found");
}
@@ -57,7 +58,7 @@ public class MainMenuServlet extends HttpServlet {
request.setAttribute("connectedUsers", connectedUsers);
}
private void manageStatistiques(HttpServletRequest request, HttpServletResponse response, User sessionUser) throws IOException, ServletException {
private void manageStatistics(HttpServletRequest request, HttpServletResponse response, User sessionUser) throws IOException, ServletException {
List<Game> games = new ArrayList<>();
if (sessionUser != null && sessionUser.getPlayedGames() != null) {
for (Player player : sessionUser.getPlayedGames()) {
@@ -0,0 +1,63 @@
/*
* RegisterServlet.java, 20/03/2024
* UPPA M1 TI 2023-2024
* Pas de copyright, aucun droits
*/
package uppa.project.web.servlet;
import com.google.gson.Gson;
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 java.io.IOException;
import java.io.PrintWriter;
import uppa.project.bean.LoginBean;
import uppa.project.bean.RegisterBean;
import uppa.project.json.HttpResponse;
import uppa.project.json.HttpResponseCode;
@WebServlet(name = "registerServlet", value = "/register")
public class RegisterServlet extends HttpServlet {
public void init() {
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
request.setAttribute("current", "register");
request.getRequestDispatcher("/WEB-INF/pages/register.jsp").forward(request, response);
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("application/json");
response.setCharacterEncoding("UTF-8");
PrintWriter out = response.getWriter();
RegisterBean registerBean = new RegisterBean()
.setUsername(request.getParameter("username"))
.setEmail(request.getParameter("email"))
.setPassword(request.getParameter("password"))
.setBirth(request.getParameter("birth"))
.setGender(request.getParameter("gender"))
;
Gson gson = new Gson();
HttpResponse httpResponse;
if (registerBean.validate()) {
httpResponse = new HttpResponse(
HttpResponseCode.OK,
"Register success"
);
} else {
httpResponse = new HttpResponse(HttpResponseCode.UNAUTHORIZED, registerBean.getErrorMessage());
}
out.println(gson.toJson(httpResponse));
out.flush();
}
public void destroy() {
}
}
@@ -1,4 +1,4 @@
package uppa.project.servlet;
package uppa.project.web.servlet;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
@@ -6,11 +6,11 @@ import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import uppa.project.dao.DAOException;
import uppa.project.dao.jpa.DAO_JPA_RecoveryPasswordToken;
import uppa.project.dao.jpa.DAO_JPA_User;
import uppa.project.pojo.RecoveryPasswordToken;
import uppa.project.pojo.User;
import uppa.project.database.dao.DAOException;
import uppa.project.database.dao.jpa.DAO_JPA_RecoveryPasswordToken;
import uppa.project.database.dao.jpa.DAO_JPA_User;
import uppa.project.database.pojo.RecoveryPasswordToken;
import uppa.project.database.pojo.User;
@WebServlet(name = "resetPasswordServlet", value = "/reset-password")
public class ResetPasswordServlet extends HttpServlet {
@@ -28,7 +28,7 @@ public class ResetPasswordServlet extends HttpServlet {
return;
}
request.setAttribute("current", "reset-password");
request.getRequestDispatcher("/WEB-INF/views/reset-password.jsp").forward(request, response);
request.getRequestDispatcher("/WEB-INF/pages/reset-password.jsp").forward(request, response);
}
/**
@@ -1,4 +1,4 @@
package uppa.project.websocket;
package uppa.project.web.websocket;
import com.google.gson.Gson;
import jakarta.websocket.OnClose;
@@ -10,18 +10,16 @@ import jakarta.websocket.Session;
import jakarta.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.util.HashMap;
import uppa.project.pojo.User;
import uppa.project.pojo.json.websocket.Message;
import uppa.project.database.pojo.User;
import uppa.project.json.websocket.Message;
@ServerEndpoint(value = "/main-menu")
public class MainMenuWS {
@ServerEndpoint(value = "/ws/connected-users")
public class ConnectedUsersWS {
private static final HashMap<Session, User> connections = new HashMap<>();
@OnOpen
public void onOpen(Session session) {
System.out.println("Connexion WebSocket ouverte : " + session.getId());
}
public void onOpen(Session session) {}
private void broadcastConnectedUsers() {
Gson gson = new Gson();
@@ -30,8 +28,6 @@ public class MainMenuWS {
Message websocketObject = new Message("userList", gson.toJson(connectedUsers));
String message = gson.toJson(websocketObject);
System.out.println("Broadcasting connected users : " + message);
for (Session session : connections.keySet()) {
RemoteEndpoint.Basic remote = session.getBasicRemote();
try {
@@ -44,7 +40,6 @@ public class MainMenuWS {
@OnClose
public void onClose(Session session) {
System.out.println("Connexion WebSocket fermée : " + session.getId());
connections.remove(session);
// Update connected users list
@@ -53,7 +48,6 @@ public class MainMenuWS {
@OnError
public void onError(Throwable throwable) {
System.out.println("Erreur WebSocket : " + throwable.getMessage());
throwable.printStackTrace();
}
@@ -62,12 +56,8 @@ public class MainMenuWS {
Gson gson = new Gson();
Message websocketMessage = gson.fromJson(message, Message.class);
System.out.println("Message reçu : " + websocketMessage);
if (websocketMessage.getType().equals("linkUserSession")) {
User user = gson.fromJson(websocketMessage.getData(), User.class);
System.out.println(user);
connections.put(session, user);
broadcastConnectedUsers();
}
@@ -5,10 +5,10 @@
version="3.0">
<persistence-unit name="prod">
<class>uppa.project.pojo.User</class>
<class>uppa.project.pojo.Game</class>
<class>uppa.project.pojo.Player</class>
<class>uppa.project.pojo.RecoveryPasswordToken</class>
<class>uppa.project.database.pojo.User</class>
<class>uppa.project.database.pojo.Game</class>
<class>uppa.project.database.pojo.Player</class>
<class>uppa.project.database.pojo.RecoveryPasswordToken</class>
<properties>
<property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/db_prod?useSSL=false&amp;allowPublicKeyRetrieval=true"/>
@@ -19,10 +19,10 @@
</persistence-unit>
<persistence-unit name="test">
<class>uppa.project.pojo.User</class>
<class>uppa.project.pojo.Game</class>
<class>uppa.project.pojo.Player</class>
<class>uppa.project.pojo.RecoveryPasswordToken</class>
<class>uppa.project.database.pojo.User</class>
<class>uppa.project.database.pojo.Game</class>
<class>uppa.project.database.pojo.Player</class>
<class>uppa.project.database.pojo.RecoveryPasswordToken</class>
<properties>
<property name="jakarta.persistence.jdbc.driver" value="com.mysql.cj.jdbc.Driver"/>
<property name="jakarta.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/db_test?useSSL=false&amp;allowPublicKeyRetrieval=true"/>
@@ -1,4 +1,4 @@
<%@ page import="uppa.project.pojo.User" %>
<%@ page import="uppa.project.database.pojo.User" %>
<%@ page pageEncoding="UTF-8" %>
<%--
Created by IntelliJ IDEA.
@@ -1,6 +1,6 @@
<%@ page import="uppa.project.pojo.User" %>
<%@ page import="uppa.project.pojo.Game" %>
<%@ page import="uppa.project.pojo.Deck" %>
<%@ page import="uppa.project.database.pojo.User" %>
<%@ page import="uppa.project.database.pojo.Game" %>
<%@ page import="uppa.project.database.pojo.Deck" %>
<%@ page pageEncoding="UTF-8" %>
<div id="newGameModal" class="modal-wrapper" style="display: none">
@@ -1,13 +1,13 @@
<%@ page import="uppa.project.pojo.User" %>
<%@ page import="uppa.project.pojo.Game" %>
<%@ page import="uppa.project.database.pojo.User" %>
<%@ page import="uppa.project.database.pojo.Game" %>
<%@ page import="java.util.ArrayList" %>
<%@ page import="uppa.project.pojo.Player" %>
<%@ page import="uppa.project.database.pojo.Player" %>
<%@ page import="java.util.Date" %>
<%@ page pageEncoding="UTF-8" %>
<%--TODO: adapter les deux lignes suivante pour ne pas vérifier la valeur nulle--%>
<% User user = (User) session.getAttribute("user") != null ? (User) session.getAttribute("user") : new User("toto", "toto@gmail.com", "totopassword", new Date(), User.Gender.MALE); %>
<% User user = session.getAttribute("user") != null ? (User) session.getAttribute("user") : new User("toto", "toto@gmail.com", "totopassword", new Date(), User.Gender.MALE); %>
<% ArrayList<Game> games = (ArrayList<Game>) request.getAttribute("games") != null ? (ArrayList<Game>) request.getAttribute("games") : new ArrayList<>() ; %>
<div id="statisticsModal" class="modal-wrapper" style="display: none">
<div class="modal">
@@ -19,7 +19,7 @@
<body>
<%@include file="../components/navbar.jsp" %>
<div class="content">
<h1>Plongez dans l'excitation de cardRush!</h1>
<h1>Plongez dans l'excitation de CardRush!</h1>
<p>Défiez votre réactivité et dominez le jeu avec des amis dans cette course effrénée aux cartes ! Rejoignez maintenant pour vivre l'adrénaline.</p>
<div class="buttons">
<a class="button" href="${pageContext.request.contextPath}/register">S'inscrire</a>
@@ -0,0 +1,24 @@
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@taglib prefix="layout" tagdir="/WEB-INF/tags/layouts" %>
<%@taglib prefix="component" tagdir="/WEB-INF/tags/components" %>
<%@taglib prefix="form" tagdir="/WEB-INF/tags/forms" %>
<layout:base>
<jsp:attribute name="title">Cards Rush - Connexion</jsp:attribute>
<jsp:body>
<div class="hero is-light is-fullheight-with-navbar">
<div class="hero-body">
<div class="container">
<div class="columns is-centered">
<div class="column is-5-tablet is-5-desktop is-5-widescreen">
<div class="box">
<h1 class="title has-text-centered">Se connecter</h1>
<form:login/>
</div>
</div>
</div>
</div>
</div>
</div>
</jsp:body>
</layout:base>
@@ -0,0 +1,61 @@
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@taglib prefix="layout" tagdir="/WEB-INF/tags/layouts" %>
<%@taglib prefix="component" tagdir="/WEB-INF/tags/components" %>
<%@taglib prefix="form" tagdir="/WEB-INF/tags/forms" %>
<layout:base>
<jsp:attribute name="title">Menu principal</jsp:attribute>
<jsp:body>
<div class="hero is-light is-fullheight-with-navbar">
<div class="hero-body">
<div class="container">
<div class="columns is-centered">
<div class="column is-5-tablet is-5-desktop is-5-widescreen">
<component:card>
<jsp:attribute name="card_head">
</jsp:attribute>
<jsp:attribute name="card_content">
<%-- <form:newGame/>--%>
</jsp:attribute>
</component:card>
</div>
<div class="column is-5-tablet is-5-desktop is-5-widescreen">
<component:connectedUserList/>
</div>
</div>
</div>
</div>
</div>
</jsp:body>
</layout:base>
<%--<!DOCTYPE html>--%>
<%--<html>--%>
<%--<head>--%>
<%-- <title>Cards Rush</title>--%>
<%-- <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap">--%>
<%-- <link href="${pageContext.request.contextPath}/static/css/global.css" rel="stylesheet">--%>
<%-- <link href="${pageContext.request.contextPath}/static/css/main-menu.css" rel="stylesheet">--%>
<%-- <link href="${pageContext.request.contextPath}/static/css/new-game.css" rel="stylesheet">--%>
<%-- <link href="${pageContext.request.contextPath}/static/css/modal.css" rel="stylesheet">--%>
<%-- <script src="${pageContext.request.contextPath}/static/js/modal.js" defer></script>--%>
<%-- <script src="${pageContext.request.contextPath}/static/js/new-game.js" defer></script>--%>
<%-- <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">--%>
<%-- <script defer src="${pageContext.request.contextPath}/static/js/main-menu.js"></script>--%>
<%--</head>--%>
<%--<body>--%>
<%--<%@include file="../components/navbar.jsp" %>--%>
<%--<main>--%>
<%-- <section id="main">--%>
<%-- <h1 id="title">Cards Rush!</h1>--%>
<%-- <div class="main-button">--%>
<%-- <button class="modal-toggle button" data-target="#newGameModal">Nouvelle Partie</button>--%>
<%-- <button class="modal-toggle button" data-target="#statisticsModal">Statistiques</button>--%>
<%-- </div>--%>
<%-- </section>--%>
<%-- <%@include file="../components/new-game.jsp" %>--%>
<%-- <%@include file="../components/statistics.jsp" %>--%>
<%--</main>--%>
<%--</body>--%>
<%--</html>--%>
@@ -0,0 +1,76 @@
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@taglib prefix="layout" tagdir="/WEB-INF/tags/layouts" %>
<%@taglib prefix="component" tagdir="/WEB-INF/tags/components" %>
<%@taglib prefix="form" tagdir="/WEB-INF/tags/forms" %>
<layout:base>
<jsp:attribute name="title">Cards Rush - Inscription</jsp:attribute>
<jsp:body>
<div class="hero is-light is-fullheight-with-navbar">
<div class="hero-body">
<div class="container">
<div class="columns is-centered">
<div class="column is-5-tablet is-5-desktop is-5-widescreen">
<div class="box">
<h1 class="title has-text-centered">S'inscrire</h1>
<form:register/>
</div>
</div>
</div>
</div>
</div>
</div>
</jsp:body>
</layout:base>
<%--<!DOCTYPE html>--%>
<%--<html>--%>
<%--<head>--%>
<%-- <title>Register</title>--%>
<%-- <link href="${pageContext.request.contextPath}/static/css/global.css" rel="stylesheet">--%>
<%-- <link href="${pageContext.request.contextPath}/static/css/login.css" rel="stylesheet">--%>
<%-- <script src="${pageContext.request.contextPath}/static/js/register.js" defer></script>--%>
<%--</head>--%>
<%--<body>--%>
<%--<%@include file="../components/navbar.jsp"%>--%>
<%--<main>--%>
<%-- <div class="flex-column register-gap">--%>
<%-- <div>--%>
<%-- <h1>S'inscrire</h1>--%>
<%-- <form id="register-form" action="${pageContext.request.contextPath}/api/auth/register" method="POST">--%>
<%-- <label for="email">Email :</label>--%>
<%-- <input type="email" id="email" name="email" required>--%>
<%-- <label for="username">Nom d'utilisateur :</label>--%>
<%-- <input type="text" id="username" name="username" required>--%>
<%-- <label for="password">Mot de passe :</label>--%>
<%-- <input type="password" id="password" name="password" required>--%>
<%-- <label for="confirmPassword">Confirmez le mot de passe :</label>--%>
<%-- <input type="password" id="confirmPassword" name="confirmPassword" required>--%>
<%-- <label for="birthdate">Date de naissance :</label>--%>
<%-- <input type="date" id="birthdate" name="birthdate" required>--%>
<%-- <label for="gender">Genre :</label>--%>
<%-- <select name="gender" id="gender" required>--%>
<%-- <option value="">--Choisissez une option--</option>--%>
<%-- <option value="MALE">Homme</option>--%>
<%-- <option value="FEMALE">Femme</option>--%>
<%-- <option value="OTHER">Autre</option>--%>
<%-- </select>--%>
<%-- <input class="button" id="register-submit" type="submit" value="Register">--%>
<%-- </form>--%>
<%-- </div>--%>
<%-- <div>--%>
<%-- <hr>--%>
<%-- <p>Déjà un compte ? <a href="${pageContext.request.contextPath}/login">Se connecter</a></p>--%>
<%-- </div>--%>
<%-- </div>--%>
<%--</main>--%>
<%--</body>--%>
<%--</html>--%>
@@ -0,0 +1,12 @@
<%@tag description="component/card" pageEncoding="UTF-8" %>
<%@attribute name="card_head" fragment="true" %>
<%@attribute name="card_content" fragment="true" %>
<div class="card">
<div class="card-head">
<jsp:invoke fragment="card_head"/>
</div>
<div class="card-content">
<jsp:invoke fragment="card_content"/>
</div>
</div>
@@ -0,0 +1,85 @@
<%@ tag import="com.google.gson.Gson" %>
<%@ tag import="uppa.project.database.pojo.User" %>
<%@tag description="component/connectedUserList" pageEncoding="UTF-8" %>
<%@taglib prefix="component" tagdir="/WEB-INF/tags/components" %>
<component:card>
<jsp:attribute name="card_head">
<div class="card-header-title">Utilisateurs connectés</div>
</jsp:attribute>
<jsp:attribute name="card_content">
<table id="connectedUserList" class="table is-fullwidth">
<thead>
<tr>
<th>Utilisateur</th>
<th>Action</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</jsp:attribute>
</component:card>
<script defer type="module">
const tbodyElement = document.querySelector('#connectedUserList tbody');
// effacer ce qu'il y a apres /project_war_exploded
const url = new URL(window.location.href);
url.pathname = "${pageContext.request.contextPath}/ws/connected-users";
url.protocol = "ws:"
const websocket = new WebSocket(url);
<%
Gson gson = new Gson();
User user = (User) request.getSession().getAttribute("user");
%>
websocket.onopen = () => {
const linkUserSession = {
type: 'linkUserSession',
data: JSON.stringify(<%= gson.toJson(user) %>)
}
websocket.send(JSON.stringify(linkUserSession));
}
websocket.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'userList') {
const users = JSON.parse(data.data);
updateUserList(users);
}
}
websocket.onclose = () => {}
websocket.onerror = (error) => {}
function updateUserList(users) {
tbodyElement.innerHTML = '';
users.forEach(user => {
const trElement = document.createElement('tr');
const tdElement = [
document.createElement('td'),
document.createElement('td')
];
const buttonElement = document.createElement('button');
tdElement[0].textContent = user.username;
// If it's not the current user, we can display the button
if (user.id !== <%= user.getId() %>) {
buttonElement.classList.add('button', 'is-light');
buttonElement.textContent = 'Inviter';
// TODO Ajouter l'événement click
}
tdElement[1].appendChild(buttonElement);
trElement.appendChild(tdElement[0]);
trElement.appendChild(tdElement[1]);
tbodyElement.appendChild(trElement);
});
}
</script>
@@ -0,0 +1,9 @@
<%@tag description="component/footer" pageEncoding="UTF-8" %>
<footer class="footer">
<div class="content has-text-centered">
<p>
<strong>Cards Rush</strong> par Kevin Mitressé & Lucàs Vabre. UPPA M1-TI 2024
</p>
</div>
</footer>
@@ -0,0 +1,35 @@
<%@tag description="component/navbar" pageEncoding="UTF-8" %>
<nav class="navbar" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a class="navbar-item" href="${pageContext.request.contextPath}/">
<img src="${pageContext.request.contextPath}/static/img/CardsRushLogoBlack.svg" height="260">
</a>
<a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false" data-target="navbarMenu">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div id="navbarMenu" class="navbar-menu">
<div class="navbar-end">
<div class="navbar-item">
<div class="buttons">
<%if (session.getAttribute("user") != null) {%>
<%-- TODO: Profil de l'utilisateur--%>
<a href="${pageContext.request.contextPath}/profile" class="button is-primary"><strong>Profil</strong></a>
<a href="${pageContext.request.contextPath}/logout" class="button is-danger is-light">Déconnexion</a>
<% } else {%>
<a href="${pageContext.request.contextPath}/register" class="button is-primary"><strong>Inscription</strong></a>
<a href="${pageContext.request.contextPath}/login" class="button is-light">Connexion</a>
<% } %>
</div>
</div>
</div>
</div>
</nav>
@@ -0,0 +1,123 @@
<%@tag description="form/login" pageEncoding="UTF-8" %>
<form id="login-form" action="${pageContext.request.contextPath}/login" method="post">
<div class="field"> <!-- Field Username -->
<label class="label" for="username">Nom d'utilisateur</label>
<input id="username" placeholder="John Doe" class="input is-fullwidth" required/>
</div>
<div class="field"> <!-- Field Password -->
<label class="label" for="password">Mot de passe</label>
<input id="password" class="input is-fullwidth" type="password" required/>
</div>
<p class="content has-text-right"><a href="${pageContext.request.contextPath}/forgotten-password" class="link">Mot de passe oublié ?</a>
</p>
<input type="submit" class="button is-primary is-fullwidth" value="Connexion">
<hr/>
<p class="content has-text-centered"><a href="${pageContext.request.contextPath}/register">S'inscrire</a></p>
</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 loginForm = document.querySelector("form#login-form");
// Form fields
const usernameInput = document.querySelector("input#username");
const passwordInput = document.querySelector("input#password");
// Add event listener to the form submission
loginForm.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} = loginForm;
const url = new URL(action);
url.searchParams.append("username", usernameInput.value);
url.searchParams.append("password", passwordInput.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}/main-menu")
.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
usernameInput.classList.add("is-danger");
passwordInput.classList.add("is-danger");
// Shake the inputs
usernameInput.style.animation = "shake 0.5s ease-in-out";
passwordInput.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
usernameInput.addEventListener("animationend", () => usernameInput.style.animation = "");
passwordInput.addEventListener("animationend", () => passwordInput.style.animation = "");
</script>
@@ -0,0 +1,56 @@
<%@tag description="form/newGame" pageEncoding="UTF-8" %>
<form id="newGame-form" action="${pageContext.request.contextPath}/main-menu" method="post">
<div>
</div>
</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">
</script>
@@ -0,0 +1,150 @@
<%@tag description="form/register" pageEncoding="UTF-8" %>
<form id="register-form" action="${pageContext.request.contextPath}/register" method="post">
<div class="field">
<label class="label" for="username">Nom d'utilisateur</label>
<input id="username" name="username" placeholder="John Doe" type="text" class="input is-fullwidth" required>
</div>
<div class="field">
<label class="label" for="email">Email</label>
<input id="email" name="email" type="email" placeholder="john.doe@mail.com" class="input is-fullwidth" required>
</div>
<div class="field">
<label class="label" for="password">Mot de passe</label>
<input id="password" name="password" type="password" class="input is-fullwidth" required>
</div>
<div class="field">
<label class="label" for="repassword">Confirmez le mot de passe</label>
<input id="repassword" name="repassword" type="password" class="input is-fullwidth" required>
</div>
<div class="field">
<label class="label" for="birth">Date de naissance</label>
<input class="input is-fullwidth" type="date" id="birth" name="birth" required>
</div>
<div class="field">
<label class="label" for="gender">Genre</label>
<div class="select is-fullwidth">
<select name="gender" id="gender" required>
<option selected value="">--Choisissez une option--</option>
<option value="MALE">Homme</option>
<option value="FEMALE">Femme</option>
<option value="OTHER">Autre</option>
</select>
</div>
</div>
<input type="submit" class="button is-primary is-fullwidth" value="S'inscrire">
<hr/>
<p class="content has-text-centered">Déjà inscrit ? <a href="${pageContext.request.contextPath}/login">Se connecter</a></p>
</form>
<style>
.notification {
position: absolute;
bottom: 0;
right: 0;
margin: 1em !important;
max-width: 40em;
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%);
}
}
</style>
<script defer type="module">
const registerForm = document.querySelector("form#register-form");
// Form fields
const usernameInput = document.querySelector("input#username");
const emailInput = document.querySelector("input#email");
const passwordInput = document.querySelector("input#password");
const repasswordInput = document.querySelector("input#repassword");
const birthInput = document.querySelector("input#birth");
const genderInput = document.querySelector("select#gender");
const submitButton = document.querySelector("input[type=submit]");
// Add event listener to the form submission
registerForm.addEventListener("submit", onSubmit)
/**
* Handle the form submission with Ajax request
* @param event {Event} - Event of the form submission
*/
function onSubmit(event) {
event.preventDefault();
// Check if the password and the confirmation password are the same
if (passwordInput.value !== repasswordInput.value) {
onError(new Error("Les mots de passe ne correspondent pas"));
return;
}
const {action, method} = registerForm;
const url = new URL(action);
url.searchParams.append("username", usernameInput.value);
url.searchParams.append("email", emailInput.value);
url.searchParams.append("password", passwordInput.value);
url.searchParams.append("birth", birthInput.value);
url.searchParams.append("gender", genderInput.value);
submitButton.classList.add("is-loading");
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)
.finally(() => submitButton.classList.remove("is-loading"));
}
/**
* 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
usernameInput.classList.add("is-danger");
emailInput.classList.add("is-danger");
passwordInput.classList.add("is-danger");
repasswordInput.classList.add("is-danger");
birthInput.classList.add("is-danger");
genderInput.classList.add("is-danger");
// Notification
const notification = document.createElement("div");
notification.classList.add("notification", "is-danger");
notification.innerHTML = error.message;
document.body.appendChild(notification);
setTimeout(() => notification.remove(), 5010);
}
</script>
@@ -0,0 +1,26 @@
<%@tag description="Base page layout" pageEncoding="UTF-8" %>
<%@attribute name="title" fragment="true" %>
<%@attribute name="head" fragment="true" %>
<%@taglib prefix="component" tagdir="/WEB-INF/tags/components" %>
<!DOCTYPE html>
<html>
<head>
<title><jsp:invoke fragment="title"/></title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bulma@1.0.0/css/bulma.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css">
<jsp:invoke fragment="head"/>
</head>
<body>
<component:navbar/>
<jsp:doBody/>
<component:footer/>
</body>
</html>
@@ -1,39 +0,0 @@
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<title> Cards Rush - Connexion</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap">
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap">
<link href="${pageContext.request.contextPath}/static/css/global.css" rel="stylesheet">
<link href="${pageContext.request.contextPath}/static/css/login.css" rel="stylesheet">
<script src="${pageContext.request.contextPath}/static/js/login.js" defer></script>
<meta charset="utf-8">
</head>
<body>
<%@include file="../components/navbar.jsp"%>
<main>
<div class="flex-column login-gap">
<div>
<h1>Se connecter</h1>
<form id="login-form" action="${pageContext.request.contextPath}/api/auth/login" method="POST">
<label id="username-label" for="username">Username:</label>
<input type="text" id="username" name="username" required>
<label id="password-label" for="password">Password:</label>
<input type="password" id="password" name="password" required>
<input class="button" id="login-submit" type="submit" value="Login">
</form>
</div>
<div>
<p><a href="${pageContext.request.contextPath}/forgotten-password">Forgotten password?</a></p>
<hr>
<p>Don't have an account? <a href="${pageContext.request.contextPath}/register">Register</a></p>
</div>
</div>
</main>
</body>
</html>
@@ -1,32 +0,0 @@
<%@ page import="java.util.List" %>
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<% List<User> connectedUsers = (List<User>) request.getAttribute("connectedUsers"); %>
<!DOCTYPE html>
<html>
<head>
<title>Cards Rush</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;700&display=swap">
<link href="${pageContext.request.contextPath}/static/css/global.css" rel="stylesheet">
<link href="${pageContext.request.contextPath}/static/css/main-menu.css" rel="stylesheet">
<link href="${pageContext.request.contextPath}/static/css/new-game.css" rel="stylesheet">
<link href="${pageContext.request.contextPath}/static/css/modal.css" rel="stylesheet">
<script src="${pageContext.request.contextPath}/static/js/modal.js" defer></script>
<script src="${pageContext.request.contextPath}/static/js/new-game.js" defer></script>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<script defer src="${pageContext.request.contextPath}/static/js/main-menu.js"></script>
</head>
<body>
<%@include file="../components/navbar.jsp"%>
<main>
<section id="main">
<h1 id="title">Cards Rush!</h1>
<div class="main-button">
<button class="modal-toggle button" data-target="#newGameModal" >Nouvelle Partie</button>
<button class="modal-toggle button" data-target="#statisticsModal" >Statistiques</button>
</div>
</section>
<%@include file="../components/new-game.jsp"%>
<%@include file="../components/statistics.jsp"%>
</main>
</body>
</html>
@@ -1,52 +0,0 @@
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
<title>Register</title>
<link href="${pageContext.request.contextPath}/static/css/global.css" rel="stylesheet">
<link href="${pageContext.request.contextPath}/static/css/login.css" rel="stylesheet">
<script src="${pageContext.request.contextPath}/static/js/register.js" defer></script>
</head>
<body>
<%@include file="../components/navbar.jsp"%>
<main>
<div class="flex-column register-gap">
<div>
<h1>S'inscrire</h1>
<form id="register-form" action="${pageContext.request.contextPath}/api/auth/register" method="POST">
<label for="email">Email :</label>
<input type="email" id="email" name="email" required>
<label for="username">Nom d'utilisateur :</label>
<input type="text" id="username" name="username" required>
<label for="password">Mot de passe :</label>
<input type="password" id="password" name="password" required>
<label for="confirmPassword">Confirmez le mot de passe :</label>
<input type="password" id="confirmPassword" name="confirmPassword" required>
<label for="birthdate">Date de naissance :</label>
<input type="date" id="birthdate" name="birthdate" required>
<label for="gender">Genre :</label>
<select name="gender" id="gender" required>
<option value="">--Choisissez une option--</option>
<option value="MALE">Homme</option>
<option value="FEMALE">Femme</option>
<option value="OTHER">Autre</option>
</select>
<input class="button" id="register-submit" type="submit" value="Register">
</form>
</div>
<div>
<hr>
<p>Déjà un compte ? <a href="${pageContext.request.contextPath}/login">Se connecter</a></p>
</div>
</div>
</main>
</body>
</html>
@@ -8,4 +8,27 @@
uppa.project.listener.SessionServletContextListener
</listener-class>
</listener>
<filter>
<filter-name>AuthenticationFilter</filter-name>
<filter-class>uppa.project.web.filter.AuthenticationFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AuthenticationFilter</filter-name>
<url-pattern>/main-menu</url-pattern>
<url-pattern>/profile</url-pattern>
<url-pattern>/game</url-pattern>
<url-pattern>/logout</url-pattern>
</filter-mapping>
<filter>
<filter-name>AlreadyLoggedFilter</filter-name>
<filter-class>uppa.project.web.filter.AlreadyLoggedFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>AlreadyLoggedFilter</filter-name>
<url-pattern>/login</url-pattern>
<url-pattern>/register</url-pattern>
<url-pattern>/forgotten-password</url-pattern>
</filter-mapping>
</web-app>
@@ -0,0 +1,16 @@
<%--
Created by IntelliJ IDEA.
User: lucas
Date: 16/04/2024
Time: 14:15
To change this template use File | Settings | File Templates.
--%>
<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<html>
<head>
<title>Title</title>
</head>
<body>
</body>
</html>
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

@@ -1,28 +0,0 @@
const loginForm = document.getElementById("login-form");
loginForm.addEventListener("submit", (event) => {
event.preventDefault();
const formData = new FormData(loginForm);
const data = {};
formData.forEach((value, key) => data[key] = value);
fetch(loginForm.getAttribute("action"), {
headers: {"Content-Type": "application/json"}, body: JSON.stringify(data), method: loginForm.getAttribute("method"),
})
.then(res => res.json())
.then(user => sessionStorage.setItem("user", JSON.stringify(user)))
.then(() => window.location.href = "./main-menu")
.catch(error => console.error("Error:", error));
});
const urlParams = new URLSearchParams(window.location.search);
if (urlParams.has('success')) {
if (urlParams.get('success') === "account-created") {
window.alert("Compte créé avec succès.");
}
if (urlParams.get('success') === "password-reseted") {
window.alert("Mot de passe réinitialisé avec succès.");
}
}
@@ -1,25 +0,0 @@
const session = JSON.parse(sessionStorage.getItem('session'));
url = new URL(window.location.href);
url.protocol = 'ws:';
const websocket = new WebSocket(url);
websocket.onopen = () => {
const linkUserSession = {
type: 'linkUserSession',
data: sessionStorage.getItem('user')
}
websocket.send(JSON.stringify(linkUserSession));
}
websocket.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === 'userList') {
console.log(JSON.parse(data.data));
}
}
websocket.onclose = () => {}
websocket.onerror = (error) => {}
@@ -1,21 +0,0 @@
const registerForm = document.getElementById("register-form");
const confirmPassword = document.getElementById("confirmPassword");
registerForm.addEventListener("submit", (event) => {
event.preventDefault();
const formData = new FormData(registerForm);
const data = {};
formData.forEach((value, key) => data[key] = value);
fetch(registerForm.getAttribute("action"), {
method: registerForm.getAttribute("method"),
headers: {"Content-Type": "application/json"},
body: JSON.stringify(data)
})
.then(res => res.json())
.then(_ => {
window.location.href = "./login"
})
.catch(error => console.error("Error: " + error))
});
@@ -4,8 +4,10 @@ import java.util.HashMap;
import java.util.Objects;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import uppa.project.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.provider.EntityManagerProvider;
import uppa.project.database.dao.AbstractDAOFactory;
import uppa.project.database.dao.PersistenceKind;
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.dao.EntityManagerProvider;
import static org.junit.jupiter.api.Assertions.*;
class AbstractDAOFactoryTest {
@@ -9,10 +9,12 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import uppa.project.dao.DAO;
import uppa.project.dao.DAOException;
import uppa.project.pojo.Game;
import uppa.project.provider.EntityManagerProvider;
import uppa.project.database.dao.DAO;
import uppa.project.database.dao.DAOException;
import uppa.project.database.dao.jpa.DAO_JPA_Game;
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.pojo.Game;
import uppa.project.database.dao.EntityManagerProvider;
import static org.junit.jupiter.api.Assertions.*;
@@ -9,13 +9,14 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import uppa.project.dao.DAO;
import uppa.project.dao.DAOException;
import uppa.project.pojo.Game;
import uppa.project.pojo.Player;
import uppa.project.pojo.RecoveryPasswordToken;
import uppa.project.pojo.User;
import uppa.project.provider.EntityManagerProvider;
import uppa.project.database.dao.DAO;
import uppa.project.database.dao.DAOException;
import uppa.project.database.dao.jpa.DAO_JPA_Player;
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.pojo.Game;
import uppa.project.database.pojo.Player;
import uppa.project.database.pojo.User;
import uppa.project.database.dao.EntityManagerProvider;
import static org.junit.jupiter.api.Assertions.*;
@@ -8,11 +8,13 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import uppa.project.dao.DAO;
import uppa.project.dao.DAOException;
import uppa.project.pojo.RecoveryPasswordToken;
import uppa.project.pojo.User;
import uppa.project.provider.EntityManagerProvider;
import uppa.project.database.dao.DAO;
import uppa.project.database.dao.DAOException;
import uppa.project.database.dao.jpa.DAO_JPA_RecoveryPasswordToken;
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.pojo.RecoveryPasswordToken;
import uppa.project.database.pojo.User;
import uppa.project.database.dao.EntityManagerProvider;
import static org.junit.jupiter.api.Assertions.*;
@@ -6,10 +6,12 @@ import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import uppa.project.dao.DAO;
import uppa.project.dao.DAOException;
import uppa.project.pojo.User;
import uppa.project.provider.EntityManagerProvider;
import uppa.project.database.dao.DAO;
import uppa.project.database.dao.DAOException;
import uppa.project.database.dao.jpa.DAO_JPA_User;
import uppa.project.database.dao.jpa.Game_JPA_DAO_Factory;
import uppa.project.database.pojo.User;
import uppa.project.database.dao.EntityManagerProvider;
import static org.junit.jupiter.api.Assertions.*;
@@ -2,10 +2,11 @@ package uppa.project.dao.jpa;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import uppa.project.dao.DAO;
import uppa.project.dao.DAOException;
import uppa.project.pojo.User;
import uppa.project.provider.EntityManagerProvider;
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.User;
import uppa.project.database.dao.EntityManagerProvider;
import static org.junit.jupiter.api.Assertions.*;
@@ -2,6 +2,7 @@ package uppa.project.pojo;
import java.util.HashMap;
import org.junit.jupiter.api.Test;
import uppa.project.database.pojo.Card;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -2,6 +2,8 @@ package uppa.project.pojo;
import java.util.HashMap;
import org.junit.jupiter.api.Test;
import uppa.project.database.pojo.Card;
import uppa.project.database.pojo.Deck;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -8,6 +8,10 @@ import java.util.HashMap;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import uppa.project.database.pojo.Deck;
import uppa.project.database.pojo.Game;
import uppa.project.database.pojo.Player;
import uppa.project.database.pojo.User;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
@@ -6,6 +6,10 @@ import java.util.HashMap;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import uppa.project.database.pojo.Deck;
import uppa.project.database.pojo.Game;
import uppa.project.database.pojo.Player;
import uppa.project.database.pojo.User;
import static org.junit.jupiter.api.Assertions.*;
@@ -7,6 +7,8 @@ import java.util.HashMap;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import uppa.project.database.pojo.RecoveryPasswordToken;
import uppa.project.database.pojo.User;
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -9,6 +9,9 @@ import java.util.HashMap;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import uppa.project.database.pojo.Game;
import uppa.project.database.pojo.Player;
import uppa.project.database.pojo.User;
import static org.junit.jupiter.api.Assertions.*;
@@ -3,6 +3,7 @@ package uppa.project.provider;
import jakarta.persistence.EntityManager;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import uppa.project.database.dao.EntityManagerProvider;
import static org.junit.jupiter.api.Assertions.*;