Skip to content

Commit

Permalink
[BE] feat: validation μΆ”κ°€ (#113) (#365)
Browse files Browse the repository at this point in the history
* feat: μ–΄λ…Έν…Œμ΄μ…˜ 기반의 Spring validation μΆ”κ°€

* feat: 도메인 validation μΆ”κ°€

* feat: lineUp 은 null 일 수 μžˆλ‹€.

* feat: dto validation μΆ”κ°€

* feat: MethodArgumentNotValidException 에 λŒ€ν•œ custom 핸듀링

* feat: dto 의 μ˜ˆμ™Έ λ©”μ‹œμ§€ μ§€μ •ν•œλ‹€

* fix: Member 의 profileImage κ°€ null 인 경우의 null check 제거

* feat: length 검증 μ „ null check κ°€ μ„ ν–‰λ˜λ„λ‘ λ³€κ²½

* refactor: Objects.isNull -> == null ν™•μΈμœΌλ‘œ λ³€κ²½

* feat: Service Entity 생성 둜직 μ‚­μ œ

* feat: socialType Enumerated μΆ”κ°€

* feat: @RequestBody validate μΆ”κ°€

* feat: dto @Valid μ‹€νŒ¨μ‹œ 400 response
  • Loading branch information
BGuga committed Oct 17, 2023
1 parent 545715d commit 046f5d4
Show file tree
Hide file tree
Showing 21 changed files with 283 additions and 43 deletions.
5 changes: 4 additions & 1 deletion backend/src/main/java/com/festago/auth/dto/LoginRequest.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package com.festago.auth.dto;

import com.festago.auth.domain.SocialType;
import jakarta.validation.constraints.NotNull;

public record LoginRequest(SocialType socialType, String accessToken) {
public record LoginRequest(
@NotNull(message = "socialType 은 null 일 수 μ—†μŠ΅λ‹ˆλ‹€.") SocialType socialType,
@NotNull(message = "acessToken 은 null 일 수 μ—†μŠ΅λ‹ˆλ‹€.") String accessToken) {

}
41 changes: 39 additions & 2 deletions backend/src/main/java/com/festago/domain/Festival.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.time.LocalDate;
import java.time.LocalDateTime;

Expand All @@ -18,12 +20,18 @@ public class Festival extends BaseTimeEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@NotNull
@Size(max = 50)
private String name;

@NotNull
private LocalDate startDate;

@NotNull
private LocalDate endDate;

@NotNull
@Size(max = 255)
private String thumbnail;

protected Festival() {
Expand All @@ -38,15 +46,44 @@ public Festival(String name, LocalDate startDate, LocalDate endDate, String thum
}

public Festival(Long id, String name, LocalDate startDate, LocalDate endDate, String thumbnail) {
validate(startDate, endDate);
validate(name, startDate, endDate, thumbnail);
this.id = id;
this.name = name;
this.startDate = startDate;
this.endDate = endDate;
this.thumbnail = thumbnail;
}

private void validate(LocalDate startDate, LocalDate endDate) {
private void validate(String name, LocalDate startDate, LocalDate endDate, String thumbnail) {
checkNotNull(name, startDate, endDate, thumbnail);
checkLength(name, thumbnail);
validateDate(startDate, endDate);
}

private void checkNotNull(String name, LocalDate startDate, LocalDate endDate, String thumbnail) {
if (name == null ||
startDate == null ||
endDate == null ||
thumbnail == null) {
throw new IllegalArgumentException("Festival 은 ν—ˆμš©λ˜μ§€ μ•Šμ€ null κ°’μœΌλ‘œ 생성할 수 μ—†μŠ΅λ‹ˆλ‹€.");
}
}

private void checkLength(String name, String thumbnail) {
if (overLength(name, 50) ||
overLength(thumbnail, 255)) {
throw new IllegalArgumentException("Festival 의 ν•„λ“œλ‘œ ν—ˆμš©λœ 길이λ₯Ό λ„˜μ€ column 을 넣을 수 μ—†μŠ΅λ‹ˆλ‹€.");
}
}

private boolean overLength(String target, int maxLength) {
if (target == null) {
return false;
}
return target.length() > maxLength;
}

private void validateDate(LocalDate startDate, LocalDate endDate) {
if (startDate.isAfter(endDate)) {
throw new BadRequestException(ErrorCode.INVALID_FESTIVAL_DURATION);
}
Expand Down
42 changes: 40 additions & 2 deletions backend/src/main/java/com/festago/domain/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.time.LocalDateTime;
import org.hibernate.annotations.SQLDelete;
import org.hibernate.annotations.Where;
Expand All @@ -17,18 +19,25 @@
public class Member extends BaseTimeEntity {

private static final String DEFAULT_IMAGE_URL = "https://festa-go.site/images/default-profile.png";

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@NotNull
@Size(max = 255)
private String socialId;

@Enumerated(EnumType.STRING)
@NotNull
@Enumerated(value = EnumType.STRING)
private SocialType socialType;

@NotNull
@Size(max = 30)
private String nickname;

@NotNull
@Size(max = 255)
private String profileImage;

private LocalDateTime deletedAt = null;
Expand All @@ -45,13 +54,42 @@ public Member(String socialId, SocialType socialType, String nickname, String pr
}

public Member(Long id, String socialId, SocialType socialType, String nickname, String profileImage) {
validate(socialId, socialType, nickname, profileImage);
this.id = id;
this.socialId = socialId;
this.socialType = socialType;
this.nickname = nickname;
this.profileImage = (profileImage != null) ? profileImage : DEFAULT_IMAGE_URL;
}

private void validate(String socialId, SocialType socialType, String nickname, String profileImage) {
checkNotNull(socialId, socialType, nickname);
checkLength(socialId, nickname, profileImage);
}

private void checkNotNull(String socialId, SocialType socialType, String nickname) {
if (socialId == null ||
socialType == null ||
nickname == null) {
throw new IllegalArgumentException("Member λŠ” ν—ˆμš©λ˜μ§€ μ•Šμ€ null κ°’μœΌλ‘œ 생성할 수 μ—†μŠ΅λ‹ˆλ‹€.");
}
}

private void checkLength(String socialId, String nickname, String profileImage) {
if (overLength(socialId, 255) ||
overLength(nickname, 30) ||
overLength(profileImage, 255)) {
throw new IllegalArgumentException("Member 의 ν•„λ“œλ‘œ ν—ˆμš©λœ 길이λ₯Ό λ„˜μ€ column 을 넣을 수 μ—†μŠ΅λ‹ˆλ‹€.");
}
}

private boolean overLength(String target, int maxLength) {
if (target == null) {
return false;
}
return target.length() > maxLength;
}

public Long getId() {
return id;
}
Expand Down
29 changes: 29 additions & 0 deletions backend/src/main/java/com/festago/domain/MemberTicket.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.Objects;

Expand All @@ -20,19 +22,25 @@ public class MemberTicket extends BaseTimeEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@NotNull
@Enumerated(EnumType.STRING)
private EntryState entryState = EntryState.BEFORE_ENTRY;

@NotNull
@ManyToOne(fetch = FetchType.LAZY)
private Member owner;

@NotNull
@ManyToOne(fetch = FetchType.LAZY)
private Stage stage;

@Min(value = 0)
private int number;

@NotNull
private LocalDateTime entryTime;

@NotNull
@Enumerated(EnumType.STRING)
private TicketType ticketType;

Expand All @@ -45,6 +53,7 @@ public MemberTicket(Member owner, Stage stage, int number, LocalDateTime entryTi

public MemberTicket(Long id, Member owner, Stage stage, int number, LocalDateTime entryTime,
TicketType ticketType) {
validate(owner, stage, number, entryTime, ticketType);
this.id = id;
this.owner = owner;
this.stage = stage;
Expand All @@ -53,6 +62,26 @@ public MemberTicket(Long id, Member owner, Stage stage, int number, LocalDateTim
this.ticketType = ticketType;
}

private void validate(Member owner, Stage stage, int number, LocalDateTime entryTime, TicketType ticketType) {
checkNotNull(owner, stage, entryTime, ticketType);
checkScope(number);
}

private void checkNotNull(Member owner, Stage stage, LocalDateTime entryTime, TicketType ticketType) {
if (owner == null ||
stage == null ||
entryTime == null ||
ticketType == null) {
throw new IllegalArgumentException("MemberTicket 은 ν—ˆμš©λ˜μ§€ μ•Šμ€ null κ°’μœΌλ‘œ 생성할 수 μ—†μŠ΅λ‹ˆλ‹€.");
}
}

private void checkScope(int number) {
if (number < 0) {
throw new IllegalArgumentException("MemberTicket 의 ν•„λ“œλ‘œ ν—ˆμš©λœ λ²”μœ„λ₯Ό λ„˜μ€ column 을 넣을 수 μ—†μŠ΅λ‹ˆλ‹€.");
}
}

public void changeState(EntryState originState) {
if (originState != this.entryState) {
return;
Expand Down
43 changes: 39 additions & 4 deletions backend/src/main/java/com/festago/domain/Stage.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@

import com.festago.exception.BadRequestException;
import com.festago.exception.ErrorCode;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
Expand All @@ -21,13 +22,16 @@ public class Stage extends BaseTimeEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(nullable = false)
@NotNull
private LocalDateTime startTime;

@Size(max = 255)
private String lineUp;

@NotNull
private LocalDateTime ticketOpenTime;

@NotNull
@ManyToOne(fetch = FetchType.LAZY)
private Festival festival;

Expand All @@ -41,17 +45,48 @@ public Stage(LocalDateTime startTime, String lineUp, LocalDateTime ticketOpenTim
this(null, startTime, lineUp, ticketOpenTime, festival);
}

public Stage(LocalDateTime startTime, LocalDateTime ticketOpenTime, Festival festival) {
this(null, startTime, null, ticketOpenTime, festival);
}

public Stage(Long id, LocalDateTime startTime, String lineUp, LocalDateTime ticketOpenTime,
Festival festival) {
validate(startTime, ticketOpenTime, festival);
validate(startTime, lineUp, ticketOpenTime, festival);
this.id = id;
this.startTime = startTime;
this.lineUp = lineUp;
this.ticketOpenTime = ticketOpenTime;
this.festival = festival;
}

private void validate(LocalDateTime startTime, LocalDateTime ticketOpenTime, Festival festival) {
private void validate(LocalDateTime startTime, String lineUp, LocalDateTime ticketOpenTime, Festival festival) {
checkNotNull(startTime, ticketOpenTime, festival);
checkLength(lineUp);
validateTime(startTime, ticketOpenTime, festival);
}

private void checkNotNull(LocalDateTime startTime, LocalDateTime ticketOpenTime, Festival festival) {
if (startTime == null ||
ticketOpenTime == null ||
festival == null) {
throw new IllegalArgumentException("Stage λŠ” ν—ˆμš©λ˜μ§€ μ•Šμ€ null κ°’μœΌλ‘œ 생성할 수 μ—†μŠ΅λ‹ˆλ‹€.");
}
}

private void checkLength(String lineUp) {
if (overLength(lineUp, 255)) {
throw new IllegalArgumentException("Stage 의 ν•„λ“œλ‘œ ν—ˆμš©λœ λ²”μœ„λ₯Ό λ„˜μ€ column 을 넣을 수 μ—†μŠ΅λ‹ˆλ‹€.");
}
}

private boolean overLength(String target, int maxLength) {
if (target == null) {
return false;
}
return target.length() > maxLength;
}

private void validateTime(LocalDateTime startTime, LocalDateTime ticketOpenTime, Festival festival) {
if (festival.isNotInDuration(startTime)) {
throw new BadRequestException(ErrorCode.INVALID_STAGE_START_TIME);
}
Expand Down
15 changes: 15 additions & 0 deletions backend/src/main/java/com/festago/domain/Ticket.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToMany;
import jakarta.persistence.OneToOne;
import jakarta.validation.constraints.NotNull;
import java.time.LocalDateTime;
import java.util.Set;
import java.util.SortedSet;
Expand All @@ -29,9 +30,11 @@ public class Ticket extends BaseTimeEntity {
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@NotNull
@ManyToOne(fetch = FetchType.LAZY)
private Stage stage;

@NotNull
@Enumerated(EnumType.STRING)
private TicketType ticketType;

Expand All @@ -51,12 +54,24 @@ public Ticket(Stage stage, TicketType ticketType) {
}

public Ticket(Long id, Stage stage, TicketType ticketType) {
validate(stage, ticketType);
this.id = id;
this.stage = stage;
this.ticketType = ticketType;
this.ticketAmount = new TicketAmount(this);
}

private void validate(Stage stage, TicketType ticketType) {
checkNotNull(stage, ticketType);
}

private void checkNotNull(Stage stage, TicketType ticketType) {
if (stage == null ||
ticketType == null) {
throw new IllegalArgumentException("Ticket 은 ν—ˆμš©λ˜μ§€ μ•Šμ€ null κ°’μœΌλ‘œ 생성할 수 μ—†μŠ΅λ‹ˆλ‹€.");
}
}

public void addTicketEntryTime(LocalDateTime currentTime, LocalDateTime entryTime, int amount) {
validateEntryTime(currentTime, entryTime);
TicketEntryTime ticketEntryTime = new TicketEntryTime(entryTime, amount);
Expand Down
Loading

0 comments on commit 046f5d4

Please sign in to comment.