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

Integración de servicios correcta

parent c1ebd314
No related branches found
No related tags found
1 merge request!26Revert "Funciona register"
Showing
with 86 additions and 186 deletions
package com.uva.monolith.services.auth; package com.uva.monolith.config;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
...@@ -7,6 +7,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe ...@@ -7,6 +7,7 @@ import org.springframework.security.config.annotation.web.configuration.EnableWe
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.filter.JwtAuthenticationFilter;
import com.uva.monolith.services.users.models.UserRol; import com.uva.monolith.services.users.models.UserRol;
@Configuration @Configuration
...@@ -23,8 +24,6 @@ public class SecurityConfig { ...@@ -23,8 +24,6 @@ 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
// Permitir todas las conexiones
.requestMatchers("").permitAll()
// Acceso restringido a usuarios y administradores // Acceso restringido a usuarios y administradores
.requestMatchers("users", "users/**") .requestMatchers("users", "users/**")
.hasAnyRole(UserRol.ADMIN.toString(), UserRol.CLIENT.toString()) .hasAnyRole(UserRol.ADMIN.toString(), UserRol.CLIENT.toString())
... ...
......
package com.uva.monolith.services.auth; package com.uva.monolith.filter;
import io.jsonwebtoken.Claims; import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.ExpiredJwtException;
... ...
......
package com.uva.monolith.services.auth;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;
import com.uva.monolith.services.users.controllers.UserService;
import com.uva.monolith.services.users.models.User;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
@RestController
@RequestMapping("/api/auth")
public class AuthController {
private final String SECRET_KEY = "clave_secreta";
@Autowired
private UserService userService;
@PostMapping("/login")
public Map<String, String> login(@RequestBody LoginRequest loginRequest) {
User user = userService.findByEmail(loginRequest.getEmail());
if (user != null && userService.verifyPassword(loginRequest.getPassword(), user.getPassword())) {
String token = Jwts.builder()
.setSubject(user.getEmail())
.signWith(new SecretKeySpec(SECRET_KEY.getBytes(), SignatureAlgorithm.HS256.getJcaName()))
.claim("email", user.getEmail())
.setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 1 hora
.compact();
Map<String, String> response = new HashMap<>();
response.put("token", token);
return response;
}
throw new ResponseStatusException(HttpStatus.FORBIDDEN, "Credenciales inválidas");
}
}
package com.uva.monolith.services.auth;
public class LoginRequest {
private String email;
private String password;
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
...@@ -14,7 +14,7 @@ import jakarta.persistence.Table; ...@@ -14,7 +14,7 @@ import jakarta.persistence.Table;
import java.time.LocalDate; import java.time.LocalDate;
import com.uva.monolith.services.hotels.models.Room; import com.uva.monolith.services.hotels.models.Room;
import com.uva.monolith.services.users.models.User; import com.uva.monolith.services.users.models.Client;
@Entity @Entity
@Table(name = "bookings") @Table(name = "bookings")
...@@ -25,7 +25,7 @@ public class Booking { ...@@ -25,7 +25,7 @@ public class Booking {
private int id; private int id;
@JoinColumn(name = "user_id", referencedColumnName = "id") @JoinColumn(name = "user_id", referencedColumnName = "id")
@ManyToOne(optional = false, fetch = FetchType.EAGER, cascade = CascadeType.MERGE) @ManyToOne(optional = false, fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
private User userId; private Client userId;
@JoinColumn(name = "room_id", referencedColumnName = "id") @JoinColumn(name = "room_id", referencedColumnName = "id")
@ManyToOne(optional = false, fetch = FetchType.EAGER, cascade = CascadeType.MERGE) @ManyToOne(optional = false, fetch = FetchType.EAGER, cascade = CascadeType.MERGE)
private Room roomId; private Room roomId;
...@@ -37,7 +37,7 @@ public class Booking { ...@@ -37,7 +37,7 @@ public class Booking {
public Booking() { public Booking() {
} }
public Booking(int id, User userId, Room roomID, LocalDate startDate, LocalDate endDate) { public Booking(int id, Client userId, Room roomID, LocalDate startDate, LocalDate endDate) {
this.id = id; this.id = id;
this.userId = userId; this.userId = userId;
this.roomId = roomID; this.roomId = roomID;
...@@ -53,11 +53,11 @@ public class Booking { ...@@ -53,11 +53,11 @@ public class Booking {
return this.id; return this.id;
} }
public void setUserId(User userId) { public void setUserId(Client userId) {
this.userId = userId; this.userId = userId;
} }
public User getUserId() { public Client getUserId() {
return this.userId; return this.userId;
} }
... ...
......
...@@ -4,8 +4,10 @@ import com.uva.monolith.services.bookings.models.Booking; ...@@ -4,8 +4,10 @@ import com.uva.monolith.services.bookings.models.Booking;
import com.uva.monolith.services.bookings.repositories.BookingRepository; import com.uva.monolith.services.bookings.repositories.BookingRepository;
import com.uva.monolith.services.hotels.models.Room; import com.uva.monolith.services.hotels.models.Room;
import com.uva.monolith.services.hotels.repositories.RoomRepository; import com.uva.monolith.services.hotels.repositories.RoomRepository;
import com.uva.monolith.services.users.models.User; import com.uva.monolith.services.users.models.Client;
import com.uva.monolith.services.users.repositories.UserRepository; import com.uva.monolith.services.users.repositories.ClientRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.time.LocalDate; import java.time.LocalDate;
...@@ -14,15 +16,14 @@ import java.util.List; ...@@ -14,15 +16,14 @@ import java.util.List;
@Service @Service
public class BookingService { public class BookingService {
private final BookingRepository bookingRepository; @Autowired
private final UserRepository userRepository; private BookingRepository bookingRepository;
private final RoomRepository roomRepository;
public BookingService(BookingRepository bookingRepository, UserRepository userRepository, RoomRepository roomRepository) { @Autowired
this.bookingRepository = bookingRepository; private RoomRepository roomRepository;
this.userRepository = userRepository;
this.roomRepository = roomRepository; @Autowired
} private ClientRepository clientRepository;
public List<Booking> getBookings(LocalDate start, LocalDate end, Integer roomId, Integer userId) { public List<Booking> getBookings(LocalDate start, LocalDate end, Integer roomId, Integer userId) {
List<Booking> bookings = null; List<Booking> bookings = null;
...@@ -56,7 +57,7 @@ public class BookingService { ...@@ -56,7 +57,7 @@ public class BookingService {
} }
public Booking createBooking(Booking booking) { public Booking createBooking(Booking booking) {
User user = userRepository.findById(booking.getUserId().getId()) Client user = clientRepository.findById(booking.getUserId().getId())
.orElseThrow(() -> new RuntimeException("User not found")); .orElseThrow(() -> new RuntimeException("User not found"));
Room room = roomRepository.findById(booking.getRoomId().getId()) Room room = roomRepository.findById(booking.getRoomId().getId())
.orElseThrow(() -> new RuntimeException("Room not found")); .orElseThrow(() -> new RuntimeException("Room not found"));
... ...
......
...@@ -2,13 +2,10 @@ package com.uva.monolith.services.hotels.models; ...@@ -2,13 +2,10 @@ 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 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;
... ...
......
...@@ -4,7 +4,6 @@ import java.util.List; ...@@ -4,7 +4,6 @@ import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonIgnore;
import com.uva.monolith.services.bookings.models.Booking; import com.uva.monolith.services.bookings.models.Booking;
import com.uva.monolith.services.users.models.Tipo;
import jakarta.persistence.Basic; import jakarta.persistence.Basic;
import jakarta.persistence.CascadeType; import jakarta.persistence.CascadeType;
...@@ -36,7 +35,7 @@ public class Room { ...@@ -36,7 +35,7 @@ public class Room {
@Column(name = "room_number", nullable = false) @Column(name = "room_number", nullable = false)
private String roomNumber; private String roomNumber;
@Column(name = "type", nullable = false) @Column(name = "type", nullable = false)
private Tipo type; private RoomType type;
@Column(name = "available", nullable = false) @Column(name = "available", nullable = false)
private boolean available; private boolean available;
@JsonIgnore @JsonIgnore
...@@ -46,7 +45,7 @@ public class Room { ...@@ -46,7 +45,7 @@ public class Room {
public Room() { public Room() {
} }
public Room(int id, Hotel hotelId, String roomNumber, Tipo type, boolean available, List<Booking> bookings) { public Room(int id, Hotel hotelId, String roomNumber, RoomType type, boolean available, List<Booking> bookings) {
this.id = id; this.id = id;
this.hotel = hotelId; this.hotel = hotelId;
this.roomNumber = roomNumber; this.roomNumber = roomNumber;
...@@ -79,11 +78,11 @@ public class Room { ...@@ -79,11 +78,11 @@ public class Room {
return this.roomNumber; return this.roomNumber;
} }
public void setType(Tipo type) { public void setType(RoomType type) {
this.type = type; this.type = type;
} }
public Tipo getType() { public RoomType getType() {
return this.type; return this.type;
} }
... ...
......
package com.uva.monolith.services.users.models; package com.uva.monolith.services.hotels.models;
public enum Tipo { public enum RoomType {
SINGLE, SINGLE,
DOUBLE, DOUBLE,
SUITE SUITE
... ...
......
package com.uva.monolith.services.users.controllers;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.server.ResponseStatusException;
import com.uva.monolith.services.users.models.User;
import org.springframework.http.HttpStatus;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.beans.factory.annotation.Autowired;
import com.uva.monolith.services.users.repositories.UserRepository;
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
private final BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
public boolean verifyPassword(String rawPassword, String encodedPassword) {
return passwordEncoder.matches(rawPassword, encodedPassword);
}
public String encodePassword(String password) {
return passwordEncoder.encode(password);
}
public User findByEmail(@RequestParam String email) {
return userRepository.findByEmail(email)
.orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, "Usuario no encontrado"));
}
}
...@@ -9,9 +9,10 @@ import org.springframework.http.HttpStatus; ...@@ -9,9 +9,10 @@ import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpClientErrorException;
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.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;
@Service @Service
...@@ -20,11 +21,14 @@ public class UserService { ...@@ -20,11 +21,14 @@ public class UserService {
@Autowired @Autowired
private UserRepository userRepository; private UserRepository userRepository;
@Autowired
private ClientRepository clientRepository;
public List<User> getAllUsers() { public List<User> getAllUsers() {
return userRepository.findAll(); return userRepository.findAll();
} }
private User assertUser(Optional<User> opUser) { private User assertUser(Optional<? extends User> opUser) {
return opUser.orElseThrow(() -> new HttpClientErrorException(HttpStatus.NOT_FOUND)); return opUser.orElseThrow(() -> new HttpClientErrorException(HttpStatus.NOT_FOUND));
} }
...@@ -37,13 +41,14 @@ public class UserService { ...@@ -37,13 +41,14 @@ public class UserService {
} }
public User addUser(User user) { public User addUser(User user) {
// TODO Introducir medidas de seguridad? // Actualmente está en el servicio AUTH
// Establecemos valores por defecto // TODO adaptar adecuadamente
user.setStatus(UserStatus.NO_BOOKINGS); throw new HttpClientErrorException(HttpStatus.MOVED_PERMANENTLY, "servicio actual en http://localhost:8101/login");
if (user.getRol() == null) // Rol por defecto // user.setStatus(UserStatus.NO_BOOKINGS);
user.setRol(UserRol.CONSUMER); // if (user.getRol() == null) // Rol por defecto
// Guardamos // user.setRol(UserRol.CONSUMER);
return userRepository.save(user); // // Guardamos
// return userRepository.save(user);
} }
public User updateUserData(int id, String name, String email) { public User updateUserData(int id, String name, String email) {
...@@ -55,7 +60,7 @@ public class UserService { ...@@ -55,7 +60,7 @@ public class UserService {
public User updateUserStatus(int id, UserStatus status) { public User updateUserStatus(int id, UserStatus status) {
User user = getUserById(id); Client user = (Client) assertUser(clientRepository.findById(id));
boolean activeBookings = user.getBookings().stream() boolean activeBookings = user.getBookings().stream()
.anyMatch(booking -> !booking.getEndDate().isBefore(LocalDate.now())); // reserva >= ahora .anyMatch(booking -> !booking.getEndDate().isBefore(LocalDate.now())); // reserva >= ahora
...@@ -63,7 +68,6 @@ public class UserService { ...@@ -63,7 +68,6 @@ public class UserService {
.anyMatch(booking -> booking.getStartDate().isBefore(LocalDate.now())); // reserva < ahora .anyMatch(booking -> booking.getStartDate().isBefore(LocalDate.now())); // reserva < ahora
switch (status) { switch (status) {
// TODO Buscar como validar las (in)active bookings
case NO_BOOKINGS: case NO_BOOKINGS:
if (!user.getBookings().isEmpty()) if (!user.getBookings().isEmpty())
throw new IllegalArgumentException("Invalid State: The user has at least one booking"); throw new IllegalArgumentException("Invalid State: The user has at least one booking");
... ...
......
...@@ -3,9 +3,7 @@ package com.uva.authentication.api; ...@@ -3,9 +3,7 @@ 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.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;
...@@ -41,10 +39,11 @@ public class UserAPI { ...@@ -41,10 +39,11 @@ public class UserAPI {
public User getUserByEmail(String email) { public User getUserByEmail(String email) {
String token = getAccessToken(); // Implementación para acceder con autentificación
HttpHeaders headers = new HttpHeaders(); // String token = getAccessToken();
headers.set("Authorization", "Bearer " + token); // HttpHeaders headers = new HttpHeaders();
HttpEntity<Void> entity = new HttpEntity<>(headers); // headers.set("Authorization", "Bearer " + token);
// HttpEntity<Void> entity = new HttpEntity<>(headers);
String url = USER_API_URL + "?email={" + email + "}"; String url = USER_API_URL + "?email={" + email + "}";
try { try {
... ...
......
...@@ -22,7 +22,6 @@ public class AuthController { ...@@ -22,7 +22,6 @@ public class AuthController {
return ResponseEntity.ok(token); return ResponseEntity.ok(token);
} catch (HttpClientErrorException e) { } catch (HttpClientErrorException e) {
if (e.getStatusCode() == HttpStatus.FORBIDDEN) { if (e.getStatusCode() == HttpStatus.FORBIDDEN) {
// return new ResponseEntity<Void>(HttpStatus.FORBIDDEN);
return new ResponseEntity<String>(e.getMessage(), HttpStatus.FORBIDDEN); return new ResponseEntity<String>(e.getMessage(), HttpStatus.FORBIDDEN);
} }
} }
...@@ -40,7 +39,6 @@ public class AuthController { ...@@ -40,7 +39,6 @@ public class AuthController {
return login(loginRequest); return login(loginRequest);
} catch (HttpClientErrorException e) { } catch (HttpClientErrorException e) {
if (e.getStatusCode() == HttpStatus.CONFLICT) { if (e.getStatusCode() == HttpStatus.CONFLICT) {
// return new ResponseEntity<Void>(HttpStatus.FORBIDDEN);
return new ResponseEntity<String>(e.getMessage(), HttpStatus.CONFLICT); return new ResponseEntity<String>(e.getMessage(), HttpStatus.CONFLICT);
} }
e.fillInStackTrace(); e.fillInStackTrace();
... ...
......
...@@ -8,7 +8,6 @@ import org.springframework.http.HttpStatus; ...@@ -8,7 +8,6 @@ import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.HttpClientErrorException;
import com.uva.authentication.api.UserAPI;
import com.uva.authentication.models.Client; import com.uva.authentication.models.Client;
import com.uva.authentication.models.HotelManager; import com.uva.authentication.models.HotelManager;
import com.uva.authentication.models.LoginRequest; import com.uva.authentication.models.LoginRequest;
...@@ -33,9 +32,6 @@ public class AuthService { ...@@ -33,9 +32,6 @@ public class AuthService {
@Autowired @Autowired
private ClientRepository clientRepository; private ClientRepository clientRepository;
@Autowired
private UserAPI userAPI;
@Autowired @Autowired
private UserRepository userRepository; private UserRepository userRepository;
...@@ -46,49 +42,57 @@ public class AuthService { ...@@ -46,49 +42,57 @@ public class AuthService {
} }
public String login(LoginRequest loginRequest) { public String login(LoginRequest loginRequest) {
// User user = userAPI.getUserByEmail(loginRequest.getEmail());
User user = userRepository.findByEmail(loginRequest.getEmail()) User user = userRepository.findByEmail(loginRequest.getEmail())
.orElseThrow(() -> new HttpClientErrorException(HttpStatus.FORBIDDEN, .orElseThrow(() -> new HttpClientErrorException(HttpStatus.FORBIDDEN,
"Invalid credentials")); "Invalid credentials"));
boolean isAuthenticated = authenticateUser(loginRequest, user);
if (!isAuthenticated) { if (!authenticateUser(loginRequest, user)) {
throw new HttpClientErrorException(HttpStatus.FORBIDDEN, "Invalid credentials"); throw new HttpClientErrorException(HttpStatus.FORBIDDEN, "Invalid credentials");
} }
// Generate a mock JWT token for simplicity return jwtUtil.generateToken(user);
String jwtToken = "Bearer " + jwtUtil.generateToken(user);
return jwtToken;
} }
public User register(RegisterRequest registerRequest) { public User register(RegisterRequest registerRequest) {
// User user = userAPI.getUserByEmail(registerRequest.getEmail());
Optional<User> user = userRepository.findByEmail(registerRequest.getEmail()); Optional<User> user = userRepository.findByEmail(registerRequest.getEmail());
if (user.isPresent()) if (user.isPresent())
throw new HttpClientErrorException(HttpStatus.CONFLICT, "Email already in use"); throw new HttpClientErrorException(HttpStatus.CONFLICT, "Email already in use");
String hashPass = SecurityUtils.encrypt(registerRequest.getPassword()); return registerNewUser(registerRequest);
// return userAPI.registerUser(registerRequest); }
private User registerNewUser(RegisterRequest registerRequest) {
User newUser; User newUser;
if (registerRequest.getRol() == UserRol.HOTEL_ADMIN) {
// Ciframos la contraseña
String hashPass = SecurityUtils.encrypt(registerRequest.getPassword());
registerRequest.setPassword(hashPass);
// Aseguramos que tenga un rol, por defecto es cliente
if (registerRequest.getRol() == null)
registerRequest.setRol(UserRol.CLIENT);
switch (registerRequest.getRol()) {
case HOTEL_ADMIN:
HotelManager hm = new HotelManager(); HotelManager hm = new HotelManager();
// hm.setName(registerRequest.getName());
// hm.setEmail(registerRequest.getEmail());
// hm.setRol(registerRequest.getRol());
BeanUtils.copyProperties(registerRequest, hm); BeanUtils.copyProperties(registerRequest, hm);
hm.setPassword(hashPass);
newUser = hotelManagerRepository.save(hm); newUser = hotelManagerRepository.save(hm);
} else { break;
case ADMIN: // TODO revisar
User admin = new User();
BeanUtils.copyProperties(registerRequest, admin);
newUser = userRepository.save(admin);
break;
case CLIENT: // Por defecto cliente normal
default:
Client client = new Client(); Client client = new Client();
// client.setName(registerRequest.getName());
// client.setEmail(registerRequest.getEmail());
BeanUtils.copyProperties(registerRequest, client); BeanUtils.copyProperties(registerRequest, client);
client.setRol(UserRol.CLIENT); client.setRol(UserRol.CLIENT);
client.setPassword(hashPass);
newUser = clientRepository.save(client); newUser = clientRepository.save(client);
break;
} }
return newUser; return newUser;
} }
} }
...@@ -80,8 +80,6 @@ public class JwtUtil { ...@@ -80,8 +80,6 @@ public class JwtUtil {
private Key getSignInKey() { private Key getSignInKey() {
byte[] keyBytes = Decoders.BASE64.decode(secretKey); byte[] keyBytes = Decoders.BASE64.decode(secretKey);
// byte[] keyBytes = secretKey.getBytes(StandardCharsets.UTF_8); // for secret
// key
return Keys.hmacShaKeyFor(keyBytes); return Keys.hmacShaKeyFor(keyBytes);
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment