Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

ZAP PR 생성 시 리뷰 메시지 변경 #803

Open
wants to merge 83 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
51b6db5
refactor: required 속성 추가
zangsu Oct 6, 2024
8312373
refactor: ArgumentResolver 에서 null 반환하도록 변경
zangsu Oct 6, 2024
82d27a3
test: AuthArgumentResolver 기능을 테스트
zangsu Oct 6, 2024
da864d9
refactor: 파라미터 이름을 로그인 한 멤버를 나타내도록 변경
zangsu Oct 6, 2024
c566ce6
refactor: 메서드 이름을 오버로딩으로 변경
zangsu Oct 6, 2024
55ca8c1
refactor: 로그인 분기 메서드를 Deprecated 처리
zangsu Oct 6, 2024
ea5fb2d
docs: 템플릿 생성 시 템플릿 공개여부도 포함하도록 변경
kyum-q Oct 7, 2024
7e9de48
docs: 템플릿 목록 조회 시 멤버 ID에 따른 반환 템플릿 차이 내용 추가
kyum-q Oct 7, 2024
d3d3abb
feat(migration): isPublic 필드 추가함에 따라 마이그레이션 파일 추가
kyum-q Oct 7, 2024
5bffa2a
fix: search.sql 수정
kyum-q Oct 7, 2024
f1f8b3a
Merge branch 'dev/be' into docs/739-private-swagger
kyum-q Oct 7, 2024
a250725
docs: DisplayName 컨벤션 적용
zangsu Oct 7, 2024
ce98d64
refactor: 불필요한 지역변수 추출 제거
zangsu Oct 7, 2024
984ff46
style: 줄바꿈 추가
zangsu Oct 7, 2024
41dae36
refactor: 불필요한 지역변수 추출 제거
zangsu Oct 7, 2024
f7fee28
refactor: 접근제한자 추가
zangsu Oct 7, 2024
02d083a
refactor: Optional.get() 개선
zangsu Oct 7, 2024
9d5e509
fix(test): 충돌 해결하면서 생긴 문제 해결
kyum-q Oct 8, 2024
287691c
docs: 사용하지 않는 given 삭제
zangsu Oct 8, 2024
3b12062
docs: DisplayName 변경
zangsu Oct 8, 2024
dfdee2f
feat(exception): error code 클래스 구현
kyum-q Oct 8, 2024
632cf61
refactor(repository): @Param 설정 추가
kyum-q Oct 8, 2024
6177306
refactor(global): 인증 정보 확인 로직 에러 코드 적용 및 에러 메시지 수정
kyum-q Oct 8, 2024
8656c84
refactor(src): CodeZapException 생성 시 HttpStatus가 아닌 ErrorCode 의존성 주입으…
kyum-q Oct 8, 2024
a41dce1
refactor(exception): codeZapException 이 아닌 경우에도 에러코드 설정되도록 수정
kyum-q Oct 8, 2024
1d028af
refactor(swagger): swagger 문서에서 설정하는 ProblemDetail 변경
kyum-q Oct 8, 2024
55772ec
refactor(exception): spring에서 에러 처리하는 ResponseEntityExceptionHandler도…
kyum-q Oct 8, 2024
8fddd6b
refactor(exception): spring이 반환하는 에러코드도 ErrorCode에 정의
kyum-q Oct 8, 2024
035a5e5
refactor: 파라미터의 final 키워드 제거
zangsu Oct 9, 2024
225430c
refactor: RFC2616 에 따라 쿠키에 들어갈 수 있는 ASCII 값으로 변형을 위해 URLEncoder, URLD…
zangsu Oct 9, 2024
c112462
refactor: 쿠키 값 세팅 방식을 변경
zangsu Oct 9, 2024
506f9dd
style: 포매팅 적용
zangsu Oct 9, 2024
0a78758
refactor(file): 파일 롤링 정책을 TimeBasedRollingPolicy으로 변경
jminkkk Oct 9, 2024
17ed74f
refactor(file): 파일 최대 크기 totalSizeCap 으로 설정
jminkkk Oct 9, 2024
c2cf02e
feat(domain): 공개 범위를 나타내는 enum Visibility 생성
kyum-q Oct 9, 2024
f83bcd3
refactor(template): 공개 범위 필드 visibility로 변환
kyum-q Oct 9, 2024
d3e09b8
refactor(exception): 사용하지 않는 메서드 제거
kyum-q Oct 9, 2024
373ca96
refactor(global): 중복 메서드 재사용되도록 수정
kyum-q Oct 9, 2024
5d5ffbc
docs: 반환 값에도 공개범위 필드 추가
kyum-q Oct 10, 2024
c4a39e1
refactor(file): 파일 롤링 정책에 따른 TotalSizeCap을 10GB로 변경
jminkkk Oct 10, 2024
40604f2
Merge branch 'dev/be' into docs/739-private-swagger
kyum-q Oct 10, 2024
b49e6d4
Merge branch 'dev/be' into refactor/745-authentication-principle-requ…
zangsu Oct 10, 2024
c978c8d
Merge branch 'dev/be' into 521/feat-be-error-code
kyum-q Oct 10, 2024
c1458fe
refactor(exception): 사용하지 않는 에러코드 삭제
kyum-q Oct 10, 2024
776fac1
refactor(exception): 에러 코드 타입 변경
kyum-q Oct 10, 2024
ab1f658
Merge pull request #747 from woowacourse-teams/refactor/745-authentic…
kyum-q Oct 10, 2024
954d41e
Merge branch 'dev/be' into docs/739-private-swagger
kyum-q Oct 11, 2024
dd9b670
Merge pull request #748 from woowacourse-teams/docs/739-private-swagger
zeus6768 Oct 11, 2024
c5cf32f
Merge pull request #761 from woowacourse-teams/521/feat-be-error-code
zeus6768 Oct 11, 2024
b34d6ce
fix(exception): 스프링 에러에 response 디테일 값 추가
kyum-q Oct 11, 2024
1ccb9ee
Merge pull request #774 from woowacourse-teams/fix/521-error-response
HoeSeong123 Oct 11, 2024
1fe1c17
refactor(file): 5GB로 재변경
jminkkk Oct 11, 2024
3be8941
Merge pull request #764 from woowacourse-teams/refactor/763-reconfig-…
zangsu Oct 12, 2024
d45adc3
TagControllerTest 작성 (#775)
jminkkk Oct 15, 2024
59a67ce
refactor(service): TemplateApplicationService.deleteAllByMemberAndTem…
kyum-q Oct 15, 2024
4e36db6
refactor(service): ThumbnailService.deleteAllByTemplateIds 네이밍 변경
kyum-q Oct 15, 2024
38b5563
refactor(service): SourceCodeService.deleteAllByTemplateIds 네이밍 변경
kyum-q Oct 15, 2024
70ffda0
chore: update cd script
zeus6768 Oct 15, 2024
2a7128f
refactor(repository): TemplateTagRepository.deleteAllByTemplateIds 네이…
kyum-q Oct 15, 2024
2a04042
refactor(repository): thumbnailRepository.deleteAllByTemplateIds 네이밍 변경
kyum-q Oct 15, 2024
0ccc90a
refactor(repository): sourceCodeRepository.deleteAllByTemplateIds 네이밍 변경
kyum-q Oct 15, 2024
9e1d6a2
refactor(repository): likesRepository.deleteAllByTemplateIds 네이밍 변경
kyum-q Oct 15, 2024
e49502a
refactor(repository): @Param 추가
kyum-q Oct 15, 2024
0d2508c
Merge pull request #791 from woowacourse-teams/fix/790-log
zeus6768 Oct 15, 2024
3dc6e4f
fix: logback configuration
zeus6768 Oct 15, 2024
5e5efe2
Merge pull request #793 from woowacourse-teams/fix/790-log
jminkkk Oct 15, 2024
9078171
refactor(GlobalExceptionHandler): HttpMessageNotReadableException 발생 …
jminkkk Oct 15, 2024
8cc7d14
refactor(rds): DataSourceConfig를 모든 환경에 적용되도록 변경
kyum-q Oct 16, 2024
260a914
refactor(rds): 사용하지 않는 값 제거
kyum-q Oct 16, 2024
655d1ad
refactor(workflows): DB 정보 환경 변수 등록
kyum-q Oct 16, 2024
12fdad8
fix(workflows): 환경 변수 설정 로직 수정
kyum-q Oct 16, 2024
c895984
fix(workflows): 설정 파일 가져오도록 수정
kyum-q Oct 16, 2024
eab9464
fix: ci 해결
zeus6768 Oct 16, 2024
fc15a10
fix: ci 해결
zeus6768 Oct 16, 2024
a984071
fix: ci 해결
zeus6768 Oct 16, 2024
e9314e7
fix: ci 해결
zeus6768 Oct 16, 2024
3a9bcc2
refactor: 사용하지 않는 sql 파일 삭제
zeus6768 Oct 16, 2024
ffd898f
chore: add gitignore
zeus6768 Oct 16, 2024
14c96fa
Update pr_notification.yml
jminkkk Oct 17, 2024
158d8e3
Update pr_notification.yml
jminkkk Oct 17, 2024
77a05f4
Merge pull request #792 from woowacourse-teams/refactor/645-change-de…
zangsu Oct 17, 2024
7535f77
Merge pull request #799 from woowacourse-teams/refactor/744-dev-db-se…
zeus6768 Oct 17, 2024
e8d68fb
Merge branch 'dev/be' into refactor/802-zap-review-git-action
kyum-q Oct 17, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions .github/workflows/backend_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,7 @@ jobs:
mysql version: ${{ secrets.MYSQL_VERSION }}
mysql database: ${{ secrets.MYSQL_DATABASE }}
mysql root password: ${{ secrets.MYSQL_PASSWORD }}

- name: DB 설정 파일 가져오기
working-directory: ./backend/src/main/resources
run: echo "${{ secrets.APPLICATION_DB_YAML }}" > application-db.yml


- name: gradle 캐싱
uses: gradle/actions/setup-gradle@v4

Expand All @@ -36,6 +32,10 @@ jobs:
java-version: 17
distribution: temurin

- name: 환경변수 주입
run: ${{ secrets.APPLICATION_YML }}
working-directory: ./backend/src/test/resources

- name: 테스트 코드 실행
run: ./gradlew test
working-directory: ./backend
8 changes: 7 additions & 1 deletion .github/workflows/pr_notification.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ jobs:
PR_TITLE="${{ github.event.pull_request.title }}"
PR_URL="${{ github.event.pull_request.html_url }}"
REVIEWERS='${{ toJson(github.event.pull_request.requested_reviewers.*.login) }}'
LABELS='${{ toJson(github.event.pull_request.labels.*.name) }}'
echo "REVIEWERS: $REVIEWERS"
echo "LABELS: $LABELS"

parse_slack_ids() {
echo "$SLACK_IDS" | jq -r 'to_entries | map("\(.key):\(.value)") | .[]'
Expand All @@ -41,11 +43,15 @@ jobs:

if [ ! -z "$mentions" ]; then
message="$mentions 님, 새로운 PR이 생성되었습니다: <$PR_URL|$PR_TITLE>"

if echo "$LABELS" | jq -e 'contains(["zap"])' > /dev/null; then
message=":rotating_light: 긴급 PR입니다. 빠른 리뷰 부탁드립니다!:rotating_light:\n$message"
fi

curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"$message\"}" \
"$SLACK_WEBHOOK_URL"
echo "Sent message: $message"
else
echo "No reviewers to notify"
fi

2 changes: 1 addition & 1 deletion backend/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ out/
.DS_Store

### YAML ###
application-db.yml
src/test/resources/application.yml

### compose ###
docker/app/*.jar
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ public Member resolveArgument(
NativeWebRequest webRequest,
WebDataBinderFactory binderFactory
) {
AuthenticationPrinciple parameterAnnotation = parameter.getParameterAnnotation(AuthenticationPrinciple.class);
HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
if (!parameterAnnotation.required() && !credentialManager.hasCredential(request)) {
return null;
}
String credential = credentialManager.getCredential(request);
return credentialProvider.extractMember(credential);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface AuthenticationPrinciple {
boolean required() default true;
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public interface SpringDocAuthController {
})
@ApiErrorResponse(status = HttpStatus.UNAUTHORIZED, instance = "/login", errorCases = {
@ErrorCase(description = "아이디 불일치", exampleMessage = "존재하지 않는 아이디 moly 입니다."),
@ErrorCase(description = "비밀번호 불일치", exampleMessage = "로그인에 실패하였습니다. 아이디 또는 비밀번호를 확인해주세요."),
@ErrorCase(description = "비밀번호 불일치", exampleMessage = "로그인에 실패하였습니다. 비밀번호를 확인해주세요."),
})
ResponseEntity<LoginResponse> login(LoginRequest request, HttpServletResponse response);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import codezap.global.exception.CodeZapException;
import codezap.global.exception.ErrorCode;

@Component
public class SHA2PasswordEncryptor implements PasswordEncryptor {
Expand All @@ -17,7 +17,7 @@ public SHA2PasswordEncryptor() {
try {
digest = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
throw new CodeZapException(HttpStatus.INTERNAL_SERVER_ERROR, "암호화 알고리즘이 잘못 명시되었습니다.");
throw new CodeZapException(ErrorCode.INTERNAL_SERVER_ERROR, "암호화 알고리즘이 잘못 명시되었습니다.");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@
import jakarta.servlet.http.HttpServletResponse;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseCookie;
import org.springframework.stereotype.Component;

import codezap.global.exception.CodeZapException;
import codezap.global.exception.ErrorCode;

@Component
public class CookieCredentialManager implements CredentialManager {
Expand All @@ -29,15 +29,25 @@ public String getCredential(final HttpServletRequest httpServletRequest) {

private void checkCookieExist(final Cookie[] cookies) {
if (cookies == null) {
throw new CodeZapException(HttpStatus.UNAUTHORIZED, "쿠키가 없어서 회원 정보를 찾을 수 없습니다. 다시 로그인해주세요.");
throw new CodeZapException(ErrorCode.UNAUTHORIZED_USER, "쿠키가 없어서 회원 정보를 찾을 수 없습니다. 다시 로그인해주세요.");
}
}

@Override
public boolean hasCredential(final HttpServletRequest httpServletRequest) {
Cookie[] cookies = httpServletRequest.getCookies();
if (cookies == null) {
return false;
}
return Arrays.stream(cookies)
.anyMatch(cookie -> cookie.getName().equals(CREDENTIAL_COOKIE_NAME));
}

private Cookie extractTokenCookie(final Cookie[] cookies) {
return Arrays.stream(cookies)
.filter(cookie -> cookie.getName().equals(CREDENTIAL_COOKIE_NAME))
.findFirst()
.orElseThrow(() -> new CodeZapException(HttpStatus.UNAUTHORIZED,
.orElseThrow(() -> new CodeZapException(ErrorCode.UNAUTHORIZED_USER,
"인증에 대한 쿠키가 없어서 회원 정보를 찾을 수 없습니다. 다시 로그인해주세요."));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ public interface CredentialManager {

String getCredential(HttpServletRequest httpServletRequest);

boolean hasCredential(HttpServletRequest httpServletRequest);

void setCredential(HttpServletResponse httpServletResponse, String credential);

void removeCredential(HttpServletResponse httpServletResponse);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
import java.nio.charset.StandardCharsets;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import codezap.auth.provider.CredentialProvider;
import codezap.global.exception.CodeZapException;
import codezap.global.exception.ErrorCode;
import codezap.member.domain.Member;
import codezap.member.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
Expand All @@ -33,7 +33,7 @@ public Member extractMember(String credential) {

private void checkMatchPassword(Member member, String password) {
if (!member.matchPassword(password)) {
throw new CodeZapException(HttpStatus.UNAUTHORIZED, "아이디 또는 비밀번호가 일치하지 않습니다.");
throw new CodeZapException(ErrorCode.UNAUTHORIZED_PASSWORD, "비밀번호가 일치하지 않습니다.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@
import java.nio.charset.StandardCharsets;
import java.util.Base64;

import org.springframework.http.HttpStatus;

import codezap.global.exception.CodeZapException;
import codezap.global.exception.ErrorCode;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;

Expand All @@ -26,13 +25,13 @@ private static String decodeBase64(String base64Credentials) {
byte[] credDecoded = Base64.getDecoder().decode(base64Credentials);
return new String(credDecoded, StandardCharsets.UTF_8);
} catch (IllegalArgumentException e) {
throw new CodeZapException(HttpStatus.UNAUTHORIZED, "잘못된 Base64 인코딩입니다.");
throw new CodeZapException(ErrorCode.UNAUTHORIZED_USER, "잘못된 Base64 인코딩입니다.");
}
}

private static void validateBasicAuth(String[] values) {
if (values.length != BASIC_AUTH_LENGTH || values[0].isEmpty() || values[1].isEmpty()) {
throw new CodeZapException(HttpStatus.UNAUTHORIZED, "인증 정보가 올바르지 않습니다. 다시 로그인 해주세요.");
throw new CodeZapException(ErrorCode.UNAUTHORIZED_USER, "인증 정보가 올바르지 않습니다. 다시 로그인 해주세요.");
}
}
}
4 changes: 2 additions & 2 deletions backend/src/main/java/codezap/auth/service/AuthService.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package codezap.auth.service;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;

import codezap.auth.dto.LoginAndCredentialDto;
Expand All @@ -9,6 +8,7 @@
import codezap.auth.encryption.PasswordEncryptor;
import codezap.auth.provider.CredentialProvider;
import codezap.global.exception.CodeZapException;
import codezap.global.exception.ErrorCode;
import codezap.member.domain.Member;
import codezap.member.repository.MemberRepository;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -37,7 +37,7 @@ private void validateCorrectPassword(Member member, String password) {
String salt = member.getSalt();
String encryptedPassword = passwordEncryptor.encrypt(password, salt);
if (!member.matchPassword(encryptedPassword)) {
throw new CodeZapException(HttpStatus.UNAUTHORIZED, "로그인에 실패하였습니다. 아이디 또는 비밀번호를 확인해주세요.");
throw new CodeZapException(ErrorCode.UNAUTHORIZED_PASSWORD, "로그인에 실패하였습니다. 비밀번호를 확인해주세요.");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ public interface SpringDocCategoryController {
@ApiErrorResponse(status = HttpStatus.BAD_REQUEST, instance = "/categories", errorCases = {
@ErrorCase(description = "모든 필드 중 null인 값이 있는 경우", exampleMessage = "카테고리 이름이 null 입니다."),
@ErrorCase(description = "카테고리 이름이 15자를 초과한 경우", exampleMessage = "카테고리 이름은 최대 15자까지 입력 가능합니다."),
})
@ApiErrorResponse(status = HttpStatus.CONFLICT, instance = "/categories", errorCases = {
@ErrorCase(description = "동일한 이름의 카테고리가 존재하는 경우", exampleMessage = "이름이 Spring 인 카테고리가 이미 존재합니다."),
})
ResponseEntity<CreateCategoryResponse> createCategory(
Expand All @@ -49,7 +51,11 @@ ResponseEntity<CreateCategoryResponse> createCategory(
@ApiResponse(responseCode = "200", description = "카테고리 수정 성공")
@ApiErrorResponse(status = HttpStatus.BAD_REQUEST, instance = "/categories/1", errorCases = {
@ErrorCase(description = "카테고리 이름이 15자를 초과한 경우", exampleMessage = "카테고리 이름은 최대 15자까지 입력 가능합니다."),
})
@ApiErrorResponse(status = HttpStatus.NOT_FOUND, instance = "/categories/1", errorCases = {
@ErrorCase(description = "해당하는 id 값인 카테고리가 없는 경우", exampleMessage = "식별자 1에 해당하는 카테고리가 존재하지 않습니다."),
})
@ApiErrorResponse(status = HttpStatus.CONFLICT, instance = "/categories", errorCases = {
@ErrorCase(description = "동일한 이름의 카테고리가 존재하는 경우", exampleMessage = "이름이 Spring 인 카테고리가 이미 존재합니다."),
})
@ApiErrorResponse(status = HttpStatus.FORBIDDEN, instance = "/categories/1", errorCases = {
Expand Down
5 changes: 2 additions & 3 deletions backend/src/main/java/codezap/category/domain/Category.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,9 @@
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;

import org.springframework.http.HttpStatus;

import codezap.global.auditing.BaseTimeEntity;
import codezap.global.exception.CodeZapException;
import codezap.global.exception.ErrorCode;
import codezap.member.domain.Member;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
Expand Down Expand Up @@ -67,7 +66,7 @@ public void updateName(String name) {

public void validateAuthorization(Member member) {
if (!getMember().equals(member)) {
throw new CodeZapException(HttpStatus.UNAUTHORIZED, "해당 카테고리를 수정 또는 삭제할 권한이 없는 유저입니다.");
throw new CodeZapException(ErrorCode.FORBIDDEN_ACCESS, "해당 카테고리를 수정 또는 삭제할 권한이 없는 유저입니다.");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,18 @@
import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.http.HttpStatus;

import codezap.category.domain.Category;
import codezap.global.exception.CodeZapException;
import codezap.global.exception.ErrorCode;
import codezap.member.domain.Member;

@SuppressWarnings("unused")
public interface CategoryJpaRepository extends CategoryRepository, JpaRepository<Category, Long> {

default Category fetchById(Long id) {
return findById(id).orElseThrow(
() -> new CodeZapException(HttpStatus.NOT_FOUND, "식별자 " + id + "에 해당하는 카테고리가 존재하지 않습니다."));
() -> new CodeZapException(ErrorCode.RESOURCE_NOT_FOUND, "식별자 " + id + "에 해당하는 카테고리가 존재하지 않습니다."));
}

List<Category> findAllByMemberIdOrderById(Long memberId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package codezap.category.service;

import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

Expand All @@ -11,6 +10,7 @@
import codezap.category.dto.response.FindAllCategoriesResponse;
import codezap.category.repository.CategoryRepository;
import codezap.global.exception.CodeZapException;
import codezap.global.exception.ErrorCode;
import codezap.member.domain.Member;
import codezap.template.repository.TemplateRepository;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -52,7 +52,7 @@ public void update(Member member, Long id, UpdateCategoryRequest updateCategoryR

private void validateDuplicatedCategory(String categoryName, Member member) {
if (categoryRepository.existsByNameAndMember(categoryName, member)) {
throw new CodeZapException(HttpStatus.CONFLICT, "이름이 " + categoryName + "인 카테고리가 이미 존재합니다.");
throw new CodeZapException(ErrorCode.DUPLICATE_CATEGORY, "이름이 " + categoryName + "인 카테고리가 이미 존재합니다.");
}
}

Expand All @@ -62,10 +62,10 @@ public void deleteById(Member member, Long id) {
category.validateAuthorization(member);

if (templateRepository.existsByCategoryId(id)) {
throw new CodeZapException(HttpStatus.BAD_REQUEST, "템플릿이 존재하는 카테고리는 삭제할 수 없습니다.");
throw new CodeZapException(ErrorCode.CATEGORY_HAS_TEMPLATES, "템플릿이 존재하는 카테고리는 삭제할 수 없습니다.");
}
if (category.isDefault()) {
throw new CodeZapException(HttpStatus.BAD_REQUEST, "기본 카테고리는 삭제할 수 없습니다.");
throw new CodeZapException(ErrorCode.DEFAULT_CATEGORY, "기본 카테고리는 삭제할 수 없습니다.");
}
categoryRepository.deleteById(id);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
package codezap.global.exception;

import org.springframework.http.HttpStatusCode;
import org.springframework.http.ProblemDetail;

import lombok.Getter;

@Getter
public class CodeZapException extends RuntimeException {

private final HttpStatusCode httpStatusCode;
private final ErrorCode errorCode;

public CodeZapException(HttpStatusCode httpStatusCode, String message) {
public CodeZapException(ErrorCode errorCode, String message) {
super(message);
this.httpStatusCode = httpStatusCode;
this.errorCode = errorCode;
}

public ProblemDetail toProblemDetail() {
ProblemDetail problemDetail = ProblemDetail.forStatusAndDetail(
errorCode.getHttpStatus(),
getMessage());
return GlobalExceptionHandler.setProperties(problemDetail, errorCode.getCode());
}
}
31 changes: 31 additions & 0 deletions backend/src/main/java/codezap/global/exception/ErrorCode.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package codezap.global.exception;

import org.springframework.http.HttpStatus;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum ErrorCode {

SPRING_GLOBAL_EXCEPTION(1000, HttpStatus.BAD_REQUEST),

INVALID_REQUEST(1101, HttpStatus.BAD_REQUEST),
CATEGORY_HAS_TEMPLATES(1102, HttpStatus.BAD_REQUEST),
DEFAULT_CATEGORY(1103, HttpStatus.BAD_REQUEST),

RESOURCE_NOT_FOUND(1201, HttpStatus.NOT_FOUND),
DUPLICATE_ID(1202, HttpStatus.CONFLICT),
DUPLICATE_CATEGORY(1203, HttpStatus.CONFLICT),

UNAUTHORIZED_USER(1301, HttpStatus.UNAUTHORIZED),
UNAUTHORIZED_ID(1302, HttpStatus.UNAUTHORIZED),
UNAUTHORIZED_PASSWORD(1303, HttpStatus.UNAUTHORIZED),
FORBIDDEN_ACCESS(1304, HttpStatus.FORBIDDEN),

INTERNAL_SERVER_ERROR(2000, HttpStatus.INTERNAL_SERVER_ERROR);

private final int code;
private final HttpStatus httpStatus;
}
Loading