Skip to content

Commit

Permalink
Add DTO validation
Browse files Browse the repository at this point in the history
  • Loading branch information
wadiim committed Jun 18, 2024
1 parent 32d5597 commit c3769e6
Show file tree
Hide file tree
Showing 18 changed files with 71 additions and 22 deletions.
2 changes: 0 additions & 2 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3'

services:
database:
image: 'postgres:latest'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ public ResponseEntity<?> getAccountById(@PathVariable("uuid") UUID uuid) {
examples = @ExampleObject("500 Internal Server Error"))}
)
})
public ResponseEntity<?> updateAccount(@RequestHeader(value = HttpHeaders.IF_MATCH, required = false) String ifMatch, @RequestBody AccountUpdateDTO accountUpdateDTO) {
public ResponseEntity<?> updateAccount(@RequestHeader(value = HttpHeaders.IF_MATCH, required = false) String ifMatch, @Valid @RequestBody AccountUpdateDTO accountUpdateDTO) {
try {
if (ifMatch == null) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("If-match header is required");
Expand Down Expand Up @@ -280,7 +280,7 @@ public ResponseEntity<?> unblockAccount(@PathVariable("uuid") UUID uuid) {
examples = @ExampleObject("500 Internal Server Error"))}
)
})
public ResponseEntity<?> changePassword(@RequestBody ChangeSelfPasswordDTO dto) {
public ResponseEntity<?> changePassword(@Valid @RequestBody ChangeSelfPasswordDTO dto) {
try {
String login = SecurityContextHolder.getContext().getAuthentication().getName();
accountService.changePassword(dto, login);
Expand Down Expand Up @@ -365,7 +365,7 @@ public ResponseEntity<?> getSelf() {
examples = @ExampleObject("500 Internal Server Error"))}
)
})
public ResponseEntity<?> updateSelf(@RequestHeader(value = HttpHeaders.IF_MATCH, required = false) String ifMatch, @RequestBody AccountUpdateDTO accountUpdateDTO) {
public ResponseEntity<?> updateSelf(@RequestHeader(value = HttpHeaders.IF_MATCH, required = false) String ifMatch, @Valid @RequestBody AccountUpdateDTO accountUpdateDTO) {
try {
if (ifMatch == null) {
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("If-match header is required");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.http.HttpStatus;
Expand Down Expand Up @@ -46,7 +48,7 @@ public class AuthenticationController {
examples = @ExampleObject("500 Internal Server Error"))}
),
})
public ResponseEntity<?> register(@RequestBody RegisterAccountDTO clientData) {
public ResponseEntity<?> register(@Valid @RequestBody RegisterAccountDTO clientData) {
try {
accountService.registerClient(clientData);
return ResponseEntity.status(HttpStatus.CREATED).body("Account created successfully");
Expand Down Expand Up @@ -88,7 +90,7 @@ public ResponseEntity<?> register(@RequestBody RegisterAccountDTO clientData) {
examples = @ExampleObject("500 Internal Server Error"))}
)
})
public ResponseEntity<?> login(@RequestBody LoginDTO credentials) {
public ResponseEntity<?> login(@Valid @RequestBody LoginDTO credentials) {
try {
String token = accountService.login(credentials);
return new ResponseEntity<>(token, HttpStatus.OK);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import jakarta.validation.Valid;

@RestController
@RequestMapping("/api/reservtions")
Expand Down Expand Up @@ -135,7 +136,7 @@ public ResponseEntity<?> getOwnReservations() {
examples = @ExampleObject("500 Internal Server Error"))}
)
})
public ResponseEntity<?> createReservation(ReservationCreateDTO reservationCreateDTO) {
public ResponseEntity<?> createReservation(@Valid ReservationCreateDTO reservationCreateDTO) {
String login = SecurityContextHolder.getContext().getAuthentication().getName();
try {
Account account = accountService.getAccountByLogin(login);
Expand Down
8 changes: 5 additions & 3 deletions src/main/java/org/zzpj/tabi/controllers/TravelController.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import io.swagger.v3.oas.annotations.responses.ApiResponses;

import jakarta.persistence.OptimisticLockException;
import jakarta.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
Expand Down Expand Up @@ -68,7 +70,7 @@ public class TravelController {
examples = @ExampleObject("500 Internal Server Error"))}
)
})
public ResponseEntity<?> createTravel(@RequestBody TravelCreateDTO travelCreateDTO) {
public ResponseEntity<?> createTravel(@Valid @RequestBody TravelCreateDTO travelCreateDTO) {
try{
String login = SecurityContextHolder.getContext().getAuthentication().getName();
Account account = accountService.getAccountByLogin(login);
Expand Down Expand Up @@ -210,7 +212,7 @@ public ResponseEntity<?> getTravelReviews(@PathVariable("uuid") UUID uuid) {
examples = @ExampleObject("500 Internal Server Error"))}
)
})
public ResponseEntity<?> addReview(@RequestBody ReviewUpdateDTO review) {
public ResponseEntity<?> addReview(@Valid @RequestBody ReviewUpdateDTO review) {
try {
String name = SecurityContextHolder.getContext().getAuthentication().getName();
reviewService.addReview(review, name);
Expand Down Expand Up @@ -259,7 +261,7 @@ public ResponseEntity<?> addReview(@RequestBody ReviewUpdateDTO review) {
examples = @ExampleObject("500 Internal Server Error"))}
)
})
public ResponseEntity<?> editReview(@RequestBody ReviewUpdateDTO review) {
public ResponseEntity<?> editReview(@Valid @RequestBody ReviewUpdateDTO review) {
try {
String name = SecurityContextHolder.getContext().getAuthentication().getName();
reviewService.editReview(review, name);
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/zzpj/tabi/dto/account/AccountUpdateDTO.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.zzpj.tabi.dto.account;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
Expand All @@ -21,6 +22,7 @@ public class AccountUpdateDTO {
private String lastName;

@Schema(example = "[email protected]")
@Email
private String email;

@Schema(example = "0")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.zzpj.tabi.dto.account;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
Expand All @@ -10,8 +11,10 @@
public class ChangeSelfPasswordDTO {

@Schema(example = "foo")
@NotEmpty
private String oldPassword;

@Schema(example = "oof")
@NotEmpty
private String newPassword;
}
3 changes: 3 additions & 0 deletions src/main/java/org/zzpj/tabi/dto/account/LoginDTO.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.zzpj.tabi.dto.account;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
Expand All @@ -10,8 +11,10 @@
public class LoginDTO {

@Schema(example = "foo")
@NotEmpty
private String login;

@Schema(example = "foo")
@NotEmpty
private String password;
}
10 changes: 9 additions & 1 deletion src/main/java/org/zzpj/tabi/dto/account/RegisterAccountDTO.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.zzpj.tabi.dto.account;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
Expand All @@ -10,17 +12,23 @@
public class RegisterAccountDTO {

@Schema(example = "qux")
@NotEmpty
private String login;

@Schema(example = "John")
@NotEmpty
private String firstName;

@Schema(example = "Doe")
@NotEmpty
private String lastName;

@Schema(example = "[email protected]")
@Schema(example = "[email protected]")
@NotEmpty
@Email
private String email;

@Schema(example = "password")
@NotEmpty
private String password;
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.util.UUID;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Positive;
import lombok.Data;

@Data
Expand All @@ -12,5 +14,7 @@ public class ReservationCreateDTO {
private UUID travelId;

@Schema(example = "1")
@NotEmpty
@Positive
private int guestCount;
}
5 changes: 5 additions & 0 deletions src/main/java/org/zzpj/tabi/dto/review/ReviewUpdateDTO.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package org.zzpj.tabi.dto.review;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotEmpty;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
Expand All @@ -12,11 +15,13 @@
public class ReviewUpdateDTO {

@Schema(example = "5")
@Min(0) @Max(10)
private int rating;

@Schema(example = "I've changed my mind.")
private String comment;

@Schema(example = "00000000-0000-0000-0001-000000000001")
@NotEmpty
private UUID travelId;
}
8 changes: 8 additions & 0 deletions src/main/java/org/zzpj/tabi/dto/travel/TravelCreateDTO.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.zzpj.tabi.dto.travel;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Positive;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
Expand All @@ -13,19 +15,23 @@
public class TravelCreateDTO {

@Schema(example = "China: Imperial cities and natural wonders")
@NotEmpty
private String title;

@Schema(
example = "From the iconic Great Wall to Shanghai's soaring "
+ "skyscrapers, all the way up to the 'Roof of the World', China "
+ "guarantees an unforgettable experience"
)
@NotEmpty
private String description;

@Schema(example = "China")
@NotEmpty
private String place;

@Schema(example = "4999.99")
@Positive
private BigDecimal basePrice;

@Schema(example = "2025-12-15")
Expand All @@ -35,8 +41,10 @@ public class TravelCreateDTO {
private LocalDate endDate;

@Schema(example = "100")
@Positive
private int maxPlaces;

@Schema(example = "10")
@Positive
private int available;
}
4 changes: 4 additions & 0 deletions src/main/java/org/zzpj/tabi/dto/travel/TravelUpdateDTO.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.zzpj.tabi.dto.travel;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Positive;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;
Expand All @@ -24,5 +26,7 @@ public class TravelUpdateDTO {
private String description;

@Schema(example = "0")
@Positive
@NotEmpty
private Long version;
}
3 changes: 2 additions & 1 deletion src/main/java/org/zzpj/tabi/entities/Travel.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import jakarta.persistence.*;
import jakarta.validation.constraints.Positive;
import jakarta.validation.constraints.PositiveOrZero;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
Expand Down Expand Up @@ -57,7 +58,7 @@ public class Travel {
@Column(name = "max_places", nullable = false)
private int maxPlaces;

@Positive
@PositiveOrZero
@Column(name = "available_places", nullable = false)
private int availablePlaces;

Expand Down
6 changes: 4 additions & 2 deletions src/main/java/org/zzpj/tabi/security/jws/JwsService.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package org.zzpj.tabi.security.jws;

import io.jsonwebtoken.Jwts;
import jakarta.validation.Valid;

import org.springframework.stereotype.Service;
import org.zzpj.tabi.dto.account.AccountUpdateDTO;
import org.zzpj.tabi.dto.travel.TravelUpdateDTO;
Expand All @@ -21,7 +23,7 @@ public String signAccount(Account account) {
.compact();
}

public String signDataFromAccountUpdateDTO(AccountUpdateDTO accountUpdateDTO) {
public String signDataFromAccountUpdateDTO(@Valid AccountUpdateDTO accountUpdateDTO) {
return Jwts.builder()
.claim("id", accountUpdateDTO.getId())
.claim("version", accountUpdateDTO.getVersion())
Expand All @@ -37,7 +39,7 @@ public String signDataFromTravelUpdateDTO(TravelUpdateDTO travelUpdateDTO) {
.compact();
}

public boolean isIfMatchValid(String if_match, AccountUpdateDTO accountUpdateDTO) {
public boolean isIfMatchValid(String if_match, @Valid AccountUpdateDTO accountUpdateDTO) {
return if_match.equals(this.signDataFromAccountUpdateDTO(accountUpdateDTO));
}

Expand Down
10 changes: 6 additions & 4 deletions src/main/java/org/zzpj/tabi/services/AccountService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import java.util.UUID;

import jakarta.persistence.OptimisticLockException;
import jakarta.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
Expand Down Expand Up @@ -48,7 +50,7 @@ public Account getAccountByLogin(String login) throws AccountNotFoundException {
return accountRepository.findByLogin(login).orElseThrow(AccountNotFoundException::new);
}

public void registerClient(RegisterAccountDTO dto) {
public void registerClient(@Valid RegisterAccountDTO dto) {
Client client = Client.builder()
.login(dto.getLogin())
.firstName(dto.getFirstName())
Expand All @@ -61,7 +63,7 @@ public void registerClient(RegisterAccountDTO dto) {
accountRepository.save(client);
}

public String login(LoginDTO credentials) {
public String login(@Valid LoginDTO credentials) {
String login = credentials.getLogin();
String password = credentials.getPassword();

Expand All @@ -71,7 +73,7 @@ public String login(LoginDTO credentials) {
return jwtService.generateToken(user.get());
}

public void modifyAccount(AccountUpdateDTO accountUpdateDTO, UUID id) throws AccountNotFoundException {
public void modifyAccount(@Valid AccountUpdateDTO accountUpdateDTO, UUID id) throws AccountNotFoundException {
Account account = accountRepository.findById(id).orElseThrow(AccountNotFoundException::new);

if (!accountUpdateDTO.getVersion().equals(account.getVersion())) {
Expand All @@ -85,7 +87,7 @@ public void modifyAccount(AccountUpdateDTO accountUpdateDTO, UUID id) throws Acc
accountRepository.save(account);
}

public void changePassword(ChangeSelfPasswordDTO dto, String login) throws AccountNotFoundException, OldPasswordNotMatchException {
public void changePassword(@Valid ChangeSelfPasswordDTO dto, String login) throws AccountNotFoundException, OldPasswordNotMatchException {
Account account = accountRepository.findByLogin(login).orElseThrow(AccountNotFoundException::new);

if (!passwordEncoder.matches(dto.getOldPassword(), account.getPassword())) {
Expand Down
Loading

0 comments on commit c3769e6

Please sign in to comment.