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

feat: [UserService] 유저 아이디로 유저정보를 조회하는 gRPC 서버 코드를 추가합니다. #140

Merged
merged 16 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from 25 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
14 changes: 14 additions & 0 deletions src/common-module/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ buildscript {
plugins {
id 'java'
id 'com.google.protobuf' version "${protobufPluginVersion}"

id("org.springframework.boot") version "3.2.1"
id("io.spring.dependency-management") version "1.1.4"
}

group 'org.palette'
Expand All @@ -21,6 +24,13 @@ repositories {
dependencies {
implementation "io.grpc:grpc-protobuf:${grpcVersion}"
implementation "io.grpc:grpc-stub:${grpcVersion}"

implementation 'com.fasterxml.jackson.core:jackson-databind'
implementation "org.springframework.boot:spring-boot-starter-web"

compileOnly("org.projectlombok:lombok")
annotationProcessor("org.projectlombok:lombok")

compileOnly 'jakarta.annotation:jakarta.annotation-api:1.3.5'
}

Expand Down Expand Up @@ -48,3 +58,7 @@ test {
clean {
delete 'src/generated'
}

bootJar {
enabled = false
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.palette.config;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.palette.passport.HMACEncoder;
import org.palette.passport.PassportExtractor;
import org.palette.passport.PassportGenerator;
import org.palette.passport.PassportValidator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@RequiredArgsConstructor
public class CommonModuleConfig {

private final ObjectMapper objectMapper;

@Value("${passport.algorithm}")
String HMacAlgorithm;

@Value("${passport.key}")
String passportSecretKey;

@Bean
public HMACEncoder hmacEncoder() {
return new HMACEncoder(HMacAlgorithm, passportSecretKey);
}

@Bean
public PassportGenerator passportGenerator() {
return new PassportGenerator(objectMapper, hmacEncoder());
}

@Bean
public PassportValidator passportValidator() {
return new PassportValidator(objectMapper, hmacEncoder());
}

@Bean
public PassportExtractor passportExtractor() {
return new PassportExtractor(objectMapper, passportValidator());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package org.palette.exception;

public class BaseException extends RuntimeException {

private final ExceptionType exceptionType;

public BaseException(ExceptionType exceptionType) {
super(exceptionType.getMessage());
this.exceptionType = exceptionType;
}

public ExceptionType getExceptionType() {
return exceptionType;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package org.palette.exception;

import lombok.AccessLevel;
import lombok.Builder;

@Builder(access = AccessLevel.PROTECTED)
public record ExceptionResponse(
String code,
String message,
String description
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package org.palette.exception;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;

@Getter
@RequiredArgsConstructor
public enum ExceptionType {

// 400
COMMON_400_000001(
"COMMON_400_000001",
"INCORRECT_PARAMETER",
"요청 파라미터가 올바르지 않습니다.",
HttpStatus.BAD_REQUEST
),

COMMON_400_000002(
"COMMON_400_000002",
"BROKEN_TOKEN",
"요청 토큰이 올바르지 않습니다.",
HttpStatus.BAD_REQUEST
),

COMMON_400_000003(
"COMMON_400_000003",
"BROKEN_ATTEMPT",
"인증번호 입력 횟수를 초과했습니다.",
HttpStatus.BAD_REQUEST
),

COMMON_400_000004(
"COMMON_400_000002",
"BROKEN_PAYLOAD",
"인증번호가 올바르지 않습니다.",
HttpStatus.BAD_REQUEST
),

// 401
COMMON_401_000001(
"COMMON_401_000001",
"MISSED COMMONENTICATION",
"해당 요청은 인증이 필요합니다.",
HttpStatus.UNAUTHORIZED
),

// 403
COMMON_403_000001(
"COMMON_403_000001",
"NOT ALLOWED PERMISSION",
"해당 요청에 대한 권한이 없습니다.",
HttpStatus.FORBIDDEN
),

COMMON_403_000002(
"COMMON_403_000002",
"EXPIRED_PAYLOAD",
"요청한 인증번호가 만료되었습니다.",
HttpStatus.FORBIDDEN
),

COMMON_403_000003(
"COMMON_403_000003",
"EXPIRED_PAYLOAD",
"토큰이 만료되었습니다. 다시 로그인해주세요",
HttpStatus.FORBIDDEN
),

// 404
COMMON_404_000001(
"COMMON_404_000001",
"NOT FOUNDED",
"해당 리소스가 존재하지 않습니다.",
HttpStatus.NOT_FOUND
),

// 405
COMMON_405_000001(
"COMMON_403_000005",
"NOT ALLOWED METHOD",
"올바르지 않은 요청 메서드입니다.",
HttpStatus.METHOD_NOT_ALLOWED
),

// 409
COMMON_409_000001(
"COMMON_409_000001",
"DUPLICATED",
"중복된 리소스가 있습니다.",
HttpStatus.CONFLICT
),

// 500
COMMON_500_000001(
"COMMON_500_000001",
"INTERNAL SERVER ERROR",
"서버 간 통신 중 예기치 못한 오류가 발생했습니다.",
HttpStatus.INTERNAL_SERVER_ERROR
),

COMMON_500_000002(
"COMMON_500_000002",
"INTERNAL SERVER ERROR",
"Passport를 처리하는 중 예기치 못한 오류가 발생했습니다.",
HttpStatus.INTERNAL_SERVER_ERROR
),

;

public String getCode() {
return code;
}

public String getMessage() {
return message;
}

public String getDescription() {
return description;
}

public HttpStatus getHttpStatus() {
return httpStatus;
}

private final String code;
private final String message;
private final String description;
private final HttpStatus httpStatus;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package org.palette.exception;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

@Slf4j
@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(value = {
MethodArgumentNotValidException.class,
MethodArgumentTypeMismatchException.class,
})
public ResponseEntity<ExceptionResponse> handleRequestValidationException(Exception e) {
ExceptionType exceptionType = ExceptionType.COMMON_400_000001;
ExceptionResponse exceptionResponse = ExceptionResponse.builder()
.code(exceptionType.getCode())
.message(exceptionType.getMessage())
.description(exceptionType.getDescription())
.build();

logException(exceptionResponse);

return ResponseEntity
.status(exceptionType.getHttpStatus())
.body(exceptionResponse);
}

@ExceptionHandler(value = {BaseException.class})
public ResponseEntity<ExceptionResponse> handleBaseException(
BaseException baseException
) {
ExceptionType exceptionType = baseException.getExceptionType();
ExceptionResponse exceptionResponse = ExceptionResponse.builder()
.code(exceptionType.getCode())
.description(exceptionType.getDescription())
.message(exceptionType.getMessage())
.build();

logException(exceptionResponse);

return ResponseEntity
.status(exceptionType.getHttpStatus())
.body(exceptionResponse);
}

@ExceptionHandler(value = {Exception.class})
public ResponseEntity<ExceptionResponse> handleException(Exception e) {
ExceptionResponse exceptionResponse = ExceptionResponse.builder()
.code("AUTH_SERVICE_EXCEPTION")
.message(e.getCause().getMessage())
.description(e.getLocalizedMessage())
.build();

logException(exceptionResponse);

return ResponseEntity
.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(exceptionResponse);
}


private static void logException(ExceptionResponse exceptionResponse) {
log.error(
"code : {}, message : {}, description : {}",
exceptionResponse.code(),
exceptionResponse.description(),
exceptionResponse.message()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package org.palette.passport;

import lombok.RequiredArgsConstructor;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Base64;

@RequiredArgsConstructor
public class HMACEncoder {

private final String HMacAlgorithm;
private final String passportSecretKey;

protected String createHMACIntegrityKey(String userInfoString) {
SecretKeySpec secretKeySpec = new SecretKeySpec(
passportSecretKey.getBytes(),
HMacAlgorithm
);
Mac mac;
try {
mac = Mac.getInstance(HMacAlgorithm);
mac.init(secretKeySpec);
} catch (Exception e) {
throw new RuntimeException(e);
}
return Base64.getEncoder()
.encodeToString(mac.doFinal(userInfoString.getBytes()));
}
}
Loading
Loading