diff --git a/Back-end/src/main/java/com/example/starter/AuthHandler.java b/Back-end/src/main/java/com/example/starter/AuthHandler.java index e3a31c3..68de2e4 100644 --- a/Back-end/src/main/java/com/example/starter/AuthHandler.java +++ b/Back-end/src/main/java/com/example/starter/AuthHandler.java @@ -30,8 +30,9 @@ public class AuthHandler { String email = body.getString("email"); String gender = body.getString("gender"); String password = body.getString("password"); + String pseudo = body.getString("pseudo"); - if (name == null || surname == null || email == null || gender == null || password == null) { + if (name == null || surname == null || email == null || gender == null || password == null || pseudo == null) { context.response() .setStatusCode(400) .end(new JsonObject().put("error", "Tous les champs sont requis").encode()); @@ -41,8 +42,8 @@ public class AuthHandler { String hashedPassword = BCrypt.withDefaults().hashToString(12, password.toCharArray()); databaseService.pool - .preparedQuery("INSERT INTO users (name, surname, email, gender, password) VALUES (?, ?, ?, ?, ?)") - .execute(Tuple.of(name, surname, email, gender, hashedPassword)) + .preparedQuery("INSERT INTO users (name, surname, email, gender, password, pseudo) VALUES (?, ?, ?, ?, ?, ?)") + .execute(Tuple.of(name, surname, email, gender, hashedPassword,pseudo)) .onSuccess(result -> { context.response() .setStatusCode(201) @@ -77,46 +78,55 @@ public class AuthHandler { } databaseService.pool - .preparedQuery("SELECT password,points FROM users WHERE email = ?") - .execute(Tuple.of(email)) - .onSuccess(result -> { - if (result.rowCount() == 0) { - context.response() - .setStatusCode(401) - .end(new JsonObject().put("error", "Email ou mot de passe incorrect").encode()); - return; - } + .preparedQuery("SELECT id,name, surname, password, points FROM users WHERE email = ?") // Ajout de name et surname + .execute(Tuple.of(email)) + .onSuccess(result -> { + if (result.rowCount() == 0) { + context.response() + .setStatusCode(401) + .end(new JsonObject().put("error", "Email ou mot de passe incorrect").encode()); + return; + } - String storedHashedPassword = result.iterator().next().getString("password"); - Integer nbPointsUser = result.iterator().next().getInteger("points"); + var row = result.iterator().next(); + Integer id = row.getInteger("id"); + String storedHashedPassword = row.getString("password"); + Integer nbPointsUser = row.getInteger("points"); + String name = row.getString("name"); + String surname = row.getString("surname"); - BCrypt.Result verification = BCrypt.verifyer().verify(password.toCharArray(), storedHashedPassword); + BCrypt.Result verification = BCrypt.verifyer().verify(password.toCharArray(), storedHashedPassword); - if (verification.verified) { - JsonObject claims = new JsonObject().put("sub", email); - if(nbPointsUser<=60){ - claims.put("role", "user"); - }else if(nbPointsUser<=100){ - claims.put("role", "complexe"); - }else if(nbPointsUser>=200){ - claims.put("role", "admin"); - } - - String token = jwtAuth.generateToken(claims); - context.response() - .setStatusCode(200) - .end(new JsonObject().put("token", token).encode()); - } else { - context.response() - .setStatusCode(401) - .end(new JsonObject().put("error", "Email ou mot de passe incorrect").encode()); - } - }) - .onFailure(err -> { - System.err.println("Erreur de connexion : " + err.getMessage()); - context.response() - .setStatusCode(500) - .end(new JsonObject().put("error", "Erreur serveur").encode()); - }); - } -} + if (verification.verified) { + JsonObject claims = new JsonObject() + .put("sub", email) + .put("name", name) + .put("surname", surname) + .put("id", id); + + if (nbPointsUser <= 60) { + claims.put("role", "user"); + } else if (nbPointsUser <= 100) { + claims.put("role", "complexe"); + } else if (nbPointsUser >= 200) { + claims.put("role", "admin"); + } + + String token = jwtAuth.generateToken(claims); + + context.response() + .setStatusCode(200) + .end(new JsonObject().put("token", token).encode()); + } else { + context.response() + .setStatusCode(401) + .end(new JsonObject().put("error", "Email ou mot de passe incorrect").encode()); + } + }) + .onFailure(err -> { + System.err.println("Erreur de connexion : " + err.getMessage()); + context.response() + .setStatusCode(500) + .end(new JsonObject().put("error", "Erreur serveur").encode()); + }); +}} \ No newline at end of file diff --git a/Back-end/src/main/java/com/example/starter/MainVerticle.java b/Back-end/src/main/java/com/example/starter/MainVerticle.java index b669774..fa171c3 100644 --- a/Back-end/src/main/java/com/example/starter/MainVerticle.java +++ b/Back-end/src/main/java/com/example/starter/MainVerticle.java @@ -43,11 +43,12 @@ public class MainVerticle extends AbstractVerticle { SetUser setUser = new SetUser(databaseService); setObjects.setUserHandler(setUser); queryObjects.setUserHandler(setUser); + setWeatherData.setUserHandler(setUser); // Déclaration des routes router.get("/objets").handler(queryObjects::getObjects); - router.get("/objet").handler(queryObjects::getParticularObject); + router.post("/objet").handler(queryObjects::getParticularObject); router.post("/modifObjet").handler(setObjects::setInfoObjet); router.get("/wind").handler(queryWeather::getWindInfos); router.get("/meteo").handler(queryWeather::getMeteoInfos); @@ -56,12 +57,17 @@ public class MainVerticle extends AbstractVerticle { router.post("/modifRangeData").handler(setWeatherData::setRangeData); router.post("/deleteObject").handler(setObjects::deleteObject); router.get("/users").handler(queryUsers::getUsers); + router.post("/user").handler(queryUsers::getUser); router.post("/setUserPoints").handler(setUser::setUserPoints); router.post("/deleteUser").handler(setUser::deleteUser); - + router.post("/updateProfil").handler(setUser::updateUserProfile); + router.post("/changePassword").handler(setUser::changeUserPassword); + router.post("/publicUser").handler(queryUsers::getPublicUser); + router.get("/getCategories").handler(queryObjects::getCategories); // Routes d'authentification router.post("/signup").handler(authHandler::handleSignup); router.post("/login").handler(authHandler::handleLogin); + // Création du serveur HTTP vertx.createHttpServer() diff --git a/Back-end/src/main/java/com/example/starter/QueryObjects.java b/Back-end/src/main/java/com/example/starter/QueryObjects.java index 029a497..abc5bca 100644 --- a/Back-end/src/main/java/com/example/starter/QueryObjects.java +++ b/Back-end/src/main/java/com/example/starter/QueryObjects.java @@ -40,10 +40,37 @@ public class QueryObjects { }); } + public void getCategories(RoutingContext context) { + databaseService.pool + .query("SELECT DISTINCT type FROM weather_objects;") + .execute() + .onFailure(e -> { + System.err.println("Erreur de récupération de la BDD :" + e.getMessage()); + context.response() + .setStatusCode(500) + .end(new JsonObject().put("error", "Erreur de récupération de la BDD").encode()); + }) + .onSuccess(rows -> { + JsonArray types = new JsonArray(); + rows.forEach(row -> types.add(row.getString("type"))); + + context.response() + .putHeader("content-type", "application/json; charset=UTF-8") + .end(types.encode()); + }); + } + public void getParticularObject(RoutingContext context) { - String id = context.request().getParam("id"); - // Integer idUser = body.getInteger("idUser"); - Integer idUser = 4; + JsonObject body = context.body().asJsonObject(); + if (body == null) { + context.response() + .setStatusCode(400) + .end(new JsonObject().put("error", "Corps de la requête manquant").encode()); + return; + } + String id = body.getString("id"); + + String idUser = body.getString("userId"); if (id == null) { context.response() .setStatusCode(400) @@ -66,10 +93,13 @@ public class QueryObjects { .end(new JsonObject().put("error", "Objet non trouvé").encode()); return; } - if (idUser != null) { - setUser.updateUserPoints(idUser, 1); + System.out.println(idUser); + + Boolean shouldUpdatePoints = body.getBoolean("shouldUpdatePoints", false); + + if (Boolean.TRUE.equals(shouldUpdatePoints) && idUser != null) { + setUser.updateUserPoints(Integer.parseInt(idUser), 1); } - ; context.response() .putHeader("content-type", "application/json: charset=UTF-8") .end(getInfosObjects(rows).encode()); @@ -91,7 +121,7 @@ public class QueryObjects { .put("status", row.getString("status")) .put("batterie", row.getInteger("batterie")) .put("type_batterie", row.getString("type_batterie")) - .put("proprio", row.getString("proprio")); + .put("proprio_id", row.getInteger("proprio_id")); objects.add(object); } return objects; diff --git a/Back-end/src/main/java/com/example/starter/QueryUsers.java b/Back-end/src/main/java/com/example/starter/QueryUsers.java index e065c02..792f575 100644 --- a/Back-end/src/main/java/com/example/starter/QueryUsers.java +++ b/Back-end/src/main/java/com/example/starter/QueryUsers.java @@ -4,6 +4,7 @@ import io.vertx.core.json.JsonArray; import io.vertx.core.json.JsonObject; import io.vertx.ext.web.RoutingContext; import io.vertx.sqlclient.Row; +import io.vertx.sqlclient.Tuple; public class QueryUsers { private DatabaseService databaseService; @@ -25,19 +26,20 @@ public class QueryUsers { .onSuccess(rows -> { JsonArray users = new JsonArray(); for (Row row : rows) { - int points=row.getInteger("points"); + int points = row.getInteger("points"); JsonObject user = new JsonObject() .put("id", row.getInteger("id")) .put("name", row.getString("name")) .put("surname", row.getString("surname")) .put("email", row.getString("email")) .put("gender", row.getString("gender")) - .put("points",points); - if(points<=60){ + .put("pseudo",row.getString("pseudo")) + .put("points", points); + if (points <= 60) { user.put("role", "user"); - }else if(points<=100){ + } else if (points <= 100) { user.put("role", "complexe"); - }else if(points>=200){ + } else if (points >= 200) { user.put("role", "admin"); } users.add(user); @@ -48,4 +50,102 @@ public class QueryUsers { }); } + + public void getUser(RoutingContext context) { + JsonObject body = context.body().asJsonObject(); + if (body == null) { + context.response() + .setStatusCode(400) + .end(new JsonObject().put("error", "Corps de la requête manquant").encode()); + return; + } + Integer idUser = body.getInteger("id"); + databaseService.pool + .preparedQuery("SELECT * FROM users WHERE id=?;") + .execute(Tuple.of(idUser)) + .onFailure(e -> { + System.err.println("Erreur de récupération de la BDD :" + e.getMessage()); + context.response() + .setStatusCode(500) + .end(new JsonObject().put("error", "Erreur de récupération de la BDD").encode()); + }) + .onSuccess(rows -> { + if (rows.size() == 0) { + context.response() + .setStatusCode(404) + .end(new JsonObject().put("error", "Utilisateur non trouvé").encode()); + return; + } + + Row row = rows.iterator().next(); + int points = row.getInteger("points"); + JsonObject user = new JsonObject() + .put("id", row.getInteger("id")) + .put("name", row.getString("name")) + .put("surname", row.getString("surname")) + .put("email", row.getString("email")) + .put("gender", row.getString("gender")) + .put("pseudo",row.getString("pseudo")) + .put("points", points); + + if (points <= 60) { + user.put("role", "user"); + } else if (points <= 100) { + user.put("role", "complexe"); + } else if (points >= 200) { + user.put("role", "admin"); + } + + context.response() + .putHeader("content-type", "application/json; charset=UTF-8") + .end(user.encode()); + }); + } + public void getPublicUser(RoutingContext context) { + JsonObject body = context.body().asJsonObject(); + if (body == null) { + context.response() + .setStatusCode(400) + .end(new JsonObject().put("error", "Corps de la requête manquant").encode()); + return; + } + Integer idUser = body.getInteger("id"); + databaseService.pool + .preparedQuery("SELECT * FROM users WHERE id=?;") + .execute(Tuple.of(idUser)) + .onFailure(e -> { + System.err.println("Erreur de récupération de la BDD :" + e.getMessage()); + context.response() + .setStatusCode(500) + .end(new JsonObject().put("error", "Erreur de récupération de la BDD").encode()); + }) + .onSuccess(rows -> { + if (rows.size() == 0) { + context.response() + .setStatusCode(404) + .end(new JsonObject().put("error", "Utilisateur non trouvé").encode()); + return; + } + + Row row = rows.iterator().next(); + int points = row.getInteger("points"); + JsonObject user = new JsonObject() + .put("id", row.getInteger("id")) + .put("gender", row.getString("gender")) + .put("pseudo",row.getString("pseudo")) + .put("points", points); + + if (points <= 60) { + user.put("role", "user"); + } else if (points <= 100) { + user.put("role", "complexe"); + } else if (points >= 200) { + user.put("role", "admin"); + } + + context.response() + .putHeader("content-type", "application/json; charset=UTF-8") + .end(user.encode()); + }); + } } diff --git a/Back-end/src/main/java/com/example/starter/SetObjects.java b/Back-end/src/main/java/com/example/starter/SetObjects.java index a1bb0e6..ad16b15 100644 --- a/Back-end/src/main/java/com/example/starter/SetObjects.java +++ b/Back-end/src/main/java/com/example/starter/SetObjects.java @@ -7,12 +7,15 @@ import io.vertx.sqlclient.Tuple; public class SetObjects { private DatabaseService databaseService; private SetUser setUser; + public SetObjects(DatabaseService ddbs) { this.databaseService = ddbs; } - public void setUserHandler(SetUser setUser){ + + public void setUserHandler(SetUser setUser) { this.setUser = setUser; } + public void setInfoObjet(RoutingContext context) { JsonObject body = context.body().asJsonObject(); if (body == null) { @@ -22,8 +25,7 @@ public class SetObjects { return; } Integer id = body.getInteger("id"); - // Integer idUser = body.getInteger("idUser"); - Integer idUser = 4; + Integer idUser = body.getInteger("idUser"); String description = body.getString("description"); String type = body.getString("type"); String location = body.getString("location"); @@ -46,88 +48,93 @@ public class SetObjects { .end(new JsonObject().put("error", "Objet non trouvé").encode()); return; } - if(idUser!=null){ - setUser.updateUserPoints(idUser,1); - }; + Boolean shouldUpdatePoints = body.getBoolean("shouldUpdatePoints", false); + + if (Boolean.TRUE.equals(shouldUpdatePoints) && idUser != null) { + setUser.updateUserPoints(idUser, 1); + } context.response() .putHeader("content-type", "application/json: charset=UTF-8") .end(new JsonObject().put("success", "L'objet à bien été mis à jour").encode()); return; }); } - public void deleteObject(RoutingContext context){ + + public void deleteObject(RoutingContext context) { JsonObject body = context.body().asJsonObject(); - if(body== null){ + if (body == null) { context.response() - .setStatusCode(400) - .end(new JsonObject().put("error","Corps de la requête manquant").encode()); + .setStatusCode(400) + .end(new JsonObject().put("error", "Corps de la requête manquant").encode()); return; } String id = body.getString("id"); databaseService.pool - .preparedQuery("DELETE FROM weather_objects WHERE id=?") - .execute(Tuple.of(Integer.parseInt(id))) - .onFailure(e->{ - System.err.println("Erreur de récupération de la BDD :"+e.getMessage()); - context.response() - .setStatusCode(500) - .end(new JsonObject().put("error","Erreur de récupération de la BDD").encode()); - }) - .onSuccess(rows -> { - if(rows.rowCount()==0){ + .preparedQuery("DELETE FROM weather_objects WHERE id=?") + .execute(Tuple.of(Integer.parseInt(id))) + .onFailure(e -> { + System.err.println("Erreur de récupération de la BDD :" + e.getMessage()); context.response() + .setStatusCode(500) + .end(new JsonObject().put("error", "Erreur de récupération de la BDD").encode()); + }) + .onSuccess(rows -> { + if (rows.rowCount() == 0) { + context.response() .setStatusCode(404) .end(new JsonObject().put("error", "Objet non trouvé").encode()); return; - } - context.response() - .putHeader("content-type","application/json: charset=UTF-8") - .end(new JsonObject().put("success", "L'objet à bien été supprimé").encode()); - return; - }); + } + context.response() + .putHeader("content-type", "application/json: charset=UTF-8") + .end(new JsonObject().put("success", "L'objet à bien été supprimé").encode()); + return; + }); } - public void newObject(RoutingContext context){ + + public void newObject(RoutingContext context) { JsonObject body = context.body().asJsonObject(); - if(body== null){ + if (body == null) { context.response() - .setStatusCode(400) - .end(new JsonObject().put("error","Corps de la requête manquant").encode()); + .setStatusCode(400) + .end(new JsonObject().put("error", "Corps de la requête manquant").encode()); return; } - // Integer idUser = body.getInteger("idUser"); - Integer idUser = 4; + Integer idUser = body.getInteger("proprio_id"); String name = body.getString("nom"); String description = body.getString("description"); String type = body.getString("type"); String location = body.getString("location"); String status = body.getString("status"); String batterieType = body.getString("batterieType"); - String proprio = body.getString("proprio"); + Integer proprio_id = body.getInteger("proprio_id"); databaseService.pool - .preparedQuery("INSERT INTO weather_objects (name,description,type,location,status,type_batterie,proprio) VALUES (?,?,?,?,?,?,?)") - .execute(Tuple.of(name,description,type,location,status,batterieType,proprio)) - .onFailure(e->{ - System.err.println("Erreur de récupération de la BDD :"+e.getMessage()); - context.response() - .setStatusCode(500) - .end(new JsonObject().put("error","Erreur de récupération de la BDD").encode()); - }) - .onSuccess(rows -> { - if(rows.rowCount()==0){ + .preparedQuery( + "INSERT INTO weather_objects (name,description,type,location,status,type_batterie,proprio_id) VALUES (?,?,?,?,?,?,?)") + .execute(Tuple.of(name, description, type, location, status, batterieType, proprio_id)) + .onFailure(e -> { + System.err.println("Erreur de récupération de la BDD :" + e.getMessage()); context.response() + .setStatusCode(500) + .end(new JsonObject().put("error", "Erreur de récupération de la BDD").encode()); + }) + .onSuccess(rows -> { + if (rows.rowCount() == 0) { + context.response() .setStatusCode(404) .end(new JsonObject().put("error", "Objet non trouvé").encode()); return; - } - if(idUser!=null){ - setUser.updateUserPoints(idUser,2); - }; - context.response() - .putHeader("content-type","application/json: charset=UTF-8") - .end(new JsonObject().put("success", "L'objet à bien été ajouté").encode()); - return; - }); + } + if (idUser != null) { + setUser.updateUserPoints(idUser, 2); + } + ; + context.response() + .putHeader("content-type", "application/json: charset=UTF-8") + .end(new JsonObject().put("success", "L'objet à bien été ajouté").encode()); + return; + }); } } diff --git a/Back-end/src/main/java/com/example/starter/SetUser.java b/Back-end/src/main/java/com/example/starter/SetUser.java index 6bcd9b2..47aa996 100644 --- a/Back-end/src/main/java/com/example/starter/SetUser.java +++ b/Back-end/src/main/java/com/example/starter/SetUser.java @@ -1,5 +1,6 @@ package com.example.starter; +import at.favre.lib.crypto.bcrypt.BCrypt; import io.vertx.core.json.JsonObject; import io.vertx.ext.web.RoutingContext; import io.vertx.sqlclient.Tuple; @@ -10,6 +11,7 @@ public class SetUser { public SetUser(DatabaseService ddbs) { this.databaseService = ddbs; } + public void updateUserPoints(Integer userId, Integer points) { databaseService.pool .preparedQuery("UPDATE users SET points=points+? WHERE id=?") @@ -25,6 +27,105 @@ public class SetUser { } }); } + + public void changeUserPassword(RoutingContext context) { + JsonObject body = context.body().asJsonObject(); + if (body == null) { + context.response() + .setStatusCode(400) + .end(new JsonObject().put("error", "Corps de la requête manquant").encode()); + return; + } + Integer id = body.getInteger("id"); + String oldPassword = body.getString("oldPassword"); + String newPassword = body.getString("newPassword"); + + databaseService.pool + .preparedQuery("SELECT password FROM users WHERE id=?") + .execute(Tuple.of(id)) + .onFailure(e -> { + System.err.println("Erreur de récupération de la BDD :" + e.getMessage()); + context.response() + .setStatusCode(500) + .end(new JsonObject().put("error", "Erreur de récupération de la BDD").encode()); + }) + .onSuccess(rows -> { + if (rows.rowCount() == 0) { + context.response() + .setStatusCode(404) + .end(new JsonObject().put("error", "Utilisateur non trouvé").encode()); + return; + } + + String currentPassword = rows.iterator().next().getString("password"); + BCrypt.Result verification = BCrypt.verifyer().verify(oldPassword.toCharArray(), currentPassword); + + if (!verification.verified) { + context.response() + .setStatusCode(401) + .end(new JsonObject().put("error", "Ancien mot de passe incorrect").encode()); + return; + } + String hashedPassword = BCrypt.withDefaults().hashToString(12, newPassword.toCharArray()); + + databaseService.pool + .preparedQuery("UPDATE users SET password=? WHERE id=?") + .execute(Tuple.of(hashedPassword, id)) + .onFailure(e -> { + System.err.println("Erreur lors de la mise à jour du mot de passe :" + e.getMessage()); + context.response() + .setStatusCode(500) + .end(new JsonObject() + .put("error", "Erreur lors de la mise à jour du mot de passe") + .encode()); + }) + .onSuccess(updateRows -> { + context.response() + .putHeader("content-type", "application/json: charset=UTF-8") + .end(new JsonObject().put("success", "Le mot de passe a bien été mis à jour") + .encode()); + }); + }); + } + + public void updateUserProfile(RoutingContext context) { + JsonObject body = context.body().asJsonObject(); + if (body == null) { + context.response() + .setStatusCode(400) + .end(new JsonObject().put("error", "Corps de la requête manquant").encode()); + return; + } + Integer id = body.getInteger("id"); + String name = body.getString("name"); + String surname = body.getString("surname"); + String pseudo = body.getString("pseudo"); + + databaseService.pool + .preparedQuery("UPDATE users SET name=?, surname=?, pseudo=? WHERE id=?") + .execute(Tuple.of(name, surname,pseudo, id)) + .onFailure(e -> { + System.err.println("Erreur de récupération de la BDD :" + e.getMessage()); + context.response() + .setStatusCode(500) + .end(new JsonObject().put("error", "Erreur de récupération de la BDD").encode()); + }) + .onSuccess(rows -> { + if (rows.rowCount() == 0) { + context.response() + .setStatusCode(404) + .end(new JsonObject().put("error", "Utilisateur non trouvé").encode()); + return; + } + context.response() + .putHeader("content-type", "application/json: charset=UTF-8") + .end(new JsonObject() + .put("success", "Les informations de l'utilisateur ont bien été mises à jour") + .encode()); + return; + }); + } + public void setUserPoints(RoutingContext context) { JsonObject body = context.body().asJsonObject(); if (body == null) { @@ -59,36 +160,37 @@ public class SetUser { return; }); } - public void deleteUser(RoutingContext context){ + + public void deleteUser(RoutingContext context) { JsonObject body = context.body().asJsonObject(); - if(body== null){ + if (body == null) { context.response() - .setStatusCode(400) - .end(new JsonObject().put("error","Corps de la requête manquant").encode()); + .setStatusCode(400) + .end(new JsonObject().put("error", "Corps de la requête manquant").encode()); return; } Integer id = body.getInteger("id"); databaseService.pool - .preparedQuery("DELETE FROM users WHERE id=?") - .execute(Tuple.of(id)) - .onFailure(e->{ - System.err.println("Erreur de récupération de la BDD :"+e.getMessage()); - context.response() - .setStatusCode(500) - .end(new JsonObject().put("error","Erreur de récupération de la BDD").encode()); - }) - .onSuccess(rows -> { - if(rows.rowCount()==0){ + .preparedQuery("DELETE FROM users WHERE id=?") + .execute(Tuple.of(id)) + .onFailure(e -> { + System.err.println("Erreur de récupération de la BDD :" + e.getMessage()); context.response() + .setStatusCode(500) + .end(new JsonObject().put("error", "Erreur de récupération de la BDD").encode()); + }) + .onSuccess(rows -> { + if (rows.rowCount() == 0) { + context.response() .setStatusCode(404) .end(new JsonObject().put("error", "Utilisateur non trouvé").encode()); return; - } - context.response() - .putHeader("content-type","application/json: charset=UTF-8") - .end(new JsonObject().put("success", "L'utilisateur à bien été supprimé").encode()); - return; - }); + } + context.response() + .putHeader("content-type", "application/json: charset=UTF-8") + .end(new JsonObject().put("success", "L'utilisateur à bien été supprimé").encode()); + return; + }); } } diff --git a/Back-end/src/main/java/com/example/starter/SetWeatherData.java b/Back-end/src/main/java/com/example/starter/SetWeatherData.java index d6ca45f..d998e73 100644 --- a/Back-end/src/main/java/com/example/starter/SetWeatherData.java +++ b/Back-end/src/main/java/com/example/starter/SetWeatherData.java @@ -13,8 +13,8 @@ public class SetWeatherData { this.databaseService = ddbs; } public void setUserHandler(SetUser setUser) { - this.setUser = setUser; - } + this.setUser = setUser; + } public void setRangeData(RoutingContext context) { JsonObject body = context.body().asJsonObject(); if (body == null) { @@ -41,8 +41,8 @@ public class SetWeatherData { return; } String query = String.format("UPDATE range_data SET %s_min=?, %s_max=? WHERE station_id=?", type, type); - // Integer idUser = body.getInteger("idUser"); - Integer idUser = 4; + Integer idUser = body.getInteger("idUser"); + System.out.println("User : "+idUser); databaseService.pool .preparedQuery( query) diff --git a/Front-end/package-lock.json b/Front-end/package-lock.json index d61485a..d7b9ad1 100644 --- a/Front-end/package-lock.json +++ b/Front-end/package-lock.json @@ -13,6 +13,7 @@ "@emotion/styled": "^11.14.0", "@mui/material": "^7.0.1", "axios": "^1.8.4", + "jwt-decode": "^4.0.0", "lucide-react": "^0.427.0", "react": "^18.3.1", "react-charts": "^3.0.0-beta.57", @@ -2070,7 +2071,6 @@ "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", "dev": true, - "license": "MIT", "engines": { "node": ">= 0.4" } @@ -2819,6 +2819,71 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-abstract": { + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-regex": "^1.2.1", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.0", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.18" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -3788,12 +3853,63 @@ "integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", "license": "ISC" }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "license": "MIT" }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-binary-path": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", @@ -4269,6 +4385,15 @@ "node": ">=4.0" } }, + "node_modules/jwt-decode": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", + "integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", diff --git a/Front-end/package.json b/Front-end/package.json index ca037c9..36bfe68 100644 --- a/Front-end/package.json +++ b/Front-end/package.json @@ -14,6 +14,7 @@ "@emotion/styled": "^11.14.0", "@mui/material": "^7.0.1", "axios": "^1.8.4", + "jwt-decode": "^4.0.0", "lucide-react": "^0.427.0", "react": "^18.3.1", "react-charts": "^3.0.0-beta.57", diff --git a/Front-end/src/App.jsx b/Front-end/src/App.jsx index 18df2c9..fbf874c 100644 --- a/Front-end/src/App.jsx +++ b/Front-end/src/App.jsx @@ -9,12 +9,12 @@ import Objet from "./pages/Gestion/Objet.jsx"; import AddObject from "./pages/Gestion/AddObject.jsx"; import Signup from "./pages/Signup.jsx"; import Login from "./pages/Login.jsx"; -import Settings from "./pages/Settings.jsx"; +import Profil from "./pages/Profil.jsx"; import Sidebar from "./pages/Admin/sidebar.jsx"; import User from "./pages/Admin/User.jsx"; import Dashboard from "./pages/Admin/Dashboard.jsx"; import AdminObjet from "./pages/Admin/AdminObjet.jsx"; -import ProtectedRoute from './ProtectedRoute.jsx'; // Correction de l'import +import ProtectedRoute from "./ProtectedRoute.jsx"; function App() { return ( @@ -23,19 +23,27 @@ function App() {
+ {/* Routes publiques */} } /> } /> - } />} /> - } />} /> - } />} /> } /> } /> - } />} /> - } /> - } /> - } /> - } /> - } />} /> + + {/* Routes protégées pour tous les utilisateurs connectés */} + } allowedRoles={['admin', 'complexe', 'user']} />} /> + } allowedRoles={['admin', 'complexe', 'user']} />} /> + } allowedRoles={['admin', 'complexe', 'user']} />} /> + + {/* Routes protégées pour les admins et complexes */} + } allowedRoles={['admin', 'complexe']} />} /> + } allowedRoles={['admin', 'complexe','user']} />} /> + + {/* Routes protégées pour tous les utilisateurs connectés */} + } allowedRoles={['admin', 'complexe', 'user']} />} /> + } allowedRoles={['admin', 'complexe', 'user']} />} /> + {/* Routes protégées pour les admins uniquement */} + } allowedRoles={['admin']} />} /> + } allowedRoles={['admin']} />} />
diff --git a/Front-end/src/AuthContext.jsx b/Front-end/src/AuthContext.jsx index ca5abc9..545e406 100644 --- a/Front-end/src/AuthContext.jsx +++ b/Front-end/src/AuthContext.jsx @@ -1,5 +1,6 @@ -// src/AuthContext.js import React, { createContext, useContext, useState, useEffect } from "react"; +import { jwtDecode } from "jwt-decode"; + // Créer le contexte const AuthContext = createContext(); @@ -7,22 +8,25 @@ const AuthContext = createContext(); // Hook pour accéder facilement au contexte export const useAuth = () => useContext(AuthContext); -// Fournisseur de contexte qui gère l'état du token +// Fournisseur de contexte qui gère l'état du token et de l'utilisateur export const AuthProvider = ({ children }) => { const [token, setToken] = useState(localStorage.getItem("token")); + const [user, setUser] = useState(null); - // Met à jour le token lorsque localStorage change + // Met à jour le token et décode l'utilisateur useEffect(() => { - const handleStorageChange = () => { - setToken(localStorage.getItem("token")); - }; - - window.addEventListener("storage", handleStorageChange); - - return () => { - window.removeEventListener("storage", handleStorageChange); - }; - }, []); + if (token) { + try { + const decoded = jwtDecode(token); + setUser(decoded); + } catch (error) { + console.error("Erreur lors du décodage du token:", error); + setUser(null); + } + } else { + setUser(null); + } + }, [token]); const login = (newToken) => { localStorage.setItem("token", newToken); @@ -32,10 +36,11 @@ export const AuthProvider = ({ children }) => { const logout = () => { localStorage.removeItem("token"); setToken(null); + setUser(null); }; return ( - + {children} ); diff --git a/Front-end/src/ProtectedRoute.jsx b/Front-end/src/ProtectedRoute.jsx index 9df0306..b329341 100644 --- a/Front-end/src/ProtectedRoute.jsx +++ b/Front-end/src/ProtectedRoute.jsx @@ -1,16 +1,20 @@ -import { useAuth } from './AuthContext'; // Utilisation du contexte d'authentification -import { Navigate } from 'react-router-dom'; // Utilisation de React Router pour la redirection - -function ProtectedRoute({ element }) { - const { token } = useAuth(); // Vérifier si un token existe, donc si l'utilisateur est authentifié +import React from "react"; +import { Navigate } from "react-router-dom"; +import { useAuth } from "./AuthContext"; // Utilisation du contexte d'authentification +function ProtectedRoute({ element, allowedRoles }) { + const { token, user } = useAuth(); // Vérifier si un token existe, donc si l'utilisateur est authentifié + // Si l'utilisateur n'est pas authentifié, redirigez-le vers la page de login if (!token) { return ; } - - // Si l'utilisateur est authentifié, permettez l'accès à la route - return element; + if(user){ + if (allowedRoles && !allowedRoles.includes(user?.role)) { + return ; + } + return element; + } } -export default ProtectedRoute; // Export de la fonction +export default ProtectedRoute; diff --git a/Front-end/src/components/AlertInactive.jsx b/Front-end/src/components/AlertInactive.jsx index 5f06a76..72df6b0 100644 --- a/Front-end/src/components/AlertInactive.jsx +++ b/Front-end/src/components/AlertInactive.jsx @@ -1,9 +1,11 @@ import React, {useState} from "react"; import { TriangleAlert,X } from "lucide-react"; +import { useAuth } from "../AuthContext"; function AlertInactive({affAlert,setAffAlert}) { + const { user } = useAuth(); return ( - (affAlert&&( + (affAlert&&(user?.role!=="user")&&(
@@ -182,19 +195,19 @@ function FormNewObject({ isAdmin }) {
setProprio(e.target.value)} + type="number" + value={proprio_id} + onChange={(e) => setProprio_id(e.target.value)} required - disabled={verif||!isAdmin} + disabled={verif || !isAdmin} />
diff --git a/Front-end/src/components/Header.jsx b/Front-end/src/components/Header.jsx index d510c46..48ca0c5 100644 --- a/Front-end/src/components/Header.jsx +++ b/Front-end/src/components/Header.jsx @@ -1,10 +1,10 @@ -import React, { useState } from "react"; -import { X, Menu, LogIn, UserPlus, LogOut, Settings } from "lucide-react"; +import React, { useState, useEffect } from "react"; +import { X, Menu, LogIn, UserPlus, LogOut, User } from "lucide-react"; import { Link } from "react-router-dom"; import { useAuth } from "../AuthContext"; function Header() { - const { token, logout } = useAuth(); + const { token, user, logout } = useAuth(); const [isMenuOpen, setIsMenuOpen] = useState(false); const [showAdminDropdown, setShowAdminDropdown] = useState(false); @@ -128,22 +128,44 @@ function Header() { ) : ( <> + {user?.role === "user" ? ( +
  • + setIsMenuOpen(false)} + className="text-gray-600 hover:text-indigo-600" + > + Visualisation + +
  • + ) : ( +
  • + setIsMenuOpen(false)} + className="text-gray-600 hover:text-indigo-600" + > + Gestion + +
  • + )}
  • setIsMenuOpen(false)} + to="/profil" + onClick={() => setIsMenuOpen(false)} className="flex items-center gap-2 text-gray-600 hover:text-indigo-600" > - - Paramètres + + Profil
  • - + )} { + console.log(user); + axios + .post(`${API_BASE_URL}/publicUser`, { + id: user, + }) + .then((response) => { + setuserInfo(response.data); + console.log("Modification réussie :", response.data); + }) + .catch((error) => { + console.error("Erreur lors de la modification :", error); + }); + },[user]); + + return ( +
    +
    +
    + +
    +

    Propriétaire

    +
    +
    +

    Pseudo :

    +

    {userInfo.pseudo}

    +
    + +
    +

    Genre :

    +

    {userInfo.gender}

    +
    + +
    +

    Nombre de points :

    +

    {userInfo.points}

    +
    +
    + ); +} + +export default UserInfosObject; diff --git a/Front-end/src/pages/Admin/AdminObjet.jsx b/Front-end/src/pages/Admin/AdminObjet.jsx index 3807719..7471ffb 100644 --- a/Front-end/src/pages/Admin/AdminObjet.jsx +++ b/Front-end/src/pages/Admin/AdminObjet.jsx @@ -205,7 +205,7 @@ function AdminObjet() { {obj.location} - {obj.proprio} + {obj.proprio_id} {obj.status} diff --git a/Front-end/src/pages/Gestion/Gestion.jsx b/Front-end/src/pages/Gestion/Gestion.jsx index dce1545..7967ffe 100644 --- a/Front-end/src/pages/Gestion/Gestion.jsx +++ b/Front-end/src/pages/Gestion/Gestion.jsx @@ -9,19 +9,21 @@ import { UserPlus, RadioTower, Binoculars, - Settings, BadgePlus, } from "lucide-react"; +import { useAuth } from "../../AuthContext"; function Gestion() { return (
    +

    Bienvenue dans le module Gestion.

    +

    - Ce module vous permet de gérer les capteur et stations connectés de France de manière simple et efficace. + Ce module vous permet de gérer les capteurs et stations connectés de France de manière simple et efficace.

    @@ -43,6 +45,7 @@ function Gestion() { Explorer les objets
    +
    diff --git a/Front-end/src/pages/Gestion/ObjectManagement.jsx b/Front-end/src/pages/Gestion/ObjectManagement.jsx index a7fedd2..3daf55d 100644 --- a/Front-end/src/pages/Gestion/ObjectManagement.jsx +++ b/Front-end/src/pages/Gestion/ObjectManagement.jsx @@ -1,14 +1,17 @@ import React from "react"; -import { Search, ArrowRight, RadioTower,Plus } from "lucide-react"; +import { Search, ArrowRight, RadioTower, Plus } from "lucide-react"; import { useEffect, useState } from "react"; import axios from "axios"; import { API_BASE_URL } from "../../config"; +import { useAuth } from "../../AuthContext"; function ObjectManagement() { + const {user} = useAuth(); const [searchQuery, setSearchQuery] = useState(""); const [activeFilter, setActiveFilter] = useState(""); const [objects, setObjects] = useState([]); - const [nbAffObject,setnbAffObject] = useState(6); + const [nbAffObject, setnbAffObject] = useState(6); + const filteredDATA = objects.filter((node) => { const matchesSearchQuery = searchQuery === "" || @@ -29,12 +32,13 @@ function ObjectManagement() { setObjects(response.data); }); }, []); + return (

    - Gestion des Objets connectés. + {(user?.role!=="user")?("Gestion"):("Visualisation")} des Objets connectés.

    @@ -51,10 +55,12 @@ function ObjectManagement() { onChange={(e) => setSearchQuery(e.target.value)} />
    -
    + + {/* Filtres responsifs - utilisation de flex-wrap et responsive spacing */} +
    -
    + + {/* Grille responsive pour les objets */} +
    {filteredDATA.length === 0 ? ( -

    Aucun objet trouvé

    +

    Aucun objet trouvé

    ) : ( - filteredDATA.slice(0,nbAffObject).map((object) => ( + filteredDATA.slice(0, nbAffObject).map((object) => (
    {object.status === "active" ? (
    @@ -143,14 +151,21 @@ function ObjectManagement() { )) )}
    - {(nbAffObject - - + +
    )}
    ); } -export default ObjectManagement; + +export default ObjectManagement; \ No newline at end of file diff --git a/Front-end/src/pages/Gestion/Objet.jsx b/Front-end/src/pages/Gestion/Objet.jsx index cd40f07..7b76169 100644 --- a/Front-end/src/pages/Gestion/Objet.jsx +++ b/Front-end/src/pages/Gestion/Objet.jsx @@ -12,7 +12,10 @@ import WindInfo from "../../components/WindInfo"; import MeteoInfos from "../../components/MeteoInfos"; import MeteoGraph from "../../components/MeteoGraph"; import BatterieInfo from "../../components/BatterieInfo"; +import { useAuth } from "../../AuthContext"; +import UserInfosObject from "../../components/UserInfosObject"; function Objet() { + const {user} =useAuth(); const identifiant = new URLSearchParams(window.location.search).get("id"); const [object, setObject] = useState({}); const [graphStates, setGraphStates] = useState({ @@ -28,12 +31,20 @@ function Objet() { humidity: useRef(null), wind: useRef(null), }; - useEffect(() => { - axios.get(`${API_BASE_URL}/objet?id=${identifiant}`).then((response) => { - setObject(response.data[0]); - }); - }, [identifiant]); + axios + .post(`${API_BASE_URL}/objet`, { + id: identifiant, + userId:user.id, + shouldUpdatePoints:true, + }) + .then((response) => { + setObject(response.data[0]); + }) + .catch((error) => { + console.error("Erreur lors de la récupération :", error); + }); + }, [user]); return object && object.id ? (
    @@ -61,6 +72,8 @@ function Objet() { graphRefs={graphRefs} /> + +
    {graphStates.wind && } diff --git a/Front-end/src/pages/Home.jsx b/Front-end/src/pages/Home.jsx index 885b92b..83dfd9d 100644 --- a/Front-end/src/pages/Home.jsx +++ b/Front-end/src/pages/Home.jsx @@ -8,6 +8,7 @@ function Home() { const [activeFilter, setActiveFilter] = useState('all'); const [name, setName] = useState([]); const { token, logout } = useAuth(); + const { user } = useAuth(); return (
    @@ -15,10 +16,15 @@ function Home() {

    Bienvenue dans ta ville intelligente.

    - {token ? ( - <>

    Tu es connecté

    + {user ? ( + <> +

    Bienvenue, {user.name} {user.surname}!

    +

    Email : {user.sub}

    +

    Rôle : {user.role}

    +

    Rôle : {user.id}

    - ):( + + ):(

    Non connecté

    )}

    diff --git a/Front-end/src/pages/Login.jsx b/Front-end/src/pages/Login.jsx index 7a06d01..8eca535 100644 --- a/Front-end/src/pages/Login.jsx +++ b/Front-end/src/pages/Login.jsx @@ -1,7 +1,7 @@ import React, { useState } from "react"; -import { Mail, Lock } from "lucide-react"; +import { Mail, Lock, AlertCircle } from "lucide-react"; import { useNavigate, Link } from "react-router-dom"; -import axios from "axios"; // Assurez-vous d'avoir axios importé +import axios from "axios"; import { useAuth } from "../AuthContext"; import { API_BASE_URL } from "../config"; @@ -10,8 +10,9 @@ function Login() { email: "", password: "", }); - const { login } = useAuth(); // Utilisation du hook useAuth pour accéder à la fonction login - const navigate = useNavigate(); // Initialisation de useNavigate + const [error, setError] = useState(""); + const { login } = useAuth(); + const navigate = useNavigate(); const handleChange = (e) => { const { name, value } = e.target; @@ -19,43 +20,68 @@ function Login() { ...prev, [name]: value, })); + if (error) setError(""); }; const handleSubmit = async (e) => { e.preventDefault(); + setError(""); try { - const response = await fetch(`${API_BASE_URL}/login`, { - method: "POST", + const response = await axios.post(`${API_BASE_URL}/login`, formData, { headers: { "Content-Type": "application/json", }, - body: JSON.stringify(formData), }); + const data = response.data; - // Récupérer les données JSON de la réponse - const data = await response.json(); - - // Vérifiez que la réponse contient bien un token if (data.token) { - // Appel de la fonction login du contexte pour stocker le token login(data.token); - - // Rediriger vers la page d'accueil après la connexion navigate("/"); } else { - console.error("Token manquant dans la réponse"); + setError("Authentification échouée : token manquant dans la réponse"); } } catch (error) { console.error("Erreur lors de la connexion", error); + + if (error.response) { + if (error.response.status === 401) { + setError("Email ou mot de passe incorrect"); + } else if (error.response.status === 422) { + setError("Données de formulaire invalides"); + } else if (error.response.status >= 500) { + setError("Erreur serveur. Veuillez réessayer plus tard."); + } else { + setError( + error.response.data.message || + "Une erreur s'est produite lors de la connexion" + ); + } + } else if (error.request) { + setError( + "Impossible de joindre le serveur. Vérifiez votre connexion internet." + ); + } else { + setError("Une erreur s'est produite. Veuillez réessayer."); + } } }; + return (

    Connexion

    + + {/* Message d'erreur */} + {error && ( +
    + + {error} +
    + )} +
    {/* Email */}
    @@ -94,6 +120,7 @@ function Login() { className="pl-10 block w-full rounded-lg border-gray-300 border p-2.5 focus:ring-2 focus:ring-indigo-500 focus:border-indigo-500" required minLength="8" + autoComplete="current-password" />
    diff --git a/Front-end/src/pages/Profil.jsx b/Front-end/src/pages/Profil.jsx new file mode 100644 index 0000000..fc1d89d --- /dev/null +++ b/Front-end/src/pages/Profil.jsx @@ -0,0 +1,328 @@ +import React, { useState, useEffect } from 'react'; +import { Mail, User, Lock, Edit, Save } from 'lucide-react'; +import { useNavigate } from 'react-router-dom'; +import { API_BASE_URL } from "../config"; +import { useAuth } from "../AuthContext"; +import axios from "axios"; + +function Profil() { + const [userData, setUserData] = useState({}); + + const { user } = useAuth(); + useEffect(() => { + if (user) { + console.log("user.role:", user.id); + } + }, [user]); + const [formData, setFormData] = useState({ + oldPassword: '', + newPassword: '', + confirmPassword: '' + }); + + const [editMode, setEditMode] = useState(false); + const [errorMessage, setErrorMessage] = useState(''); + const [successMessage, setSuccessMessage] = useState(''); + const navigate = useNavigate(); + + useEffect(() => { + axios + .post(`${API_BASE_URL}/user`, { + id: user.id, + }) + .then((response) => { + setUserData(response.data); + console.log("Infos récupérées :", response.data); + }) + .catch((error) => { + console.error("Erreur lors de la récupération :", error); + }); + }, [user]); + + const handleChange = (e) => { + const { name, value } = e.target; + setFormData(prev => ({ + ...prev, + [name]: value + })); + }; + + const handleProfileChange = (e) => { + const { name, value } = e.target; + setUserData(prev => ({ + ...prev, + [name]: value + })); + }; + + const handleSubmit = async (e) => { + e.preventDefault(); + setErrorMessage(''); + setSuccessMessage(''); + + if (formData.newPassword !== formData.confirmPassword) { + setErrorMessage("Les nouveaux mots de passe ne correspondent pas !"); + return; + } + + try { + axios + .post(`${API_BASE_URL}/changePassword`, { + id: userData.id, + oldPassword: formData.oldPassword, + newPassword: formData.newPassword + }) + .then((response) => { + console.log("Modification du mot de passe réussie :", response.data); + setSuccessMessage("Mot de passe modifié avec succès !"); + setFormData({ + oldPassword: '', + newPassword: '', + confirmPassword: '' + }); + }) + .catch((error) => { + console.error("Erreur lors de la modification du mot de passe :", error); + setErrorMessage(error.response?.data?.error || "Une erreur est survenue"); + }); + + setSuccessMessage("Mot de passe modifié avec succès !"); + setFormData({ + oldPassword: '', + newPassword: '', + confirmPassword: '' + }); + } catch (error) { + setErrorMessage(error.message || "Une erreur est survenue"); + } + }; + + const handleProfileSubmit = async (e) => { + e.preventDefault(); + setErrorMessage(''); + setSuccessMessage(''); + + axios + .post(`${API_BASE_URL}/updateProfil`, { + id: userData.id, + name: userData.name, + surname: userData.surname, + pseudo:userData.pseudo, + email: userData.email + }) + + .catch((error) => { + console.error("Erreur lors de la mise à jour du profil :", error); + setErrorMessage(error.response?.data?.error || "Une erreur est survenue"); + }) + .then((response) => { + console.log("Mise à jour du profil réussie :", response.data); + setSuccessMessage("Profil mis à jour avec succès !"); + setEditMode(false); + }); + }; + + return ( +
    +
    +

    Mon Profil

    + + {errorMessage && ( +
    + {errorMessage} +
    + )} + + {successMessage && ( +
    + {successMessage} +
    + )} + +
    + {/* Informations du profil */} +
    +
    +

    Informations Personnelles

    + +
    + + +
    +
    + +
    +
    +

    {userData.name} {userData.surname} ({userData.pseudo})

    +

    {userData.email}

    +
    +
    + +
    +

    Points de fidélité: {userData.points} ({userData.role})

    +
    + + {editMode ? ( + <> +
    + + +
    + +
    + + +
    +
    + + +
    + +
    + +
    +
    + +
    + +
    +
    + + + + ) : ( +
    +
    +

    Prénom

    +

    {userData.name}

    +
    +
    +

    Nom

    +

    {userData.surname}

    +
    +
    +

    Pseudo

    +

    {userData.pseudo}

    +
    +
    +

    Email

    +

    {userData.email}

    +
    +
    + )} + +
    + + {/* Changement de mot de passe */} +
    +

    Modifier le mot de passe

    +
    +
    + +
    +
    + +
    + +
    +
    + +
    + +
    +
    + +
    + +
    +
    + +
    + +
    +
    + +
    + +
    +
    + + +
    +
    +
    +
    +
    + ); +} + +export default Profil; \ No newline at end of file diff --git a/Front-end/src/pages/Settings.jsx b/Front-end/src/pages/Settings.jsx deleted file mode 100644 index 924a6b4..0000000 --- a/Front-end/src/pages/Settings.jsx +++ /dev/null @@ -1,161 +0,0 @@ -import React, { useState } from 'react'; -import { Mail, User, Lock } from 'lucide-react'; -import { useNavigate, Link} from 'react-router-dom'; // Importation du hook useNavigate - -function Settings() { - const [formData, setFormData] = useState({ - name: '', - surname: '', - email: '', - gender: '', - password: '', - confirmPassword: '' - }); - const navigate = useNavigate(); // Initialisation de useNavigate - - const handleChange = (e) => { - const { name, value } = e.target; - setFormData(prev => ({ - ...prev, - [name]: value - })); - }; - - const handleSubmit = async (e) => { - e.preventDefault(); - - if (formData.password !== formData.confirmPassword) { - alert("Les mots de passe ne correspondent pas !"); - return; - } - - try { - const response = await fetch(`${API_BASE_URL}/settings`, { - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify(formData), - }); - - const data = await response.json(); - - if (!response.ok) { - throw new Error(data.error || "Erreur lors de la modification"); - } - - alert("Modification réussie !"); - - // Redirection vers la page d'accueil après une inscription réussie - navigate("/home"); // Remplace "/home" par l'URL de ta page d'accueil - } catch (error) { - alert(error.message); - } - }; - - return ( -
    -
    -

    Settings

    -
    - {/* (Formulaire changement Email, Mot de passe) */} - - - - {/* Email */} -
    - -
    -
    - -
    - -
    -
    - - {/* Mot de passe */} -
    - -
    -
    - -
    - -
    -
    - - {/* nouveau mot de passe */} -
    - -
    -
    - -
    - -
    -
    -
    - -
    -
    - -
    - -
    -
    - {/* Bouton d'inscription */} -
    - -
    -
    - -
    -
    - ); -} - -export default Settings; diff --git a/Front-end/src/pages/Signup.jsx b/Front-end/src/pages/Signup.jsx index e18140f..c6703db 100644 --- a/Front-end/src/pages/Signup.jsx +++ b/Front-end/src/pages/Signup.jsx @@ -7,6 +7,7 @@ function Signup() { const [formData, setFormData] = useState({ name: '', surname: '', + pseudo:'', email: '', gender: '', password: '', @@ -62,7 +63,7 @@ function Signup() { {/* Formulaire (Nom, Prénom, Sexe, Email, Mot de passe) */}
    @@ -81,7 +82,7 @@ function Signup() {
    @@ -98,6 +99,25 @@ function Signup() {
    +
    + +
    +
    + +
    + +
    +
    + {/* Sexe */}