From fe34479ebba79392aab5d886b7c3f907bfac9885 Mon Sep 17 00:00:00 2001 From: kovba18 <kovacs.balazs.2@hallgato.ppke.hu> Date: Wed, 15 May 2024 01:01:10 +0200 Subject: [PATCH] request validations for dogs and users --- .../hu/pazmany/controller/Controller.java | 385 +++++++++--------- 1 file changed, 184 insertions(+), 201 deletions(-) diff --git a/backend/src/main/java/hu/pazmany/controller/Controller.java b/backend/src/main/java/hu/pazmany/controller/Controller.java index bf9396b..8ba5156 100644 --- a/backend/src/main/java/hu/pazmany/controller/Controller.java +++ b/backend/src/main/java/hu/pazmany/controller/Controller.java @@ -7,6 +7,7 @@ import hu.pazmany.dto.UserDTO; import hu.pazmany.security.JwtTokenProvider; import hu.pazmany.service.DogService; import hu.pazmany.service.UserService; +import io.micrometer.common.lang.Nullable; import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -17,211 +18,193 @@ import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.regex.Pattern; @RestController @RequestMapping("/api") public class Controller { - private final DogService dogService; - private final UserService userService; - private final JwtTokenProvider jwtTokenProvider = JwtTokenProvider.getInstance(); - - @Autowired - public Controller(DogService dogService, UserService userService) { - this.dogService = dogService; - this.userService = userService; - } - - - @GetMapping("/dogs") - public List<DogDTO> getAllDogs() { - return dogService.getAllDogs(); - } - - @GetMapping("/dogs/{id}") - public ResponseEntity<?> getDogById(@PathVariable Integer id) { - return dogService.get(id) - .map(dogEntity -> ResponseEntity.ok(new DetailedDogDTO( - dogEntity.getId(), - dogEntity.getName(), - dogEntity.getPicture(), - dogEntity.getAge(), - dogEntity.getBreed()))) - .orElse(ResponseEntity.notFound().build()); - } - - @PostMapping(value = "/newdog") - public ResponseEntity<?> addNewDog(@RequestHeader("Authorization") String token, @RequestParam("dog") String stringDogDTO, @RequestParam(value = "picture", required = false) MultipartFile mpf) { - if (!isValidToken(token)) return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - - ObjectMapper objectMapper = new ObjectMapper(); - DetailedDogDTO dogDTO; - try { - dogDTO = objectMapper.readValue(stringDogDTO, DetailedDogDTO.class); - } catch (IOException e) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Hibás JSON formátum"); - } - // Save the dog and picture - try { - if (mpf != null && !mpf.isEmpty()) { - dogService.addNewDog(dogDTO, mpf); - } else { - dogService.addNewDog(dogDTO, null); - } - } catch (IOException e) { - return ResponseEntity.status(HttpStatus.NO_CONTENT).body("Hibás képformátum"); - } - return ResponseEntity.status(HttpStatus.CREATED).body("Kutya sikeresen hozzáadva"); - } - - @PostMapping(value = "/dogs/{id}/edit", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - public ResponseEntity<?> editDog(@PathVariable Integer id, @RequestHeader("Authorization") String token, @RequestParam("dog") String stringDogDTO, @RequestParam(value = "picture", required = false) MultipartFile mpf) { - if (!isValidToken(token)) return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - - // Retrieve the dog entity from the database - Optional<DetailedDogDTO> optionalDog = dogService.get(id); - ObjectMapper objectMapper = new ObjectMapper(); - DetailedDogDTO dogDTO; - if (optionalDog.isPresent()) { - try { - dogDTO = objectMapper.readValue(stringDogDTO, DetailedDogDTO.class); - } catch (IOException e) { - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Hibás JSON formátum"); - } - // Save the updated dog entity - try { - if (mpf != null && !mpf.isEmpty()) { - dogService.editDog(id, dogDTO, mpf); - } else { - dogService.editDog(id, dogDTO, null); - } - } catch (IOException e) { - return ResponseEntity.status(HttpStatus.NO_CONTENT).body("Hibás képformátum"); - } - - return ResponseEntity.ok("Kutya sikeresen módosítva"); - } else { - return ResponseEntity.notFound().build(); - } - } - - @DeleteMapping("/dogs/{id}") - public ResponseEntity<?> deleteDog(@PathVariable Integer id, @RequestHeader("Authorization") String token) { - if (!isValidToken(token)) return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - - dogService.deleteDog(id); - return ResponseEntity.ok().build(); - } - - @PostMapping("/register") - public ResponseEntity<?> registerUser(@Valid @RequestBody UserDTO request) { - // Validate the registration request - ValidationError validationError = validateRegisterRequest(request); - if (validationError != null) { - return ResponseEntity.badRequest().body(validationError.getMessage()); - } - - // Check if the username is already taken - if (userService.isUserExists(request.getUsername())) { - return ResponseEntity.badRequest().body("Felhasználónév foglalt"); - } - - // Save the user entity - userService.registerUser(request); - - return ResponseEntity.status(HttpStatus.CREATED).body("Felhasználó sikeresen létrehozva"); - } - - @PostMapping("/login") - public ResponseEntity<UserDTO> login(@Valid @RequestBody UserDTO request) { - if (!isValidLoginRequest(request)) { - return ResponseEntity.badRequest().body(null); - } - - UserDTO userDTO = userService.login(request, jwtTokenProvider); - - if (userDTO == null) { - return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); - } - - return ResponseEntity.ok(userDTO); - } - - - /*-------- Validation functions --------*/ - - private boolean isValidLoginRequest(UserDTO request) { - if (request == null) { - return false; - } - - String username = request.getUsername(); - String password = request.getPassword(); - return username != null && !username.isEmpty() && password != null && !password.isEmpty(); - - // If all checks pass, return true - } - - private ValidationError validateRegisterRequest(UserDTO request) { - String username_regex = "^\\w{5,20}$"; - // username can contain numbers, upper and lowercase characters - String password_regex = "^(?=.*[A-Z])(?=.*\\d)[A-Za-z\\d]{8,20}$"; - - if (request == null || request.getUsername() == null || request.getPassword() == null) { - return new RequestValidationError(); - } - if (!Pattern.matches(username_regex, request.getUsername())) { - return new UsernameValidationError(); - } - if (!Pattern.matches(password_regex, request.getPassword())) { - return new PasswordValidationError(); - } - - return null; - } - - private boolean isValidToken(String token) { - return token != null && verifyTokenSignature(token); - } - - private boolean verifyTokenSignature(String token) { - if (token.startsWith("Bearer ")) { - token = token.substring(7); - return jwtTokenProvider.validateToken(token); - } else { - return false; - } - - } - - private abstract static class ValidationError { - private final String message; - - public String getMessage() { - return message; - } - - ValidationError(String m) { - message = m; - } - } - - private static class RequestValidationError extends ValidationError { - RequestValidationError() { - super("Érvénytelen kérés"); - } - } - - private static class UsernameValidationError extends ValidationError { - UsernameValidationError() { - super("Érvénytelen felhasználónév"); - } - } - - private static class PasswordValidationError extends ValidationError { - PasswordValidationError() { - super("Érvénytelen jelszó"); - } - } + private final DogService dogService; + private final UserService userService; + private final JwtTokenProvider jwtTokenProvider = JwtTokenProvider.getInstance(); + + @Autowired + public Controller(DogService dogService, UserService userService) { + this.dogService = dogService; + this.userService = userService; + } + + + @GetMapping("/dogs") + public List<DogDTO> getAllDogs() { + return dogService.getAllDogs(); + } + + @GetMapping("/dogs/{id}") + public ResponseEntity<?> getDogById(@PathVariable Integer id) { + return dogService.get(id) + .map(dogEntity -> ResponseEntity.ok(new DetailedDogDTO( + dogEntity.getId(), + dogEntity.getName(), + dogEntity.getPicture(), + dogEntity.getAge(), + dogEntity.getBreed()))) + .orElse(ResponseEntity.notFound().build()); + } + + @PostMapping(value = "/newdog") + public ResponseEntity<?> addNewDog(@RequestHeader("Authorization") String token, @RequestParam("dog") String stringDogDTO, @RequestParam(value = "picture", required = false) MultipartFile mpf) { + if (inValidToken(token)) return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + + ObjectMapper objectMapper = new ObjectMapper(); + DetailedDogDTO dogDTO; + try { + dogDTO = objectMapper.readValue(stringDogDTO, DetailedDogDTO.class); + ResponseEntity<?> response = validateDogData(dogDTO); + if (Objects.nonNull(response)) return response; + } catch (IOException e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Hibás JSON formátum"); + } + // Save the dog and picture + try { + if (mpf != null && !mpf.isEmpty()) { + dogService.addNewDog(dogDTO, mpf); + } else { + dogService.addNewDog(dogDTO, null); + } + } catch (IOException e) { + return ResponseEntity.status(HttpStatus.NO_CONTENT).body("Hibás képformátum"); + } + return ResponseEntity.status(HttpStatus.CREATED).body("Kutya sikeresen hozzáadva"); + } + + @PostMapping(value = "/dogs/{id}/edit", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + public ResponseEntity<?> editDog(@PathVariable Integer id, @RequestHeader("Authorization") String token, @RequestParam("dog") String stringDogDTO, @RequestParam(value = "picture", required = false) MultipartFile mpf) { + if (inValidToken(token)) return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + + // Retrieve the dog entity from the database + Optional<DetailedDogDTO> optionalDog = dogService.get(id); + ObjectMapper objectMapper = new ObjectMapper(); + DetailedDogDTO dogDTO; + if (optionalDog.isPresent()) { + try { + dogDTO = objectMapper.readValue(stringDogDTO, DetailedDogDTO.class); + ResponseEntity<?> response = validateDogData(dogDTO); + if (Objects.nonNull(response)) return response; + } catch (IOException e) { + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("Hibás JSON formátum"); + } + // Save the updated dog entity + try { + if (mpf != null && !mpf.isEmpty()) { + dogService.editDog(id, dogDTO, mpf); + } else { + dogService.editDog(id, dogDTO, null); + } + } catch (IOException e) { + return ResponseEntity.status(HttpStatus.NO_CONTENT).body("Hibás képformátum"); + } + + return ResponseEntity.ok("Kutya sikeresen módosítva"); + } else { + return ResponseEntity.notFound().build(); + } + } + + @DeleteMapping("/dogs/{id}") + public ResponseEntity<?> deleteDog(@PathVariable Integer id, @RequestHeader("Authorization") String token) { + if (inValidToken(token)) return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + + dogService.deleteDog(id); + return ResponseEntity.ok().build(); + } + + @PostMapping("/register") + public ResponseEntity<?> registerUser(@Valid @RequestBody UserDTO request) { + // Validating and registering user inside a single function + if (request == null || request.getUsername() == null || request.getPassword() == null) + return ResponseEntity.badRequest().body("Érvénytelen kérés"); + + ResponseEntity<?> response = validateRegister(request); + if (Objects.nonNull(response)) return response; + + // Save the user entity + userService.registerUser(request); + return ResponseEntity.status(HttpStatus.CREATED).body("Felhasználó sikeresen regisztrálva"); + } + + @PostMapping("/login") + public ResponseEntity<UserDTO> login(@Valid @RequestBody UserDTO request) { + if (!isValidLoginRequest(request)) { + return ResponseEntity.badRequest().body(null); + } + + UserDTO userDTO = userService.login(request, jwtTokenProvider); + + if (userDTO == null) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); + } + + return ResponseEntity.ok(userDTO); + } + + + /*-------- Independent validation functions --------*/ + + @Nullable + public ResponseEntity<?> validateDogData(@Valid @RequestBody DetailedDogDTO request) { + if (request.getName().length() < 2 || request.getName().length() > 20) + return ResponseEntity.badRequest().body("A kutyanév 2 és 20 karakter között legyen"); + if (!Pattern.matches("^[A-Z][a-z]*$",request.getName())) + return ResponseEntity.badRequest().body("A kutyanév kis- és nagybetűkből álljon"); + if (request.getAge() < 0) + return ResponseEntity.badRequest().body("A kutya életkora nem lehet negatív"); + return null; + } + @Nullable + private ResponseEntity<?> validateRegister(@Valid @RequestBody UserDTO request) { + // Check if the username is already taken + if (userService.isUserExists(request.getUsername())) + return ResponseEntity.badRequest().body("Felhasználónév már létezik"); + + if(!Pattern.matches("^[a-zA-Z0-9]+$", request.getUsername())) + return ResponseEntity.badRequest().body("A felhasználónév csak betűket és számokat tartalmazhat"); + + if(request.getUsername().length() < 5 || request.getUsername().length() > 20) + return ResponseEntity.badRequest().body("A felhasználónév hossza 5 és 20 karakter között legyen"); + + if(request.getPassword().length() < 8 || request.getPassword().length() > 20) + return ResponseEntity.badRequest().body("A jelszó hossza 5 és 20 karakter között legyen"); + + if(!Pattern.matches("^(?=.*[A-Z])(?=.*\\d)[A-Za-z\\d]+$", request.getPassword())) + return ResponseEntity.badRequest().body("A jelszó tartalmazzon nagybetűt és számot"); + return null; + } + + private boolean isValidLoginRequest(UserDTO request) { + if (request == null) { + return false; + } + + String username = request.getUsername(); + String password = request.getPassword(); + return username != null && !username.isEmpty() && password != null && !password.isEmpty(); + + // If all checks pass, return true + } + private boolean inValidToken(String token) { + return token == null || !verifyTokenSignature(token); + } + + private boolean verifyTokenSignature(String token) { + if (token.startsWith("Bearer ")) { + token = token.substring(7); + return jwtTokenProvider.validateToken(token); + } else { + return false; + } + + } + } -- GitLab