From 364a6ee65ae6ca8574b313fa1451d67353d42aad Mon Sep 17 00:00:00 2001
From: hugcubi <hugo.cubino@estudiantes.uva.es>
Date: Wed, 25 Dec 2024 23:11:13 +0100
Subject: [PATCH] Mejora del manejo de errores en users y auth

---
 .../java/com/uva/api/auth/api/UserAPI.java    | 14 +++----
 .../api/auth/controllers/AuthController.java  | 19 +---------
 .../exceptions/GlobalExceptionHandler.java    | 32 ++++++++++++++++
 .../uva/api/auth/services/AuthService.java    | 38 +++++++++----------
 .../exceptions/GlobalExceptionHandler.java    | 10 +++++
 .../users/repositories/UserRepository.java    |  2 +
 .../api/users/services/ManagerService.java    |  1 -
 .../uva/api/users/services/UserService.java   |  5 +++
 8 files changed, 76 insertions(+), 45 deletions(-)
 create mode 100644 java/services/auth/src/main/java/com/uva/api/auth/exceptions/GlobalExceptionHandler.java

diff --git a/java/services/auth/src/main/java/com/uva/api/auth/api/UserAPI.java b/java/services/auth/src/main/java/com/uva/api/auth/api/UserAPI.java
index 57f661e..b41d97f 100644
--- a/java/services/auth/src/main/java/com/uva/api/auth/api/UserAPI.java
+++ b/java/services/auth/src/main/java/com/uva/api/auth/api/UserAPI.java
@@ -55,14 +55,14 @@ public class UserAPI {
    */
   public User registerUser(RegisterRequest registerRequest) {
     String url = USER_API_URL;
-    System.out.println(url + " " + registerRequest);
-    ResponseEntity<User> userResponse = restTemplate.postForEntity(url, registerRequest, User.class);
-    if (!userResponse.getStatusCode().is2xxSuccessful()) {
-      String errorMessage = "Failed to register user: " + userResponse.getStatusCode() + ". " + userResponse.getBody();
-      throw new HttpClientErrorException(userResponse.getStatusCode(), errorMessage);
+    try {
+      ResponseEntity<User> userResponse = restTemplate.postForEntity(url, registerRequest, User.class);
+      return userResponse.getBody();
+    } catch (HttpClientErrorException ex) {
+      if (ex.getStatusCode() == HttpStatus.BAD_REQUEST)
+        throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, "Register failed");
+      throw ex;
     }
-
-    return userResponse.getBody();
   }
 
   /**
diff --git a/java/services/auth/src/main/java/com/uva/api/auth/controllers/AuthController.java b/java/services/auth/src/main/java/com/uva/api/auth/controllers/AuthController.java
index ceda96e..f84a840 100644
--- a/java/services/auth/src/main/java/com/uva/api/auth/controllers/AuthController.java
+++ b/java/services/auth/src/main/java/com/uva/api/auth/controllers/AuthController.java
@@ -6,7 +6,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.*;
-import org.springframework.web.client.HttpClientErrorException;
 
 import com.uva.api.auth.models.auth.LoginRequest;
 import com.uva.api.auth.models.auth.RegisterRequest;
@@ -25,26 +24,12 @@ public class AuthController {
 
     @PostMapping("/login")
     public ResponseEntity<?> login(@RequestBody LoginRequest loginRequest) {
-        try {
-            return authService.login(loginRequest);
-        } catch (HttpClientErrorException e) {
-            if (e.getStatusCode() == HttpStatus.FORBIDDEN) {
-                return new ResponseEntity<>(e.getMessage(), HttpStatus.FORBIDDEN);
-            }
-        }
-        return new ResponseEntity<>("Algo no fue bien", HttpStatus.UNAUTHORIZED);
+        return authService.login(loginRequest);
     }
 
     @PostMapping("/register")
     public ResponseEntity<?> register(@RequestBody RegisterRequest registerRequest) {
-        try {
-            return authService.register(registerRequest);
-        } catch (HttpClientErrorException e) {
-            if (e.getStatusCode() == HttpStatus.CONFLICT)
-                return new ResponseEntity<>(e.getMessage(), HttpStatus.CONFLICT);
-        }
-
-        return new ResponseEntity<>("Algo no fue bien", HttpStatus.UNAUTHORIZED);
+        return authService.register(registerRequest);
     }
 
     @PostMapping("/password")
diff --git a/java/services/auth/src/main/java/com/uva/api/auth/exceptions/GlobalExceptionHandler.java b/java/services/auth/src/main/java/com/uva/api/auth/exceptions/GlobalExceptionHandler.java
new file mode 100644
index 0000000..f82af24
--- /dev/null
+++ b/java/services/auth/src/main/java/com/uva/api/auth/exceptions/GlobalExceptionHandler.java
@@ -0,0 +1,32 @@
+package com.uva.api.auth.exceptions;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.web.bind.annotation.ControllerAdvice;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.client.HttpClientErrorException;
+
+import java.time.LocalDateTime;
+import java.util.HashMap;
+import java.util.Map;
+
+@ControllerAdvice
+public class GlobalExceptionHandler {
+  @ExceptionHandler(HttpClientErrorException.class)
+  public ResponseEntity<Map<String, Object>> handleHttpClientErrorException(HttpClientErrorException ex) {
+    Map<String, Object> body = new HashMap<>();
+    body.put("timestamp", LocalDateTime.now());
+    body.put("message", ex.getMessage());
+
+    return new ResponseEntity<>(body, ex.getStatusCode());
+  }
+
+  @ExceptionHandler(Exception.class)
+  public ResponseEntity<Map<String, Object>> handleGeneralException(Exception ex) {
+    Map<String, Object> body = new HashMap<>();
+    body.put("timestamp", LocalDateTime.now());
+    body.put("message", "An unexpected error occurred: " + ex.getMessage());
+
+    return new ResponseEntity<>(body, HttpStatus.INTERNAL_SERVER_ERROR);
+  }
+}
diff --git a/java/services/auth/src/main/java/com/uva/api/auth/services/AuthService.java b/java/services/auth/src/main/java/com/uva/api/auth/services/AuthService.java
index 1449758..5cf22ae 100644
--- a/java/services/auth/src/main/java/com/uva/api/auth/services/AuthService.java
+++ b/java/services/auth/src/main/java/com/uva/api/auth/services/AuthService.java
@@ -79,7 +79,7 @@ public class AuthService {
   public ResponseEntity<?> changePassword(String token, String actualPass, String newPass) {
     JwtData decoded = jwtUtil.decodeToken(token);
     if (decoded == null)
-      return new ResponseEntity<>(HttpStatus.FORBIDDEN);
+      throw new HttpClientErrorException(HttpStatus.FORBIDDEN);
 
     String email = decoded.getEmail();
     User user = getUser(email, actualPass);
@@ -87,23 +87,22 @@ public class AuthService {
     boolean changePasswordAllowed = decoded.isAdmin() || user != null;
 
     if (user != null && !validStrings(actualPass, newPass))
-      return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
-
-    if (changePasswordAllowed) {
-      // Actualizamos la nueva
-      String hashPass = SecurityUtils.encrypt(newPass);
-      userAPI.changePassword(user, hashPass);
-      // Hacemos un login con los nuevos datos
-      return login(new LoginRequest(email, newPass));
-    } else {
-      return new ResponseEntity<>("Invalid credentials", HttpStatus.FORBIDDEN);
-    }
+      throw new HttpClientErrorException(HttpStatus.BAD_REQUEST);
+
+    if (!changePasswordAllowed)
+      throw new HttpClientErrorException(HttpStatus.FORBIDDEN, "Invalid credentials");
+
+    // Actualizamos la nueva
+    String hashPass = SecurityUtils.encrypt(newPass);
+    userAPI.changePassword(user, hashPass);
+    // Hacemos un login con los nuevos datos
+    return login(new LoginRequest(email, newPass));
   }
 
   public ResponseEntity<?> deleteUser(String token, int id, String password) {
     JwtData decoded = jwtUtil.decodeToken(token);
     if (decoded == null)
-      return new ResponseEntity<>(HttpStatus.FORBIDDEN);
+      throw new HttpClientErrorException(HttpStatus.FORBIDDEN);
 
     String email = decoded.getEmail();
     User user = getUser(email, password);
@@ -112,13 +111,12 @@ public class AuthService {
         || (user != null && user.getId() == id);
 
     if (user != null && !validStrings(password))
-      return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
+      throw new HttpClientErrorException(HttpStatus.BAD_REQUEST);
 
-    if (changePasswordAllowed) {
-      userAPI.deleteUser(user);
-      return new ResponseEntity<>(HttpStatus.OK);
-    } else {
-      return new ResponseEntity<>("Invalid credentials", HttpStatus.FORBIDDEN);
-    }
+    if (!changePasswordAllowed)
+      throw new HttpClientErrorException(HttpStatus.FORBIDDEN, "Invalid credentials");
+
+    userAPI.deleteUser(user);
+    return ResponseEntity.ok(user);
   }
 }
diff --git a/java/services/users/src/main/java/com/uva/api/users/exceptions/GlobalExceptionHandler.java b/java/services/users/src/main/java/com/uva/api/users/exceptions/GlobalExceptionHandler.java
index 4241b4d..f7e1e6f 100644
--- a/java/services/users/src/main/java/com/uva/api/users/exceptions/GlobalExceptionHandler.java
+++ b/java/services/users/src/main/java/com/uva/api/users/exceptions/GlobalExceptionHandler.java
@@ -4,6 +4,7 @@ import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.client.HttpClientErrorException;
 
 import java.time.LocalDateTime;
 import java.util.HashMap;
@@ -21,6 +22,15 @@ public class GlobalExceptionHandler {
         return new ResponseEntity<>(body, HttpStatus.NOT_FOUND);
     }
 
+    @ExceptionHandler(HttpClientErrorException.class)
+    public ResponseEntity<Map<String, Object>> handleHttpClientErrorException(HttpClientErrorException ex) {
+        Map<String, Object> body = new HashMap<>();
+        body.put("timestamp", LocalDateTime.now());
+        body.put("message", ex.getMessage());
+
+        return new ResponseEntity<>(body, ex.getStatusCode());
+    }
+
     @ExceptionHandler(Exception.class)
     public ResponseEntity<Map<String, Object>> handleGeneralException(Exception ex) {
         Map<String, Object> body = new HashMap<>();
diff --git a/java/services/users/src/main/java/com/uva/api/users/repositories/UserRepository.java b/java/services/users/src/main/java/com/uva/api/users/repositories/UserRepository.java
index 94c7526..bf5e152 100644
--- a/java/services/users/src/main/java/com/uva/api/users/repositories/UserRepository.java
+++ b/java/services/users/src/main/java/com/uva/api/users/repositories/UserRepository.java
@@ -8,4 +8,6 @@ import com.uva.api.users.models.User;
 
 public interface UserRepository extends JpaRepository<User, Integer> {
   Optional<User> findByEmail(String email);
+
+  Boolean existsByEmail(String email);
 }
diff --git a/java/services/users/src/main/java/com/uva/api/users/services/ManagerService.java b/java/services/users/src/main/java/com/uva/api/users/services/ManagerService.java
index 9c9dba2..bc776e6 100644
--- a/java/services/users/src/main/java/com/uva/api/users/services/ManagerService.java
+++ b/java/services/users/src/main/java/com/uva/api/users/services/ManagerService.java
@@ -5,7 +5,6 @@ import java.util.List;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-
 import com.uva.api.users.api.HotelApi;
 import com.uva.api.users.models.Manager;
 import com.uva.api.users.models.User;
diff --git a/java/services/users/src/main/java/com/uva/api/users/services/UserService.java b/java/services/users/src/main/java/com/uva/api/users/services/UserService.java
index bf2d04f..1a7cd8b 100644
--- a/java/services/users/src/main/java/com/uva/api/users/services/UserService.java
+++ b/java/services/users/src/main/java/com/uva/api/users/services/UserService.java
@@ -4,8 +4,10 @@ import java.util.List;
 
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
+import org.springframework.web.client.HttpClientErrorException;
 
 import com.uva.api.users.models.AuthDTO;
 import com.uva.api.users.models.User;
@@ -47,6 +49,9 @@ public class UserService {
   }
 
   public ResponseEntity<User> registerNewUser(AuthDTO request) {
+    if (userRepository.existsByEmail(request.getEmail()))
+      throw new HttpClientErrorException(HttpStatus.BAD_REQUEST);
+
     User user = new User();
     BeanUtils.copyProperties(request, user);
 
-- 
GitLab