diff --git a/.github/workflows/hmh-cd-prod.yml b/.github/workflows/hmh-cd-prod.yml index 0ca6ee51..3353b393 100644 --- a/.github/workflows/hmh-cd-prod.yml +++ b/.github/workflows/hmh-cd-prod.yml @@ -49,7 +49,7 @@ jobs: aws-region: ${{ secrets.AWS_REGION }} - name: ๐Ÿš€ s3 upload - run: aws s3 cp --region ap-northeast-2 ./$GITHUB_SHA.zip s3://${{matrix.s3-bucket}}/prod/deploy/$GITHUB_SHA.zip # ์ˆ˜์ • ๊ณ ๋ ค + run: aws s3 cp --region ap-northeast-2 ./$GITHUB_SHA.zip s3://${{matrix.s3-bucket}}/prod/deploy/$GITHUB_SHA.zip - name: โ˜€๏ธ CodeDeploy~! run: aws deploy create-deployment diff --git a/.github/workflows/hmh-ci.yml b/.github/workflows/hmh-ci-dev.yml similarity index 96% rename from .github/workflows/hmh-ci.yml rename to .github/workflows/hmh-ci-dev.yml index eedf0287..8648100a 100644 --- a/.github/workflows/hmh-ci.yml +++ b/.github/workflows/hmh-ci-dev.yml @@ -3,8 +3,6 @@ name: ๐Ÿญ APPLICATION-BUILD! on: pull_request: branches: [ "develop" ] - push: - branches: [ "develop" ] permissions: contents: read diff --git a/.github/workflows/hmh-ci-prod.yml b/.github/workflows/hmh-ci-prod.yml new file mode 100644 index 00000000..c9aa1877 --- /dev/null +++ b/.github/workflows/hmh-ci-prod.yml @@ -0,0 +1,40 @@ +name: ๐Ÿญ APPLICATION-BUILD! + +on: + pull_request: + branches: [ "main" ] + +permissions: + contents: read + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: checkout + uses: actions/checkout@v3 + + - name: Set up JDK 17 + uses: actions/setup-java@v3 + with: + java-version: '17' + distribution: 'corretto' + + - name: Copy application.yml + run: | + mkdir ./src/main/resources + touch ./src/main/resources/application.yml + + echo "${{ secrets.APPLICATION_PROD_YML }}" >> ./src/main/resources/application.yml + + cat ./src/main/resources/application.yml + shell: bash + + - name: Grant execute permission for gradlew + run: | + chmod +x gradlew + + - name: Build with Gradle + run: | + ./gradlew clean build \ No newline at end of file diff --git a/README.md b/README.md index 1a8eb0cc..352f5b01 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ - **Language** : Java (jdk-17) - **Web application Framework** : Spring boot (3.2.1), Spring Data JPA -- **DataBase** : MySql (8.1.0), Redis +- **DataBase** : MySql (8.1.0) - **Cloud/Infra** : Aws EC2, RDS, code deploy - **web server** : Tomcat, Nginx - **Collaborative Tool** : Github, Slack, Notion @@ -28,34 +28,4 @@ | image | image | | [jumining](https://github.com/jumining) | [kseysh](https://github.com/kseysh) | -
- -## โœ… Convention - - - -### ๐Ÿš€Convention - -- [๐Ÿ’ป ํ˜‘์—… ์ปจ๋ฒค์…˜](https://hmhteam.notion.site/6fa22000670d4cf783559f7808c01d1a?pvs=4)
- -### ๐Ÿš€ Branch Strategy - -- [๐Ÿ’ป ๋ธŒ๋žœ์น˜ ์ „๋žต](https://hmhteam.notion.site/9d8065b238c543b890ceeb9912966dd0?pvs=4) - -
- -## ๐Ÿ’พ ERD - -![image](https://github.com/Team-HMH/HMH-Server/assets/69035864/f4b95b3d-6507-4d33-be41-8a4847bc076f) - -
- -
- -## โš™๏ธ Architecture - -![architecture](https://github.com/Team-HMH/HMH-Server/assets/69035864/e0eefac1-d8be-4a08-a3de-6e9786557042) - - -
diff --git a/script/start.sh b/script/start.sh index 1cf49ca4..abc9f911 100644 --- a/script/start.sh +++ b/script/start.sh @@ -1,12 +1,8 @@ # ์ธ์Šคํ„ด์Šค์— ํด๋ก  ๋ฐ›์€ ๋””๋ ‰ํ† ๋ฆฌ ์ด๋ฆ„์„ `app`์œผ๋กœ ๋ฐ”๊ฟ”์•ผํ•ฉ๋‹ˆ๋‹ค. APPLICATION_PATH=/home/ubuntu/app -# shellcheck disable=SC2164 cd $APPLICATION_PATH -# shellcheck disable=SC2010 JAR_NAME=$(ls $APPLICATION_PATH/build/libs/ | grep '.jar' | tail -n 1) - -# shellcheck disable=SC2034 JAR_PATH=build/libs/$JAR_NAME JAR_PID=$(pgrep -f $JAR_NAME) @@ -20,7 +16,15 @@ JAR_PID=$(pgrep -f $JAR_NAME) fi echo "> $JAR_PATH ๋ฐฐํฌ" #3 - # shellcheck disable=SC2153 - # shellcheck disable=SC2024 + source ~/.bashrc - sudo nohup java -jar -Dspring.profiles.active=prod "$JAR_PATH" >nohup.out 2>&1 nohup.out 2>&1 nohup.out 2>&1 apps = new ArrayList<>(); @@ -39,7 +37,6 @@ private Challenge(Integer period, Long userId, Long goalTime, List this.period = period; this.userId = userId; this.goalTime = goalTime; - this.isChallengeFailedToday = false; this.apps = apps; } } \ No newline at end of file diff --git a/src/main/java/sopt/org/hmh/domain/challenge/domain/ChallengeConstants.java b/src/main/java/sopt/org/hmh/domain/challenge/domain/ChallengeConstants.java index 55da8024..d12eb0c3 100644 --- a/src/main/java/sopt/org/hmh/domain/challenge/domain/ChallengeConstants.java +++ b/src/main/java/sopt/org/hmh/domain/challenge/domain/ChallengeConstants.java @@ -5,8 +5,8 @@ @NoArgsConstructor(access = AccessLevel.PRIVATE) public abstract class ChallengeConstants { - public static final Long MINIMUM_GOAL_TIME = 7200000L; - public static final Long MAXIMUM_GOAL_TIME = 21600000L; + public static final Long MINIMUM_GOAL_TIME = 3_600_000L; // 1์‹œ๊ฐ„ + 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; diff --git a/src/main/java/sopt/org/hmh/domain/challenge/service/ChallengeService.java b/src/main/java/sopt/org/hmh/domain/challenge/service/ChallengeService.java index 5e08363f..628589bd 100644 --- a/src/main/java/sopt/org/hmh/domain/challenge/service/ChallengeService.java +++ b/src/main/java/sopt/org/hmh/domain/challenge/service/ChallengeService.java @@ -20,7 +20,6 @@ import sopt.org.hmh.domain.challenge.dto.response.DailyChallengeResponse; import sopt.org.hmh.domain.challenge.repository.ChallengeRepository; import sopt.org.hmh.domain.dailychallenge.domain.DailyChallenge; -import sopt.org.hmh.domain.dailychallenge.domain.Status; import sopt.org.hmh.domain.dailychallenge.repository.DailyChallengeRepository; import sopt.org.hmh.domain.user.domain.User; import sopt.org.hmh.domain.user.service.UserService; @@ -100,9 +99,6 @@ public DailyChallengeResponse getDailyChallenge(Long userId) { Challenge challenge = findCurrentChallengeByUserId(userId); return DailyChallengeResponse.builder() - .status(Boolean.TRUE.equals(challenge.isChallengeFailedToday()) - ? Status.FAILURE - : Status.NONE) .goalTime(challenge.getGoalTime()) .apps(challenge.getApps().stream() .map(app -> new ChallengeAppResponse(app.getAppCode(), app.getGoalTime())).toList()) diff --git a/src/main/java/sopt/org/hmh/domain/dailychallenge/controller/DailyChallengeApi.java b/src/main/java/sopt/org/hmh/domain/dailychallenge/controller/DailyChallengeApi.java index a902fbd7..62c85780 100644 --- a/src/main/java/sopt/org/hmh/domain/dailychallenge/controller/DailyChallengeApi.java +++ b/src/main/java/sopt/org/hmh/domain/dailychallenge/controller/DailyChallengeApi.java @@ -8,6 +8,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import org.springframework.http.ResponseEntity; import sopt.org.hmh.domain.dailychallenge.dto.request.FinishedDailyChallengeListRequest; +import sopt.org.hmh.domain.dailychallenge.dto.request.FinishedDailyChallengeStatusListRequest; import sopt.org.hmh.global.auth.jwt.JwtConstants; import sopt.org.hmh.global.common.response.BaseResponse; import sopt.org.hmh.global.common.response.EmptyJsonResponse; @@ -33,6 +34,13 @@ public interface DailyChallengeApi { ResponseEntity> orderAddHistoryDailyChallenge( @Parameter(hidden = true) final Long userId, final String os, - final FinishedDailyChallengeListRequest request); + final FinishedDailyChallengeListRequest request + ); + + ResponseEntity> orderChangeStatusDailyChallenge( + @Parameter(hidden = true) final Long userId, + final String os, + final FinishedDailyChallengeStatusListRequest request + ); } diff --git a/src/main/java/sopt/org/hmh/domain/dailychallenge/controller/DailyChallengeController.java b/src/main/java/sopt/org/hmh/domain/dailychallenge/controller/DailyChallengeController.java index 2a30c4db..6f3c37a1 100644 --- a/src/main/java/sopt/org/hmh/domain/dailychallenge/controller/DailyChallengeController.java +++ b/src/main/java/sopt/org/hmh/domain/dailychallenge/controller/DailyChallengeController.java @@ -5,7 +5,9 @@ import org.springframework.web.bind.annotation.*; import sopt.org.hmh.domain.dailychallenge.domain.exception.DailyChallengeSuccess; import sopt.org.hmh.domain.dailychallenge.dto.request.FinishedDailyChallengeListRequest; +import sopt.org.hmh.domain.dailychallenge.dto.request.FinishedDailyChallengeStatusListRequest; import sopt.org.hmh.domain.dailychallenge.service.DailyChallengeFacade; +import sopt.org.hmh.domain.dailychallenge.service.DailyChallengeService; import sopt.org.hmh.global.auth.UserId; import sopt.org.hmh.global.common.response.BaseResponse; import sopt.org.hmh.global.common.response.EmptyJsonResponse; @@ -16,6 +18,7 @@ public class DailyChallengeController implements DailyChallengeApi { private final DailyChallengeFacade dailyChallengeFacade; + private final DailyChallengeService dailyChallengeService; @Override @PostMapping("/finish") @@ -29,4 +32,17 @@ public ResponseEntity> orderAddHistoryDailyChall .status(DailyChallengeSuccess.SEND_FINISHED_DAILY_CHALLENGE_SUCCESS.getHttpStatus()) .body(BaseResponse.success(DailyChallengeSuccess.SEND_FINISHED_DAILY_CHALLENGE_SUCCESS, new EmptyJsonResponse())); } + + @Override + @PostMapping("/success") + public ResponseEntity> orderChangeStatusDailyChallenge( + @UserId final Long userId, + @RequestHeader("OS") final String os, + @RequestBody final FinishedDailyChallengeStatusListRequest request + ) { + dailyChallengeService.changeDailyChallengeStatusByIsSuccess(userId, request); + return ResponseEntity + .status(DailyChallengeSuccess.SEND_FINISHED_DAILY_CHALLENGE_SUCCESS.getHttpStatus()) + .body(BaseResponse.success(DailyChallengeSuccess.SEND_FINISHED_DAILY_CHALLENGE_SUCCESS, new EmptyJsonResponse())); + } } \ No newline at end of file diff --git a/src/main/java/sopt/org/hmh/domain/dailychallenge/dto/request/FinishedDailyChallengeStatusListRequest.java b/src/main/java/sopt/org/hmh/domain/dailychallenge/dto/request/FinishedDailyChallengeStatusListRequest.java new file mode 100644 index 00000000..d5692b78 --- /dev/null +++ b/src/main/java/sopt/org/hmh/domain/dailychallenge/dto/request/FinishedDailyChallengeStatusListRequest.java @@ -0,0 +1,9 @@ +package sopt.org.hmh.domain.dailychallenge.dto.request; + +import java.util.List; + +public record FinishedDailyChallengeStatusListRequest( + List finishedDailyChallenges +) { + +} diff --git a/src/main/java/sopt/org/hmh/domain/dailychallenge/dto/request/FinishedDailyChallengeStatusRequest.java b/src/main/java/sopt/org/hmh/domain/dailychallenge/dto/request/FinishedDailyChallengeStatusRequest.java new file mode 100644 index 00000000..a2baadc0 --- /dev/null +++ b/src/main/java/sopt/org/hmh/domain/dailychallenge/dto/request/FinishedDailyChallengeStatusRequest.java @@ -0,0 +1,10 @@ +package sopt.org.hmh.domain.dailychallenge.dto.request; + +import java.time.LocalDate; + +public record FinishedDailyChallengeStatusRequest( + LocalDate challengeDate, + boolean isSuccess +) { + +} diff --git a/src/main/java/sopt/org/hmh/domain/dailychallenge/service/DailyChallengeService.java b/src/main/java/sopt/org/hmh/domain/dailychallenge/service/DailyChallengeService.java index 3134f88d..bf8a48ca 100644 --- a/src/main/java/sopt/org/hmh/domain/dailychallenge/service/DailyChallengeService.java +++ b/src/main/java/sopt/org/hmh/domain/dailychallenge/service/DailyChallengeService.java @@ -1,6 +1,7 @@ package sopt.org.hmh.domain.dailychallenge.service; import java.time.LocalDate; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -8,6 +9,7 @@ import sopt.org.hmh.domain.dailychallenge.domain.Status; import sopt.org.hmh.domain.dailychallenge.domain.exception.DailyChallengeError; import sopt.org.hmh.domain.dailychallenge.domain.exception.DailyChallengeException; +import sopt.org.hmh.domain.dailychallenge.dto.request.FinishedDailyChallengeStatusListRequest; import sopt.org.hmh.domain.dailychallenge.repository.DailyChallengeRepository; @Service @@ -22,8 +24,16 @@ public DailyChallenge findByChallengeDateAndUserIdOrThrowException(LocalDate cha .orElseThrow(() -> new DailyChallengeException(DailyChallengeError.DAILY_CHALLENGE_NOT_FOUND)); } - public void validateDailyChallengeStatus(DailyChallenge dailyChallenge, Status expected) { - if (dailyChallenge.getStatus() != expected) { + public void validateDailyChallengeStatus(Status dailyChallengeStatus, List expectedStatuses) { + boolean isAlreadyProcessed = true; + for (Status expected : expectedStatuses) { + if (dailyChallengeStatus == expected) { + isAlreadyProcessed = false; + break; + } + } + + if (isAlreadyProcessed) { throw new DailyChallengeException(DailyChallengeError.DAILY_CHALLENGE_ALREADY_PROCESSED); } } @@ -42,4 +52,17 @@ private void handleAlreadyProcessedDailyChallenge(DailyChallenge dailyChallenge) } throw new DailyChallengeException(DailyChallengeError.DAILY_CHALLENGE_ALREADY_PROCESSED); } + + public void changeDailyChallengeStatusByIsSuccess(Long userId, FinishedDailyChallengeStatusListRequest requests) { + requests.finishedDailyChallenges().forEach(request -> { + DailyChallenge dailyChallenge = this.findByChallengeDateAndUserIdOrThrowException(request.challengeDate(), userId); + if (request.isSuccess()) { + this.validateDailyChallengeStatus(dailyChallenge.getStatus(), List.of(Status.NONE)); + dailyChallenge.changeStatus(Status.UNEARNED); + } else { + this.validateDailyChallengeStatus(dailyChallenge.getStatus(), List.of(Status.NONE, Status.FAILURE)); + dailyChallenge.changeStatus(Status.FAILURE); + } + }); + } } \ No newline at end of file diff --git a/src/main/java/sopt/org/hmh/domain/dummy/DummyApp.java b/src/main/java/sopt/org/hmh/domain/dummy/DummyApp.java deleted file mode 100644 index f6ff4f55..00000000 --- a/src/main/java/sopt/org/hmh/domain/dummy/DummyApp.java +++ /dev/null @@ -1,14 +0,0 @@ -package sopt.org.hmh.domain.dummy; - -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Deprecated -@Getter -@AllArgsConstructor -public class DummyApp { - String appName; - String appImageUrl; - Long goalTime; - Long usageTime; -} diff --git a/src/main/java/sopt/org/hmh/domain/dummy/DummyAppController.java b/src/main/java/sopt/org/hmh/domain/dummy/DummyAppController.java deleted file mode 100644 index 6ffeedf8..00000000 --- a/src/main/java/sopt/org/hmh/domain/dummy/DummyAppController.java +++ /dev/null @@ -1,21 +0,0 @@ -package sopt.org.hmh.domain.dummy; - -import lombok.RequiredArgsConstructor; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; -import sopt.org.hmh.global.common.response.BaseResponse; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/v1/dummy") -@Deprecated -public class DummyAppController { - @GetMapping("/app") - public ResponseEntity> orderModifyDailyChallenge() { - return ResponseEntity - .status(DummyAppSuccess.GET_DUMMY_SUCCESS.getHttpStatus()) - .body(BaseResponse.success(DummyAppSuccess.GET_DUMMY_SUCCESS, DummyAppListResponse.of())); - } -} diff --git a/src/main/java/sopt/org/hmh/domain/dummy/DummyAppListResponse.java b/src/main/java/sopt/org/hmh/domain/dummy/DummyAppListResponse.java deleted file mode 100644 index 40a92324..00000000 --- a/src/main/java/sopt/org/hmh/domain/dummy/DummyAppListResponse.java +++ /dev/null @@ -1,17 +0,0 @@ -package sopt.org.hmh.domain.dummy; - -import java.util.ArrayList; -import java.util.List; - -@Deprecated -public record DummyAppListResponse( - List apps -) { - public static DummyAppListResponse of() { - List dummyAppList = new ArrayList<>(); - dummyAppList.add(new DummyApp("Netflix","https://github.com/Team-HMH/HMH-Server/assets/69035864/dd068b83-641a-4bff-b4f5-381ea6e04d44",2_400_000L,1_320_000L)); - dummyAppList.add(new DummyApp("Instagram","https://github.com/Team-HMH/HMH-Server/assets/69035864/bd572377-9dd9-47e7-a9f4-9efbbe66cd2e",5_400_000L,2_880_000L)); - dummyAppList.add(new DummyApp("YouTube","https://github.com/Team-HMH/HMH-Server/assets/69035864/8afa60c0-bf1d-4ff0-9b50-4d1558a71f0a",3_300_000L,900_000L)); - return new DummyAppListResponse(dummyAppList); - } -} diff --git a/src/main/java/sopt/org/hmh/domain/dummy/DummyAppSuccess.java b/src/main/java/sopt/org/hmh/domain/dummy/DummyAppSuccess.java deleted file mode 100644 index 49f1a2c4..00000000 --- a/src/main/java/sopt/org/hmh/domain/dummy/DummyAppSuccess.java +++ /dev/null @@ -1,31 +0,0 @@ -package sopt.org.hmh.domain.dummy; - -import lombok.AllArgsConstructor; -import org.springframework.http.HttpStatus; -import sopt.org.hmh.global.common.exception.base.SuccessBase; - -@AllArgsConstructor -@Deprecated -public enum DummyAppSuccess implements SuccessBase { - - GET_DUMMY_SUCCESS(HttpStatus.OK, "๋”๋ฏธ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ค๊ธฐ์— ์„ฑ๊ณตํ•˜์˜€์Šต๋‹ˆ๋‹ค."), - ; - - private final HttpStatus status; - private final String successMessage; - - @Override - public int getHttpStatusCode() { - return this.status.value(); - } - - @Override - public HttpStatus getHttpStatus() { - return this.status; - } - - @Override - public String getSuccessMessage() { - return this.successMessage; - } -} diff --git a/src/main/java/sopt/org/hmh/domain/point/controller/PointApi.java b/src/main/java/sopt/org/hmh/domain/point/controller/PointApi.java index a06ed9af..97d5eea4 100644 --- a/src/main/java/sopt/org/hmh/domain/point/controller/PointApi.java +++ b/src/main/java/sopt/org/hmh/domain/point/controller/PointApi.java @@ -6,15 +6,13 @@ import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.security.SecurityRequirement; import io.swagger.v3.oas.annotations.tags.Tag; -import java.time.LocalDate; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.PatchMapping; +import sopt.org.hmh.domain.point.dto.request.ChallengeDateRequest; import sopt.org.hmh.domain.point.dto.response.ChallengePointStatusListResponse; import sopt.org.hmh.domain.point.dto.response.EarnPointResponse; +import sopt.org.hmh.domain.point.dto.response.EarnedPointResponse; import sopt.org.hmh.domain.point.dto.response.UsagePointResponse; import sopt.org.hmh.domain.point.dto.response.UsePointResponse; -import sopt.org.hmh.domain.point.exception.PointSuccess; -import sopt.org.hmh.global.auth.UserId; import sopt.org.hmh.global.auth.jwt.JwtConstants; import sopt.org.hmh.global.common.response.BaseResponse; @@ -54,7 +52,7 @@ ResponseEntity> orderGetChallenge description = "์„œ๋ฒ„ ๋‚ด๋ถ€ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.", content = @Content)}) ResponseEntity> orderUsagePointAndChallengeFailed( - @Parameter(hidden = true) Long userId, LocalDate challengeDate); + @Parameter(hidden = true) Long userId, ChallengeDateRequest challengeDateRequest); @Operation( summary = "ํฌ์ธํŠธ ๋ฐ›๊ธฐ API", @@ -71,7 +69,7 @@ ResponseEntity> orderUsagePointAndChallengeFailed description = "์„œ๋ฒ„ ๋‚ด๋ถ€ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.", content = @Content)}) ResponseEntity> orderEarnPointAndChallengeEarned( - @Parameter(hidden = true) Long userId, LocalDate challengeDate); + @Parameter(hidden = true) Long userId, ChallengeDateRequest challengeDateRequest); @Operation( summary = "์‚ฌ์šฉํ•  ํฌ์ธํŠธ ๋ฐ›๊ธฐ API", @@ -88,4 +86,20 @@ ResponseEntity> orderEarnPointAndChallengeEarned description = "์„œ๋ฒ„ ๋‚ด๋ถ€ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.", content = @Content)}) ResponseEntity> orderGetUsagePoint(); + + @Operation( + summary = "๋ฐ›์„ ํฌ์ธํŠธ ๋ฐ›๊ธฐ API", + responses = { + @ApiResponse( + responseCode = "200", + description = "์‚ฌ์šฉํ•  ํฌ์ธํŠธ ๋ฐ˜ํ™˜์— ์„ฑ๊ณตํ•˜์˜€์Šต๋‹ˆ๋‹ค."), + @ApiResponse( + responseCode = "400", + description = "์ž˜๋ชป๋œ ์š”์ฒญ์ž…๋‹ˆ๋‹ค.", + content = @Content), + @ApiResponse( + responseCode = "500", + description = "์„œ๋ฒ„ ๋‚ด๋ถ€ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.", + content = @Content)}) + ResponseEntity> orderGetEarnedPoint(); } diff --git a/src/main/java/sopt/org/hmh/domain/point/controller/PointController.java b/src/main/java/sopt/org/hmh/domain/point/controller/PointController.java index e05e862a..5ed744ea 100644 --- a/src/main/java/sopt/org/hmh/domain/point/controller/PointController.java +++ b/src/main/java/sopt/org/hmh/domain/point/controller/PointController.java @@ -1,8 +1,5 @@ package sopt.org.hmh.domain.point.controller; -import java.time.LocalDate; -import java.util.List; - import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; @@ -10,7 +7,8 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import sopt.org.hmh.domain.challenge.domain.Challenge; +import sopt.org.hmh.domain.challenge.domain.ChallengeConstants; +import sopt.org.hmh.domain.point.dto.request.ChallengeDateRequest; import sopt.org.hmh.domain.point.dto.response.*; import sopt.org.hmh.domain.point.exception.PointSuccess; import sopt.org.hmh.domain.point.service.PointFacade; @@ -40,24 +38,33 @@ public ResponseEntity> orderGetCh @PatchMapping("/use") public ResponseEntity> orderUsagePointAndChallengeFailed( @UserId final Long userId, - @RequestBody final LocalDate challengeDate + @RequestBody final ChallengeDateRequest challengeDateRequest ) { return ResponseEntity .status(PointSuccess.POINT_USAGE_SUCCESS.getHttpStatus()) .body(BaseResponse.success(PointSuccess.POINT_USAGE_SUCCESS, - pointFacade.usePointAndChallengeFailed(userId, challengeDate))); + pointFacade.usePointAndChallengeFailed(userId, challengeDateRequest.challengeDate()))); } @Override @PatchMapping("/earn") public ResponseEntity> orderEarnPointAndChallengeEarned( @UserId final Long userId, - @RequestBody final LocalDate challengeDate + @RequestBody final ChallengeDateRequest challengeDateRequest ) { return ResponseEntity .status(PointSuccess.POINT_EARN_SUCCESS.getHttpStatus()) .body(BaseResponse.success(PointSuccess.POINT_EARN_SUCCESS, - pointFacade.earnPointAndChallengeEarned(userId, challengeDate))); + pointFacade.earnPointAndChallengeEarned(userId, challengeDateRequest.challengeDate()))); + } + + @Override + @GetMapping("/earn") + public ResponseEntity> orderGetEarnedPoint() { + return ResponseEntity + .status(PointSuccess.GET_EARNED_POINT_SUCCESS.getHttpStatus()) + .body(BaseResponse.success(PointSuccess.GET_EARNED_POINT_SUCCESS, + new EarnedPointResponse(ChallengeConstants.EARNED_POINT))); } @Override @@ -66,6 +73,6 @@ public ResponseEntity> orderGetUsagePoint() { return ResponseEntity .status(PointSuccess.GET_USAGE_POINT_SUCCESS.getHttpStatus()) .body(BaseResponse.success(PointSuccess.GET_USAGE_POINT_SUCCESS, - pointFacade.getUsagePoint())); + new UsagePointResponse(ChallengeConstants.USAGE_POINT))); } } diff --git a/src/main/java/sopt/org/hmh/domain/point/dto/request/ChallengeDateRequest.java b/src/main/java/sopt/org/hmh/domain/point/dto/request/ChallengeDateRequest.java new file mode 100644 index 00000000..931db058 --- /dev/null +++ b/src/main/java/sopt/org/hmh/domain/point/dto/request/ChallengeDateRequest.java @@ -0,0 +1,8 @@ +package sopt.org.hmh.domain.point.dto.request; + +import java.time.LocalDate; + +public record ChallengeDateRequest( + LocalDate challengeDate +) { +} \ No newline at end of file diff --git a/src/main/java/sopt/org/hmh/domain/point/dto/response/EarnedPointResponse.java b/src/main/java/sopt/org/hmh/domain/point/dto/response/EarnedPointResponse.java new file mode 100644 index 00000000..85c892a0 --- /dev/null +++ b/src/main/java/sopt/org/hmh/domain/point/dto/response/EarnedPointResponse.java @@ -0,0 +1,6 @@ +package sopt.org.hmh.domain.point.dto.response; + +public record EarnedPointResponse( + Integer earnPoint +) { +} diff --git a/src/main/java/sopt/org/hmh/domain/point/dto/response/UsagePointResponse.java b/src/main/java/sopt/org/hmh/domain/point/dto/response/UsagePointResponse.java index e394564d..a5b614d0 100644 --- a/src/main/java/sopt/org/hmh/domain/point/dto/response/UsagePointResponse.java +++ b/src/main/java/sopt/org/hmh/domain/point/dto/response/UsagePointResponse.java @@ -1,6 +1,7 @@ package sopt.org.hmh.domain.point.dto.response; public record UsagePointResponse( - Integer usagePoint + Integer usagePoint ) { + } diff --git a/src/main/java/sopt/org/hmh/domain/point/exception/PointSuccess.java b/src/main/java/sopt/org/hmh/domain/point/exception/PointSuccess.java index 31cf7471..ea6608e0 100644 --- a/src/main/java/sopt/org/hmh/domain/point/exception/PointSuccess.java +++ b/src/main/java/sopt/org/hmh/domain/point/exception/PointSuccess.java @@ -10,6 +10,7 @@ public enum PointSuccess implements SuccessBase { POINT_USAGE_SUCCESS(HttpStatus.OK, "ํฌ์ธํŠธ ์‚ฌ์šฉ์— ์„ฑ๊ณตํ•˜์˜€์Šต๋‹ˆ๋‹ค"), POINT_EARN_SUCCESS(HttpStatus.OK, "ํฌ์ธํŠธ ๋ฐ›๊ธฐ์— ์„ฑ๊ณตํ•˜์˜€์Šต๋‹ˆ๋‹ค"), GET_USAGE_POINT_SUCCESS(HttpStatus.OK, "์‚ฌ์šฉํ•  ํฌ์ธํŠธ ๋ฐ˜ํ™˜์— ์„ฑ๊ณตํ•˜์˜€์Šต๋‹ˆ๋‹ค"), + GET_EARNED_POINT_SUCCESS(HttpStatus.OK, "๋ฐ›์„ ํฌ์ธํŠธ ๋ฐ˜ํ™˜์— ์„ฑ๊ณตํ•˜์˜€์Šต๋‹ˆ๋‹ค"), GET_CHALLENGE_POINT_STATUS_LIST_SUCCESS(HttpStatus.OK, "์ฑŒ๋ฆฐ์ง€ ํฌ์ธํŠธ ์ˆ˜๋ น ์—ฌ๋ถ€ ๋ฆฌ์ŠคํŠธ ์กฐํšŒ์— ์„ฑ๊ณตํ•˜์˜€์Šต๋‹ˆ๋‹ค."), ; diff --git a/src/main/java/sopt/org/hmh/domain/point/service/PointFacade.java b/src/main/java/sopt/org/hmh/domain/point/service/PointFacade.java index 26cf8b05..606db230 100644 --- a/src/main/java/sopt/org/hmh/domain/point/service/PointFacade.java +++ b/src/main/java/sopt/org/hmh/domain/point/service/PointFacade.java @@ -1,9 +1,7 @@ package sopt.org.hmh.domain.point.service; import java.time.LocalDate; -import java.util.ArrayList; import java.util.List; -import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -31,7 +29,7 @@ public UsePointResponse usePointAndChallengeFailed(Long userId, LocalDate challe DailyChallenge dailyChallenge = dailyChallengeService.findByChallengeDateAndUserIdOrThrowException(challengeDate, userId); User user = userService.findByIdOrThrowException(userId); - dailyChallengeService.validateDailyChallengeStatus(dailyChallenge, Status.NONE); + dailyChallengeService.validateDailyChallengeStatus(dailyChallenge.getStatus(), List.of(Status.NONE)); dailyChallenge.changeStatus(Status.FAILURE); return new UsePointResponse( @@ -44,7 +42,7 @@ public EarnPointResponse earnPointAndChallengeEarned(Long userId, LocalDate chal DailyChallenge dailyChallenge = dailyChallengeService.findByChallengeDateAndUserIdOrThrowException(challengeDate, userId); User user = userService.findByIdOrThrowException(userId); - dailyChallengeService.validateDailyChallengeStatus(dailyChallenge, Status.UNEARNED); + dailyChallengeService.validateDailyChallengeStatus(dailyChallenge.getStatus(), List.of(Status.UNEARNED)); dailyChallenge.changeStatus(Status.EARNED); return new EarnPointResponse( @@ -52,11 +50,6 @@ public EarnPointResponse earnPointAndChallengeEarned(Long userId, LocalDate chal ); } - @Transactional(readOnly = true) - public UsagePointResponse getUsagePoint() { - return new UsagePointResponse(ChallengeConstants.USAGE_POINT); - } - public ChallengePointStatusListResponse getChallengePointStatusList(Long userId) { Challenge challenge = challengeService.findCurrentChallengeByUserId(userId); List challengePointStatusResponseList = diff --git a/src/main/java/sopt/org/hmh/domain/user/controller/UserApi.java b/src/main/java/sopt/org/hmh/domain/user/controller/UserApi.java index 56617336..e390f419 100644 --- a/src/main/java/sopt/org/hmh/domain/user/controller/UserApi.java +++ b/src/main/java/sopt/org/hmh/domain/user/controller/UserApi.java @@ -2,23 +2,34 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import java.time.LocalDate; import org.springframework.http.ResponseEntity; -import sopt.org.hmh.global.auth.UserId; +import sopt.org.hmh.domain.user.dto.request.UserRequest.LockDateRequest; +import sopt.org.hmh.domain.user.dto.response.UserResponse.IsLockTodayResponse; +import sopt.org.hmh.domain.user.dto.response.UserResponse.UserInfoResponse; import sopt.org.hmh.global.common.response.BaseResponse; +import sopt.org.hmh.global.common.response.EmptyJsonResponse; public interface UserApi { @Operation(summary = "๋กœ๊ทธ์•„์›ƒ") - ResponseEntity> orderLogout(@UserId @Parameter(hidden = true) final Long userId); + ResponseEntity> orderLogout(); @Operation(summary = "์œ ์ € ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ") - ResponseEntity> orderGetUserInfo(@UserId @Parameter(hidden = true) final Long userId); + ResponseEntity> orderGetUserInfo(@Parameter(hidden = true) final Long userId); @Operation(summary = "์œ ์ € ํฌ์ธํŠธ ์ •๋ณด ๋ถˆ๋Ÿฌ์˜ค๊ธฐ") - public ResponseEntity> orderGetUserPoint(@UserId final Long userId); + ResponseEntity> orderGetUserPoint(@Parameter(hidden = true) final Long userId); - @Operation( - summary = "ํšŒ์› ํƒˆํ‡ด") - ResponseEntity> orderWithdraw(@UserId @Parameter(hidden = true) final Long userId); + @Operation(summary = "ํšŒ์› ํƒˆํ‡ด") + ResponseEntity> orderWithdraw(@Parameter(hidden = true) final Long userId); + + @Operation(summary = "๋‹น์ผ ์ž ๊ธˆ ์—ฌ๋ถ€ ์ „์†ก") + ResponseEntity> orderChangeRecentLockDate( + @Parameter(hidden = true) final Long userId, final LockDateRequest request); + + @Operation(summary = "๋‹น์ผ ์ž ๊ธˆ ์—ฌ๋ถ€ ํ™•์ธ") + ResponseEntity> orderGetRecentLockDate( + @Parameter(hidden = true) final Long userId, final LocalDate lockCheckDate); } diff --git a/src/main/java/sopt/org/hmh/domain/user/controller/UserController.java b/src/main/java/sopt/org/hmh/domain/user/controller/UserController.java index 853f88b7..9e5d80f9 100644 --- a/src/main/java/sopt/org/hmh/domain/user/controller/UserController.java +++ b/src/main/java/sopt/org/hmh/domain/user/controller/UserController.java @@ -1,13 +1,21 @@ package sopt.org.hmh.domain.user.controller; +import jakarta.validation.Valid; +import java.time.LocalDate; import lombok.RequiredArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; +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.RestController; import sopt.org.hmh.domain.user.domain.exception.UserSuccess; +import sopt.org.hmh.domain.user.dto.request.UserRequest.LockDateRequest; +import sopt.org.hmh.domain.user.dto.response.UserResponse.IsLockTodayResponse; +import sopt.org.hmh.domain.user.dto.response.UserResponse.UserInfoResponse; import sopt.org.hmh.domain.user.service.UserService; import sopt.org.hmh.global.auth.UserId; import sopt.org.hmh.global.common.response.BaseResponse; @@ -16,14 +24,13 @@ @RestController @RequiredArgsConstructor @RequestMapping("/api/v1/user") -public class UserController implements UserApi{ +public class UserController implements UserApi { private final UserService userService; @PostMapping("/logout") @Override - public ResponseEntity> orderLogout(@UserId final Long userId) { - userService.logout(userId); + public ResponseEntity> orderLogout() { return ResponseEntity .status(UserSuccess.LOGOUT_SUCCESS.getHttpStatus()) .body(BaseResponse.success(UserSuccess.LOGOUT_SUCCESS, new EmptyJsonResponse())); @@ -31,7 +38,7 @@ public ResponseEntity> orderLogout(@UserId final Long userId) { @GetMapping @Override - public ResponseEntity> orderGetUserInfo(@UserId final Long userId) { + public ResponseEntity> orderGetUserInfo(@UserId final Long userId) { return ResponseEntity .status(UserSuccess.GET_USER_INFO_SUCCESS.getHttpStatus()) .body(BaseResponse.success(UserSuccess.GET_USER_INFO_SUCCESS, userService.getUserInfo(userId))); @@ -39,18 +46,40 @@ public ResponseEntity> orderGetUserInfo(@UserId final Long userI @GetMapping("/point") @Override - public ResponseEntity> orderGetUserPoint(@UserId final Long userId) { + public ResponseEntity> orderGetUserPoint(@UserId final Long userId) { return ResponseEntity .status(UserSuccess.GET_USER_POINT_SUCCESS.getHttpStatus()) - .body(BaseResponse.success(UserSuccess.GET_USER_POINT_SUCCESS, userService.getUserInfo(userId).point())); + .body(BaseResponse.success(UserSuccess.GET_USER_POINT_SUCCESS, + userService.getUserInfo(userId).point())); } @DeleteMapping - public ResponseEntity> orderWithdraw(@UserId final Long userId) { + public ResponseEntity> orderWithdraw(@UserId final Long userId) { userService.withdraw(userId); return ResponseEntity .status(UserSuccess.WITHDRAW_SUCCESS.getHttpStatus()) .body(BaseResponse.success(UserSuccess.WITHDRAW_SUCCESS, new EmptyJsonResponse())); } + @PostMapping("/daily/lock") + @Override + public ResponseEntity> orderChangeRecentLockDate( + @UserId final Long userId, @Valid @RequestBody final LockDateRequest request) { + userService.changeRecentLockDate(userId, request.lockDate()); + return ResponseEntity + .status(UserSuccess.CHANGE_RECENT_LOCK_DATE_SUCCESS.getHttpStatus()) + .body(BaseResponse.success(UserSuccess.CHANGE_RECENT_LOCK_DATE_SUCCESS, new EmptyJsonResponse())); + } + + @GetMapping("/daily/lock") + @Override + public ResponseEntity> orderGetRecentLockDate( + @UserId final Long userId, + @RequestParam(name = "lockCheckDate") @DateTimeFormat(pattern = "yyyy-MM-dd") final LocalDate lockCheckDate) { + return ResponseEntity + .status(UserSuccess.GET_RECENT_LOCK_DATE_SUCCESS.getHttpStatus()) + .body(BaseResponse.success(UserSuccess.GET_RECENT_LOCK_DATE_SUCCESS, + userService.checkIsTodayLock(userId, lockCheckDate))); + } + } diff --git a/src/main/java/sopt/org/hmh/domain/user/domain/User.java b/src/main/java/sopt/org/hmh/domain/user/domain/User.java index 9f92f77a..d67594a8 100644 --- a/src/main/java/sopt/org/hmh/domain/user/domain/User.java +++ b/src/main/java/sopt/org/hmh/domain/user/domain/User.java @@ -11,6 +11,7 @@ import jakarta.persistence.Id; import jakarta.persistence.Table; import jakarta.validation.constraints.Min; +import java.time.LocalDate; import java.time.LocalDateTime; import lombok.AccessLevel; import lombok.Builder; @@ -45,6 +46,8 @@ public class User extends BaseTimeEntity { @Column(columnDefinition = "TEXT") private String profileImageUrl; + private LocalDate recentLockDate; + private boolean isDeleted = false; private LocalDateTime deletedAt; @@ -88,4 +91,8 @@ public Integer increasePoint(Integer earnedPoint) { public void changeCurrentChallengeId(Long currentChallengeId) { this.currentChallengeId = currentChallengeId; } + + public void changeRecentLockDate(LocalDate recentLockDate) { + this.recentLockDate = recentLockDate; + } } \ No newline at end of file diff --git a/src/main/java/sopt/org/hmh/domain/user/domain/exception/UserSuccess.java b/src/main/java/sopt/org/hmh/domain/user/domain/exception/UserSuccess.java index afd35fb3..8f2c3757 100644 --- a/src/main/java/sopt/org/hmh/domain/user/domain/exception/UserSuccess.java +++ b/src/main/java/sopt/org/hmh/domain/user/domain/exception/UserSuccess.java @@ -12,6 +12,8 @@ public enum UserSuccess implements SuccessBase { GET_USER_POINT_SUCCESS(HttpStatus.OK, "์œ ์ €์˜ ํฌ์ธํŠธ ์ •๋ณด๋ฅผ ๋ถˆ๋Ÿฌ์˜ค๋Š”๋ฐ์— ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค."), LOGOUT_SUCCESS(HttpStatus.OK, "๋กœ๊ทธ์•„์›ƒ์— ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค."), WITHDRAW_SUCCESS(HttpStatus.OK, "ํšŒ์› ํƒˆํ‡ด๋ฅผ ์„ฑ๊ณตํ•˜์˜€์Šต๋‹ˆ๋‹ค."), + CHANGE_RECENT_LOCK_DATE_SUCCESS(HttpStatus.OK, "๋‹น์ผ ์ž ๊ธˆ ์—ฌ๋ถ€ ์ „์†ก์— ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค."), + GET_RECENT_LOCK_DATE_SUCCESS(HttpStatus.OK, "๋‹น์ผ ์ž ๊ธˆ ์—ฌ๋ถ€ ํ™•์ธ์— ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค."), ; private final HttpStatus status; diff --git a/src/main/java/sopt/org/hmh/domain/user/dto/request/UserRequest.java b/src/main/java/sopt/org/hmh/domain/user/dto/request/UserRequest.java new file mode 100644 index 00000000..3a3f9bbc --- /dev/null +++ b/src/main/java/sopt/org/hmh/domain/user/dto/request/UserRequest.java @@ -0,0 +1,19 @@ +package sopt.org.hmh.domain.user.dto.request; + +import jakarta.validation.constraints.NotNull; +import java.time.LocalDate; +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.springframework.format.annotation.DateTimeFormat; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class UserRequest { + + public record LockDateRequest( + @DateTimeFormat(pattern = "yyyy-MM-dd") + @NotNull(message = "์ž ๊ธˆ ๋‚ ์งœ๋Š” null์ผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.") + LocalDate lockDate + ) { + } + +} diff --git a/src/main/java/sopt/org/hmh/domain/user/dto/response/UserInfoResponse.java b/src/main/java/sopt/org/hmh/domain/user/dto/response/UserInfoResponse.java deleted file mode 100644 index 0cf207b8..00000000 --- a/src/main/java/sopt/org/hmh/domain/user/dto/response/UserInfoResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package sopt.org.hmh.domain.user.dto.response; - -import sopt.org.hmh.domain.user.domain.User; - -public record UserInfoResponse( - String name, - Integer point -) { - public static UserInfoResponse of(User user) { - return new UserInfoResponse( - user.getName(), - user.getPoint() - ); - } -} \ No newline at end of file diff --git a/src/main/java/sopt/org/hmh/domain/user/dto/response/UserResponse.java b/src/main/java/sopt/org/hmh/domain/user/dto/response/UserResponse.java new file mode 100644 index 00000000..e91748a0 --- /dev/null +++ b/src/main/java/sopt/org/hmh/domain/user/dto/response/UserResponse.java @@ -0,0 +1,26 @@ +package sopt.org.hmh.domain.user.dto.response; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import sopt.org.hmh.domain.user.domain.User; + +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public class UserResponse { + + public record UserInfoResponse( + String name, + Integer point + ) { + public static UserInfoResponse of(User user) { + return new UserInfoResponse( + user.getName(), + user.getPoint() + ); + } + } + + public record IsLockTodayResponse( + boolean isLockToday + ) { + } +} diff --git a/src/main/java/sopt/org/hmh/domain/user/service/UserService.java b/src/main/java/sopt/org/hmh/domain/user/service/UserService.java index a631adb7..54466c4d 100644 --- a/src/main/java/sopt/org/hmh/domain/user/service/UserService.java +++ b/src/main/java/sopt/org/hmh/domain/user/service/UserService.java @@ -1,5 +1,6 @@ package sopt.org.hmh.domain.user.service; +import java.time.LocalDate; import java.util.List; import java.util.Optional; @@ -12,17 +13,15 @@ import sopt.org.hmh.domain.auth.exception.AuthException; import sopt.org.hmh.domain.auth.repository.OnboardingInfoRepository; import sopt.org.hmh.domain.auth.repository.ProblemRepository; -import sopt.org.hmh.domain.challenge.domain.exception.ChallengeError; -import sopt.org.hmh.domain.challenge.domain.exception.ChallengeException; import sopt.org.hmh.domain.user.domain.OnboardingInfo; import sopt.org.hmh.domain.user.domain.OnboardingProblem; import sopt.org.hmh.domain.user.domain.User; import sopt.org.hmh.domain.user.domain.UserConstants; import sopt.org.hmh.domain.user.domain.exception.UserError; import sopt.org.hmh.domain.user.domain.exception.UserException; -import sopt.org.hmh.domain.user.dto.response.UserInfoResponse; +import sopt.org.hmh.domain.user.dto.response.UserResponse.IsLockTodayResponse; +import sopt.org.hmh.domain.user.dto.response.UserResponse.UserInfoResponse; import sopt.org.hmh.domain.user.repository.UserRepository; -import sopt.org.hmh.global.auth.redis.RedisManagerService; import sopt.org.hmh.global.auth.social.SocialPlatform; @Service @@ -30,7 +29,6 @@ @Transactional(readOnly = true) public class UserService { - private final RedisManagerService redisManagerService; private final UserRepository userRepository; private final OnboardingInfoRepository onboardingInfoRepository; private final ProblemRepository problemRepository; @@ -38,14 +36,9 @@ public class UserService { @Transactional public void withdraw(Long userId) { - redisManagerService.deleteRefreshToken(userId); this.findByIdOrThrowException(userId).softDelete(); } - public void logout(Long userId) { - redisManagerService.deleteRefreshToken(userId); - } - public UserInfoResponse getUserInfo(Long userId) { return UserInfoResponse.of(this.findByIdOrThrowException(userId)); } @@ -109,4 +102,19 @@ public Long getCurrentChallengeIdByUserId(Long userId) { return Optional.ofNullable(this.findByIdOrThrowException(userId).getCurrentChallengeId()) .orElseThrow(() -> new UserException(UserError.NOT_FOUND_CURRENT_CHALLENGE_ID)); } + + @Transactional + public void changeRecentLockDate(Long userId, LocalDate localDate) { + this.findByIdOrThrowException(userId).changeRecentLockDate(localDate); + } + + public IsLockTodayResponse checkIsTodayLock(Long userId, LocalDate lockCheckDate) { + LocalDate userRecentLockDate = this.findByIdOrThrowException(userId).getRecentLockDate(); + + if (userRecentLockDate == null) { + return new IsLockTodayResponse(false); + } + + return new IsLockTodayResponse(userRecentLockDate.equals(lockCheckDate)); + } } \ No newline at end of file diff --git a/src/main/java/sopt/org/hmh/global/auth/jwt/JwtGenerator.java b/src/main/java/sopt/org/hmh/global/auth/jwt/JwtGenerator.java index 185280db..5da40648 100644 --- a/src/main/java/sopt/org/hmh/global/auth/jwt/JwtGenerator.java +++ b/src/main/java/sopt/org/hmh/global/auth/jwt/JwtGenerator.java @@ -11,8 +11,6 @@ import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import sopt.org.hmh.global.auth.redis.RefreshToken; -import sopt.org.hmh.global.auth.redis.TokenRepository; @Component @RequiredArgsConstructor @@ -25,29 +23,17 @@ public class JwtGenerator { @Value("${jwt.refresh-token-expiration-time}") private Long REFRESH_TOKEN_EXPIRATION_TIME; - private final TokenRepository tokenRepository; - public String generateToken(Long userId, boolean isRefreshToken) { final Date now = generateNowDate(); final Date expiration = generateExpirationDate(isRefreshToken, now); - String token = Jwts.builder() + return Jwts.builder() .setHeaderParam(Header.TYPE, Header.JWT_TYPE) .setSubject(String.valueOf(userId)) .setIssuedAt(now) .setExpiration(expiration) .signWith(getSigningKey()) .compact(); - - if (isRefreshToken) { - tokenRepository.save( - RefreshToken.builder() - .userId(userId) - .token(token) - .expiration(REFRESH_TOKEN_EXPIRATION_TIME / 1000) - .build()); - } - return token; } public JwtParser getJwtParser() { diff --git a/src/main/java/sopt/org/hmh/global/auth/jwt/TokenService.java b/src/main/java/sopt/org/hmh/global/auth/jwt/TokenService.java index 66292c1e..64e2f6b9 100644 --- a/src/main/java/sopt/org/hmh/global/auth/jwt/TokenService.java +++ b/src/main/java/sopt/org/hmh/global/auth/jwt/TokenService.java @@ -6,7 +6,6 @@ import sopt.org.hmh.domain.auth.dto.response.ReissueResponse; import sopt.org.hmh.global.auth.jwt.exception.JwtError; import sopt.org.hmh.global.auth.jwt.exception.JwtException; -import sopt.org.hmh.global.auth.redis.RedisManagerService; @Service @RequiredArgsConstructor @@ -14,14 +13,12 @@ public class TokenService { private final JwtProvider jwtProvider; private final JwtValidator jwtValidator; - private final RedisManagerService redisManagerService; @Transactional public ReissueResponse reissueToken(String refreshToken) { String parsedRefreshToken = parseTokenString(refreshToken); Long userId = jwtProvider.getSubject(parsedRefreshToken); jwtValidator.validateRefreshToken(parsedRefreshToken); - redisManagerService.deleteRefreshToken(userId); return ReissueResponse.of(jwtProvider.issueToken(userId)); } diff --git a/src/main/java/sopt/org/hmh/global/auth/redis/RedisManagerService.java b/src/main/java/sopt/org/hmh/global/auth/redis/RedisManagerService.java deleted file mode 100644 index 812a5681..00000000 --- a/src/main/java/sopt/org/hmh/global/auth/redis/RedisManagerService.java +++ /dev/null @@ -1,21 +0,0 @@ -package sopt.org.hmh.global.auth.redis; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import sopt.org.hmh.global.auth.jwt.exception.JwtError; -import sopt.org.hmh.global.auth.jwt.exception.JwtException; - -@Service -@RequiredArgsConstructor -public class RedisManagerService { - - private final TokenRepository tokenRepository; - - public void deleteRefreshToken(Long userId) { - if (tokenRepository.existsById(userId)) { - tokenRepository.deleteById(userId); - } else { - throw new JwtException(JwtError.INVALID_REFRESH_TOKEN); - } - } -} diff --git a/src/main/java/sopt/org/hmh/global/auth/redis/RefreshToken.java b/src/main/java/sopt/org/hmh/global/auth/redis/RefreshToken.java deleted file mode 100644 index cfb6e848..00000000 --- a/src/main/java/sopt/org/hmh/global/auth/redis/RefreshToken.java +++ /dev/null @@ -1,25 +0,0 @@ -package sopt.org.hmh.global.auth.redis; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.springframework.data.annotation.Id; -import org.springframework.data.redis.core.RedisHash; -import org.springframework.data.redis.core.TimeToLive; - -@Getter -@RedisHash(value = "refresh") -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class RefreshToken { - - @Id - private Long userId; - - private String token; - - @TimeToLive - private Long expiration; -} \ No newline at end of file diff --git a/src/main/java/sopt/org/hmh/global/auth/redis/TokenRepository.java b/src/main/java/sopt/org/hmh/global/auth/redis/TokenRepository.java deleted file mode 100644 index e550e700..00000000 --- a/src/main/java/sopt/org/hmh/global/auth/redis/TokenRepository.java +++ /dev/null @@ -1,6 +0,0 @@ -package sopt.org.hmh.global.auth.redis; - -import org.springframework.data.repository.CrudRepository; - -public interface TokenRepository extends CrudRepository { -} \ No newline at end of file diff --git a/src/main/java/sopt/org/hmh/global/config/RedisConfig.java b/src/main/java/sopt/org/hmh/global/config/RedisConfig.java deleted file mode 100644 index ff8e702e..00000000 --- a/src/main/java/sopt/org/hmh/global/config/RedisConfig.java +++ /dev/null @@ -1,32 +0,0 @@ -package sopt.org.hmh.global.config; - -import org.springframework.beans.factory.annotation.Value; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.data.redis.connection.RedisConnectionFactory; -import org.springframework.data.redis.connection.RedisStandaloneConfiguration; -import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; -import org.springframework.data.redis.repository.configuration.EnableRedisRepositories; - -@Configuration -@EnableRedisRepositories -public class RedisConfig { - - @Value("${spring.data.redis.host}") - private String host; - - @Value("${spring.data.redis.port}") - private int port; - - @Value("${spring.data.redis.password}") - private String password; - - @Bean - public RedisConnectionFactory redisConnectionFactory() { - RedisStandaloneConfiguration redisConfiguration = new RedisStandaloneConfiguration(); - redisConfiguration.setHostName(host); - redisConfiguration.setPort(port); - redisConfiguration.setPassword(password); - return new LettuceConnectionFactory(redisConfiguration); - } -} \ No newline at end of file diff --git a/src/main/java/sopt/org/hmh/global/config/SecurityConfig.java b/src/main/java/sopt/org/hmh/global/config/SecurityConfig.java index 7c07c0c0..5c7e1203 100644 --- a/src/main/java/sopt/org/hmh/global/config/SecurityConfig.java +++ b/src/main/java/sopt/org/hmh/global/config/SecurityConfig.java @@ -41,9 +41,6 @@ public class SecurityConfig { "/api/v1/user/reissue", "/api/v1/user/signup", "/api/v1/user/social/token/kakao", - - // etc - "/api/v1/dummy/**", }; @Bean