Skip to content

Commit

Permalink
[Feat/#125] Validate Enum Fields (#134)
Browse files Browse the repository at this point in the history
* [Feat/#125] Reorganize Status Files

* [Feat/#125] Refactor EnumValidator

* [Feat/#125] Apply Enum Validation to PetRequest

* [Feat/#125] Apply Enum Validation to TeamRequest

* [Feat/#125] Apply Enum Validation to SirenRequest

* [Feat/#125] Apply Enum Validation to QuestionRequest

* [Feat/#125] Change Annotation location

* [Feat/#125] Change builder format
  • Loading branch information
ahnsugyeong committed Feb 18, 2024
1 parent 273df55 commit 9a50728
Show file tree
Hide file tree
Showing 23 changed files with 174 additions and 86 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.example.waggle.domain.board;

public enum ResolutionStatus {
RESOLVED, UNRESOLVED
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.example.waggle.domain.board.question.entity;

import com.example.waggle.domain.board.Board;
import com.example.waggle.domain.board.ResolutionStatus;
import com.example.waggle.web.dto.question.QuestionRequest;
import jakarta.persistence.*;
import lombok.AccessLevel;
Expand All @@ -21,19 +22,16 @@ public class Question extends Board {

@Enumerated(EnumType.STRING)
@Column(nullable = false)
private Status status;
private ResolutionStatus status;

public void changeQuestion(QuestionRequest.Post request) {
this.content = request.getContent();
this.title = request.getTitle();
this.status = request.getStatus();
}

public void changeStatus(Status status) {
public void changeStatus(ResolutionStatus status) {
this.status = status;
}

public enum Status {
RESOLVED, UNRESOLVED
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.example.waggle.domain.board.siren.entity;

import com.example.waggle.domain.board.Board;
import com.example.waggle.domain.board.ResolutionStatus;
import com.example.waggle.domain.member.entity.Gender;
import com.example.waggle.web.dto.siren.SirenRequest;
import jakarta.persistence.*;
Expand Down Expand Up @@ -30,7 +31,11 @@ public class Siren extends Board {
private String contact;
@Enumerated(EnumType.STRING)
@Column(nullable = false)
private Category category;
private SirenCategory category;

@Enumerated(EnumType.STRING)
@Column(nullable = false)
private ResolutionStatus status;

public void changeSiren(SirenRequest.Post request) {
this.title = request.getTitle();
Expand All @@ -42,9 +47,7 @@ public void changeSiren(SirenRequest.Post request) {
this.contact = request.getContact();
this.content = request.getContent();
this.category = request.getCategory();
this.status = request.getStatus();
}

public enum Category {
FIND_PET, FIND_OWNER, PROTECT, ETC
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.example.waggle.domain.board.siren.entity;

public enum SirenCategory {
FIND_PET, FIND_OWNER, PROTECT, ETC
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ public class Pet extends BaseEntity {
public void update(PetRequest.Post petDto) {
this.name = petDto.getName();
this.breed = petDto.getBreed();
this.gender = petDto.getGender();
this.gender = Gender.valueOf(petDto.getGender());
this.age = petDto.getAge();
this.profileImgUrl = petDto.getProfileImgUrl();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.waggle.domain.pet.service;

import com.example.waggle.domain.member.entity.Gender;
import com.example.waggle.domain.member.entity.Member;
import com.example.waggle.domain.member.repository.MemberRepository;
import com.example.waggle.domain.member.service.MemberQueryService;
Expand Down Expand Up @@ -101,7 +102,7 @@ private static Pet buildPet(PetRequest.Post petDto, Member member) {
.age(petDto.getAge())
.name(petDto.getName())
.breed(petDto.getBreed())
.gender(petDto.getGender())
.gender(Gender.valueOf(petDto.getGender()))
.member(member)
.profileImgUrl(petDto.getProfileImgUrl())
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,4 @@ public class Participation {
@Column(nullable = false)
private ParticipationStatus status;

public enum ParticipationStatus {
PENDING, ACCEPTED, REJECTED
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.example.waggle.domain.schedule.entity;

public enum ParticipationStatus {
PENDING, ACCEPTED, REJECTED
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.example.waggle.domain.member.repository.MemberRepository;
import com.example.waggle.domain.member.service.MemberQueryService;
import com.example.waggle.domain.schedule.entity.*;
import com.example.waggle.domain.schedule.entity.Participation.ParticipationStatus;
import com.example.waggle.domain.schedule.entity.ParticipationStatus;
import com.example.waggle.domain.schedule.repository.*;
import com.example.waggle.domain.schedule.service.schedule.ScheduleCommandService;
import com.example.waggle.global.exception.handler.MemberHandler;
Expand Down Expand Up @@ -165,8 +165,11 @@ public void requestParticipation(Long teamId, String username) {

validateNonExistenceOfParticipationRequest(team, member);

Participation participation = Participation.builder().team(team).member(member)
.status(ParticipationStatus.PENDING).build();
Participation participation = Participation.builder()
.team(team)
.member(member)
.status(ParticipationStatus.PENDING)
.build();

participationRepository.save(participation);
}
Expand All @@ -187,10 +190,10 @@ public void respondToParticipation(Long teamId, Long memberId, String leaderUser
if (accept) {
validateTeamMemberCount(team);
validateLimitOfTeamCapacity(team);
participation.setStatus(Participation.ParticipationStatus.ACCEPTED);
participation.setStatus(ParticipationStatus.ACCEPTED);
addMemberToTeam(team, member);
} else {
participation.setStatus(Participation.ParticipationStatus.REJECTED);
participation.setStatus(ParticipationStatus.REJECTED);
}
participationRepository.save(participation);
}
Expand Down Expand Up @@ -247,7 +250,10 @@ private void validateLimitOfTeamCapacity(Team team) {
}

private void addMemberToTeam(Team team, Member member) {
TeamMember teamMember = TeamMember.builder().team(team).member(member).build();
TeamMember teamMember = TeamMember.builder()
.team(team)
.member(member)
.build();
teamMember.addTeamMember(team, member);
teamMemberRepository.save(teamMember);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,25 @@

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
import org.springframework.stereotype.Component;

import java.util.EnumSet;
import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.stereotype.Component;

@Component
public class ValidEnumValidator implements ConstraintValidator<ValidEnum, String> {
public class EnumValidator implements ConstraintValidator<ValidEnum, String> {
private Set<String> enumValues;

@Override
public void initialize(ValidEnum targetEnum) {
Class<? extends Enum> enumSelected = targetEnum.target();
enumValues = (Set<String>) EnumSet.allOf(enumSelected).stream()
.map(e -> ((Enum<? extends Enum<?>>) e).name()).collect(Collectors
.toSet());
enumValues = Arrays.stream(targetEnum.target().getEnumConstants())
.map(Enum::name)
.collect(Collectors.toSet());
}

@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
return enumValues.contains(value);
return value == null || enumValues.contains(value);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@
import java.lang.annotation.*;

@Documented
@Constraint(validatedBy = {ValidEnumValidator.class})
@Constraint(validatedBy = {EnumValidator.class})
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidEnum {
String message() default "enum not contains this field";
String message() default "The provided value is not valid for this enum.";

Class<?>[] groups() default {};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,21 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDate;
Expand Down Expand Up @@ -93,7 +102,7 @@ public ApiResponseDto<MemberResponse.DetailDto> getMemberInfo(@PathVariable Stri
@ApiResponse(responseCode = "200", description = "이메일 전송 성공.")
@ApiResponse(responseCode = "400", description = "이메일 전송 실패. 잘못된 이메일 형식 등.")
@PostMapping("/email/send")
public ApiResponseDto<Boolean> sendMail(@RequestBody @Valid VerifyMailRequest.ConfirmationDto confirmationDto) {
public ApiResponseDto<Boolean> sendMail(@RequestBody @Validated VerifyMailRequest.ConfirmationDto confirmationDto) {
emailService.sendMail(confirmationDto.getEmail(), "email");
return ApiResponseDto.onSuccess(Boolean.TRUE);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,22 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

@Slf4j
@RequiredArgsConstructor
@RequestMapping("/api/pets")
Expand All @@ -35,7 +43,7 @@ public class PetApiController {
@ApiResponse(responseCode = "200", description = "반려견 정보 입력 성공. 입력한 반려견 고유의 ID를 반환.")
@ApiResponse(responseCode = "400", description = "정보 입력 실패. 잘못된 요청 또는 파일 저장 실패.")
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ApiResponseDto<Long> createPet(@RequestPart PetRequest.Post request,
public ApiResponseDto<Long> createPet(@RequestPart @Validated PetRequest.Post request,
@RequestPart(value = "file", required = false) MultipartFile multipartFile) {
request.setProfileImgUrl(MediaUtil.saveProfileImg(multipartFile, awsS3Service));
Long petId = petCommandService.createPet(request);
Expand All @@ -48,7 +56,7 @@ public ApiResponseDto<Long> createPet(@RequestPart PetRequest.Post request,
@ApiResponse(responseCode = "400", description = "정보 수정 실패. 잘못된 요청 또는 파일 저장 실패.")
@PutMapping(value = "/{petId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ApiResponseDto<Long> updatePet(@PathVariable Long petId,
@RequestPart PetRequest.Post request,
@RequestPart @Validated PetRequest.Post request,
@RequestPart(value = "file", required = false) MultipartFile profileImg,
@RequestParam boolean allowUpload) {
String removePrefixProfileUrl = MediaUtil.removePrefix(request.getProfileImgUrl());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,26 @@
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

@Slf4j
@RequiredArgsConstructor
@RequestMapping("/api/questions")
Expand All @@ -41,7 +49,7 @@ public class QuestionApiController {
@ApiResponse(responseCode = "200", description = "질문 작성 성공. 작성한 질문의 고유 ID를 반환합니다.")
@ApiResponse(responseCode = "400", description = "잘못된 요청. 입력 데이터 유효성 검사 실패 등의 이유로 질문 작성에 실패했습니다.")
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ApiResponseDto<Long> createQuestion(@RequestPart QuestionRequest.Post request,
public ApiResponseDto<Long> createQuestion(@RequestPart @Validated QuestionRequest.Post request,
@RequestPart(required = false, value = "files") List<MultipartFile> multipartFiles) {
Long boardId = questionCommandService.createQuestion(request, multipartFiles);
return ApiResponseDto.onSuccess(boardId);
Expand All @@ -52,11 +60,12 @@ public ApiResponseDto<Long> createQuestion(@RequestPart QuestionRequest.Post req
@ApiResponse(responseCode = "400", description = "잘못된 요청. 입력 데이터 유효성 검사 실패 등의 이유로 질문 수정에 실패했습니다.")
@PutMapping(value = "/{boardId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ApiResponseDto<Long> updateQuestion(@PathVariable Long boardId,
@RequestPart QuestionRequest.Post request,
@RequestPart @Validated QuestionRequest.Post request,
@RequestPart MediaRequest.Put mediaUpdateDto,
@RequestPart(required = false, value = "files") List<MultipartFile> multipartFiles) {
mediaUpdateDto.getMediaList().forEach(media -> media.setImageUrl(MediaUtil.removePrefix(media.getImageUrl())));
mediaUpdateDto.getDeleteMediaList().forEach(media -> media.setImageUrl(MediaUtil.removePrefix(media.getImageUrl())));
mediaUpdateDto.getDeleteMediaList()
.forEach(media -> media.setImageUrl(MediaUtil.removePrefix(media.getImageUrl())));
questionCommandService.updateQuestionV2(boardId, request, mediaUpdateDto, multipartFiles);
return ApiResponseDto.onSuccess(boardId);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

Expand All @@ -43,7 +44,7 @@ public class SirenApiController {
@ApiResponse(responseCode = "200", description = "사이렌 작성 성공. 작성한 사이렌의 고유 ID를 반환합니다.")
@ApiResponse(responseCode = "400", description = "잘못된 요청. 입력 데이터 유효성 검사 실패 등의 이유로 사이렌 작성에 실패했습니다.")
@PostMapping(consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ApiResponseDto<Long> createSiren(@RequestPart SirenRequest.Post sirenWriteDto,
public ApiResponseDto<Long> createSiren(@RequestPart @Validated SirenRequest.Post sirenWriteDto,
@RequestPart(required = false, value = "files") List<MultipartFile> multipartFiles) {
Long boardId = sirenCommandService.createSiren(sirenWriteDto, multipartFiles);
return ApiResponseDto.onSuccess(boardId);
Expand All @@ -54,7 +55,7 @@ public ApiResponseDto<Long> createSiren(@RequestPart SirenRequest.Post sirenWrit
@ApiResponse(responseCode = "400", description = "잘못된 요청. 입력 데이터 유효성 검사 실패 등의 이유로 사이렌의 수정에 실패했습니다.")
@PutMapping(value = "/{boardId}", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ApiResponseDto<Long> updateSiren(@PathVariable Long boardId,
@RequestPart SirenRequest.Post request,
@RequestPart @Validated SirenRequest.Post request,
@RequestPart MediaRequest.Put mediaUpdateDto,
@RequestPart(required = false, value = "files") List<MultipartFile> multipartFiles) {
mediaUpdateDto.getMediaList().forEach(media -> media.setImageUrl(MediaUtil.removePrefix(media.getImageUrl())));
Expand Down
Loading

0 comments on commit 9a50728

Please sign in to comment.