Skip to content

Commit

Permalink
Feat/#32 API 문서 작성 방식을 변경합니다. (#33)
Browse files Browse the repository at this point in the history
* Chore : .gitignore

* Feat : Swagger Config 구현

* Feat : Swagger interface 로 분리

* Feat : build.gradle 변경

* Feat : Swagger 경로 추가 및 기존 테스트 제거

* Faet : 표기 방식 설정
  • Loading branch information
hyunw9 authored Jul 6, 2024
1 parent 0d938bc commit 93557a7
Show file tree
Hide file tree
Showing 10 changed files with 245 additions and 206 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,5 @@ replay_pid*
./gradle
/out
/secret
/.gradle
/.gradle/
/.gradle
59 changes: 3 additions & 56 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@ plugins {
id 'java'
id 'org.springframework.boot' version '3.3.1'
id 'io.spring.dependency-management' version '1.1.5'

id 'com.epages.restdocs-api-spec' version '0.18.4'
id 'org.hidetake.swagger.generator' version '2.18.2'

}

group = 'com.donkeys_today'
Expand Down Expand Up @@ -57,73 +54,23 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-redis:3.2.1'

//Api
testImplementation 'org.springframework.restdocs:spring-restdocs-mockmvc'
testImplementation 'com.epages:restdocs-api-spec-mockmvc:'+ restdocsApiSpecVersion
implementation 'org.springdoc:springdoc-openapi-ui:1.6.15'
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.2.0'

testImplementation 'io.rest-assured:spring-mock-mvc:5.4.0'
testImplementation "io.rest-assured:json-path:5.4.0"
testImplementation "io.rest-assured:xml-path:5.4.0"
swaggerUI 'org.webjars:swagger-ui:4.11.1'

//actuator
implementation 'org.springframework.boot:spring-boot-starter-actuator'


}

tasks.named('test') {
useJUnitPlatform()
}

swaggerSources {
sample{
setInputFile(file("${project.buildDir}/api-spec/openapi3.yaml"))
}
}

openapi3{
setServer("http://localhost:8080")
title = "API 문서"
description = "RestDocsWithSwaggerDocs"
version = "0.0.1"
format = "yaml"
}

//API 문서 AuthHeader 용
tasks.withType(GenerateSwaggerUI).configureEach {
dependsOn 'openapi3'
doFirst {
def swaggerUIFile = file("${openapi3.outputDirectory}/openapi3.yaml")
def securitySchemesContent =" securitySchemes:\n" + \
" APIKey:\n" + \
" type: apiKey\n" + \
" name: Authorization\n" + \
" in: header\n" + \
"security:\n" +
" - APIKey: [] # Apply the security scheme here"
swaggerUIFile.append securitySchemesContent
}
}

// 태스크 순서 재정의
tasks.named('generateSwaggerUISample') {
mustRunAfter 'test'
mustRunAfter 'processResources'
}

//정적 파일 호스팅을 위한 파일 복사
task copyDocument(type: Copy) {
dependsOn 'generateSwaggerUISample'
from file("build/swagger-ui-sample")
into file("src/main/resources/static/docs")
}

//Jar 로 빌드
bootJar{
dependsOn processResources
from("${generateSwaggerUISample.outputDir}"){
into 'static/docs'
}

}

//Feign
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.donkeys_today.server.presentation.api;

import com.donkeys_today.server.common.constants.Constants;
import com.donkeys_today.server.presentation.user.dto.requset.UserSignInRequest;
import com.donkeys_today.server.presentation.user.dto.requset.UserSignUpRequest;
import com.donkeys_today.server.presentation.user.dto.response.UserSignInResponse;
import com.donkeys_today.server.presentation.user.dto.response.UserSignUpResponse;
import com.donkeys_today.server.support.dto.ApiResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@Tag(name = "인증/인가")
@RequestMapping("/api/v1")
@RestController
public interface UserController {

@Operation(summary = "유저 회원가입 ", description = "Authorization code 와 UserSignUpRequest 로 회원가입을 진행합니다.")
@PostMapping("/auth/signup")
ResponseEntity<ApiResponse<UserSignUpResponse>> signUp(
@RequestHeader(Constants.AUTHORIZATION) @Parameter(name = "Authorization", description = "클라이언트가 인증 서버로부터 받은 인증 코드", required = true) final String auth_code,
@RequestBody(
description = "회원가입을 위하여 부가적으로 받는 정보 객체",
required = true,
content = @Content(schema = @Schema(implementation = UserSignUpRequest.class))
) final UserSignUpRequest request
);

@Operation(summary = "유저 로그인 ", description = "Authorization code로 로그인을 진행합니다.")
@PostMapping("/auth/signin")
ResponseEntity<ApiResponse<UserSignInResponse>> signIn(
@RequestHeader(Constants.AUTHORIZATION) @Parameter(name = "Authorization", description = "클라이언트가 인증 서버로부터 받은 인증 코드", required = true) final String auth_code,
@RequestBody(
description = "로그인을 위하여 부가적으로 받는 정보 객체",
required = true,
content = @Content(schema = @Schema(implementation = UserSignInRequest.class))
) final UserSignInRequest userSignInRequest
);


}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.donkeys_today.server.application.user.UserService;
import com.donkeys_today.server.common.constants.Constants;
import com.donkeys_today.server.presentation.api.UserController;
import com.donkeys_today.server.presentation.user.dto.requset.UserSignInRequest;
import com.donkeys_today.server.presentation.user.dto.requset.UserSignUpRequest;
import com.donkeys_today.server.presentation.user.dto.response.UserSignInResponse;
Expand All @@ -15,28 +16,28 @@
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1")
public class UserController {
public class UserControllerImpl implements UserController {

private final UserService userService;

@PostMapping("/auth/signup")
public ResponseEntity<ApiResponse<?>> signUp(
@Override
public ResponseEntity<ApiResponse<UserSignUpResponse>> signUp(
@RequestHeader(Constants.AUTHORIZATION) final String authorization_code,
@RequestBody final UserSignUpRequest userSignUpRequest) {
final UserSignUpResponse response = userService.signUp(authorization_code,userSignUpRequest);
return ResponseEntity.status(HttpStatus.CREATED)
.body(ApiResponse.success(SuccessType.CREATED_SUCCESS, response));
}

@ResponseBody
@Override
@PostMapping("/auth/signin")
public ResponseEntity<?> signIn(@RequestHeader(Constants.AUTHORIZATION) String code,
public ResponseEntity<ApiResponse<UserSignInResponse>> signIn(@RequestHeader(Constants.AUTHORIZATION) String code,
@RequestBody final UserSignInRequest userSignInRequest) {
System.out.println(code);
final UserSignInResponse response = userService.signIn(code,userSignInRequest);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package com.donkeys_today.server.presentation.user.dto.requset;

import io.swagger.v3.oas.annotations.media.Schema;

public record UserSignInRequest(
@Schema(description = "플랫폼", example = "apple/kakao")
String platform
) {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.donkeys_today.server.presentation.user.dto.requset;

import io.swagger.v3.oas.annotations.media.Schema;
import java.time.LocalTime;

public record UserSignUpRequest(
@Schema(description = "로그인 플랫폼", example = "apple/kakao")
String platform,
boolean alarmAgreement,
LocalTime alarmTime
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,21 @@ public class WhiteListConstants {
"/oauth/authorize",
"/actuator/health",
"/error",
"/swagger-ui/",
"/swagger-resources/",
"/api-docs/"
"/swagger",
"/swagger-ui/**",
"/api-docs/**"
);

public static final String[] SECURITY_WHITE_LIST = {
"/api/v1/kakao",
"/api/v1/auth/**",
"/",
"/actuator/health",
"/api-docs/**",
"swagger-ui/**",
"/swagger",
"/swagger-ui/**",
"/redirect",
"/login/oauth2/code/kakao",
"/v3/api-docs/**",

};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.donkeys_today.server.support.swagger.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.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SwaggerConfig {

@Bean
public OpenAPI customOpenAPI(){
String jwt = "JWT";
SecurityRequirement securityRequirement = new SecurityRequirement().addList(jwt);
Components components = new Components().addSecuritySchemes(jwt, new SecurityScheme()
.name(jwt)
.type(SecurityScheme.Type.HTTP)
.scheme("bearer")
.bearerFormat("JWT")
);
return new OpenAPI()
.components(new Components())
.info(apiInfo());
}

private Info apiInfo(){
return new Info()
.title("Clody API 문서")
.description("Clody API ")
.version("1.0");
}
}
58 changes: 29 additions & 29 deletions src/test/java/com/donkeys_today/server/docs/RestDocsSupport.java
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
package com.donkeys_today.server.docs;

import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;

import com.fasterxml.jackson.databind.ObjectMapper;
import io.restassured.module.mockmvc.RestAssuredMockMvc;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.restdocs.RestDocumentationContextProvider;
import org.springframework.restdocs.RestDocumentationExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

@ExtendWith(RestDocumentationExtension.class)
public abstract class RestDocsSupport {

protected MockMvc mockMvc;
protected ObjectMapper objectMapper = new ObjectMapper();

@BeforeEach
public void setUp(RestDocumentationContextProvider provider) throws Exception {
this.mockMvc = MockMvcBuilders.standaloneSetup(initController())
.apply(documentationConfiguration(provider))
.build();
RestAssuredMockMvc.mockMvc(this.mockMvc);
}

protected abstract Object initController() throws Exception;
}
//package com.donkeys_today.server.docs;
//
//import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
//
//import com.fasterxml.jackson.databind.ObjectMapper;
//import io.restassured.module.mockmvc.RestAssuredMockMvc;
//import org.junit.jupiter.api.BeforeEach;
//import org.junit.jupiter.api.extension.ExtendWith;
//import org.springframework.restdocs.RestDocumentationContextProvider;
//import org.springframework.restdocs.RestDocumentationExtension;
//import org.springframework.test.web.servlet.MockMvc;
//import org.springframework.test.web.servlet.setup.MockMvcBuilders;
//
//@ExtendWith(RestDocumentationExtension.class)
//public abstract class RestDocsSupport {
//
// protected MockMvc mockMvc;
// protected ObjectMapper objectMapper = new ObjectMapper();
//
// @BeforeEach
// public void setUp(RestDocumentationContextProvider provider) throws Exception {
// this.mockMvc = MockMvcBuilders.standaloneSetup(initController())
// .apply(documentationConfiguration(provider))
// .build();
// RestAssuredMockMvc.mockMvc(this.mockMvc);
// }
//
// protected abstract Object initController() throws Exception;
//}
Loading

0 comments on commit 93557a7

Please sign in to comment.