Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor - request dto에서 validation을 진행할 수 있도록 변경 #165

Merged
merged 21 commits into from
Jun 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6fcdd21
fix - #155 챌린지 최소 시간 수정
kseysh Jun 11, 2024
94d9c4d
refactor - #164 챌린지 기간 및 목표시간 validate request dto에서 진행하도록 변경
kseysh Jun 12, 2024
fbe6f92
refactor - #164 challenge 기간을 List로 관리하여 contain 메서드를 통해 validation을 …
kseysh Jun 12, 2024
ee2e7f7
refactor - #164 appcode validation을 DTO생성시에 진행하도록 변경
kseysh Jun 12, 2024
fa5529d
refactor - #164 app 목표 시간 validation을 DTO 생성 로직에서 진행하도록 변경
kseysh Jun 12, 2024
4110639
refactor - #164 request dto 제약조건 추가
kseysh Jun 12, 2024
2602926
refactor - #164 사용하지 않는 Error constants 제거
kseysh Jun 12, 2024
017e953
refactor - #164 사용하지 않는 Error constants 제거
kseysh Jun 12, 2024
3f66596
refactor - #164 app time validation에서 어노테이션에서 상수만을 사용해야하여 생성자에서 valid…
kseysh Jun 12, 2024
35d0fda
refactor - #164 addChallenge의 매개변수 수정
kseysh Jun 12, 2024
715ee75
Merge branch 'refactor/#164-validation-use-annotation' of https://git…
kseysh Jun 12, 2024
d1c6094
merge - #164 깃에서 꼬인 AppError 다시 복구
kseysh Jun 12, 2024
bfc6325
refactor - #166 사용되지 않는 상수 값 삭제
kseysh Jun 18, 2024
9742bda
refactor - #166 요구사항에 맞도록 App 최대 시간을 2시간으로 변경
kseysh Jun 18, 2024
113f53c
refactor - #166 GOAL TIME ERROR 문구 변경
kseysh Jun 18, 2024
1a4a98d
refactor - #166 잘못 정의된 challenge constants 변경
kseysh Jun 18, 2024
1f3062a
refactor - #166 AuthController valid 어노테이션 적용
kseysh Jun 18, 2024
38cc570
refactor - #166 ChallengeController valid 어노테이션 적용
kseysh Jun 18, 2024
b433262
refactor - #166 DailyChallengeController valid 어노테이션 적용
kseysh Jun 18, 2024
2ed097e
refactor - #166 PointController @Valid 적용
kseysh Jun 18, 2024
fd415d3
merge - #166 충돌 병합 해
kseysh Jun 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public abstract class AppConstants {
public static final Long MINIMUM_APP_TIME = 0L;
public static final Long MAXIMUM_APP_TIME = 21_600_000L; // 6시간
public static final Long MAXIMUM_APP_TIME = 7_200_000L; // 2시간
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ public enum AppError implements ErrorBase {

APP_NOT_FOUND(HttpStatus.NOT_FOUND, "앱을 찾을 수 없습니다."),
APP_EXIST_ALREADY(HttpStatus.CONFLICT, "이미 추가된 앱입니다."),
INVALID_APP_CODE_NULL(HttpStatus.BAD_REQUEST, "앱 코드 값이 비어있습니다"),
INVALID_TIME_RANGE(HttpStatus.BAD_REQUEST, "앱 시간의 범위가 유효한지 확인해주세요"),
INVALID_TIME_NULL(HttpStatus.BAD_REQUEST, "앱 시간을 입력해주세요"),
INVALID_GOAL_TIME(HttpStatus.BAD_REQUEST, "앱 목표 시간이 유효하지 않습니다."),
;

private final HttpStatus status;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package sopt.org.hmh.domain.app.dto.request;

import jakarta.validation.constraints.NotNull;

public record AppRemoveRequest(
@NotNull(message = "앱 코드는 null일 수 없습니다.")
String appCode
) {
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package sopt.org.hmh.domain.app.dto.request;

import jakarta.validation.Valid;
import java.util.List;

public record ChallengeAppArrayRequest(
List<ChallengeAppRequest> apps
List<@Valid ChallengeAppRequest> apps
) {
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
package sopt.org.hmh.domain.app.dto.request;

import jakarta.validation.constraints.NotNull;
import sopt.org.hmh.domain.app.domain.AppConstants;
import sopt.org.hmh.domain.app.domain.exception.AppError;
import sopt.org.hmh.domain.app.domain.exception.AppException;

public record ChallengeAppRequest(
@NotNull(message = "앱 코드는 null일 수 없습니다.")
String appCode,
@NotNull(message = "앱 시간은 null일 수 없습니다.")
Long goalTime
) {
public ChallengeAppRequest {
if (goalTime > AppConstants.MAXIMUM_APP_TIME || goalTime < AppConstants.MINIMUM_APP_TIME) {
throw new AppException(AppError.INVALID_GOAL_TIME);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package sopt.org.hmh.domain.app.dto.request;

import jakarta.validation.constraints.NotNull;

public record HistoryAppRequest(
@NotNull(message = "앱 코드는 null일 수 없습니다.")
String appCode,
@NotNull(message = "앱 사용시간은 null일 수 없습니다.")
Long usageTime
) {
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package sopt.org.hmh.domain.auth.controller;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
Expand Down Expand Up @@ -39,7 +40,7 @@ public ResponseEntity<BaseResponse<?>> orderLogin(
public ResponseEntity<BaseResponse<?>> orderSignup(
@RequestHeader("Authorization") final String socialAccessToken,
@RequestHeader("OS") final String os,
@RequestBody final SocialSignUpRequest request
@RequestBody @Valid final SocialSignUpRequest request
) {
return ResponseEntity
.status(AuthSuccess.SIGNUP_SUCCESS.getHttpStatus())
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
package sopt.org.hmh.domain.auth.dto.request;

import com.fasterxml.jackson.annotation.JsonProperty;
import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import sopt.org.hmh.domain.challenge.dto.request.ChallengeRequest;
import sopt.org.hmh.domain.challenge.dto.request.ChallengeSignUpRequest;
import sopt.org.hmh.global.auth.social.SocialPlatform;

public record SocialSignUpRequest(
@NotNull(message = "소셜 플랫폼은 null일 수 없습니다.")
SocialPlatform socialPlatform,
String name,
@JsonProperty(value = "onboarding")
OnboardingRequest onboardingRequest,
@Valid
@JsonProperty(value = "challenge")
ChallengeSignUpRequest challengeSignUpRequest
) {
public ChallengeRequest toChallengeRequest() {
return new ChallengeRequest(challengeSignUpRequest.period(), challengeSignUpRequest.goalTime());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
public enum AuthError implements ErrorBase {

// 400 BAD REQUEST
INVALID_USER(HttpStatus.BAD_REQUEST, "Principle 객체가 없습니다."),
DUPLICATE_USER(HttpStatus.BAD_REQUEST, "이미 회원가입된 유저입니다."),

// 403 FORBIDDEN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,7 @@ public LoginResponse signup(String socialAccessToken, SocialSignUpRequest reques

User user = userService.addUser(socialPlatform, socialId, request.name());

Challenge challenge = challengeService.addChallenge(user.getId(), request.challengeSignUpRequest().period(),
request.challengeSignUpRequest().goalTime(), os);
Challenge challenge = challengeService.addChallenge(user.getId(), request.toChallengeRequest() , os);
challengeService.addApps(challenge, request.challengeSignUpRequest().apps(), os);

userService.registerOnboardingInfo(request);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package sopt.org.hmh.domain.challenge.controller;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
Expand Down Expand Up @@ -27,8 +28,8 @@ public class ChallengeController implements ChallengeApi {
@Override
public ResponseEntity<BaseResponse<?>> orderAddChallenge(@UserId final Long userId,
@RequestHeader("OS") final String os,
@RequestBody final ChallengeRequest request) {
challengeService.addChallenge(userId, request.period(), request.goalTime(), os);
@RequestBody @Valid final ChallengeRequest request) {
challengeService.addChallenge(userId, request, os);

return ResponseEntity
.status(ChallengeSuccess.ADD_CHALLENGE_SUCCESS.getHttpStatus())
Expand Down Expand Up @@ -59,7 +60,7 @@ public ResponseEntity<BaseResponse<DailyChallengeResponse>> orderGetDailyChallen
@Override
public ResponseEntity<BaseResponse<?>> orderAddApps(@UserId final Long userId,
@RequestHeader("OS") final String os,
@RequestBody final ChallengeAppArrayRequest requests) {
@RequestBody @Valid final ChallengeAppArrayRequest requests) {
Challenge challenge = challengeService.findCurrentChallengeByUserId(userId);
challengeService.addApps(challenge, requests.apps(), os);

Expand All @@ -73,7 +74,7 @@ public ResponseEntity<BaseResponse<?>> orderAddApps(@UserId final Long userId,
@Override
public ResponseEntity<BaseResponse<?>> orderRemoveApp(@UserId final Long userId,
@RequestHeader("OS") final String os,
@RequestBody final AppRemoveRequest request) {
@RequestBody @Valid final AppRemoveRequest request) {
Challenge challenge = challengeService.findCurrentChallengeByUserId(userId);
challengeService.removeApp(challenge, request, os);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package sopt.org.hmh.domain.challenge.domain;

import java.util.List;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

Expand All @@ -9,5 +10,5 @@ public abstract class ChallengeConstants {
public static final Long MAXIMUM_GOAL_TIME = 21_600_000L; // 6시간
public static final Integer USAGE_POINT = 100;
public static final Integer EARNED_POINT = 20;

public static final List<Integer> AVAILABLE_CHALLENGE_PERIODS = List.of(7, 14, 20, 30);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@
public enum ChallengeError implements ErrorBase {

CHALLENGE_NOT_FOUND(HttpStatus.NOT_FOUND, "챌린지를 찾을 수 없습니다."),
INVALID_PERIOD_NULL(HttpStatus.BAD_REQUEST, "챌린지 기간은 null일 수 없습니다."),
INVALID_PERIOD_NUMERIC(HttpStatus.BAD_REQUEST, "유효한 숫자의 챌린지 기간을 입력해주세요."),
INVALID_GOAL_TIME_NULL(HttpStatus.BAD_REQUEST, "목표시간은 null일 수 없습니다."),
INVALID_GOAL_TIME_NUMERIC(HttpStatus.BAD_REQUEST, "유효한 숫자의 목표 시간을 입력해주세요."),
CHALLENGE_ALREADY_FAILED_TODAY(HttpStatus.BAD_REQUEST, "이미 실패 처리 된 챌린지입니다."),
INVALID_PERIOD_NUMERIC(HttpStatus.BAD_REQUEST, "유효한 챌린지 기간이 아닙니다."),
INVALID_GOAL_TIME(HttpStatus.BAD_REQUEST, "챌린지 목표 시간이 유효하지 않습니다."),
;

private final HttpStatus status;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package sopt.org.hmh.domain.challenge.dto.request;

import jakarta.validation.constraints.NotNull;
import java.time.LocalDate;

public record ChallengeDateRequest(
@NotNull(message = "챌린지 날짜는 null일 수 없습니다.")
LocalDate challengeDate
) {
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
package sopt.org.hmh.domain.challenge.dto.request;

import jakarta.validation.constraints.NotNull;
import sopt.org.hmh.domain.app.domain.AppConstants;
import sopt.org.hmh.domain.app.domain.exception.AppError;
import sopt.org.hmh.domain.app.domain.exception.AppException;
import sopt.org.hmh.domain.challenge.domain.ChallengeConstants;
import sopt.org.hmh.domain.challenge.domain.exception.ChallengeError;
import sopt.org.hmh.domain.challenge.domain.exception.ChallengeException;

public record ChallengeRequest(
@NotNull(message = "챌린지 기간은 null일 수 없습니다.")
Integer period,
@NotNull(message = "챌린지 목표시간은 null일 수 없습니다.")
Long goalTime
) {
}

public ChallengeRequest {
if (!ChallengeConstants.AVAILABLE_CHALLENGE_PERIODS.contains(period)) {
throw new ChallengeException(ChallengeError.INVALID_PERIOD_NUMERIC);
}
if (goalTime > ChallengeConstants.MAXIMUM_GOAL_TIME || goalTime < ChallengeConstants.MINIMUM_GOAL_TIME) {
throw new ChallengeException(ChallengeError.INVALID_GOAL_TIME);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,12 +1,24 @@
package sopt.org.hmh.domain.challenge.dto.request;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import sopt.org.hmh.domain.app.dto.request.ChallengeAppRequest;

import java.util.List;
import sopt.org.hmh.domain.challenge.domain.ChallengeConstants;
import sopt.org.hmh.domain.challenge.domain.exception.ChallengeError;
import sopt.org.hmh.domain.challenge.domain.exception.ChallengeException;

public record ChallengeSignUpRequest(
@NotNull(message = "챌린지 기간은 null일 수 없습니다.")
Integer period,
@NotNull(message = "챌린지 목표시간은 null일 수 없습니다.")
Long goalTime,
List<ChallengeAppRequest> apps
List<@Valid ChallengeAppRequest> apps
) {
public ChallengeSignUpRequest {
if (goalTime > ChallengeConstants.MAXIMUM_GOAL_TIME || goalTime < ChallengeConstants.MINIMUM_GOAL_TIME) {
throw new ChallengeException(ChallengeError.INVALID_GOAL_TIME);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sopt.org.hmh.domain.app.domain.AppConstants;
import sopt.org.hmh.domain.app.domain.ChallengeApp;
import sopt.org.hmh.domain.app.domain.exception.AppError;
import sopt.org.hmh.domain.app.domain.exception.AppException;
Expand All @@ -12,10 +11,9 @@
import sopt.org.hmh.domain.app.dto.response.ChallengeAppResponse;
import sopt.org.hmh.domain.app.repository.ChallengeAppRepository;
import sopt.org.hmh.domain.challenge.domain.Challenge;
import sopt.org.hmh.domain.challenge.domain.ChallengeConstants;
import sopt.org.hmh.domain.challenge.domain.ChallengeDay;
import sopt.org.hmh.domain.challenge.domain.exception.ChallengeError;
import sopt.org.hmh.domain.challenge.domain.exception.ChallengeException;
import sopt.org.hmh.domain.challenge.dto.request.ChallengeRequest;
import sopt.org.hmh.domain.challenge.dto.response.ChallengeResponse;
import sopt.org.hmh.domain.challenge.dto.response.DailyChallengeResponse;
import sopt.org.hmh.domain.challenge.repository.ChallengeRepository;
Expand All @@ -40,9 +38,9 @@ public class ChallengeService {
private final UserService userService;

@Transactional
public Challenge addChallenge(Long userId, Integer period, Long goalTime, String os) {
validateChallengePeriod(period);
validateChallengeGoalTime(goalTime);
public Challenge addChallenge(Long userId, ChallengeRequest challengeRequest, String os) {
Integer period = challengeRequest.period();
Long goalTime = challengeRequest.goalTime();

Challenge challenge = challengeRepository.save(Challenge.builder()
.userId(userId)
Expand Down Expand Up @@ -107,7 +105,6 @@ public DailyChallengeResponse getDailyChallenge(Long userId) {

@Transactional
public void removeApp(Challenge challenge, AppRemoveRequest request, String os) {
validateAppCode(request.appCode());
ChallengeApp appToRemove = challengeAppRepository
.findFirstByChallengeIdAndAppCodeAndOsOrElseThrow(challenge.getId(), request.appCode(), os);
challengeAppRepository.delete(appToRemove);
Expand All @@ -118,8 +115,6 @@ public void addApps(Challenge challenge, List<ChallengeAppRequest> requests, Str
List<ChallengeApp> appsToUpdate = requests.stream()
.map(request -> {
validateAppExist(challenge.getId(), request.appCode(), os);
validateAppCode(request.appCode());
validateAppTime(request.goalTime());
return ChallengeApp.builder()
.challenge(challenge)
.appCode(request.appCode())
Expand All @@ -140,44 +135,12 @@ private Integer calculateTodayIndex(LocalDateTime challengeCreateAt, int period)
return (daysBetween >= period) ? -1 : daysBetween;
}

private void validateChallengePeriod(Integer period) {
if (period == null) {
throw new ChallengeException(ChallengeError.INVALID_PERIOD_NULL);
}
if (period != ChallengeDay.DAYS7.getValue() && period != ChallengeDay.DAYS14.getValue() && period != ChallengeDay.DAYS20.getValue() && period != ChallengeDay.DAYS30.getValue()) {
throw new ChallengeException(ChallengeError.INVALID_PERIOD_NUMERIC);
}
}

private void validateChallengeGoalTime(Long goalTime) {
if (goalTime == null) {
throw new ChallengeException(ChallengeError.INVALID_GOAL_TIME_NULL);
}
if (goalTime < ChallengeConstants.MINIMUM_GOAL_TIME || goalTime > ChallengeConstants.MAXIMUM_GOAL_TIME) {
throw new ChallengeException(ChallengeError.INVALID_GOAL_TIME_NUMERIC);
}
}

private void validateAppExist(Long challengeId, String appCode, String os) {
if (challengeAppRepository.existsByChallengeIdAndAppCodeAndOs(challengeId, appCode, os)) {
throw new AppException(AppError.APP_EXIST_ALREADY);
}
}

private void validateAppCode(String appCode) {
if (appCode.isEmpty()) {
throw new AppException(AppError.INVALID_APP_CODE_NULL);
}
}

private void validateAppTime(Long appTime) {
if (appTime == null) {
throw new AppException(AppError.INVALID_TIME_NULL);
}
if (appTime > AppConstants.MAXIMUM_APP_TIME || appTime < AppConstants.MINIMUM_APP_TIME)
throw new AppException(AppError.INVALID_TIME_RANGE);
}

public Challenge findByIdOrElseThrow(Long challengeId) {
return challengeRepository.findById(challengeId).orElseThrow(
() -> new ChallengeException(ChallengeError.CHALLENGE_NOT_FOUND));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package sopt.org.hmh.domain.dailychallenge.controller;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
Expand All @@ -25,7 +26,7 @@ public class DailyChallengeController implements DailyChallengeApi {
public ResponseEntity<BaseResponse<EmptyJsonResponse>> orderAddHistoryDailyChallenge(
@UserId final Long userId,
@RequestHeader("OS") final String os,
@RequestBody final FinishedDailyChallengeListRequest request
@RequestBody @Valid final FinishedDailyChallengeListRequest request
) {
dailyChallengeFacade.addFinishedDailyChallengeHistory(userId, request, os);
return ResponseEntity
Expand Down
Loading
Loading