From d684f5edb4e60fb28cec716dde5b7918fa1a9580 Mon Sep 17 00:00:00 2001 From: Haena <67584244+EUNJEONGMUN@users.noreply.github.com> Date: Mon, 20 Mar 2023 10:02:15 +0900 Subject: [PATCH] =?UTF-8?q?[FEATURE]=20BaseResponse=20=EB=B0=8F=20?= =?UTF-8?q?=EA=B8=B0=EB=B3=B8=20=EC=84=A4=EC=A0=95=20(#16)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * application.yml 추가 * Create deploy.yml * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * 자동 배포 설정 * [FEATURE] 엔티티를 생성한다. (#9) (#10) * feat: Avatar 엔티티 생성 * feat: Category enum 생성 * feat: Member 엔티티 생성 * feat: Post 엔티티 생성 * feat: Comment 엔티티 생성 * feat: PostLike 엔티티 생성 * feat: PostPhoto 엔티티 생성 * feat: Record 엔티티 생성 * feat: RecordPhoto 엔티티 생성 * feat: Report 엔티티 생성 * feat: Tag 엔티티 생성 * feat: BaseTimeEntity 추상 클래스 생성 * feat: ReportType enum 생성 * chore: category id 추가 * chore: submodule 변경사항 * Readme.md 추가 * deploy.sh 주석 추가 (자동 배포 마무리) * chore: controller, service, repository 생성 * feature: BaseResponse 생성 * feature: ExceptionResponse 생성 * feature: ErrorCode interface 생성 * feature: BaseException 생성 * feature: ControllerAdvice 생성 * feature: GlobalErrorCode 생성 * feature: 도메인별 errorCode 생성 * feature: 도메인별 Repository 생성 * fix: ErrorCode 구현하도록 수정 * feature: UtilService 생성 * fix: 필요 없는 에러 코드 제거 --------- Co-authored-by: Sewoong --- .github/workflows/deploy.yml | 111 ++++++++++++++++++ .gitmodules | 1 + README.md | 52 +++++++- appspec.yml | 23 ++++ build.gradle | 9 +- config | 2 +- scripts/start.sh | 19 +++ scripts/stop.sh | 19 +++ .../todaysgym/config/ControllerAdvice.java | 75 ++++++++++++ .../config/exception/BaseException.java | 15 +++ .../todaysgym/config/exception/ErrorCode.java | 8 ++ .../exception/errorCode/AuthErrorCode.java | 16 +++ .../errorCode/CategoryErrorCode.java | 13 ++ .../exception/errorCode/CommentErrorCode.java | 14 +++ .../exception/errorCode/GlobalErrorCode.java | 19 +++ .../exception/errorCode/MemberErrorCode.java | 14 +++ .../exception/errorCode/PostErrorCode.java | 14 +++ .../exception/errorCode/RecordErrorCode.java | 14 +++ .../exception/errorCode/ReportErrorCode.java | 14 +++ .../config/response/BaseResponse.java | 20 ++++ .../config/response/ExceptionResponse.java | 15 +++ .../todaysgym/member/MemberRepository.java | 9 ++ .../todaysgym/post/PostRepository.java | 9 ++ .../post/comment/CommentRepository.java | 9 ++ .../post/like/PostLikeRepository.java | 7 ++ .../post/photo/PostPhotoRepository.java | 7 ++ .../todaysgym/record/RecordRepository.java | 9 ++ .../record/photo/RecordPhotoRepository.java | 7 ++ .../todaysgym/report/ReportController.java | 10 ++ .../todaysgym/report/ReportRepository.java | 7 ++ .../todaysgym/report/ReportService.java | 10 ++ .../todaysgym/tag/TagRepository.java | 7 ++ .../todaysgym/utils/UtilService.java | 102 ++++++++++++++++ src/main/resources/application.yml | 6 + 34 files changed, 682 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/deploy.yml create mode 100644 appspec.yml create mode 100644 scripts/start.sh create mode 100644 scripts/stop.sh create mode 100644 src/main/java/com/todaysgym/todaysgym/config/ControllerAdvice.java create mode 100644 src/main/java/com/todaysgym/todaysgym/config/exception/BaseException.java create mode 100644 src/main/java/com/todaysgym/todaysgym/config/exception/ErrorCode.java create mode 100644 src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/AuthErrorCode.java create mode 100644 src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/CategoryErrorCode.java create mode 100644 src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/CommentErrorCode.java create mode 100644 src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/GlobalErrorCode.java create mode 100644 src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/MemberErrorCode.java create mode 100644 src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/PostErrorCode.java create mode 100644 src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/RecordErrorCode.java create mode 100644 src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/ReportErrorCode.java create mode 100644 src/main/java/com/todaysgym/todaysgym/config/response/BaseResponse.java create mode 100644 src/main/java/com/todaysgym/todaysgym/config/response/ExceptionResponse.java create mode 100644 src/main/java/com/todaysgym/todaysgym/member/MemberRepository.java create mode 100644 src/main/java/com/todaysgym/todaysgym/post/PostRepository.java create mode 100644 src/main/java/com/todaysgym/todaysgym/post/comment/CommentRepository.java create mode 100644 src/main/java/com/todaysgym/todaysgym/post/like/PostLikeRepository.java create mode 100644 src/main/java/com/todaysgym/todaysgym/post/photo/PostPhotoRepository.java create mode 100644 src/main/java/com/todaysgym/todaysgym/record/RecordRepository.java create mode 100644 src/main/java/com/todaysgym/todaysgym/record/photo/RecordPhotoRepository.java create mode 100644 src/main/java/com/todaysgym/todaysgym/report/ReportController.java create mode 100644 src/main/java/com/todaysgym/todaysgym/report/ReportRepository.java create mode 100644 src/main/java/com/todaysgym/todaysgym/report/ReportService.java create mode 100644 src/main/java/com/todaysgym/todaysgym/tag/TagRepository.java create mode 100644 src/main/java/com/todaysgym/todaysgym/utils/UtilService.java create mode 100644 src/main/resources/application.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..20b552a --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,111 @@ +# This workflow will build and push a new container image to Amazon ECR, +# and then will deploy a new task definition to Amazon ECS, when there is a push to the "main" branch. +# +# To use this workflow, you will need to complete the following set-up steps: +# +# 1. Create an ECR repository to store your images. +# For example: `aws ecr create-repository --repository-name my-ecr-repo --region us-east-2`. +# Replace the value of the `ECR_REPOSITORY` environment variable in the workflow below with your repository's name. +# Replace the value of the `AWS_REGION` environment variable in the workflow below with your repository's region. +# +# 2. Create an ECS task definition, an ECS cluster, and an ECS service. +# For example, follow the Getting Started guide on the ECS console: +# https://us-east-2.console.aws.amazon.com/ecs/home?region=us-east-2#/firstRun +# Replace the value of the `ECS_SERVICE` environment variable in the workflow below with the name you set for the Amazon ECS service. +# Replace the value of the `ECS_CLUSTER` environment variable in the workflow below with the name you set for the cluster. +# +# 3. Store your ECS task definition as a JSON file in your repository. +# The format should follow the output of `aws ecs register-task-definition --generate-cli-skeleton`. +# Replace the value of the `ECS_TASK_DEFINITION` environment variable in the workflow below with the path to the JSON file. +# Replace the value of the `CONTAINER_NAME` environment variable in the workflow below with the name of the container +# in the `containerDefinitions` section of the task definition. +# +# 4. Store an IAM user access key in GitHub Actions secrets named `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. +# See the documentation for each action used below for the recommended IAM policies for this IAM user, +# and best practices on handling the access key credentials. + +name: Deploy to Amazon EC2 + +on: + push: + branches: [ "main" ] + +env: + AWS_REGION: ap-northeast-2 + S3_BUCKET_NAME: todaysgym-github-actios-s3-bucket + CODE_DEPLOY_APPLICATION_NAME: todaysgym-codedeploy-app + CODE_DEPLOY_DEPLOYMENT_GROUP_NAME: todaysgym-codedeploy-deployment-group + +permissions: + contents: read + +jobs: + deploy: + name: Deploy + runs-on: ubuntu-latest + environment: production + + steps: + # (1) 기본 체크아웃 + - name: Checkout + uses: actions/checkout@v3 + + # (2) JDK 11 세팅 + - name: Set up JDK 11 + uses: actions/setup-java@v3 + with: + distribution: 'temurin' + java-version: '11' + + # (3) 서브 모듈 접근하기 + - name: Checkout repo + uses: actions/checkout@v3 + with: + token: ${{ secrets.TOKEN }} + submodules: true + + # (4) 서브 모듈 변경 점 있으면 update + - name: Git Sumbodule Update + run: | + git pull --recurse-submodules + git submodule update --remote --recursive + + # (5) gradle 권한 변경 + - name: Run chmod to make gradlew executable + run: chmod +x ./gradlew + + # (6) Gradle build (Test 제외) + - name: Build with Gradle + uses: gradle/gradle-build-action@0d13054264b0bb894ded474f08ebb30921341cee + with: + arguments: clean build -x test + + # (7) 원하는 파일 Zip 하기 + - name: Zip build file and deploy sh + run: | + mv ./build/libs/*.jar ./ + zip buildFile.zip ./appspec.yml ./*.jar ./scripts/start.sh ./scripts/stop.sh + + # (8) AWS 인증 (IAM 사용자 Access Key, Secret Key 활용) + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@v1 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ env.AWS_REGION }} + + # (9) 빌드 결과물을 S3 버킷에 업로드 + - name: Upload to AWS S3 + run: | + aws s3 cp \ + --region ap-northeast-2 \ + buildFile.zip s3://$S3_BUCKET_NAME/community-build/ + + # (10) S3 버킷에 있는 파일을 대상으로 CodeDeploy 실행 + - name: Deploy to AWS EC2 from S3 + run: | + aws deploy create-deployment \ + --application-name ${{ env.CODE_DEPLOY_APPLICATION_NAME }} \ + --deployment-config-name CodeDeployDefault.AllAtOnce \ + --deployment-group-name ${{ env.CODE_DEPLOY_DEPLOYMENT_GROUP_NAME }} \ + --s3-location bucket=$S3_BUCKET_NAME,key=community-build/buildFile.zip,bundleType=zip diff --git a/.gitmodules b/.gitmodules index 3151a5f..c8b1d77 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,4 @@ [submodule "config"] path = config url = https://github.com/Today-s-Gym/application.git + branch = "main" diff --git a/README.md b/README.md index af60ddd..4f4d71e 100644 --- a/README.md +++ b/README.md @@ -1 +1,51 @@ -# TodaysGym Backend +

오늘의 짐(Gym)

+ +

아바타와 함께 성장하는 운동기록 & SNS

+ +## 💪 오늘의 짐(Gym) 소개 + +운동을 기록하면 당신의 아바타가 성장합니다! + +하루에 한 번 운동을 기록할 수 있으며 태그 기능으로 손쉽게 관리할 수 있습니다. + +다양한 운동 게시판이 준비되어 있습니다. 여러 사람들과 함께 운동 경험을 공유하세요! + +## 🥋 팀원 +| Backend | Backend | Backend | Backend | +|:--------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------:|:------------------------------------:|:--------------------------------------------------------------------------------------:| +| 보라 | 풀솦 | 해나 | 헤론 | +| [보라](https://github.com/YooJisu826) | [풀솦](https://github.com/injoon149) | [해나](https://github.com/EUNJEONGMUN) | [헤론](https://github.com/Heron-Woong) | + +## ⚒ 프로젝트 기술 스택 +- Java 11 +- Spring Boot 2.7.7 +- Spring Data JPA +- MySQL + +## 🎯 ERD +erd + + +## 👨‍💻 협업 규칙 +### 1. 브랜치 규칙 +feature/{기능} 형식 + +예시 : feature/Login, feature/Chart + +### 2. Commit Message +* feat : 새로운 기능 추가 +* fix : 버그 수정, 기능 수정 +* docs : 문서 수정 +* refactor : 코드 리팩토링 (변수명 수정 등) +* test : 테스트 코드, 리팩토링 테스트 코드 추가 +* style : 코드 스타일 변경, 코드 자체 변경이 없는 경우 +* remove : 파일 또는 코드, 리소스 제거 +* resource : 이미지 리소스, prefab 등의 코드와 상관없는 리소스 추가 + +예시 : +* resource : 이미지 리소스, prefab 등의 코드와 상관없는 리소스 추가 +* feat : Add translation to missing strings +* feat : Disable publishing +* feat : Sort list context menu +* feat : Resize minimize/delete handle icons so they take up the entire topbar +* fix : Fix typo in cleanup.sh file \ No newline at end of file diff --git a/appspec.yml b/appspec.yml new file mode 100644 index 0000000..9882a4f --- /dev/null +++ b/appspec.yml @@ -0,0 +1,23 @@ +version: 0.0 +os: linux + +files: + - source: / + destination: /home/ubuntu/app + overwrite: yes + +permissions: + - object: / + pattern: "**" + owner: ubuntu + group: ubuntu + +hooks: + AfterInstall: + - location: scripts/stop.sh + timeout: 60 + runas: ubuntu + ApplicationStart: + - location: scripts/start.sh + timeout: 60 + runas: ubuntu \ No newline at end of file diff --git a/build.gradle b/build.gradle index 206d63d..d2a969d 100644 --- a/build.gradle +++ b/build.gradle @@ -33,7 +33,6 @@ dependencies { //implementation group: 'org.springframework.cloud', name: 'spring-cloud-aws', version: '2.2.1.RELEASE', ext: 'pom' implementation 'com.amazonaws:aws-java-sdk-s3:1.11.901' implementation 'io.awspring.cloud:spring-cloud-aws:2.4.2' - // jwt implementation 'io.jsonwebtoken:jjwt-api:0.11.5' implementation 'io.jsonwebtoken:jjwt-impl:0.11.5' @@ -47,8 +46,14 @@ tasks.named('test') { useJUnitPlatform() } + +processResources.dependsOn('copyGitSubmodule') task copyGitSubmodule(type: Copy) { from './config' include '*.yml' - into './src/main/resources' + into 'src/main/resources' +} + +jar { + enabled = false } \ No newline at end of file diff --git a/config b/config index a53969a..c9bd833 160000 --- a/config +++ b/config @@ -1 +1 @@ -Subproject commit a53969a30c4f51d1d7d31964e16d5088a68ce433 +Subproject commit c9bd833945e3fbfd6dc5bf6b9403b51eb64d8740 diff --git a/scripts/start.sh b/scripts/start.sh new file mode 100644 index 0000000..55e6b8c --- /dev/null +++ b/scripts/start.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +PROJECT_ROOT="/home/ubuntu/app" +JAR_FILE="$PROJECT_ROOT/todaysgym-0.0.1-SNAPSHOT.jar" + +APP_LOG="$PROJECT_ROOT/application.log" +ERROR_LOG="$PROJECT_ROOT/error.log" +DEPLOY_LOG="$PROJECT_ROOT/deploy.log" + +TIME_NOW=$(date +%c) + +# jar 파일 실행 +echo "$TIME_NOW > $JAR_FILE 파일 실행" >> $DEPLOY_LOG +nohup java -jar \ +-Dspring.profiles.active=main \ +$JAR_FILE > $APP_LOG 2> $ERROR_LOG & + +CURRENT_PID=$(pgrep -f $JAR_FILE) +echo "$TIME_NOW > 실행된 프로세스 아이디 $CURRENT_PID 입니다." >> $DEPLOY_LOG \ No newline at end of file diff --git a/scripts/stop.sh b/scripts/stop.sh new file mode 100644 index 0000000..bf9d3af --- /dev/null +++ b/scripts/stop.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +PROJECT_ROOT="/home/ubuntu/app" +JAR_FILE="$PROJECT_ROOT/todaysgym-0.0.1-SNAPSHOT.jar" + +DEPLOY_LOG="$PROJECT_ROOT/deploy.log" + +TIME_NOW=$(date +%c) + +# 현재 구동 중인 애플리케이션 pid 확인 +CURRENT_PID=$(pgrep -f $JAR_FILE) + +# 프로세스가 켜져 있으면 종료 +if [ -z $CURRENT_PID ]; then + echo "$TIME_NOW > 현재 실행중인 애플리케이션이 없습니다" >> $DEPLOY_LOG +else + echo "$TIME_NOW > 실행중인 $CURRENT_PID 애플리케이션 종료 " >> $DEPLOY_LOG + kill -15 $CURRENT_PID +fi \ No newline at end of file diff --git a/src/main/java/com/todaysgym/todaysgym/config/ControllerAdvice.java b/src/main/java/com/todaysgym/todaysgym/config/ControllerAdvice.java new file mode 100644 index 0000000..c3e7d4f --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/config/ControllerAdvice.java @@ -0,0 +1,75 @@ +package com.todaysgym.todaysgym.config; + +import com.todaysgym.todaysgym.config.exception.BaseException; +import com.todaysgym.todaysgym.config.exception.ErrorCode; +import com.todaysgym.todaysgym.config.exception.errorCode.GlobalErrorCode; +import com.todaysgym.todaysgym.config.response.ExceptionResponse; +import java.util.List; +import org.springframework.validation.FieldError; +import org.springframework.web.HttpMediaTypeNotSupportedException; +import org.springframework.web.HttpRequestMethodNotSupportedException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.servlet.NoHandlerFoundException; + +@RestControllerAdvice +public class ControllerAdvice { + + @ExceptionHandler(BaseException.class) + public ExceptionResponse handleBaseException(BaseException e) { + ExceptionResponse exceptionResponse = new ExceptionResponse(e.getErrorCode(), + e.getMessage()); + return exceptionResponse; + } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ExceptionResponse handleException(MethodArgumentNotValidException e) { + String detailMessage = extractMessage(e.getBindingResult().getFieldErrors()); + return convert(GlobalErrorCode.NOT_VALID_ARGUMENT_ERROR, detailMessage); + } + + private String extractMessage(List fieldErrors) { + StringBuilder builder = new StringBuilder(); + fieldErrors.forEach((error) -> { + builder.append("["); + builder.append(error.getField()); + builder.append(": "); + builder.append(error.getDefaultMessage()); + builder.append(" || input value: "); + builder.append("]"); + builder.append(System.lineSeparator()); + }); + return builder.toString(); + } + + @ExceptionHandler(NoHandlerFoundException.class) + public ExceptionResponse handleNoHandlerFoundException() { + return convert(GlobalErrorCode.NOT_SUPPORTED_URI_ERROR); + } + + @ExceptionHandler(HttpRequestMethodNotSupportedException.class) + public ExceptionResponse handleMethodNotSupportedException() { + return convert(GlobalErrorCode.NOT_SUPPORTED_METHOD_ERROR); + } + + @ExceptionHandler(HttpMediaTypeNotSupportedException.class) + public ExceptionResponse handleMediaTypeNotSupportedException() { + return convert(GlobalErrorCode.NOT_SUPPORTED_MEDIA_TYPE_ERROR); + } + + @ExceptionHandler(RuntimeException.class) + public ExceptionResponse handleRuntimeException() { + return convert(GlobalErrorCode.SERVER_ERROR); + } + + private ExceptionResponse convert(ErrorCode e) { + ExceptionResponse exceptionRes = new ExceptionResponse(e.getErrorCode(), e.getMessage()); + return exceptionRes; + } + + private ExceptionResponse convert(ErrorCode e, String detailMessage) { + ExceptionResponse exceptionRes = new ExceptionResponse(e.getErrorCode(), detailMessage); + return exceptionRes; + } +} \ No newline at end of file diff --git a/src/main/java/com/todaysgym/todaysgym/config/exception/BaseException.java b/src/main/java/com/todaysgym/todaysgym/config/exception/BaseException.java new file mode 100644 index 0000000..33cf286 --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/config/exception/BaseException.java @@ -0,0 +1,15 @@ +package com.todaysgym.todaysgym.config.exception; + +import lombok.Getter; + +@Getter +public class BaseException extends RuntimeException { + + private final String errorCode; + private final String message; + + public BaseException(ErrorCode code) { + errorCode = code.getErrorCode(); + message = code.getMessage(); + } +} \ No newline at end of file diff --git a/src/main/java/com/todaysgym/todaysgym/config/exception/ErrorCode.java b/src/main/java/com/todaysgym/todaysgym/config/exception/ErrorCode.java new file mode 100644 index 0000000..319cd3c --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/config/exception/ErrorCode.java @@ -0,0 +1,8 @@ +package com.todaysgym.todaysgym.config.exception; + +public interface ErrorCode { + + String getErrorCode(); + + String getMessage(); +} \ No newline at end of file diff --git a/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/AuthErrorCode.java b/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/AuthErrorCode.java new file mode 100644 index 0000000..26340fd --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/AuthErrorCode.java @@ -0,0 +1,16 @@ +package com.todaysgym.todaysgym.config.exception.errorCode; + +import com.todaysgym.todaysgym.config.exception.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum AuthErrorCode implements ErrorCode { + EMPTY_JWT("AUTH_001", "JWT를 입력해주세요."), + INVALID_JWT("AUTH_002", "유효하지 않은 JWT입니다."), + EXPIRED_MEMBER_JWT("AUTH_003", "만료된 JWT입니다."), + ; + private final String errorCode; + private final String message; +} \ No newline at end of file diff --git a/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/CategoryErrorCode.java b/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/CategoryErrorCode.java new file mode 100644 index 0000000..3025115 --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/CategoryErrorCode.java @@ -0,0 +1,13 @@ +package com.todaysgym.todaysgym.config.exception.errorCode; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum CategoryErrorCode { + EMPTY_CATEGORY("CATEGORY_001", "존재하지 않는 카테고리입니다."), + ; + private final String errorCode; + private final String message; +} diff --git a/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/CommentErrorCode.java b/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/CommentErrorCode.java new file mode 100644 index 0000000..8c2f86b --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/CommentErrorCode.java @@ -0,0 +1,14 @@ +package com.todaysgym.todaysgym.config.exception.errorCode; + +import com.todaysgym.todaysgym.config.exception.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum CommentErrorCode implements ErrorCode { + EMPTY_COMMENT("COMMENT_001", "존재하지 않는 댓글입니다."), + ; + private final String errorCode; + private final String message; +} diff --git a/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/GlobalErrorCode.java b/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/GlobalErrorCode.java new file mode 100644 index 0000000..d644d38 --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/GlobalErrorCode.java @@ -0,0 +1,19 @@ +package com.todaysgym.todaysgym.config.exception.errorCode; + +import com.todaysgym.todaysgym.config.exception.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum GlobalErrorCode implements ErrorCode { + NOT_VALID_ARGUMENT_ERROR("GLOBAL_001", "올바른 argument를 입력해주세요."), + NOT_SUPPORTED_URI_ERROR("GLOBAL_002", "올바른 URI로 접근해주세요."), + NOT_SUPPORTED_METHOD_ERROR("GLOBAL_003", "지원하지 않는 Method입니다."), + NOT_SUPPORTED_MEDIA_TYPE_ERROR("GLOBAL_004", "지원하지 않는 Media type입니다."), + SERVER_ERROR("GLOBAL_005", "서버와의 연결에 실패하였습니다."), + ; + + private final String errorCode; + private final String message; +} \ No newline at end of file diff --git a/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/MemberErrorCode.java b/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/MemberErrorCode.java new file mode 100644 index 0000000..17b5441 --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/MemberErrorCode.java @@ -0,0 +1,14 @@ +package com.todaysgym.todaysgym.config.exception.errorCode; + +import com.todaysgym.todaysgym.config.exception.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum MemberErrorCode implements ErrorCode { + EMPTY_MEMBER("MEMBER_001", "존재하지 않는 사용자입니다."), + ; + private final String errorCode; + private final String message; +} \ No newline at end of file diff --git a/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/PostErrorCode.java b/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/PostErrorCode.java new file mode 100644 index 0000000..7bcfc10 --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/PostErrorCode.java @@ -0,0 +1,14 @@ +package com.todaysgym.todaysgym.config.exception.errorCode; + +import com.todaysgym.todaysgym.config.exception.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum PostErrorCode implements ErrorCode { + EMPTY_POST("POST_001", "존재하지 않는 게시글입니다."), + ; + private final String errorCode; + private final String message; +} \ No newline at end of file diff --git a/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/RecordErrorCode.java b/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/RecordErrorCode.java new file mode 100644 index 0000000..3dc72e3 --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/RecordErrorCode.java @@ -0,0 +1,14 @@ +package com.todaysgym.todaysgym.config.exception.errorCode; + +import com.todaysgym.todaysgym.config.exception.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum RecordErrorCode implements ErrorCode { + EMPTY_RECORD("RECORD_001", "존재하지 않는 기록입니다."), + ; + private final String errorCode; + private final String message; +} \ No newline at end of file diff --git a/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/ReportErrorCode.java b/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/ReportErrorCode.java new file mode 100644 index 0000000..3bd78dc --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/config/exception/errorCode/ReportErrorCode.java @@ -0,0 +1,14 @@ +package com.todaysgym.todaysgym.config.exception.errorCode; + +import com.todaysgym.todaysgym.config.exception.ErrorCode; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public enum ReportErrorCode implements ErrorCode { + REPORT_USER_DUPLICATE("REPORT_001", "이미 신고한 유저입니다."); + + private final String errorCode; + private final String message; +} \ No newline at end of file diff --git a/src/main/java/com/todaysgym/todaysgym/config/response/BaseResponse.java b/src/main/java/com/todaysgym/todaysgym/config/response/BaseResponse.java new file mode 100644 index 0000000..a5abf14 --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/config/response/BaseResponse.java @@ -0,0 +1,20 @@ +package com.todaysgym.todaysgym.config.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; + + +@Getter +@AllArgsConstructor +public class BaseResponse { + + private final String code; + private final String message; + private T result; + + public BaseResponse(T result) { + this.code = "SUCCESS"; + this.message = "요청에 성공했습니다."; + this.result = result; + } +} \ No newline at end of file diff --git a/src/main/java/com/todaysgym/todaysgym/config/response/ExceptionResponse.java b/src/main/java/com/todaysgym/todaysgym/config/response/ExceptionResponse.java new file mode 100644 index 0000000..17923c3 --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/config/response/ExceptionResponse.java @@ -0,0 +1,15 @@ +package com.todaysgym.todaysgym.config.response; + +import lombok.Getter; + +@Getter +public class ExceptionResponse { + + private final String code; + private final String message; + + public ExceptionResponse(String code, String message) { + this.code = code; + this.message = message; + } +} \ No newline at end of file diff --git a/src/main/java/com/todaysgym/todaysgym/member/MemberRepository.java b/src/main/java/com/todaysgym/todaysgym/member/MemberRepository.java new file mode 100644 index 0000000..fa29675 --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/member/MemberRepository.java @@ -0,0 +1,9 @@ +package com.todaysgym.todaysgym.member; + +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface MemberRepository extends JpaRepository { + + Optional getByMemberId(Long memberId); +} diff --git a/src/main/java/com/todaysgym/todaysgym/post/PostRepository.java b/src/main/java/com/todaysgym/todaysgym/post/PostRepository.java new file mode 100644 index 0000000..ce1b628 --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/post/PostRepository.java @@ -0,0 +1,9 @@ +package com.todaysgym.todaysgym.post; + +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PostRepository extends JpaRepository { + Optional getByPostId(Long postId); + +} diff --git a/src/main/java/com/todaysgym/todaysgym/post/comment/CommentRepository.java b/src/main/java/com/todaysgym/todaysgym/post/comment/CommentRepository.java new file mode 100644 index 0000000..c31e08a --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/post/comment/CommentRepository.java @@ -0,0 +1,9 @@ +package com.todaysgym.todaysgym.post.comment; + +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CommentRepository extends JpaRepository { + Optional getByCommentId(Long commentId); + +} diff --git a/src/main/java/com/todaysgym/todaysgym/post/like/PostLikeRepository.java b/src/main/java/com/todaysgym/todaysgym/post/like/PostLikeRepository.java new file mode 100644 index 0000000..9108dba --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/post/like/PostLikeRepository.java @@ -0,0 +1,7 @@ +package com.todaysgym.todaysgym.post.like; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PostLikeRepository extends JpaRepository { + +} diff --git a/src/main/java/com/todaysgym/todaysgym/post/photo/PostPhotoRepository.java b/src/main/java/com/todaysgym/todaysgym/post/photo/PostPhotoRepository.java new file mode 100644 index 0000000..0c3e165 --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/post/photo/PostPhotoRepository.java @@ -0,0 +1,7 @@ +package com.todaysgym.todaysgym.post.photo; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PostPhotoRepository extends JpaRepository { + +} diff --git a/src/main/java/com/todaysgym/todaysgym/record/RecordRepository.java b/src/main/java/com/todaysgym/todaysgym/record/RecordRepository.java new file mode 100644 index 0000000..039cc95 --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/record/RecordRepository.java @@ -0,0 +1,9 @@ +package com.todaysgym.todaysgym.record; + +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface RecordRepository extends JpaRepository { + Optional getByRecordId(Long recordId); + +} diff --git a/src/main/java/com/todaysgym/todaysgym/record/photo/RecordPhotoRepository.java b/src/main/java/com/todaysgym/todaysgym/record/photo/RecordPhotoRepository.java new file mode 100644 index 0000000..efec800 --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/record/photo/RecordPhotoRepository.java @@ -0,0 +1,7 @@ +package com.todaysgym.todaysgym.record.photo; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface RecordPhotoRepository extends JpaRepository { + +} diff --git a/src/main/java/com/todaysgym/todaysgym/report/ReportController.java b/src/main/java/com/todaysgym/todaysgym/report/ReportController.java new file mode 100644 index 0000000..a9c495b --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/report/ReportController.java @@ -0,0 +1,10 @@ +package com.todaysgym.todaysgym.report; + +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class ReportController { + +} \ No newline at end of file diff --git a/src/main/java/com/todaysgym/todaysgym/report/ReportRepository.java b/src/main/java/com/todaysgym/todaysgym/report/ReportRepository.java new file mode 100644 index 0000000..49fbd4c --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/report/ReportRepository.java @@ -0,0 +1,7 @@ +package com.todaysgym.todaysgym.report; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface ReportRepository extends JpaRepository { + +} diff --git a/src/main/java/com/todaysgym/todaysgym/report/ReportService.java b/src/main/java/com/todaysgym/todaysgym/report/ReportService.java new file mode 100644 index 0000000..9400566 --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/report/ReportService.java @@ -0,0 +1,10 @@ +package com.todaysgym.todaysgym.report; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class ReportService { + +} diff --git a/src/main/java/com/todaysgym/todaysgym/tag/TagRepository.java b/src/main/java/com/todaysgym/todaysgym/tag/TagRepository.java new file mode 100644 index 0000000..376add0 --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/tag/TagRepository.java @@ -0,0 +1,7 @@ +package com.todaysgym.todaysgym.tag; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TagRepository extends JpaRepository { + +} diff --git a/src/main/java/com/todaysgym/todaysgym/utils/UtilService.java b/src/main/java/com/todaysgym/todaysgym/utils/UtilService.java new file mode 100644 index 0000000..f1b62ab --- /dev/null +++ b/src/main/java/com/todaysgym/todaysgym/utils/UtilService.java @@ -0,0 +1,102 @@ +package com.todaysgym.todaysgym.utils; + +import com.todaysgym.todaysgym.config.exception.BaseException; +import com.todaysgym.todaysgym.config.exception.errorCode.CommentErrorCode; +import com.todaysgym.todaysgym.config.exception.errorCode.MemberErrorCode; +import com.todaysgym.todaysgym.config.exception.errorCode.PostErrorCode; +import com.todaysgym.todaysgym.config.exception.errorCode.RecordErrorCode; +import com.todaysgym.todaysgym.member.Member; +import com.todaysgym.todaysgym.member.MemberRepository; +import com.todaysgym.todaysgym.post.Post; +import com.todaysgym.todaysgym.post.PostRepository; +import com.todaysgym.todaysgym.post.comment.Comment; +import com.todaysgym.todaysgym.post.comment.CommentRepository; +import com.todaysgym.todaysgym.record.Record; +import com.todaysgym.todaysgym.record.RecordRepository; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class UtilService { + + public static final int SEC = 60; + public static final int MIN = 60; + public static final int HOUR = 24; + public static final int DAY = 30; + public static final int MONTH = 12; + private final MemberRepository memberRepository; + private final PostRepository postRepository; + private final CommentRepository commentRepository; + private final RecordRepository recordRepository; + + + public Member findByMemberIdWithValidation(Long memberId) throws BaseException { + Member member = memberRepository.getByMemberId(memberId).orElse(null); + if (member == null) { + throw new BaseException(MemberErrorCode.EMPTY_MEMBER); + } + return member; + } + + public Post findByPostIdWithValidation(Long postId) throws BaseException { + Post post = postRepository.getByPostId(postId).orElse(null); + if (post == null) { + throw new BaseException(PostErrorCode.EMPTY_POST); + } + return post; + } + + public Comment findByCommentIdWithValidation(Long commentId) throws BaseException { + Comment comment = commentRepository.getByCommentId(commentId).orElse(null); + if (comment == null) { + throw new BaseException(CommentErrorCode.EMPTY_COMMENT); + } + return comment; + } + + public Record findByRecordIdWithValidation(Long recordId) throws BaseException { + Record record = recordRepository.getByRecordId(recordId).orElse(null); + if (record == null) { + throw new BaseException(RecordErrorCode.EMPTY_RECORD); + } + return record; + } + + public static String convertLocalDateTimeToLocalDate(LocalDateTime localDateTime) { + return localDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")); + } + + public static String convertLocalDateTimeToTime(LocalDateTime localDateTime) { + LocalDateTime now = LocalDateTime.now(); + + long diffTime = localDateTime.until(now, ChronoUnit.SECONDS); // now보다 이후면 +, 전이면 - + + String msg = null; + if (diffTime < SEC) { + return diffTime + "초전"; + } + diffTime = diffTime / SEC; + if (diffTime < MIN) { + return diffTime + "분 전"; + } + diffTime = diffTime / MIN; + if (diffTime < HOUR) { + return diffTime + "시간 전"; + } + diffTime = diffTime / HOUR; + if (diffTime < DAY) { + return diffTime + "일 전"; + } + diffTime = diffTime / DAY; + if (diffTime < MONTH) { + return diffTime + "개월 전"; + } + + diffTime = diffTime / MONTH; + return diffTime + "년 전"; + } +} \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..bd3f3b9 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,6 @@ +spring: + profiles: + active: ${profile} + mvc: + pathmatch: + matching-strategy: ant_path_matcher \ No newline at end of file