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

Ya se comunican y funciona pero falla el hash

parent 4d05956d
No related branches found
No related tags found
2 merge requests!26Revert "Funciona register",!21Dev/auth backend
Showing
with 525 additions and 100 deletions
...@@ -8,7 +8,7 @@ networks: ...@@ -8,7 +8,7 @@ networks:
services: services:
Auth-API: Auth-API:
image: auth-api-image image: auth-api-image
hostname: ${AUTH_SERVICE_HOSTNAME} hostname: $${AUTH_SERVICE_HOSTNAME}
build: build:
context: ./java/services/auth context: ./java/services/auth
dockerfile: Dockerfile dockerfile: Dockerfile
...@@ -18,13 +18,13 @@ services: ...@@ -18,13 +18,13 @@ services:
networks: networks:
- kong-net - kong-net
environment: environment:
SPRING_DATASOURCE_URL: jdbc:mysql://${DB_SERVICE_HOSTNAME}:3306/${DB_DATABASE_NAME}?createDatabaseIfNotExist=true SPRING_DATASOURCE_URL: jdbc:mysql://$${DB_SERVICE_HOSTNAME}:3306/$${DB_DATABASE_NAME}?createDatabaseIfNotExist=true
depends_on: depends_on:
- RoomsBooking-database - RoomsBooking-database
Users-API: Users-API:
image: users-api-image image: users-api-image
hostname: "${USERS_SERVICE_HOSTNAME}" hostname: "$${USERS_SERVICE_HOSTNAME}"
build: build:
context: ./java/services/users context: ./java/services/users
dockerfile: Dockerfile dockerfile: Dockerfile
...@@ -34,13 +34,13 @@ services: ...@@ -34,13 +34,13 @@ services:
networks: networks:
- kong-net - kong-net
environment: environment:
SPRING_DATASOURCE_URL: jdbc:mysql://${DB_SERVICE_HOSTNAME}:3306/${DB_DATABASE_NAME}?createDatabaseIfNotExist=true SPRING_DATASOURCE_URL: jdbc:mysql://$${DB_SERVICE_HOSTNAME}:3306/$${DB_DATABASE_NAME}?createDatabaseIfNotExist=true
depends_on: depends_on:
- RoomsBooking-database - RoomsBooking-database
Hotels-API: Hotels-API:
image: hotels-api-image image: hotels-api-image
hostname: ${HOTELS_SERVICE_HOSTNAME} hostname: $${HOTELS_SERVICE_HOSTNAME}
build: build:
context: ./java/services/hotels context: ./java/services/hotels
dockerfile: Dockerfile dockerfile: Dockerfile
...@@ -50,16 +50,16 @@ services: ...@@ -50,16 +50,16 @@ services:
networks: networks:
- kong-net - kong-net
environment: environment:
SPRING_DATASOURCE_URL: jdbc:mysql://${DB_SERVICE_HOSTNAME}:3306/${DB_DATABASE_NAME}?createDatabaseIfNotExist=true SPRING_DATASOURCE_URL: jdbc:mysql://$${DB_SERVICE_HOSTNAME}:3306/$${DB_DATABASE_NAME}?createDatabaseIfNotExist=true
SPRING_DATASOURCE_USER: ${USER_DATABASE} SPRING_DATASOURCE_USER: $${USER_DATABASE}
SPRING_DATASOURCE_PASSWORD: ${} SPRING_DATASOURCE_PASSWORD: $${}
depends_on: depends_on:
- RoomsBooking-database - RoomsBooking-database
- Bookings-API - Bookings-API
Bookings-API: Bookings-API:
image: bookings-api-image image: bookings-api-image
hostname: ${BOOKINGS_SERVICE_HOSTNAME} hostname: $${BOOKINGS_SERVICE_HOSTNAME}
build: build:
context: ./java/services/bookings context: ./java/services/bookings
dockerfile: Dockerfile dockerfile: Dockerfile
...@@ -69,13 +69,13 @@ services: ...@@ -69,13 +69,13 @@ services:
networks: networks:
- kong-net - kong-net
environment: environment:
SPRING_DATASOURCE_URL: jdbc:mysql://${DB_SERVICE_HOSTNAME}:3306/${DB_DATABASE_NAME}?createDatabaseIfNotExist=true SPRING_DATASOURCE_URL: jdbc:mysql://$${DB_SERVICE_HOSTNAME}:3306/$${DB_DATABASE_NAME}?createDatabaseIfNotExist=true
depends_on: depends_on:
- RoomsBooking-database - RoomsBooking-database
RoomsBooking-database: RoomsBooking-database:
image: mysql image: mysql
hostname: ${DB_SERVICE_HOSTNAME} hostname: $${DB_SERVICE_HOSTNAME}
cap_add: cap_add:
- SYS_NICE - SYS_NICE
restart: unless-stopped restart: unless-stopped
...@@ -103,6 +103,6 @@ services: ...@@ -103,6 +103,6 @@ services:
networks: networks:
- kong-net - kong-net
environment: environment:
SPRING_DATASOURCE_URL: jdbc:mysql://${DB_SERVICE_HOSTNAME}:3306/${DB_DATABASE_NAME}?createDatabaseIfNotExist=true SPRING_DATASOURCE_URL: jdbc:mysql://$${DB_SERVICE_HOSTNAME}:3306/$${DB_DATABASE_NAME}?createDatabaseIfNotExist=true
depends_on: depends_on:
- RoomsBooking-database - RoomsBooking-database
package com.uva.monolith.services.auth; package com.uva.monolith.services.auth;
import io.jsonwebtoken.Claims; import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts; import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SignatureException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.uva.monolith.services.users.models.UserRol;
import jakarta.servlet.FilterChain; import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException; import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest; import jakarta.servlet.ServletRequest;
...@@ -13,33 +24,95 @@ import jakarta.servlet.ServletResponse; ...@@ -13,33 +24,95 @@ import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.Filter; import jakarta.servlet.Filter;
import java.io.IOException; import java.io.IOException;
import java.security.Key;
import java.util.Collections;
import java.util.Date;
@Component @Component
public class JwtAuthenticationFilter implements Filter { public class JwtAuthenticationFilter implements Filter {
private final String SECRET_KEY = "clave_secreta"; private final String SECRET_KEY = "3cfa76ef14937c1c0ea519f8fc057a80fcd04a7420f8e8bcd0a7567c272e007b";
private Key getSignInKey() {
byte[] keyBytes = Decoders.BASE64.decode(SECRET_KEY);
return Keys.hmacShaKeyFor(keyBytes);
}
private String getTokenFromRequest(HttpServletRequest request) {
String authHeader = request.getHeader("Authorization");
if (authHeader == null || !authHeader.startsWith("Bearer "))
return null;
return authHeader.substring(7);
}
private Claims getClaimsFromToken(String token) {
return Jwts.parserBuilder()
.setSigningKey(getSignInKey())
.build()
.parseClaimsJws(token)
.getBody();
}
private boolean validateToken(String token) {
if (token == null)
return false;// no token
try {
// Verifica y analiza el token
Claims claims = getClaimsFromToken(token);
// Verifica que el token no esté expirado
return claims.getExpiration().after(new Date());
} catch (ExpiredJwtException e) {
System.out.println("Token expirado: " + e.getMessage());
} catch (UnsupportedJwtException e) {
System.out.println("Token no soportado: " + e.getMessage());
} catch (MalformedJwtException e) {
System.out.println("Token malformado: " + e.getMessage());
} catch (SignatureException e) {
System.out.println("Firma inválida: " + e.getMessage());
} catch (IllegalArgumentException e) {
System.out.println("Token vacío o nulo: " + e.getMessage());
}
return false; // Si ocurre cualquier excepción, el token es inválido
}
private String getEmailFromToken(String token) {
return getClaimsFromToken(token).getSubject();
}
private UserRol getRoleFromToken(String token) {
String rol = getClaimsFromToken(token).get("rol", String.class);
return UserRol.valueOf(rol);
}
public static String getRol(UserRol rol) {
return String.format("ROLE_%s", rol.toString());
}
@Override @Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException { throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request; HttpServletRequest httpRequest = (HttpServletRequest) request;
String authHeader = httpRequest.getHeader("Authorization"); String token = getTokenFromRequest(httpRequest);
if (authHeader != null && authHeader.startsWith("Bearer ")) { if (validateToken(token)) {
String token = authHeader.substring(7);
Claims claims = Jwts.parserBuilder()
.setSigningKey(SECRET_KEY.getBytes())
.build()
.parseClaimsJws(token)
.getBody();
String username = claims.getSubject(); String email = getEmailFromToken(token);
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { UserRol role = getRoleFromToken(token); // Extraer el rol del token
if (email != null && SecurityContextHolder.getContext().getAuthentication() == null) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
username, null, null); email, null, null);
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest)); authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(httpRequest));
SecurityContextHolder.getContext().setAuthentication(authentication); SecurityContextHolder.getContext().setAuthentication(authentication);
} }
// Agregar el rol como autoridad
SimpleGrantedAuthority authority = new SimpleGrantedAuthority(getRol(role));
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(email, null,
Collections.singletonList(authority));
SecurityContextHolder.getContext().setAuthentication(authentication);
} }
chain.doFilter(request, response); chain.doFilter(request, response);
......
...@@ -2,11 +2,14 @@ package com.uva.monolith.services.auth; ...@@ -2,11 +2,14 @@ package com.uva.monolith.services.auth;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.uva.monolith.services.users.models.UserRol;
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
public class SecurityConfig { public class SecurityConfig {
...@@ -21,8 +24,22 @@ public class SecurityConfig { ...@@ -21,8 +24,22 @@ public class SecurityConfig {
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.disable()) http.csrf(csrf -> csrf.disable())
.authorizeHttpRequests(authorize -> authorize .authorizeHttpRequests(authorize -> authorize
.requestMatchers("/api/auth/login", "/api/auth/register").permitAll() // Rutas públicas .requestMatchers("/users").access((authentication, context) -> {
.requestMatchers("/api/users/**", "/api/hotels/**", "/api/reservas/**").authenticated() // Protegidas String method = context.getRequest().getMethod();
String email = context.getRequest().getParameter("email");
// Permitir POST a /users solo al rol ADMIN
boolean register = method.equals("POST") && authentication.get().getAuthorities().stream()
.anyMatch(auth -> auth.getAuthority().equals("ROLE_ADMIN"));
// Permitir GET a /users con parámetro email solo al rol ADMIN
boolean access = method.equals("GET") && email != null && !email.isEmpty() &&
authentication.get().getAuthorities().stream()
.anyMatch(auth -> auth.getAuthority().equals("ROLE_ADMIN"));
return new AuthorizationDecision(register || access);
})
.requestMatchers("/users/**").hasRole(UserRol.CLIENT.toString())
.requestMatchers("/hotels/**", "/booking/**").permitAll() //
// .requestMatchers("/users/**", "/hotels/**", "/booking/**").authenticated() //
// Protegidas
) )
// Registra el filtro antes del filtro estándar de autenticación // Registra el filtro antes del filtro estándar de autenticación
.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
......
package com.uva.monolith.services.hotels.models; package com.uva.monolith.services.hotels.models;
import java.util.List; import java.util.List;
import org.hibernate.annotations.ManyToAny;
import com.uva.monolith.services.users.models.HotelManager;
import jakarta.persistence.Basic; import jakarta.persistence.Basic;
import jakarta.persistence.CascadeType; import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.FetchType; import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType; import jakarta.persistence.GenerationType;
import jakarta.persistence.Id; import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn; import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany; import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne; import jakarta.persistence.OneToOne;
import jakarta.persistence.Table; import jakarta.persistence.Table;
...@@ -34,14 +41,19 @@ public class Hotel { ...@@ -34,14 +41,19 @@ public class Hotel {
@OneToMany(mappedBy = "hotel", fetch = FetchType.EAGER, cascade = CascadeType.ALL) @OneToMany(mappedBy = "hotel", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Room> rooms; private List<Room> rooms;
@ManyToOne(optional = false)
@JoinColumn(name = "hotel_manager", referencedColumnName = "id")
private HotelManager hotelManager;
public Hotel() { public Hotel() {
} }
public Hotel(int id, String name, Address address, List<Room> rooms) { public Hotel(int id, String name, Address address, List<Room> rooms, HotelManager hotelManager) {
setId(id); setId(id);
setName(name); setName(name);
setAddress(address); setAddress(address);
setRooms(rooms); setRooms(rooms);
setHotelManager(hotelManager);
} }
public int getId() { public int getId() {
...@@ -77,4 +89,11 @@ public class Hotel { ...@@ -77,4 +89,11 @@ public class Hotel {
rooms.forEach(room -> room.setHotel(this)); rooms.forEach(room -> room.setHotel(this));
} }
public void setHotelManager(HotelManager hotelManager) {
this.hotelManager = hotelManager;
}
public HotelManager getHotelManager() {
return hotelManager;
}
} }
...@@ -5,6 +5,7 @@ import java.util.ArrayList; ...@@ -5,6 +5,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CrossOrigin; import org.springframework.web.bind.annotation.CrossOrigin;
...@@ -21,20 +22,23 @@ import org.springframework.web.bind.annotation.RestController; ...@@ -21,20 +22,23 @@ import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.server.ResponseStatusException; import org.springframework.web.server.ResponseStatusException;
import com.uva.monolith.services.bookings.models.Booking; import com.uva.monolith.services.bookings.models.Booking;
import com.uva.monolith.services.users.models.Client;
import com.uva.monolith.services.users.models.User; import com.uva.monolith.services.users.models.User;
import com.uva.monolith.services.users.models.UserRol; import com.uva.monolith.services.users.models.UserRol;
import com.uva.monolith.services.users.models.UserStatus; import com.uva.monolith.services.users.models.UserStatus;
import com.uva.monolith.services.users.repositories.ClientRepository;
import com.uva.monolith.services.users.repositories.UserRepository; import com.uva.monolith.services.users.repositories.UserRepository;
@RestController @RestController
@RequestMapping("users") @RequestMapping("users")
@CrossOrigin(origins = "*") @CrossOrigin(origins = "*")
public class UserController { public class UserController {
private final UserRepository userRepository;
public UserController(UserRepository userRepository) { @Autowired
this.userRepository = userRepository; private UserRepository userRepository;
}
@Autowired
private ClientRepository clientRepository;
@GetMapping @GetMapping
public List<User> getAllUsers() { public List<User> getAllUsers() {
...@@ -52,9 +56,9 @@ public class UserController { ...@@ -52,9 +56,9 @@ public class UserController {
@PostMapping @PostMapping
public User addUser(@RequestBody User user) { public User addUser(@RequestBody User user) {
user.setStatus(UserStatus.NO_BOOKINGS); // user.setStatus(UserStatus.NO_BOOKINGS);
if (user.getRol() == null) // Rol por defecto if (user.getRol() == null) // Rol por defecto
user.setRol(UserRol.CONSUMER); user.setRol(UserRol.CLIENT);
return userRepository.save(user); return userRepository.save(user);
} }
...@@ -77,7 +81,7 @@ public class UserController { ...@@ -77,7 +81,7 @@ public class UserController {
@PatchMapping("/{id}") @PatchMapping("/{id}")
public User updateUserState(@PathVariable int id, @RequestBody Map<String, String> json) { public User updateUserState(@PathVariable int id, @RequestBody Map<String, String> json) {
User target = userRepository.findById(id).orElseThrow(); Client target = clientRepository.findById(id).orElseThrow();
String strStatus = json.get("status"); String strStatus = json.get("status");
if (strStatus == null) { if (strStatus == null) {
// TODO cambiar manejo // TODO cambiar manejo
...@@ -126,9 +130,8 @@ public class UserController { ...@@ -126,9 +130,8 @@ public class UserController {
@GetMapping("/{id}/bookings") @GetMapping("/{id}/bookings")
public List<Booking> getUserBookingsById(@PathVariable int id) { public List<Booking> getUserBookingsById(@PathVariable int id) {
User user = userRepository.findById(id).orElseThrow(); Client user = clientRepository.findById(id).orElseThrow();
return user.getBookings(); return user.getBookings();
} }
} }
package com.uva.monolith.services.users.models;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.uva.monolith.services.bookings.models.Booking;
import jakarta.persistence.Basic;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
@Entity
@Table(name = "user_client")
public class Client extends User {
@Basic(optional = false)
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private UserStatus status;
@JsonIgnore
@OneToMany(mappedBy = "userId", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Booking> bookings;
public Client() {
super();
bookings = new ArrayList<>();
status = UserStatus.NO_BOOKINGS;
}
public Client(int id, String name, String email, String password, UserStatus status,
List<Booking> bookings) {
super(id, name, email, password, UserRol.CLIENT);
setStatus(status);
setBookings(bookings);
}
public UserStatus getStatus() {
if (getBookings() == null || getBookings().isEmpty())
return UserStatus.NO_BOOKINGS;
boolean activeBookings = getBookings().stream()
.anyMatch(booking -> !booking.getEndDate().isBefore(LocalDate.now())); // reserva >= ahora
return activeBookings ? UserStatus.WITH_ACTIVE_BOOKINGS : UserStatus.WITH_INACTIVE_BOOKINGS;
}
public void setStatus(UserStatus status) {
this.status = status;
}
public List<Booking> getBookings() {
return this.bookings;
}
public void setBookings(List<Booking> bookings) {
this.bookings = bookings;
}
}
package com.uva.monolith.services.users.models;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.uva.monolith.services.hotels.models.Hotel;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
@Entity
@Table(name = "hotel_manager_user")
public class HotelManager extends User {
@JsonIgnore
@OneToMany(mappedBy = "hotelManager", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Hotel> hotels;
public HotelManager() {
super();
hotels = new ArrayList<>();
}
public HotelManager(int id, String name, String email, String password, List<Hotel> hotels) {
super(id, name, email, password, UserRol.HOTEL_ADMIN);
setHotels(hotels);
}
public List<Hotel> getHotels() {
return this.hotels;
}
public void setHotels(List<Hotel> hotels) {
this.hotels = hotels;
}
}
package com.uva.monolith.services.users.models; package com.uva.monolith.services.users.models;
import java.time.LocalDate;
import java.util.List;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.uva.monolith.services.bookings.models.Booking;
import jakarta.persistence.Basic; import jakarta.persistence.Basic;
import jakarta.persistence.CascadeType; import jakarta.persistence.Column;
import jakarta.persistence.Entity; import jakarta.persistence.Entity;
import jakarta.persistence.EnumType; import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated; import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue; import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType; import jakarta.persistence.GenerationType;
import jakarta.persistence.Id; import jakarta.persistence.Id;
import jakarta.persistence.OneToMany; import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.Table; import jakarta.persistence.Table;
@Entity @Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "users") @Table(name = "users")
public class User { public class User {
// TODO extraer a dos clases hijas, una por cada tipo
@Id @Id
@GeneratedValue(strategy = GenerationType.IDENTITY) @GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false) @Basic(optional = false)
@Column(nullable = false)
private int id; private int id;
@Basic(optional = false) @Basic(optional = false)
@Column(nullable = false)
private String name; private String name;
@Basic(optional = false) @Basic(optional = false)
@Column(nullable = false, unique = true)
private String email; private String email;
@JsonIgnore
@Basic(optional = false) @Basic(optional = false)
@Column(nullable = false)
private String password; private String password;
@Basic(optional = false) @Basic(optional = false)
@Column(nullable = false)
@Enumerated(EnumType.STRING) @Enumerated(EnumType.STRING)
private UserRol rol = UserRol.CONSUMER; private UserRol rol = UserRol.CLIENT;
@Basic(optional = false)
@Enumerated(EnumType.STRING)
private UserStatus status;
@JsonIgnore
@OneToMany(mappedBy = "userId", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
private List<Booking> bookings;
public User() { public User() {
} }
public User(int id, String name, String email, String password, UserRol rol, UserStatus status, public User(int id, String name, String email, String password, UserRol rol) {
List<Booking> bookings) {
setId(id); setId(id);
setName(name); setName(name);
setEmail(email); setEmail(email);
setRol(rol); setRol(rol);
setStatus(status);
setBookings(bookings);
} }
public int getId() { public int getId() {
...@@ -92,8 +82,7 @@ public class User { ...@@ -92,8 +82,7 @@ public class User {
} }
public void setPassword(String rawPassword) { public void setPassword(String rawPassword) {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); this.password = rawPassword;
this.password = encoder.encode(rawPassword);
} }
public UserRol getRol() { public UserRol getRol() {
...@@ -103,25 +92,4 @@ public class User { ...@@ -103,25 +92,4 @@ public class User {
public void setRol(UserRol rol) { public void setRol(UserRol rol) {
this.rol = rol; this.rol = rol;
} }
public UserStatus getStatus() {
if (getBookings() == null || getBookings().isEmpty())
return UserStatus.NO_BOOKINGS;
boolean activeBookings = getBookings().stream()
.anyMatch(booking -> !booking.getEndDate().isBefore(LocalDate.now())); // reserva >= ahora
return activeBookings ? UserStatus.WITH_ACTIVE_BOOKINGS : UserStatus.WITH_INACTIVE_BOOKINGS;
}
public void setStatus(UserStatus status) {
this.status = status;
}
public List<Booking> getBookings() {
return this.bookings;
}
public void setBookings(List<Booking> bookings) {
this.bookings = bookings;
}
} }
package com.uva.monolith.services.users.models; package com.uva.monolith.services.users.models;
public enum UserRol { public enum UserRol {
HOTEL_ADMIN, CONSUMER ADMIN, HOTEL_ADMIN, CLIENT
} }
package com.uva.monolith.services.users.repositories;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import com.uva.monolith.services.users.models.Client;
public interface ClientRepository extends JpaRepository<Client, Integer> {
Optional<Client> findByEmail(String email);
}
\ No newline at end of file
package com.uva.monolith.services.users.repositories;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import com.uva.monolith.services.users.models.HotelManager;
public interface HotelManagerRepository extends JpaRepository<HotelManager, Integer> {
Optional<HotelManager> findByEmail(String email);
}
\ No newline at end of file
...@@ -48,6 +48,10 @@ ...@@ -48,6 +48,10 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId> <artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope> <scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.jsonwebtoken</groupId> <groupId>io.jsonwebtoken</groupId>
......
...@@ -2,6 +2,9 @@ package com.uva.authentication.api; ...@@ -2,6 +2,9 @@ package com.uva.authentication.api;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
...@@ -10,6 +13,8 @@ import org.springframework.web.client.RestTemplate; ...@@ -10,6 +13,8 @@ import org.springframework.web.client.RestTemplate;
import com.uva.authentication.models.RegisterRequest; import com.uva.authentication.models.RegisterRequest;
import com.uva.authentication.models.User; import com.uva.authentication.models.User;
import com.uva.authentication.models.UserRol;
import com.uva.authentication.utils.JwtUtil;
@Component @Component
public class UserAPI { public class UserAPI {
...@@ -20,10 +25,30 @@ public class UserAPI { ...@@ -20,10 +25,30 @@ public class UserAPI {
@Value("${external.services.users.baseurl}") @Value("${external.services.users.baseurl}")
private String USER_API_URL; private String USER_API_URL;
@Autowired
private JwtUtil jwtUtil;
private String token;
private final User USER = new User(-1, "admin", null, null, UserRol.ADMIN);
private String getAccessToken() {
if (token == null || token.isEmpty() || jwtUtil.isTokenValid(token, USER)) {
token = jwtUtil.generateToken(USER);
}
return token;
}
public User getUserByEmail(String email) { public User getUserByEmail(String email) {
String url = USER_API_URL + "?email={email}";
String token = getAccessToken();
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + token);
HttpEntity<Void> entity = new HttpEntity<>(headers);
String url = USER_API_URL + "?email={" + email + "}";
try { try {
ResponseEntity<User> userResponse = restTemplate.getForEntity(url, User.class, email); ResponseEntity<User> userResponse = // restTemplate.getForEntity(url, User.class, email, headers);
restTemplate.exchange(url, HttpMethod.GET, entity, User.class);
return userResponse.getBody(); return userResponse.getBody();
} catch (HttpClientErrorException e) { } catch (HttpClientErrorException e) {
if (e.getStatusCode() != HttpStatus.NOT_FOUND) if (e.getStatusCode() != HttpStatus.NOT_FOUND)
...@@ -33,8 +58,13 @@ public class UserAPI { ...@@ -33,8 +58,13 @@ public class UserAPI {
} }
public User registerUser(RegisterRequest registerRequest) { public User registerUser(RegisterRequest registerRequest) {
String token = getAccessToken();
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization", "Bearer " + token);
String url = USER_API_URL; String url = USER_API_URL;
ResponseEntity<User> userResponse = restTemplate.postForEntity(url, registerRequest, User.class); ResponseEntity<User> userResponse = restTemplate.postForEntity(url, registerRequest, User.class, headers);
if (!userResponse.getStatusCode().is2xxSuccessful()) if (!userResponse.getStatusCode().is2xxSuccessful())
throw new RuntimeException("Failed to register user"); throw new RuntimeException("Failed to register user");
......
package com.uva.authentication.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf(crsf -> crsf.disable())
.authorizeHttpRequests(auth -> auth.anyRequest().permitAll());
return http.build();
}
}
...@@ -42,6 +42,7 @@ public class AuthController { ...@@ -42,6 +42,7 @@ public class AuthController {
// return new ResponseEntity<Void>(HttpStatus.FORBIDDEN); // return new ResponseEntity<Void>(HttpStatus.FORBIDDEN);
return new ResponseEntity<String>(e.getMessage(), HttpStatus.CONFLICT); return new ResponseEntity<String>(e.getMessage(), HttpStatus.CONFLICT);
} }
e.fillInStackTrace();
} }
return new ResponseEntity<String>("Algo no fue bien", HttpStatus.UNAUTHORIZED); return new ResponseEntity<String>("Algo no fue bien", HttpStatus.UNAUTHORIZED);
......
package com.uva.authentication.models;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.Basic;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.FetchType;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
@Entity
@Table(name = "user_client")
public class Client extends User {
@Basic(optional = false)
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private UserStatus status;
// @JsonIgnore
// @OneToMany(mappedBy = "userId", fetch = FetchType.EAGER, cascade =
// CascadeType.ALL)
// private List<?> bookings;
public Client() {
super();
// bookings = new ArrayList<>();
status = UserStatus.NO_BOOKINGS;
}
public Client(int id, String name, String email, String password, UserStatus status) {
// , List<?> bookings) {
super(id, name, email, password, UserRol.CLIENT);
setStatus(status);
// setBookings(bookings);
}
public UserStatus getStatus() {
return this.status;
}
public void setStatus(UserStatus status) {
this.status = status;
}
// public List<?> getBookings() {
// return this.bookings;
// }
// public void setBookings(List<?> bookings) {
// this.bookings = bookings;
// }
}
package com.uva.authentication.models;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.OneToMany;
import jakarta.persistence.Table;
@Entity
@Table(name = "hotel_manager_user")
public class HotelManager extends User {
// TODO tener en cuenta que esto hay que tener un control adecuado
// @JsonIgnore
// @OneToMany(mappedBy = "userId", fetch = FetchType.EAGER, cascade =
// CascadeType.ALL)
// private List<?> hotels;
public HotelManager() {
super();
// hotels = new ArrayList<>();
}
public HotelManager(int id, String name, String email, String password) { // , List<?> hotels) {
super(id, name, email, password, UserRol.HOTEL_ADMIN);
// setHotels(hotels);
}
// public List<?> getHotels() {
// return this.hotels;
// }
// public void setHotels(List<?> hotels) {
// this.hotels = hotels;
// }
}
package com.uva.authentication.models; package com.uva.authentication.models;
public class User extends RegisterRequest { import com.fasterxml.jackson.annotation.JsonIgnore;
import jakarta.persistence.Basic;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Inheritance;
import jakarta.persistence.InheritanceType;
import jakarta.persistence.Table;
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(nullable = false)
private int id; private int id;
private UserStatus status;
@Basic(optional = false)
@Column(nullable = false)
private String name;
@Basic(optional = false)
@Column(nullable = false, unique = true)
private String email;
@JsonIgnore
@Basic(optional = false)
@Column(nullable = false)
private String password;
@Basic(optional = false)
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private UserRol rol = UserRol.CLIENT;
public User() { public User() {
} }
public User(int id, String name, String email, String password, UserRol rol) {
setId(id);
setName(name);
setEmail(email);
setRol(rol);
}
public int getId() { public int getId() {
return this.id; return this.id;
} }
...@@ -15,11 +61,35 @@ public class User extends RegisterRequest { ...@@ -15,11 +61,35 @@ public class User extends RegisterRequest {
this.id = id; this.id = id;
} }
public UserStatus getStatus() { public String getName() {
return this.status; return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return this.email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String rawPassword) {
this.password = rawPassword;
}
public UserRol getRol() {
return this.rol;
} }
public void setStatus(UserStatus status) { public void setRol(UserRol rol) {
this.status = status; this.rol = rol;
} }
} }
package com.uva.authentication.models; package com.uva.authentication.models;
public enum UserRol { public enum UserRol {
HOTEL_ADMIN, CONSUMER ADMIN, HOTEL_ADMIN, CLIENT
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment