From 7e53828bdf3a5bf86f24e85d5d05ed21a54f14c2 Mon Sep 17 00:00:00 2001 From: Santiago Botero <157855016+LePeanutButter@users.noreply.github.com> Date: Sat, 24 May 2025 20:10:14 -0500 Subject: [PATCH 1/3] fix(cors): set Access-Control-Allow-Origin correctly --- .../eci/cvds/prometeo/config/CorsConfig.java | 9 ++++---- .../prometeo/config/JwtRequestFilter.java | 5 ++++ .../cvds/prometeo/config/SecurityConfig.java | 23 ++++++++++++++++--- .../prometeo/controller/UserController.java | 8 +++++-- 4 files changed, 35 insertions(+), 10 deletions(-) diff --git a/src/main/java/edu/eci/cvds/prometeo/config/CorsConfig.java b/src/main/java/edu/eci/cvds/prometeo/config/CorsConfig.java index 3c84d21..831a40b 100644 --- a/src/main/java/edu/eci/cvds/prometeo/config/CorsConfig.java +++ b/src/main/java/edu/eci/cvds/prometeo/config/CorsConfig.java @@ -6,13 +6,12 @@ @Configuration public class CorsConfig implements WebMvcConfigurer { - @Override - public void addCorsMappings(@SuppressWarnings("null") CorsRegistry registry) { + public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") - .allowedOrigins("*") // Cambiar el origen al necesario - .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE") + .allowedOrigins("http://localhost:3000") + .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") - .allowCredentials(false); + .allowCredentials(true); } } \ No newline at end of file diff --git a/src/main/java/edu/eci/cvds/prometeo/config/JwtRequestFilter.java b/src/main/java/edu/eci/cvds/prometeo/config/JwtRequestFilter.java index 1f8e10d..1ca9458 100644 --- a/src/main/java/edu/eci/cvds/prometeo/config/JwtRequestFilter.java +++ b/src/main/java/edu/eci/cvds/prometeo/config/JwtRequestFilter.java @@ -28,6 +28,11 @@ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException { + if ("OPTIONS".equalsIgnoreCase(request.getMethod())) { + response.setStatus(HttpServletResponse.SC_OK); + return; + } + final String authHeader = request.getHeader("Authorization"); System.out.println("🔍 Checking Authorization header..."); diff --git a/src/main/java/edu/eci/cvds/prometeo/config/SecurityConfig.java b/src/main/java/edu/eci/cvds/prometeo/config/SecurityConfig.java index b28a9b2..7788b0e 100644 --- a/src/main/java/edu/eci/cvds/prometeo/config/SecurityConfig.java +++ b/src/main/java/edu/eci/cvds/prometeo/config/SecurityConfig.java @@ -7,6 +7,11 @@ import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; + +import java.util.List; @Slf4j @Configuration @@ -22,13 +27,12 @@ public SecurityConfig(JwtRequestFilter jwtRequestFilter) { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http + .cors(cors -> {}) .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(auth -> auth - .requestMatchers("/api/users/create").authenticated() - + .requestMatchers("/api/users/by-institutional-id/{institutionalId}").authenticated() .requestMatchers("/api/users/trainer/**").hasRole("TRAINER") - .anyRequest().hasAnyRole("TRAINER", "STUDENT", "ADMIN") ) .formLogin(form -> form.disable()) @@ -37,4 +41,17 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .addFilterBefore(new LoggingFilter(), JwtRequestFilter.class); return http.build(); } + + @Bean + public CorsConfigurationSource corsConfigurationSource() { + CorsConfiguration config = new CorsConfiguration(); + config.setAllowedOrigins(List.of("http://localhost:3000")); + config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS")); + config.setAllowedHeaders(List.of("*")); + config.setAllowCredentials(true); + + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + source.registerCorsConfiguration("/**", config); + return source; + } } \ No newline at end of file diff --git a/src/main/java/edu/eci/cvds/prometeo/controller/UserController.java b/src/main/java/edu/eci/cvds/prometeo/controller/UserController.java index 20d581e..ff906d8 100644 --- a/src/main/java/edu/eci/cvds/prometeo/controller/UserController.java +++ b/src/main/java/edu/eci/cvds/prometeo/controller/UserController.java @@ -56,7 +56,6 @@ */ @RestController @RequestMapping("/api/users") -@CrossOrigin(origins = "*") @Tag(name = "User Controller", description = "API for managing user profiles, physical tracking, goals, routines, and reservations") public class UserController { @@ -100,7 +99,12 @@ public ResponseEntity getUserById(@Parameter(description = "User ID") @Pat @ApiResponse(responseCode = "404", description = "User not found") public ResponseEntity getUserByInstitutionalId( @Parameter(description = "Institutional ID") @PathVariable String institutionalId) { - return ResponseEntity.ok(userService.getUserByInstitutionalId(institutionalId)); + try { + User user = userService.getUserByInstitutionalId(institutionalId); + return ResponseEntity.ok(user); + } catch (RuntimeException e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); + } } @GetMapping From 5ea795639c57e09048d1fe8ec9333cb6195cf0ac Mon Sep 17 00:00:00 2001 From: Santiago Botero <157855016+LePeanutButter@users.noreply.github.com> Date: Sun, 25 May 2025 12:08:03 -0500 Subject: [PATCH 2/3] fix(user): map institutionalId correctly to database column --- .../eci/cvds/prometeo/controller/UserController.java | 11 ++++++++--- src/main/java/edu/eci/cvds/prometeo/model/User.java | 2 +- .../cvds/prometeo/controller/UserControllerTest.java | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/edu/eci/cvds/prometeo/controller/UserController.java b/src/main/java/edu/eci/cvds/prometeo/controller/UserController.java index ff906d8..1fea9f4 100644 --- a/src/main/java/edu/eci/cvds/prometeo/controller/UserController.java +++ b/src/main/java/edu/eci/cvds/prometeo/controller/UserController.java @@ -90,20 +90,25 @@ public class UserController { @ApiResponse(responseCode = "200", description = "User found", content = @Content(schema = @Schema(implementation = User.class))) @ApiResponse(responseCode = "404", description = "User not found") public ResponseEntity getUserById(@Parameter(description = "User ID") @PathVariable String id) { - return ResponseEntity.ok(userService.getUserById(id)); + try { + User user = userService.getUserById(id); + return ResponseEntity.ok(user); + } catch (RuntimeException e) { + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); + } } @GetMapping("/by-institutional-id/{institutionalId}") @Operation(summary = "Get user by institutional ID", description = "Retrieves a user by their institutional identifier") @ApiResponse(responseCode = "200", description = "User found", content = @Content(schema = @Schema(implementation = User.class))) @ApiResponse(responseCode = "404", description = "User not found") - public ResponseEntity getUserByInstitutionalId( + public ResponseEntity getUserByInstitutionalId( @Parameter(description = "Institutional ID") @PathVariable String institutionalId) { try { User user = userService.getUserByInstitutionalId(institutionalId); return ResponseEntity.ok(user); } catch (RuntimeException e) { - return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null); + return ResponseEntity.status(HttpStatus.NOT_FOUND).body(e.getMessage()); } } diff --git a/src/main/java/edu/eci/cvds/prometeo/model/User.java b/src/main/java/edu/eci/cvds/prometeo/model/User.java index 486da33..f6e0fba 100644 --- a/src/main/java/edu/eci/cvds/prometeo/model/User.java +++ b/src/main/java/edu/eci/cvds/prometeo/model/User.java @@ -17,7 +17,7 @@ public class User extends BaseEntity { @GeneratedValue(strategy = GenerationType.AUTO) private UUID id; - @Column(name = "instutional_id", unique = true, nullable = false) + @Column(name = "institutional_id", unique = true, nullable = false) private String institutionalId; @Column(name = "name", nullable = false) diff --git a/src/test/java/edu/eci/cvds/prometeo/controller/UserControllerTest.java b/src/test/java/edu/eci/cvds/prometeo/controller/UserControllerTest.java index b414b6b..9dbf71a 100644 --- a/src/test/java/edu/eci/cvds/prometeo/controller/UserControllerTest.java +++ b/src/test/java/edu/eci/cvds/prometeo/controller/UserControllerTest.java @@ -87,7 +87,7 @@ void testGetUserById() { public void testGetUserByInstitutionalId() { when(userService.getUserByInstitutionalId(anyString())).thenReturn(testUser); - ResponseEntity response = userController.getUserByInstitutionalId("A12345"); + ResponseEntity response = (ResponseEntity) userController.getUserByInstitutionalId("A12345"); assertEquals(HttpStatus.OK, response.getStatusCode()); assertEquals(testUser, response.getBody()); From 9472624e684308112b751ac59cf2d2e22fc6cb2b Mon Sep 17 00:00:00 2001 From: Santiago Botero <157855016+LePeanutButter@users.noreply.github.com> Date: Sun, 25 May 2025 15:02:39 -0500 Subject: [PATCH 3/3] fix(auth): resolve permission issue for session queries --- src/main/java/edu/eci/cvds/prometeo/config/SecurityConfig.java | 2 +- .../java/edu/eci/cvds/prometeo/controller/UserController.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/edu/eci/cvds/prometeo/config/SecurityConfig.java b/src/main/java/edu/eci/cvds/prometeo/config/SecurityConfig.java index 7788b0e..cd31946 100644 --- a/src/main/java/edu/eci/cvds/prometeo/config/SecurityConfig.java +++ b/src/main/java/edu/eci/cvds/prometeo/config/SecurityConfig.java @@ -31,7 +31,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .csrf(csrf -> csrf.disable()) .authorizeHttpRequests(auth -> auth .requestMatchers("/api/users/create").authenticated() - .requestMatchers("/api/users/by-institutional-id/{institutionalId}").authenticated() + .requestMatchers("/api/users/trainer/sessions").hasAnyRole("STUDENT", "TRAINER") .requestMatchers("/api/users/trainer/**").hasRole("TRAINER") .anyRequest().hasAnyRole("TRAINER", "STUDENT", "ADMIN") ) diff --git a/src/main/java/edu/eci/cvds/prometeo/controller/UserController.java b/src/main/java/edu/eci/cvds/prometeo/controller/UserController.java index 1fea9f4..bd80607 100644 --- a/src/main/java/edu/eci/cvds/prometeo/controller/UserController.java +++ b/src/main/java/edu/eci/cvds/prometeo/controller/UserController.java @@ -867,7 +867,7 @@ public ResponseEntity cancelSession( @GetMapping("/trainer/sessions") @Operation(summary = "Get sessions by date", description = "Retrieves all gym sessions for a specific date") @ApiResponse(responseCode = "200", description = "Sessions retrieved successfully") - @PreAuthorize("hasRole('TRAINER') or hasRole('ADMIN')") + @PreAuthorize("hasRole('TRAINER') or hasRole('ADMIN') or hasRole('STUDENT')") public ResponseEntity> getSessionsByDate( @Parameter(description = "Date to check") @RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate date) {