Skip to content
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
6 changes: 6 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation "org.springdoc:springdoc-openapi-starter-webmvc-api:2.8.5"
implementation "org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.5"
compileOnly 'org.projectlombok:lombok'
runtimeOnly 'com.h2database:h2'
implementation("io.jsonwebtoken:jjwt-api:0.12.6")
Expand All @@ -37,6 +39,10 @@ dependencies {
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

implementation 'com.querydsl:querydsl-jpa:5.1.0:jakarta'
annotationProcessor 'com.querydsl:querydsl-apt:5.1.0:jakarta'
annotationProcessor 'jakarta.persistence:jakarta.persistence-api'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package com.retrip.auth.application.out.repository;

import java.util.List;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.NoRepositoryBean;

@NoRepositoryBean
public interface ReadRepository<T, ID> extends JpaRepository<T, ID> {

@Override
default <S extends T> S save(S entity) {
throw new UnsupportedOperationException("해당 Repository는 Read만 가능합니다.");
}

@Override
default <S extends T> S saveAndFlush(S entity) {
throw new UnsupportedOperationException("해당 Repository는 Read만 가능합니다.");
}

@Override
default <S extends T> List<S> saveAllAndFlush(Iterable<S> entities) {
throw new UnsupportedOperationException("해당 Repository는 Read만 가능합니다.");
}

@Override
default void deleteAllInBatch(Iterable<T> entities) {
throw new UnsupportedOperationException("해당 Repository는 Read만 가능합니다.");
}

@Override
default void deleteAllByIdInBatch(Iterable<ID> ids) {
throw new UnsupportedOperationException("해당 Repository는 Read만 가능합니다.");
}

@Override
default void deleteAllInBatch() {
throw new UnsupportedOperationException("해당 Repository는 Read만 가능합니다.");
}

@Override
default <S extends T> List<S> saveAll(Iterable<S> entities) {
throw new UnsupportedOperationException("해당 Repository는 Read만 가능합니다.");
}

@Override
default void deleteById(ID id) {
throw new UnsupportedOperationException("해당 Repository는 Read만 가능합니다.");
}

@Override
default void delete(T entity) {
throw new UnsupportedOperationException("해당 Repository는 Read만 가능합니다.");
}

@Override
default void deleteAllById(Iterable<? extends ID> ids) {
throw new UnsupportedOperationException("해당 Repository는 Read만 가능합니다.");
}

@Override
default void deleteAll(Iterable<? extends T> entities) {
throw new UnsupportedOperationException("해당 Repository는 Read만 가능합니다.");
}

@Override
default void deleteAll() {
throw new UnsupportedOperationException("해당 Repository는 Read만 가능합니다.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.retrip.auth.infra.adapter.in.rest.common;

import static org.springframework.http.HttpStatus.*;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.http.HttpStatus;

@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class ApiResponse<T> {
private boolean success;
private int status;
private String message;
private T data;

public static <T> ApiResponse<T> created(T data) {
return success(data, CREATED);
}

public static <T> ApiResponse<T> ok(T data) {
return success(data, OK);
}

public static <T> ApiResponse<T> noContent() {
return success(null, NO_CONTENT);
}

public static <T> ApiResponse<T> of(T data, HttpStatus status) {
return success(data, status);
}

private static <T> ApiResponse<T> success(T data, HttpStatus status) {
return new ApiResponse<>(true, status.value(), status.getReasonPhrase(), data);
}

public static ApiResponse<ErrorResponse> of(ErrorResponse errorResponse) {
return new ApiResponse<>(false, errorResponse.getStatus(), valueOf(errorResponse.getStatus()).getReasonPhrase(), errorResponse);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.retrip.auth.infra.adapter.in.rest.common;

import com.retrip.auth.domain.exception.common.ErrorCode;

import java.util.ArrayList;

import java.util.List;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;

@Getter
@AllArgsConstructor
public class ErrorResponse {
private int status;
private String code;
private String message;
private String url = "Not available";
private String method;
private List<FieldError> errors = new ArrayList<>();

private ErrorResponse(int status, String code, String message, String url, String method) {
this.status = status;
this.code = code;
this.message = message;
this.url = url;
this.method = method;
}

public static ErrorResponse of(ErrorCode code, String url, String method, BindingResult bindingResult) {
return new ErrorResponse(code.getStatus().value(), code.getCode(), code.getMessage(), url, method, bindingResult.getFieldErrors());
}

public static ErrorResponse of(ErrorCode code, String url, String method) {
return new ErrorResponse(code.getStatus().value(), code.getCode(), code.getMessage(), url, method);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package com.retrip.auth.infra.adapter.in.rest.common;

import com.retrip.auth.domain.exception.common.BusinessException;
import com.retrip.auth.domain.exception.common.ErrorCode;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.nio.file.AccessDeniedException;

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(AccessDeniedException.class)
public ApiResponse<ErrorResponse> handleAccessDeniedException(HttpServletRequest request, AccessDeniedException e) {
log.error("handleAccessDeniedException: ", e);
return handle(ErrorCode.HANDLE_ACCESS_DENIED, request);
}

@ExceptionHandler(BindException.class)
public ApiResponse<ErrorResponse> handleBindException(HttpServletRequest request, BindException e) {
log.error("handleBindException: ", e);
return ApiResponse.of(
ErrorResponse.of(
ErrorCode.INVALID_INPUT_VALUE,
request.getRequestURL().toString(),
request.getMethod(),
e.getBindingResult()
));
}

@ExceptionHandler(BusinessException.class)
public ApiResponse<ErrorResponse> handleBusinessException(HttpServletRequest request, BusinessException e) {
log.error("handleBusinessException: ", e);
return handle(e.getErrorCode(), request);
}


@ExceptionHandler(Exception.class)
public ApiResponse<ErrorResponse> handleException(HttpServletRequest request, Exception e) {
log.error("handleException: ", e);
return handle(ErrorCode.SERVER_ERROR, request);
}

private static ApiResponse<ErrorResponse> handle(ErrorCode errorCode, HttpServletRequest request) {
return ApiResponse.of(
ErrorResponse.of(
errorCode, request.getRequestURL().toString(), request.getMethod()
));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.retrip.auth.infra.adapter.in.rest.common;

import java.util.List;

import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class ScrollPageResponse<T> {
private Long totalCount;
private boolean hasNext;
private List<T> list;

public static <T> ScrollPageResponse<T> of(Long totalCount, boolean hasNext, List<T> list) {
return new ScrollPageResponse<>(totalCount, hasNext, list);
}
}
20 changes: 20 additions & 0 deletions src/main/java/com/retrip/auth/infra/config/QuerydslConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.retrip.auth.infra.config;

import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@EnableJpaAuditing
@RequiredArgsConstructor
@Configuration
public class QuerydslConfig {
private final EntityManager entityManager;

@Bean
public JPAQueryFactory jpaQueryFactory() {
return new JPAQueryFactory(entityManager);
}
}
33 changes: 33 additions & 0 deletions src/main/java/com/retrip/auth/infra/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.retrip.auth.infra.config;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.servers.Server;
import org.springdoc.core.models.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class SwaggerConfig {
@Bean
public OpenAPI springShopOpenAPI() {
return new OpenAPI()
.addServersItem(new Server().url("/"))
.components(
new Components()
).info(
new Info()
.title("Auth Application")
.version("v0.0.1")
);
}
@Bean
public GroupedOpenApi authApi(){
return GroupedOpenApi.builder()
.group("auth")
.pathsToMatch("/auth/**")
.build();
}
}
1 change: 0 additions & 1 deletion src/main/resources/application.properties

This file was deleted.

31 changes: 31 additions & 0 deletions src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
spring:
application:
name: auth
#dataSource
datasource:
driver-class-name: org.h2.Driver
url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;DATABASE_TO_UPPER=false;MODE=MySQL
username: sa
#JPA
jpa:
properties:
hibernate:
show_sql: true
format_sql: true
dialect: org.hibernate.dialect.MySQL8Dialect
hibernate:
ddl-auto: create-drop
open-in-view: false

#logging
logging:
level:
org:
hibernate:
type:
descriptor:
sql: trace
springframework:
web:
client:
RestTemplate: DEBUG