Skip to content

Commit

Permalink
[feat] 로그인 ArgumentResolver 추가 (#97)
Browse files Browse the repository at this point in the history
* refactor: 패키지 구조 변경 (#96)

* refactor: 어드민 question API 클래스 분리

* feat: 로그인 ArgumentResolver 추가

* refactor: 어드민 question API 분리 원상태로 변경

* test: 워크플로우 실행 환경 확인을 위한 설정 추가

* chore: 테스트 컨테이너 reuse 옵션 추가

* chore: ci 테스트 h2 DB 설정
  • Loading branch information
donggi-lee-bit authored Feb 8, 2024
1 parent 7a88c25 commit d0b9e22
Show file tree
Hide file tree
Showing 98 changed files with 561 additions and 385 deletions.
10 changes: 7 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,16 @@ dependencies {
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'

// db
runtimeOnly 'com.h2database:h2'
runtimeOnly 'com.h2database:h2:1.4.200'
runtimeOnly 'com.mysql:mysql-connector-j'

// test
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'io.rest-assured:rest-assured'

// test containers
testImplementation 'org.testcontainers:junit-jupiter'
testImplementation 'org.testcontainers:mysql'
// testImplementation 'org.testcontainers:junit-jupiter'
// testImplementation 'org.testcontainers:mysql'

// api docs
testImplementation 'org.springframework.restdocs:spring-restdocs-restassured'
Expand All @@ -65,6 +65,10 @@ dependencyManagement {
}
}

test {
systemProperty "testcontainers.reuse.enable", "true"
}

tasks.named('test') {
outputs.dir snippetsDir
useJUnitPlatform()
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/donggi/dev/kkeuroolryo/auth/Auth.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package donggi.dev.kkeuroolryo.auth;

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

@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Auth {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package donggi.dev.kkeuroolryo.auth;

import donggi.dev.kkeuroolryo.auth.application.AuthExtractor;
import donggi.dev.kkeuroolryo.auth.application.dto.AuthPayload;
import donggi.dev.kkeuroolryo.common.exception.BadRequestException;
import donggi.dev.kkeuroolryo.common.exception.ErrorCodeAndMessage;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

@Component
public class LoginArgumentResolver implements HandlerMethodArgumentResolver {

private static final String BEARER_TYPE = "Bearer ";

private final AuthExtractor authExtractor;

public LoginArgumentResolver(final AuthExtractor authExtractor) {
this.authExtractor = authExtractor;
}

@Override
public boolean supportsParameter(final MethodParameter parameter) {
return parameter.getParameterType().equals(Long.class) &&
parameter.hasParameterAnnotation(Auth.class);
}

@Override
public Object resolveArgument(
final MethodParameter parameter,
final ModelAndViewContainer mavContainer,
final NativeWebRequest webRequest,
final WebDataBinderFactory binderFactory
) {
final HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);

if (request == null) {
throw new BadRequestException(ErrorCodeAndMessage.INVALID_REQUEST);
}

final String accessToken = extractAccessToken(request.getHeader(HttpHeaders.AUTHORIZATION));
final AuthPayload authPayload = authExtractor.extract(accessToken);
return authPayload.id();
}

private String extractAccessToken(final String header) {
if (header != null && header.startsWith(BEARER_TYPE)) {
return header.substring(BEARER_TYPE.length()).trim();
}

throw new BadRequestException(ErrorCodeAndMessage.INVALID_AUTH_TOKEN);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package donggi.dev.kkeuroolryo.auth.application;

import donggi.dev.kkeuroolryo.auth.application.dto.AuthPayload;

public interface AuthExtractor {

AuthPayload extract(String token);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package donggi.dev.kkeuroolryo.auth.application.dto;

public record AuthPayload(
// String role,
Long id
) {

}
22 changes: 22 additions & 0 deletions src/main/java/donggi/dev/kkeuroolryo/auth/config/AuthConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package donggi.dev.kkeuroolryo.auth.config;

import donggi.dev.kkeuroolryo.auth.application.AuthExtractor;
import donggi.dev.kkeuroolryo.auth.infrastructure.JwtAuthExtractor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AuthConfig {

private final String secretKey;

public AuthConfig(@Value("${security.jwt.secret-key}") final String secretKey) {
this.secretKey = secretKey;
}

@Bean
public AuthExtractor authExtractor() {
return new JwtAuthExtractor(secretKey);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package donggi.dev.kkeuroolryo.auth.infrastructure;

import donggi.dev.kkeuroolryo.auth.application.AuthExtractor;
import donggi.dev.kkeuroolryo.auth.application.dto.AuthPayload;
import donggi.dev.kkeuroolryo.common.exception.ErrorCodeAndMessage;
import donggi.dev.kkeuroolryo.common.exception.UnauthorizedException;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import java.nio.charset.StandardCharsets;
import javax.crypto.SecretKey;

public class JwtAuthExtractor implements AuthExtractor {

private final JwtParser parser;

public JwtAuthExtractor(final String secretKey) {
SecretKey key = Keys.hmacShaKeyFor(secretKey.getBytes(StandardCharsets.UTF_8));
this.parser = Jwts.parserBuilder()
.setSigningKey(key)
.build();
}

@Override
public AuthPayload extract(final String token) {
final Claims claims = getClaims(token);
return new AuthPayload(Long.parseLong(claims.getSubject()));
}

private Claims getClaims(final String token) {
try {
return parser.parseClaimsJws(token)
.getBody();
} catch (ExpiredJwtException e) {
throw new UnauthorizedException(ErrorCodeAndMessage.EXPIRED_TOKEN);
} catch (JwtException e) {
throw new UnauthorizedException(ErrorCodeAndMessage.INVALID_TOKEN);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package donggi.dev.kkeuroolryo.core.comment.application;
package donggi.dev.kkeuroolryo.comment.application;

import donggi.dev.kkeuroolryo.core.comment.application.dto.CommentDto;
import donggi.dev.kkeuroolryo.web.comment.dto.CommentRegisterDto;
import donggi.dev.kkeuroolryo.comment.application.dto.CommentDto;
import donggi.dev.kkeuroolryo.comment.presentation.dto.CommentRegisterDto;

public interface CommentEditor {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package donggi.dev.kkeuroolryo.core.comment.application;
package donggi.dev.kkeuroolryo.comment.application;

import donggi.dev.kkeuroolryo.core.comment.application.dto.CommentPaginationDto;
import donggi.dev.kkeuroolryo.web.comment.dto.NoOffsetPageCommand;
import donggi.dev.kkeuroolryo.comment.application.dto.CommentPaginationDto;
import donggi.dev.kkeuroolryo.comment.presentation.dto.NoOffsetPageCommand;

public interface CommentFinder {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package donggi.dev.kkeuroolryo.core.comment.application;

import donggi.dev.kkeuroolryo.core.comment.application.dto.CommentDto;
import donggi.dev.kkeuroolryo.core.comment.application.dto.CommentPaginationDto;
import donggi.dev.kkeuroolryo.core.comment.domain.Comment;
import donggi.dev.kkeuroolryo.core.comment.domain.CommentRepository;
import donggi.dev.kkeuroolryo.core.comment.domain.exception.CommentNotFoundException;
import donggi.dev.kkeuroolryo.core.comment.domain.exception.NoOffsetPageInvalidException;
import donggi.dev.kkeuroolryo.core.question.domain.QuestionRepository;
import donggi.dev.kkeuroolryo.core.question.domain.exception.QuestionNotFoundException;
import donggi.dev.kkeuroolryo.web.comment.dto.CommentRegisterDto;
import donggi.dev.kkeuroolryo.web.comment.dto.NoOffsetPageCommand;
package donggi.dev.kkeuroolryo.comment.application;

import donggi.dev.kkeuroolryo.comment.application.dto.CommentDto;
import donggi.dev.kkeuroolryo.comment.application.dto.CommentPaginationDto;
import donggi.dev.kkeuroolryo.comment.domain.Comment;
import donggi.dev.kkeuroolryo.comment.domain.CommentRepository;
import donggi.dev.kkeuroolryo.comment.domain.exception.CommentNotFoundException;
import donggi.dev.kkeuroolryo.comment.domain.exception.NoOffsetPageInvalidException;
import donggi.dev.kkeuroolryo.question.domain.QuestionRepository;
import donggi.dev.kkeuroolryo.question.domain.exception.QuestionNotFoundException;
import donggi.dev.kkeuroolryo.comment.presentation.dto.CommentRegisterDto;
import donggi.dev.kkeuroolryo.comment.presentation.dto.NoOffsetPageCommand;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package donggi.dev.kkeuroolryo.core.comment.application.dto;
package donggi.dev.kkeuroolryo.comment.application.dto;

import donggi.dev.kkeuroolryo.core.comment.domain.Comment;
import donggi.dev.kkeuroolryo.comment.domain.Comment;
import lombok.Getter;

@Getter
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package donggi.dev.kkeuroolryo.core.comment.application.dto;
package donggi.dev.kkeuroolryo.comment.application.dto;

import donggi.dev.kkeuroolryo.core.comment.domain.Comment;
import donggi.dev.kkeuroolryo.core.common.PageDto;
import donggi.dev.kkeuroolryo.comment.domain.Comment;
import donggi.dev.kkeuroolryo.common.PageDto;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package donggi.dev.kkeuroolryo.core.comment.domain;
package donggi.dev.kkeuroolryo.comment.domain;

import donggi.dev.kkeuroolryo.core.comment.domain.exception.CommentUnauthorizedException;
import donggi.dev.kkeuroolryo.web.comment.dto.CommentRegisterDto;
import donggi.dev.kkeuroolryo.comment.domain.exception.CommentUnauthorizedException;
import donggi.dev.kkeuroolryo.comment.presentation.dto.CommentRegisterDto;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package donggi.dev.kkeuroolryo.core.comment.domain;
package donggi.dev.kkeuroolryo.comment.domain;

import donggi.dev.kkeuroolryo.core.comment.domain.exception.CommentInvalidContentException;
import donggi.dev.kkeuroolryo.comment.domain.exception.CommentInvalidContentException;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import java.util.Objects;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package donggi.dev.kkeuroolryo.core.comment.domain;
package donggi.dev.kkeuroolryo.comment.domain;

import donggi.dev.kkeuroolryo.core.comment.domain.exception.CommentInvalidPasswordException;
import donggi.dev.kkeuroolryo.comment.domain.exception.CommentInvalidPasswordException;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import java.util.Objects;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package donggi.dev.kkeuroolryo.core.comment.domain;
package donggi.dev.kkeuroolryo.comment.domain;

import java.util.Optional;
import org.springframework.data.domain.Pageable;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package donggi.dev.kkeuroolryo.core.comment.domain;
package donggi.dev.kkeuroolryo.comment.domain;

import donggi.dev.kkeuroolryo.core.comment.domain.exception.CommentInvalidUsernameException;
import donggi.dev.kkeuroolryo.comment.domain.exception.CommentInvalidUsernameException;
import jakarta.persistence.Column;
import jakarta.persistence.Embeddable;
import java.util.Objects;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package donggi.dev.kkeuroolryo.core.comment.domain.exception;
package donggi.dev.kkeuroolryo.comment.domain.exception;

import donggi.dev.kkeuroolryo.common.exception.ErrorCodeAndMessage;
import donggi.dev.kkeuroolryo.common.exception.GolrabaException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package donggi.dev.kkeuroolryo.core.comment.domain.exception;
package donggi.dev.kkeuroolryo.comment.domain.exception;

import donggi.dev.kkeuroolryo.common.exception.ErrorCodeAndMessage;
import donggi.dev.kkeuroolryo.common.exception.GolrabaException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package donggi.dev.kkeuroolryo.core.comment.domain.exception;
package donggi.dev.kkeuroolryo.comment.domain.exception;

import donggi.dev.kkeuroolryo.common.exception.ErrorCodeAndMessage;
import donggi.dev.kkeuroolryo.common.exception.GolrabaException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package donggi.dev.kkeuroolryo.core.comment.domain.exception;
package donggi.dev.kkeuroolryo.comment.domain.exception;

import donggi.dev.kkeuroolryo.common.exception.ErrorCodeAndMessage;
import donggi.dev.kkeuroolryo.common.exception.GolrabaException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package donggi.dev.kkeuroolryo.core.comment.domain.exception;
package donggi.dev.kkeuroolryo.comment.domain.exception;

import donggi.dev.kkeuroolryo.common.exception.ErrorCodeAndMessage;
import donggi.dev.kkeuroolryo.common.exception.GolrabaException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package donggi.dev.kkeuroolryo.core.comment.domain.exception;
package donggi.dev.kkeuroolryo.comment.domain.exception;

import donggi.dev.kkeuroolryo.common.exception.ErrorCodeAndMessage;
import donggi.dev.kkeuroolryo.common.exception.GolrabaException;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package donggi.dev.kkeuroolryo.core.comment.infrastructure;
package donggi.dev.kkeuroolryo.comment.infrastructure;

import donggi.dev.kkeuroolryo.core.comment.domain.Comment;
import donggi.dev.kkeuroolryo.core.comment.domain.CommentRepository;
import donggi.dev.kkeuroolryo.core.comment.domain.exception.CommentNotFoundException;
import donggi.dev.kkeuroolryo.comment.domain.Comment;
import donggi.dev.kkeuroolryo.comment.domain.CommentRepository;
import donggi.dev.kkeuroolryo.comment.domain.exception.CommentNotFoundException;
import java.util.Optional;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Slice;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package donggi.dev.kkeuroolryo.web.comment;
package donggi.dev.kkeuroolryo.comment.presentation;

import donggi.dev.kkeuroolryo.common.response.ApiResponse;
import donggi.dev.kkeuroolryo.core.comment.application.CommentEditor;
import donggi.dev.kkeuroolryo.core.comment.application.CommentFinder;
import donggi.dev.kkeuroolryo.core.comment.application.dto.CommentDto;
import donggi.dev.kkeuroolryo.core.comment.application.dto.CommentPaginationDto;
import donggi.dev.kkeuroolryo.web.comment.dto.CommentDeleteCommand;
import donggi.dev.kkeuroolryo.web.comment.dto.CommentRegisterDto;
import donggi.dev.kkeuroolryo.web.comment.dto.NoOffsetPageCommand;
import donggi.dev.kkeuroolryo.comment.application.CommentEditor;
import donggi.dev.kkeuroolryo.comment.application.CommentFinder;
import donggi.dev.kkeuroolryo.comment.application.dto.CommentDto;
import donggi.dev.kkeuroolryo.comment.application.dto.CommentPaginationDto;
import donggi.dev.kkeuroolryo.comment.presentation.dto.CommentDeleteCommand;
import donggi.dev.kkeuroolryo.comment.presentation.dto.CommentRegisterDto;
import donggi.dev.kkeuroolryo.comment.presentation.dto.NoOffsetPageCommand;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package donggi.dev.kkeuroolryo.web.comment.dto;
package donggi.dev.kkeuroolryo.comment.presentation.dto;

import lombok.Getter;
import lombok.NoArgsConstructor;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package donggi.dev.kkeuroolryo.web.comment.dto;
package donggi.dev.kkeuroolryo.comment.presentation.dto;

import donggi.dev.kkeuroolryo.core.comment.domain.Comment;
import donggi.dev.kkeuroolryo.comment.domain.Comment;
import lombok.Getter;
import lombok.NoArgsConstructor;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package donggi.dev.kkeuroolryo.web.comment.dto;
package donggi.dev.kkeuroolryo.comment.presentation.dto;

import donggi.dev.kkeuroolryo.core.comment.domain.exception.NoOffsetPageInvalidException;
import donggi.dev.kkeuroolryo.comment.domain.exception.NoOffsetPageInvalidException;
import lombok.Getter;

@Getter
Expand Down
Loading

0 comments on commit d0b9e22

Please sign in to comment.