Skip to content

Commit

Permalink
Merge branch 'main' into feat/#480
Browse files Browse the repository at this point in the history
  • Loading branch information
ukkodeveloper committed Oct 19, 2023
2 parents ba945b9 + fa8be3c commit 6588a85
Show file tree
Hide file tree
Showing 235 changed files with 8,830 additions and 2,281 deletions.
10 changes: 7 additions & 3 deletions .github/workflows/frontend-ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,20 @@ jobs:
node-version: ${{ env.node-version }}

- name: Cache dependencies
id: cache
id: cache-npm
uses: actions/cache@v3
env:
cache-name: cache-node-modules
with:
path: '**/node_modules'
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
key: ${{ runner.os }}-node-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-${{ env.cache-name }}-
${{ runner.os }}-node-
${{ runner.os }}-
- name: Install Dependencies
if: steps.cache.outputs.cache-hit != 'true'
if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
run: npm ci
working-directory: ${{ env.working-directory }}

Expand Down
34 changes: 25 additions & 9 deletions .github/workflows/frontend-dev-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,31 +6,47 @@ on:
jobs:
build:
name: Frontend Develop Deploy

runs-on: shook-runner

steps:
- name: Checkout Source Code
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Setting env
shell: bash
run: |
rm -rf frontend/.env
mkdir frontend/.env
echo "BASE_URL=${{ secrets.FRONT_DEV_BASE_URL }}" > frontend/.env/.env.production
- name: Package clean install
- name: Cache dependencies
id: cache-npm
uses: actions/cache@v3
env:
cache-name: cache-node-modules
with:
path: '**/node_modules'
key: ${{ runner.os }}-node-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-${{ env.cache-name }}-
${{ runner.os }}-node-
${{ runner.os }}-
- name: Install Dependencies
shell: bash
run: |
cd frontend
npm ci
if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
run: npm ci
working-directory: ./frontend

- name: Build files
shell: bash
run: |
cd frontend
npm run build
run: npm run build
working-directory: ./frontend

- name: Remove legacy static pages
shell: bash
run: rm -rf /home/ubuntu/dist

- name: Move generated new static pages
shell: bash
run: cp -r frontend/dist ~/
33 changes: 25 additions & 8 deletions .github/workflows/frontend-prod-cd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,26 +10,43 @@ jobs:

steps:
- name: Checkout Source Code
uses: actions/checkout@v2
uses: actions/checkout@v3

- name: Setting env
shell: bash
run: |
rm -rf frontend/.env
mkdir frontend/.env
echo "BASE_URL=${{ secrets.FRONT_PROD_BASE_URL }}" > frontend/.env/.env.production
- name: Package clean install
- name: Cache dependencies
id: cache-npm
uses: actions/cache@v3
env:
cache-name: cache-node-modules
with:
path: '**/node_modules'
key: ${{ runner.os }}-node-${{ env.cache-name }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-${{ env.cache-name }}-
${{ runner.os }}-node-
${{ runner.os }}-
- name: Install Dependencies
shell: bash
run: |
cd frontend
npm ci
if: ${{ steps.cache-npm.outputs.cache-hit != 'true' }}
run: npm ci
working-directory: ./frontend

- name: Build files
shell: bash
run: |
cd frontend
npm run build
run: npm run build
working-directory: ./frontend

- name: Remove legacy static pages
shell: bash
run: rm -rf home/ubuntu/dist

- name: Move generated new static pages
shell: bash
run: cp -r frontend/dist ~/
44 changes: 44 additions & 0 deletions .github/workflows/nginx-server-cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Blue-Green Backend Production Deploy (CD)

on:
workflow_dispatch:

jobs:
deploy:
name: Deploy Backend Production Server
runs-on: shook-nginx-runner

steps:
- name: Checkout Source Code
uses: actions/checkout@v2
with:
token: ${{ secrets.SUBMODULE_PAT }}
submodules: recursive
- name: Grant execute permission to gradlew
shell: bash
run: chmod +x backend/gradlew
- name: Check Java Version
shell: bash
run: java --version
- name: Gradlew bootJar
shell: bash
run: |
cd backend
./gradlew bootJar
- name: Copy Jar
shell: bash
run: cp backend/build/libs/shook-0.0.1-SNAPSHOT.jar /home/ubuntu/application-jar
- name: Backend Deploy
shell: bash
run: bash /home/ubuntu/blue-green.sh

switch-server:
name: Switch Backend Production Server
runs-on: shook-prod
needs: deploy

steps:
- name: Run switch_server.sh
shell: bash
run: bash /home/ubuntu/blue-green/server_switch.sh

3 changes: 3 additions & 0 deletions backend/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ dependencies {
//xlsx reader
implementation group: 'org.apache.poi', name: 'poi', version: '5.0.0'
implementation group: 'org.apache.poi', name: 'poi-ooxml', version: '5.0.0'

//actuator
implementation 'org.springframework.boot:spring-boot-starter-actuator'
}

tasks.named('test') {
Expand Down
9 changes: 7 additions & 2 deletions backend/src/main/java/shook/shook/auth/config/AuthConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,20 @@ public void addInterceptors(final InterceptorRegistry registry) {

private HandlerInterceptor loginCheckerInterceptor() {
return new PathMatcherInterceptor(loginCheckerInterceptor)
.includePathPattern("/songs/high-liked/**", PathMethod.GET);
.includePathPattern("/songs/high-liked/*", PathMethod.GET)
.includePathPattern("/songs/high-liked/*/prev", PathMethod.GET)
.includePathPattern("/songs/high-liked/*/next", PathMethod.GET)
.includePathPattern("/songs/*", PathMethod.GET);
}

private HandlerInterceptor tokenInterceptor() {
return new PathMatcherInterceptor(tokenInterceptor)
.includePathPattern("/my-page", PathMethod.GET)
.includePathPattern("/my-page/**", PathMethod.GET)
.includePathPattern("/songs/*/parts/*/likes", PathMethod.PUT)
.includePathPattern("/voting-songs/*/parts", PathMethod.POST)
.includePathPattern("/songs/*/parts/*/comments", PathMethod.POST)
.includePathPattern("/songs/*/member-parts", PathMethod.POST)
.includePathPattern("/member-parts/*", PathMethod.DELETE)
.includePathPattern("/members/*", PathMethod.DELETE);
}

Expand Down
3 changes: 2 additions & 1 deletion backend/src/main/java/shook/shook/auth/ui/AuthContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public void setAuthenticatedMember(final Long memberId) {
}

public boolean isAnonymous() {
return this.authority == Authority.ANONYMOUS;
return authority.isAnonymous();
}

public long getMemberId() {
Expand All @@ -29,3 +29,4 @@ public Authority getAuthority() {
return authority;
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.util.Map;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import shook.shook.auth.application.TokenProvider;
Expand All @@ -12,6 +11,8 @@
import shook.shook.member.application.MemberService;
import shook.shook.member.domain.Nickname;

import java.util.Map;

@Component
public class TokenInterceptor implements HandlerInterceptor {

Expand All @@ -20,9 +21,9 @@ public class TokenInterceptor implements HandlerInterceptor {
private final MemberService memberService;

public TokenInterceptor(
final TokenProvider tokenProvider,
final AuthContext authContext,
final MemberService memberService
final TokenProvider tokenProvider,
final AuthContext authContext,
final MemberService memberService
) {
this.tokenProvider = tokenProvider;
this.authContext = authContext;
Expand All @@ -31,14 +32,14 @@ public TokenInterceptor(

@Override
public boolean preHandle(
final HttpServletRequest request,
final HttpServletResponse response,
final Object handler
final HttpServletRequest request,
final HttpServletResponse response,
final Object handler
) {
final String token = TokenHeaderExtractor.extractToken(request)
.orElseThrow(() -> new AuthorizationException.AccessTokenNotFoundException(
Map.of("RequestURL", request.getRequestURL().toString())
));
.orElseThrow(() -> new AuthorizationException.AccessTokenNotFoundException(
Map.of("RequestURL", request.getRequestURL().toString())
));
final Claims claims = tokenProvider.parseClaims(token);
final Long memberId = claims.get("memberId", Long.class);
final String nickname = claims.get("nickname", String.class);
Expand Down
22 changes: 19 additions & 3 deletions backend/src/main/java/shook/shook/globalexception/ErrorCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public enum ErrorCode {
EMPTY_KILLING_PARTS(2011, "노래의 킬링파트는 비어있을 수 없습니다."),

// 3000: 노래

NOT_POSITIVE_SONG_LENGTH(3001, "노래 길이는 0보다 커야합니다."),
SONG_NOT_EXIST(3002, "존재하지 않는 노래입니다."),
EMPTY_SONG_TITLE(3003, "노래 제목은 비어있을 수 없습니다."),
Expand All @@ -53,20 +54,28 @@ public enum ErrorCode {
CAN_NOT_READ_SONG_DATA_FILE(3011, "노래 데이터 파일을 읽을 수 없습니다."),
SONG_ALREADY_EXIST(3012, "등록하려는 노래가 이미 존재합니다."),
WRONG_GENRE_TYPE(3013, "잘못된 장르 타입입니다."),
EMPTY_ARTIST_PROFILE_URL(3014, "가수 프로필 이미지는 비어있을 수 없습니다."),
TOO_LONG_ARTIST_PROFILE_URL(3015, "가수 프로필 이미지URL은 65,356자를 넘길 수 없습니다."),
EMPTY_ARTIST_SYNONYM(3016, "가수 동의어는 비어있을 수 없습니다."),
TOO_LONG_ARTIST_SYNONYM(3017, "가수 동의어는 255자를 넘길 수 없습니다."),
ARTIST_NOT_EXIST(3018, "존재하지 않는 가수입니다."),


// 4000: 투표

VOTING_PART_START_LESS_THAN_ZERO(4001, "파트의 시작 초는 0보다 작을 수 없습니다."),
VOTING_PART_START_OVER_SONG_LENGTH(4002, "파트의 시작 초는 노래 길이를 초과할 수 없습니다."),
VOTING_PART_END_OVER_SONG_LENGTH(4003, "파트의 끝 초는 노래 길이를 초과할 수 없습니다."),
INVALID_VOTING_PART_LENGTH(4004, "파트의 길이는 5, 10, 15초 중 하나여야합니다."),
INVALID_VOTING_PART_LENGTH(4004, "파트의 길이는 5초 이상, 15초 이하여야 합니다."),
VOTING_PART_DUPLICATE_START_AND_LENGTH_EXCEPTION(4005,
"한 노래에 동일한 파트를 두 개 이상 등록할 수 없습니다."),
"한 노래에 동일한 파트를 두 개 이상 등록할 수 없습니다."),
VOTING_SONG_PART_NOT_EXIST(4006, "투표 대상 파트가 존재하지 않습니다."),

VOTING_SONG_PART_FOR_OTHER_SONG(4007, "해당 파트는 다른 노래의 파트입니다."),
VOTING_SONG_NOT_EXIST(4008, "존재하지 않는 투표 노래입니다."),
VOTE_FOR_OTHER_PART(4009, "해당 투표는 다른 파트에 대한 투표입니다."),
DUPLICATE_VOTE_EXIST(4010, "중복된 투표입니다."),

// 5000: 사용자

EMPTY_EMAIL(5001, "이메일은 비어있을 수 없습니다."),
Expand All @@ -80,7 +89,14 @@ public enum ErrorCode {
REQUEST_BODY_VALIDATION_FAIL(10001, ""),
WRONG_REQUEST_URL(10002, "URL의 pathVariable 은 비어있을 수 없습니다."),

INTERNAL_SERVER_ERROR(10003, "알 수 없는 서버 오류가 발생했습니다. 관리자에게 문의해주세요.");
INTERNAL_SERVER_ERROR(10003, "알 수 없는 서버 오류가 발생했습니다. 관리자에게 문의해주세요."),

// 6000: 멤버 파트

NEGATIVE_START_SECOND(6001, "멤버 파트의 시작 초는 0보다 작을 수 없습니다."),
MEMBER_PART_END_OVER_SONG_LENGTH(6002, "파트의 끝 초는 노래 길이를 초과할 수 없습니다."),
MEMBER_PART_ALREADY_EXIST(6003, "멤버 파트가 이미 존재합니다."),
;

private final int code;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@
import shook.shook.auth.exception.OAuthException;
import shook.shook.auth.exception.TokenException;
import shook.shook.member.exception.MemberException;
import shook.shook.member_part.exception.MemberPartException;
import shook.shook.part.exception.PartException;
import shook.shook.song.exception.ArtistException;
import shook.shook.song.exception.SongException;
import shook.shook.song.exception.killingpart.KillingPartCommentException;
import shook.shook.song.exception.killingpart.KillingPartException;
Expand Down Expand Up @@ -55,7 +57,9 @@ public ResponseEntity<ErrorResponse> handleTokenException(final CustomException
MemberException.class,
VotingSongException.class,
VotingSongPartException.PartNotExistException.class,
PartException.class
PartException.class,
ArtistException.class,
MemberPartException.class
})
public ResponseEntity<ErrorResponse> handleGlobalBadRequestException(final CustomException e) {
log.error(e.getErrorInfoLog());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,15 @@ public MemberNotExistException(final Map<String, String> inputValuesByProperty)
super(ErrorCode.MEMBER_NOT_EXIST, inputValuesByProperty);
}
}

public static class MemberPartAlreadyExistException extends MemberException {

public MemberPartAlreadyExistException() {
super(ErrorCode.MEMBER_PART_ALREADY_EXIST);
}

public MemberPartAlreadyExistException(final Map<String, String> inputValuesByProperty) {
super(ErrorCode.MEMBER_PART_ALREADY_EXIST, inputValuesByProperty);
}
}
}
Loading

0 comments on commit 6588a85

Please sign in to comment.