Skip to content
Snippets Groups Projects
Commit a001f2c7 authored by migudel's avatar migudel :speech_balloon:
Browse files

Comprobación de integridad y testeo

parent 808556a3
Branches
Tags
1 merge request!36Develop
Showing
with 228 additions and 53 deletions
......@@ -61,7 +61,7 @@ public class AuthController {
return authService.changePassword(token, actualPassword, newPassword);
}
@PostMapping("/delete/{id}")
@DeleteMapping("/delete/{id}")
public Object postMethodName(@PathVariable int id, @RequestBody Map<String, String> json,
@RequestHeader(value = "Authorization", required = true) String authorization) {
if (authorization == null || !authorization.startsWith("Bearer "))
......
......@@ -116,7 +116,7 @@ public class AuthService {
if (changePasswordAllowed) {
userAPI.deleteUser(user);
return new ResponseEntity<>(HttpStatus.ACCEPTED);
return new ResponseEntity<>(HttpStatus.OK);
} else {
return new ResponseEntity<>("Invalid credentials", HttpStatus.FORBIDDEN);
}
......
spring.application.name=authService
spring.application.name=authentication
server.port=8101
security.jwt.secret-key=MiClaveDeSeguridadMuyLargaParaQueNoFalleSpringBoot
......
package com.uva.roomBooking;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class RoomBookingApplicationTests {
@Test
void contextLoads() {
}
}
......@@ -192,7 +192,7 @@ public class BookingService {
throw new HttpClientErrorException(HttpStatus.BAD_REQUEST);
}
if (bookings.isEmpty()) {
throw new HttpClientErrorException(HttpStatus.BAD_REQUEST, message);
throw new HttpClientErrorException(HttpStatus.NOT_FOUND, message);
}
return ResponseEntity.ok(bookings);
}
......
package com.uva.api;
package com.uva.api.hotels;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
......
package com.uva.api.apis;
package com.uva.api.hotels.apis;
import java.time.LocalDate;
import java.util.HashSet;
......@@ -7,7 +7,9 @@ import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestTemplate;
@Component
......@@ -16,14 +18,9 @@ public class BookingAPI {
@Autowired
private RestTemplate restTemplate;
@Value("${external.services.bookings.url}")
@Value("${services.external.bookings.url}")
private String BOOKING_API_URL;
public void deleteAllByHotelId(Integer id) {
String url = BOOKING_API_URL + "?hotelId={id}";
restTemplate.delete(url, id);
}
public Set<Integer> getNotAvailableRooms(LocalDate start, LocalDate end) {
String url = BOOKING_API_URL + "?start={start}&end={end}";
Map<?, ?>[] bookingsArray = restTemplate
......@@ -46,8 +43,23 @@ public class BookingAPI {
return notAvailableRooms;
}
public void deleteAllByHotelId(Integer id) {
try {
String url = BOOKING_API_URL + "?hotelId={id}";
restTemplate.delete(url, id);
} catch (HttpClientErrorException ex) {
if (ex.getStatusCode() != HttpStatus.NOT_FOUND)
throw ex;
}
}
public void deleteAllByManagerId(Integer managerId) {
try {
String url = BOOKING_API_URL + "?managerId={managerId}";
restTemplate.delete(url, managerId);
} catch (HttpClientErrorException ex) {
if (ex.getStatusCode() != HttpStatus.NOT_FOUND)
throw ex;
}
}
}
\ No newline at end of file
package com.uva.api.apis;
package com.uva.api.hotels.apis;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
......@@ -15,7 +15,7 @@ public class ManagerAPI {
@Autowired
private RestTemplate restTemplate;
@Value("${external.services.managers.url}")
@Value("${services.external.managers.url}")
private String MANAGERS_API_URL;
public Boolean existsManagerById(int id) {
......
package com.uva.api.hotels.apis;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.databind.JsonNode;
import com.uva.api.hotels.models.external.JwtData;
@Component
public class TokenAPI {
@Autowired
private RestTemplate restTemplate;
@Value("${spring.application.name}")
private String service;
@Value("${services.internal.token.url}")
private String TOKEN_API_URL;
public JwtData getServiceToken() {
String url = TOKEN_API_URL + "/service";
Map<String, String> body = new HashMap<>();
body.put("service", service);
String token = restTemplate.postForObject(url, body, JsonNode.class)
.get("token").asText();
return decodeToken(token);
}
public JwtData decodeToken(String token) {
String url = TOKEN_API_URL + "/info";
Map<String, String> body = new HashMap<>();
body.put("token", token);
JwtData response = restTemplate.postForObject(url, body, JwtData.class);
response.setToken(token);
return response;
}
}
package com.uva.api.config;
package com.uva.api.hotels.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
......
package com.uva.api.interceptor;
package com.uva.api.hotels.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpRequest;
......@@ -7,40 +7,25 @@ import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.stereotype.Component;
import com.uva.api.models.external.users.UserRol;
import com.uva.api.utils.JwtUtil;
import com.uva.api.hotels.services.TokenService;
import java.io.IOException;
@Component
public class AuthHttpInterceptor implements ClientHttpRequestInterceptor {
public class RestTemplateInterceptor implements ClientHttpRequestInterceptor {
@Autowired
private JwtUtil jwtUtil;
private String token;
private String getAccessToken() {
if (token == null || token.isEmpty()) {
// TODO cambiar también si el token ha caducado
token = jwtUtil.generateToken("auth", "auth@dev.com", UserRol.ADMIN);
}
return token;
}
private TokenService service;
@Override
public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution)
throws IOException {
// Generar o cargar el JWT token desde el bean JwtUtil
String jwtToken = getAccessToken();
// System.out.println("Using token " + jwtToken);
String jwtToken = service.getServiceToken();
System.out.println("Using token " + jwtToken);
// Agregar el token al encabezado Authorization
request.getHeaders().add("Authorization", "Bearer " + jwtToken);
// Continuar con la ejecución de la solicitud
return execution.execute(request, body);
}
}
package com.uva.api.config;
package com.uva.api.hotels.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
......@@ -8,8 +8,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.uva.api.filter.JwtAuthenticationFilter;
import com.uva.api.models.external.users.UserRol;
import com.uva.api.hotels.filter.JwtAuthenticationFilter;
@Configuration
@EnableWebSecurity
......
package com.uva.api.controllers;
package com.uva.api.hotels.controllers;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
......@@ -11,16 +10,10 @@ import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import com.uva.api.apis.BookingAPI;
import com.uva.api.apis.ManagerAPI;
import com.uva.api.exceptions.HotelNotFoundException;
import com.uva.api.exceptions.InvalidDateRangeException;
import com.uva.api.exceptions.InvalidRequestException;
import com.uva.api.models.Hotel;
import com.uva.api.models.Room;
import com.uva.api.repositories.HotelRepository;
import com.uva.api.repositories.RoomRepository;
import com.uva.api.services.HotelService;
import com.uva.api.hotels.exceptions.InvalidRequestException;
import com.uva.api.hotels.models.Hotel;
import com.uva.api.hotels.models.Room;
import com.uva.api.hotels.services.HotelService;
@RestController
@RequestMapping("hotels")
......@@ -57,9 +50,9 @@ public class HotelController {
@DeleteMapping("/{id}")
@Transactional
public ResponseEntity<Void> deleteHotel(@PathVariable Integer id) {
public ResponseEntity<?> deleteHotel(@PathVariable Integer id) {
hotelService.deleteHotel(id);
return new ResponseEntity<>(HttpStatus.NO_CONTENT);
return ResponseEntity.ok().build();
}
@GetMapping("/{hotelId}/rooms")
......
package com.uva.api.exceptions;
package com.uva.api.hotels.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;
......@@ -30,6 +31,16 @@ public class GlobalExceptionHandler {
return new ResponseEntity<>(body, HttpStatus.BAD_REQUEST);
}
@ExceptionHandler(HttpClientErrorException.class)
public ResponseEntity<Map<String, Object>> handleHttpClientError(HttpClientErrorException ex) {
ex.printStackTrace(System.err);
Map<String, Object> body = new HashMap<>();
body.put("timestamp", LocalDateTime.now());
body.put("message", ex.getMessage());
return new ResponseEntity<>(body, ex.getStatusCode());
}
@ExceptionHandler(InvalidDateRangeException.class)
public ResponseEntity<Map<String, Object>> handleInvalidDateRange(InvalidDateRangeException ex) {
Map<String, Object> body = new HashMap<>();
......@@ -41,6 +52,7 @@ public class GlobalExceptionHandler {
@ExceptionHandler(Exception.class)
public ResponseEntity<Map<String, Object>> handleGeneralException(Exception ex) {
ex.printStackTrace(System.err);
Map<String, Object> body = new HashMap<>();
body.put("timestamp", LocalDateTime.now());
body.put("message", "An unexpected error occurred: " + ex.getMessage());
......
package com.uva.api.exceptions;
package com.uva.api.hotels.exceptions;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
......
package com.uva.api.exceptions;
package com.uva.api.hotels.exceptions;
public class InvalidDateRangeException extends RuntimeException {
public InvalidDateRangeException(String message) {
......
package com.uva.api.exceptions;
package com.uva.api.hotels.exceptions;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;
......
package com.uva.api.filter;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.uva.api.models.external.users.UserRol;
import com.auth0.jwt.exceptions.JWTVerificationException;
package com.uva.api.hotels.filter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
......@@ -14,6 +8,10 @@ import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import com.uva.api.hotels.models.external.JwtData;
import com.uva.api.hotels.models.external.users.UserRol;
import com.uva.api.hotels.services.TokenService;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
......@@ -28,12 +26,8 @@ import java.util.Collections;
@Component
public class JwtAuthenticationFilter implements Filter {
@Value("${security.jwt.secret-key}")
private String secretKey;
private Algorithm getSigningAlgorithm() {
return Algorithm.HMAC256(secretKey); // Usar HMAC256 con la clave secreta
}
@Autowired
private TokenService service;
private String getTokenFromRequest(HttpServletRequest request) {
String authHeader = request.getHeader("Authorization");
......@@ -43,26 +37,17 @@ public class JwtAuthenticationFilter implements Filter {
return authHeader.substring(7);
}
private DecodedJWT validateAndDecodeToken(String token) {
private JwtData validateAndDecodeToken(String token) {
try {
JWTVerifier verifier = JWT.require(getSigningAlgorithm()).build();
return verifier.verify(token); // Verifica y decodifica el token
} catch (JWTVerificationException ex) {
System.out.println(
"[" + LocalDateTime.now().toString() + "] Error de verificación del token: " + ex.getMessage());
return service.decodeToken(token);
} catch (Exception ex) {
System.err.println(
"[" + LocalDateTime.now().toString() + "] Error de verificación del token");
ex.printStackTrace(System.err);
return null;
}
}
private String getEmailFromToken(DecodedJWT jwt) {
return jwt.getClaim("email").asString();
}
private UserRol getRoleFromToken(DecodedJWT jwt) {
String role = jwt.getClaim("rol").asString();
return UserRol.valueOf(role);
}
private String formatRole(UserRol rol) {
return String.format("ROLE_%s", rol.toString());
}
......@@ -70,34 +55,42 @@ public class JwtAuthenticationFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String token = getTokenFromRequest(httpRequest);
System.out.print("[" + LocalDateTime.now().toString() + "] TOKEN: " + token);
System.out.println("[" + LocalDateTime.now().toString() + "] TOKEN: " + token);
if (token != null) {
DecodedJWT jwt = validateAndDecodeToken(token);
System.out.print(" " + jwt.toString() + " ");
JwtData jwt = validateAndDecodeToken(token);
if (jwt != null) {
String email = getEmailFromToken(jwt);
UserRol role = getRoleFromToken(jwt);
System.out.print(" email=" + email + " role=" + role + " ");
if (email != null && role != null && SecurityContextHolder.getContext().getAuthentication() == null) {
// Crear la autoridad con el rol del token
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(formatRole(role));
// Crear autenticación
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(email,
null, Collections.singletonList(authority));
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
// Establecer autenticación en el contexto de seguridad
SecurityContextHolder.getContext().setAuthentication(authentication);
}
System.out.println("-->" + jwt + "<--");
}
}
// String email = getEmailFromToken(jwt);
// UserRol role = getRoleFromToken(jwt);
// System.out.print(" email=" + email + " role=" + role + " ");
// if (email != null && role != null &&
// SecurityContextHolder.getContext().getAuthentication() == null) {
// // Crear la autoridad con el rol del token
// SimpleGrantedAuthority authority = new
// SimpleGrantedAuthority(formatRole(role));
// // Crear autenticación
// UsernamePasswordAuthenticationToken authentication = new
// UsernamePasswordAuthenticationToken(email,
// null, Collections.singletonList(authority));
// authentication.setDetails(new
// WebAuthenticationDetailsSource().buildDetails(httpRequest));
// // Establecer autenticación en el contexto de seguridad
// SecurityContextHolder.getContext().setAuthentication(authentication);
// }
// }
// }
// Continuar con el resto de filtros
chain.doFilter(request, response);
}
......
package com.uva.api.models;
package com.uva.api.hotels.models;
import com.fasterxml.jackson.annotation.JsonIgnore;
......
package com.uva.api.models;
package com.uva.api.hotels.models;
import java.util.List;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment