From 68f8592a9ce8d670d7df48be9f395ee6c0114124 Mon Sep 17 00:00:00 2001 From: hod Date: Thu, 5 Feb 2026 01:17:40 +0900 Subject: [PATCH 1/4] Update production deployment configuration and secret reference --- .github/workflows/prod-deploy.yml | 2 +- src/main/resources/moa-secret | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/prod-deploy.yml b/.github/workflows/prod-deploy.yml index 32c5094..4ef0872 100644 --- a/.github/workflows/prod-deploy.yml +++ b/.github/workflows/prod-deploy.yml @@ -95,5 +95,5 @@ jobs: --name moa-test-server \ --restart unless-stopped \ -p 8080:8080 \ - -e PROFILE=prod\ + -e SPRING_PROFILES_ACTIVE=prod\ -d godqhr721/moa_server:${{ needs.setup.outputs.docker_tag }} diff --git a/src/main/resources/moa-secret b/src/main/resources/moa-secret index 990182b..ffc16e3 160000 --- a/src/main/resources/moa-secret +++ b/src/main/resources/moa-secret @@ -1 +1 @@ -Subproject commit 990182b8bf35a88c417a3d7ee62c874c7e9b6a1d +Subproject commit ffc16e3af877893dcd5c8df73137bb1b4559ede9 From 934d444b549f401ecaeb51770d5818d3731957ff Mon Sep 17 00:00:00 2001 From: hod Date: Thu, 5 Feb 2026 01:18:17 +0900 Subject: [PATCH 2/4] Add OpenAPI support and enhance JWT error handling --- build.gradle.kts | 1 + .../com/moa/common/config/SwaggerConfig.kt | 50 +++++++++++++++++++ .../com/moa/common/exception/ErrorCode.kt | 2 +- .../common/filter/JwtAuthenticationFilter.kt | 33 ++++++++---- 4 files changed, 74 insertions(+), 12 deletions(-) create mode 100644 src/main/kotlin/com/moa/common/config/SwaggerConfig.kt diff --git a/build.gradle.kts b/build.gradle.kts index 68e873b..86d0793 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -24,6 +24,7 @@ dependencies { implementation("org.springframework.boot:spring-boot-starter-webmvc") implementation("org.springframework.boot:spring-boot-starter-actuator") implementation("org.springframework.boot:spring-boot-starter-validation") + implementation("org.springdoc:springdoc-openapi-starter-webmvc-ui:3.0.0") // data implementation("org.springframework.boot:spring-boot-starter-data-jpa") diff --git a/src/main/kotlin/com/moa/common/config/SwaggerConfig.kt b/src/main/kotlin/com/moa/common/config/SwaggerConfig.kt new file mode 100644 index 0000000..5303fab --- /dev/null +++ b/src/main/kotlin/com/moa/common/config/SwaggerConfig.kt @@ -0,0 +1,50 @@ +package com.moa.common.config + +import com.moa.common.auth.AuthenticatedMember +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 io.swagger.v3.oas.models.servers.Server +import org.springdoc.core.utils.SpringDocUtils +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +@Configuration +class SwaggerConfig { + + init { + SpringDocUtils.getConfig().addAnnotationsToIgnore(AuthenticatedMember::class.java) + } + + @Bean + fun openAPI(): OpenAPI { + val jwt = "JWT" + val securitySchemeName = "bearerAuth" + + val securityRequirement = SecurityRequirement().addList(securitySchemeName) + + val securityScheme = SecurityScheme() + .name(securitySchemeName) + .type(SecurityScheme.Type.HTTP) + .scheme("bearer") + .bearerFormat(jwt) + .`in`(SecurityScheme.In.HEADER) + + return OpenAPI() + .components(Components().addSecuritySchemes(securitySchemeName, securityScheme)) + .addSecurityItem(securityRequirement) + .servers( + listOf( + Server().url("/") + ) + ) + .info(apiInfo()) + } + + private fun apiInfo() = Info() + .title("MOA SERVER API") + .description("Nexters 28th MOA SERVER") + .version("1.0.0") +} diff --git a/src/main/kotlin/com/moa/common/exception/ErrorCode.kt b/src/main/kotlin/com/moa/common/exception/ErrorCode.kt index 6f65a9f..64cdfcd 100644 --- a/src/main/kotlin/com/moa/common/exception/ErrorCode.kt +++ b/src/main/kotlin/com/moa/common/exception/ErrorCode.kt @@ -19,5 +19,5 @@ enum class ErrorCode( INVALID_ID_TOKEN("INVALID_ID_TOKEN", "유효하지 않은 ID 토큰입니다"), INVALID_PROVIDER("INVALID_PROVIDER", "유효하지 않는 로그인 방식입니다."), - OIDC_PROVIDER_ERROR("OIDC_PROVIDER_ERROR", "인증 제공자 연동 중 오류가 발생했습니다"), + EXPIRED_TOKEN("EXPIRED_TOKEN", "토큰이 만료되었습니다"), } diff --git a/src/main/kotlin/com/moa/common/filter/JwtAuthenticationFilter.kt b/src/main/kotlin/com/moa/common/filter/JwtAuthenticationFilter.kt index 4aa8827..4cb875f 100644 --- a/src/main/kotlin/com/moa/common/filter/JwtAuthenticationFilter.kt +++ b/src/main/kotlin/com/moa/common/filter/JwtAuthenticationFilter.kt @@ -3,6 +3,7 @@ package com.moa.common.filter import com.moa.common.auth.AuthConstants import com.moa.common.auth.JwtTokenProvider import com.moa.common.exception.ErrorCode +import io.jsonwebtoken.ExpiredJwtException import jakarta.servlet.FilterChain import jakarta.servlet.http.HttpServletRequest import jakarta.servlet.http.HttpServletResponse @@ -21,6 +22,10 @@ class JwtAuthenticationFilter( private val EXCLUDED_PATHS = listOf( "/api/v1/auth", "/h2-console", + "/api-docs-ui", + "/swagger-ui", + "/swagger-resources", + "/v3/api-docs", ) } @@ -36,27 +41,33 @@ class JwtAuthenticationFilter( ) { val token = jwtTokenProvider.extractToken(request) - if (token == null || !jwtTokenProvider.validateToken(token)) { - writeUnauthorizedResponse(response) + if (token == null) { + writeErrorResponse(response, ErrorCode.UNAUTHORIZED) return } - val memberId = jwtTokenProvider.getUserIdFromToken(token) - if (memberId == null) { - writeUnauthorizedResponse(response) - return - } + try { + jwtTokenProvider.validateToken(token) - request.setAttribute(AuthConstants.CURRENT_MEMBER_ID, memberId) - filterChain.doFilter(request, response) + val memberId = jwtTokenProvider.getUserIdFromToken(token) + if (memberId == null) { + writeErrorResponse(response, ErrorCode.UNAUTHORIZED) + return + } + request.setAttribute(AuthConstants.CURRENT_MEMBER_ID, memberId) + filterChain.doFilter(request, response) + } catch (ex: ExpiredJwtException) { + writeErrorResponse(response, ErrorCode.EXPIRED_TOKEN) + } catch (ex: Exception) { + writeErrorResponse(response, ErrorCode.UNAUTHORIZED) + } } - private fun writeUnauthorizedResponse(response: HttpServletResponse) { + private fun writeErrorResponse(response: HttpServletResponse, errorCode: ErrorCode) { response.status = HttpServletResponse.SC_UNAUTHORIZED response.contentType = MediaType.APPLICATION_JSON_VALUE response.characterEncoding = "UTF-8" - val errorCode = ErrorCode.UNAUTHORIZED val errorResponse = mapOf( "code" to errorCode.code, "message" to errorCode.message, From 7b4ecb856b51fc08ce704d800b37c83ad0eb3fc6 Mon Sep 17 00:00:00 2001 From: hod Date: Thu, 5 Feb 2026 01:20:55 +0900 Subject: [PATCH 3/4] Fix formatting in production deployment configuration --- .github/workflows/prod-deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prod-deploy.yml b/.github/workflows/prod-deploy.yml index 4ef0872..d33f92b 100644 --- a/.github/workflows/prod-deploy.yml +++ b/.github/workflows/prod-deploy.yml @@ -95,5 +95,5 @@ jobs: --name moa-test-server \ --restart unless-stopped \ -p 8080:8080 \ - -e SPRING_PROFILES_ACTIVE=prod\ + -e SPRING_PROFILES_ACTIVE=prod \ -d godqhr721/moa_server:${{ needs.setup.outputs.docker_tag }} From 72932d568a55c7573c0cadf3faee0c2d23fdd7d0 Mon Sep 17 00:00:00 2001 From: hod Date: Thu, 5 Feb 2026 20:41:01 +0900 Subject: [PATCH 4/4] Fix container name in production deployment configuration --- .github/workflows/prod-deploy.yml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/.github/workflows/prod-deploy.yml b/.github/workflows/prod-deploy.yml index d33f92b..17e3e39 100644 --- a/.github/workflows/prod-deploy.yml +++ b/.github/workflows/prod-deploy.yml @@ -81,9 +81,9 @@ jobs: - name: Stop existing container and pull latest image run: | - if sudo docker inspect moa-test-server &>/dev/null; then - sudo docker stop moa-test-server || true - sudo docker rm -f moa-test-server || true + if sudo docker inspect moa-server &>/dev/null; then + sudo docker stop moa-server || true + sudo docker rm -f moa-server || true sudo docker image prune -af || true fi @@ -92,7 +92,8 @@ jobs: - name: Run container run: | sudo docker run -v /home/ubuntu/app/logs:/app/logs \ - --name moa-test-server \ + --name moa-server \ + --add-host host.docker.internal:host-gateway \ --restart unless-stopped \ -p 8080:8080 \ -e SPRING_PROFILES_ACTIVE=prod \