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

v0.0.3 #86

Merged
merged 2 commits into from
Aug 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.todaysfail.common.annotation;

import com.todaysfail.common.exception.BaseErrorCode;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiErrorCodeExample {
Class<? extends BaseErrorCode> value();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.todaysfail.common.annotation;

import com.todaysfail.common.interfaces.SwaggerExampleExceptions;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiErrorExceptionsExample {
Class<? extends SwaggerExampleExceptions> value();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.todaysfail.common.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface DevelopOnly {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.todaysfail.common.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DisableSwaggerSecurity {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.todaysfail.common.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;
import org.springframework.stereotype.Component;

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ExceptionDoc {
@AliasFor(annotation = Component.class)
String value() default "";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.todaysfail.common.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.stereotype.Component;

@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ExplainError {
String value() default "";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.todaysfail.common.aop;

import static com.todaysfail.common.consts.TodaysFailConst.*;

import com.todaysfail.common.exception.TodaysFailDynamicException;
import com.todaysfail.common.helper.SpringEnvironmentHelper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Slf4j
@RequiredArgsConstructor
public class ApiBlockingAspect {

private final SpringEnvironmentHelper springEnvironmentHelper;

@Around("@annotation(com.todaysfail.common.annotation.DevelopOnly)")
public Object checkApiAcceptingCondition(ProceedingJoinPoint joinPoint) throws Throwable {
if (springEnvironmentHelper.isProdProfile()) {
throw new TodaysFailDynamicException(
METHOD_NOT_ALLOWED, "Blocked API", "PRODUCTION 환경에서 사용할 수 없는 API 입니다.");
}
return joinPoint.proceed();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@

public interface BaseErrorCode {
ErrorReason getErrorReason();

String getExplainError() throws NoSuchFieldException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,75 @@

import static com.todaysfail.common.consts.TodaysFailConst.*;

import com.todaysfail.common.annotation.ExplainError;
import com.todaysfail.common.dto.ErrorReason;
import java.lang.reflect.Field;
import java.util.Objects;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public enum GlobalErrorCode implements BaseErrorCode {
INTERNAL_SERVER_ERROR(INTERNAL_SERVER, "GLOBAL_500_1", "서버 오류, 관리자에게 문의하세요"),

// 400 번대 에러
@ExplainError("밸리데이션(검증 과정)중 발생하는 오류입니다.")
ARGUMENT_NOT_VALID_ERROR(BAD_REQUEST, "GLOBAL_400_1", "잘못된 요청입니다."),

@ExplainError("accessToken 만료시 발생하는 오류입니다.")
TOKEN_EXPIRED(UNAUTHORIZED, "AUTH_401_1", "토큰이 만료되었습니다."),

@ExplainError("refreshToken 만료시 발생하는 오류입니다.")
REFRESH_TOKEN_EXPIRED(FORBIDDEN, "AUTH_403_1", "인증시간이 만료되었습니다. 인증토큰 재발급을 요청하세요"),

@ExplainError("인증 토큰이 잘못됐을 때 발생하는 오류입니다.")
INVALID_TOKEN(FORBIDDEN, "AUTH_403_2", "토큰의 형식이 일치하지 않습니다. 적절한 형식으로 다시 요청하세요"),
@ExplainError("헤더에 올바른 accessToken을 담지않았을 때 발생하는 오류(형식 불일치 등)")
ACCESS_TOKEN_NOT_EXIST(UNAUTHORIZED, "AUTH_403_3", "토큰이 존재하지 않습니다. 적절한 토큰을 헤더에 넣어주세요"),

ACCESS_TOKEN_NOT_EXIST(UNAUTHORIZED, "AUTH_401_2", "토큰이 존재하지 않습니다. 적절한 토큰을 헤더에 넣어주세요"),

ACCESS_TOKEN_NOT_FOUND(FORBIDDEN, "AUTH_403_3", "토큰이 존재하지 않습니다. 적절한 토큰을 헤더에 넣어주세요"),
@ExplainError("없는 resource로 요청했습니다. 다른 요청으로 다시 시도해주세요")
RESOURCE_NOT_FOUND(NOT_FOUND, "GLOBAL_404_1", "요청한 리소스를 서버에서 찾을 수 없습니다."),

RESOURCE_NOT_FOUND(
NOT_FOUND, "GLOBAL_404_1", "The requested resource was not found on the server."),
@ExplainError("요청한 메소드가 허용되지 않을 떄 발생하는 오류입니다.")
SERVER_METHOD_NOT_ALLOWED(METHOD_NOT_ALLOWED, "GLOBAL_405_1", "요청한 메소드가 허용되지 않습니다."),

@ExplainError("요청시간이 초과되었습니다.")
RESOURCE_REQUEST_TIMEOUT(REQUEST_TIMEOUT, "GLOBAL_408_1", "요청 시간이 초과되었습니다."),

@ExplainError("많은 요청을 보냈을 때 발생하는 오류입니다.")
SERVER_TOO_MANY_REQUESTS(TOO_MANY_REQUESTS, "GLOBAL_429_1", "많은 요청을 보냈습니다. 잠시 후 다시 시도해주세요"),

SERVER_METHOD_NOT_ALLOWED(METHOD_NOT_ALLOWED, "GLOBAL_405_1", "요청한 메소드가 허용되지 않습니다."),
// 500 번대 에러
@ExplainError("알 수 없는 오류 발생 서버 관리자에게 문의하세요.")
INTERNAL_SERVER_ERROR(INTERNAL_SERVER, "GLOBAL_500_1", "서버 오류, 관리자에게 문의하세요"),
@ExplainError("SecurityContext를 찾을 수 없을 때 발생하는 오류입니다.")
SECURITY_CONTEXT_NOT_FOUND(INTERNAL_SERVER, "GLOBAL_500_2", "SecurityContext를 찾을 수 없습니다"),

@ExplainError("레디스 락을 사용할 수 없을 때 발생하는 오류입니다.")
NOT_AVAILABLE_REDISSON_LOCK(INTERNAL_SERVER, "REDISSON_500_1", "락을 사용할 수 없습니다"),
@ExplainError("잘못된 락 식별자를 사용했을 때 발생하는 오류입니다.")
BAD_LOCK_IDENTIFIER(INTERNAL_SERVER, "REDISSON_500_2", "락의 키값이 잘못 세팅 되었습니다"),

@ExplainError("서버가 현재 유지보수이거나 과부하로 이용할 수 없을 때 발생하는 오류입니다.")
SERVER_UNAVAILABLE(
SERVICE_UNAVAILABLE, "GLOBAL_503_1", "현재 유지보수 및 과부하로 서버를 이용할 수 없습니다. 잠시 후 다시 시도해주세요"),

OTHER_SERVER_BAD_REQUEST(BAD_REQUEST, "FEIGN_400_1", "Other server bad request"),
OTHER_SERVER_UNAUTHORIZED(BAD_REQUEST, "FEIGN_400_2", "Other server unauthorized"),
OTHER_SERVER_FORBIDDEN(BAD_REQUEST, "FEIGN_400_3", "Other server forbidden"),
OTHER_SERVER_EXPIRED_TOKEN(BAD_REQUEST, "FEIGN_400_4", "Other server expired token"),
OTHER_SERVER_NOT_FOUND(BAD_REQUEST, "FEIGN_400_5", "Other server not found error"),
OTHER_SERVER_INTERNAL_SERVER_ERROR(
BAD_REQUEST, "FEIGN_400_6", "Other server internal server error"),

NOT_AVAILABLE_REDISSON_LOCK(500, "REDISSON_500_1", "락을 사용할 수 없습니다"),
BAD_LOCK_IDENTIFIER(500, "REDISSON_500_2", "락의 키값이 잘못 세팅 되었습니다"),
SECURITY_CONTEXT_NOT_FOUND(500, "GLOBAL_500_3", "SecurityContext를 찾을 수 없습니다"),
// 외부 서버
@ExplainError("외부 서버에 잘못된 요청을 보냈을 때 발생하는 예외입니다.")
OTHER_SERVER_BAD_REQUEST(BAD_REQUEST, "FEIGN_400_1", "외부 서버에 잘못된 요청을 보냈습니다."),

@ExplainError("외부 서버에 인증되지 않은 요청을 보냈을 때 발생하는 예외입니다.")
OTHER_SERVER_UNAUTHORIZED(BAD_REQUEST, "FEIGN_400_2", "외부 서버에 인증되지 않은 요청을 보냈습니다."),

@ExplainError("외부 서버에 접근이 거부된 요청을 보냈을 때 발생하는 예외입니다.")
OTHER_SERVER_FORBIDDEN(BAD_REQUEST, "FEIGN_400_3", "외부 서버에 접근이 거부된 요청을 보냈습니다."),

@ExplainError("외부 서버에 만료된 토큰으로 인증되지 않은 요청을 보냈습니다.")
OTHER_SERVER_EXPIRED_TOKEN(BAD_REQUEST, "FEIGN_400_4", "외부 서버에 만료된 토큰으로 인증되지 않은 요청을 보냈습니다."),

@ExplainError("외부 서버에 잘못된 Resource를 요청했을 때 발생하는 예외입니다.")
OTHER_SERVER_NOT_FOUND(BAD_REQUEST, "FEIGN_400_5", "외부 서버에 요청한 리소스를 찾을 수 없습니다."),

@ExplainError("외부 서버의 내부 서버 오류가 발생했을 때 발생하는 예외입니다.")
OTHER_SERVER_INTERNAL_SERVER_ERROR(BAD_REQUEST, "FEIGN_400_6", "외부 서버의 알 수 없는 서버 오류가 발생했습니다."),
;

private Integer status;
Expand All @@ -56,4 +81,11 @@ public enum GlobalErrorCode implements BaseErrorCode {
public ErrorReason getErrorReason() {
return ErrorReason.builder().status(status).code(code).reason(reason).build();
}

@Override
public String getExplainError() throws NoSuchFieldException {
Field field = this.getClass().getField(this.name());
ExplainError annotation = field.getAnnotation(ExplainError.class);
return Objects.nonNull(annotation) ? annotation.value() : this.getReason();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package com.todaysfail.common.exception;

import com.todaysfail.common.dto.ErrorReason;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class TodaysFailCodeException extends RuntimeException {
private final BaseErrorCode errorCode;

public ErrorReason getErrorReason() {
return this.errorCode.getErrorReason();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.todaysfail.common.interfaces;

import com.todaysfail.common.annotation.ExceptionDoc;

@ExceptionDoc
public interface SwaggerExampleExceptions {}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@

@EnableConfigurationProperties({OauthProperties.class, JwtProperties.class})
@Configuration
public class EnableConfigProperties {}
public class EnableCommonConfigProperties {}

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

import static com.todaysfail.common.consts.TodaysFailConst.*;

import com.todaysfail.common.annotation.ExplainError;
import com.todaysfail.common.dto.ErrorReason;
import com.todaysfail.common.exception.BaseErrorCode;
import java.lang.reflect.Field;
import java.util.Objects;
import lombok.AllArgsConstructor;
import lombok.Getter;

Expand All @@ -26,4 +29,11 @@ public enum UserErrorCode implements BaseErrorCode {
public ErrorReason getErrorReason() {
return ErrorReason.builder().reason(reason).code(code).status(status).build();
}

@Override
public String getExplainError() throws NoSuchFieldException {
Field field = this.getClass().getField(this.name());
ExplainError annotation = field.getAnnotation(ExplainError.class);
return Objects.nonNull(annotation) ? annotation.value() : this.getReason();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.todaysfail.config.mysql;

import java.util.List;
import org.springframework.context.annotation.Profile;

@Profile({"prod", "dev"})
public class ReadOnlyDataSourceCycle<T> {
private List<T> readOnlyDataSourceLookupKeys;
private int index = 0;

public void setReadOnlyDataSourceLookupKeys(List<T> readOnlyDataSourceLookupKeys) {
this.readOnlyDataSourceLookupKeys = readOnlyDataSourceLookupKeys;
}

public T getReadOnlyDataSourceLookupKey() {
if (index + 1 >= readOnlyDataSourceLookupKeys.size()) {
index = -1;
}
return readOnlyDataSourceLookupKeys.get(++index);
}
}
Loading
Loading