From f81cbac6522d16b646c321f3e76ce00272423982 Mon Sep 17 00:00:00 2001 From: skywalker Date: Tue, 20 Aug 2024 22:53:15 +0300 Subject: [PATCH] feat(openapi-generator): add openapi-generator for server and refactor get profile endpoint to use it --- server/.editorconfig | 3 ++ server/app/build.gradle.kts | 51 +++++++++++++++++++ .../main/kotlin/mu/muse/rest/EndpointURL.kt | 1 - .../muse/rest/profile/GetProfileEndpoint.kt | 23 ++++++--- .../main/kotlin/mu/muse/usecase/GetProfile.kt | 4 +- .../dto/{ProfileDetails.kt => Username.kt} | 6 +-- .../scenario/profile/GetProfileUseCase.kt | 8 +-- .../main/resources/openapi/get-profile.yml | 43 ++++++++++++++++ 8 files changed, 121 insertions(+), 18 deletions(-) rename server/app/src/main/kotlin/mu/muse/usecase/dto/{ProfileDetails.kt => Username.kt} (76%) create mode 100644 server/app/src/main/resources/openapi/get-profile.yml diff --git a/server/.editorconfig b/server/.editorconfig index 45f65c25..6b950e96 100644 --- a/server/.editorconfig +++ b/server/.editorconfig @@ -8,6 +8,9 @@ charset = utf-8 trim_trailing_whitespace = true insert_final_newline = true +[**openapi/*.yml] +indent_size = 2 + [*.{kt,kts}] ktlint_standard = disabled ktlint_standard_wrapping = enabled diff --git a/server/app/build.gradle.kts b/server/app/build.gradle.kts index f0f18858..549b8634 100644 --- a/server/app/build.gradle.kts +++ b/server/app/build.gradle.kts @@ -11,6 +11,54 @@ plugins { id("org.jlleitschuh.gradle.ktlint") version "12.1.1" id("io.gitlab.arturbosch.detekt") version "1.23.6" id("org.sonarqube") version "5.0.0.4638" + id("org.openapi.generator") version "7.8.0" +} + +openApiGenerate { + apiPackage = "mu.muse.rest.api" + modelPackage = "mu.muse.rest.dto" + generateApiTests = false + generateModelTests = false + generateApiDocumentation = false + generateModelDocumentation = false + inputSpecRootDirectory = "$projectDir/src/main/resources/openapi" + outputDir = "$buildDir/openapi" + + validateSpec = true +// library = "jvm-spring-restclient" + +// outputDir = "$buildDir/generated" + generatorName = "kotlin-spring" + configOptions = mapOf( + "idea" to "true", + "sourceFolder" to "src/main/kotlin", + "useSpringBoot3" to "true", + "serializationLibrary" to "jackson", + "useCoroutines" to "true", + "useTags" to "true", + "exceptionHandler" to "false", + "interfaceOnly" to "true", + "skipDefaultInterface" to "true", + "documentationProvider" to "none", + + ) +// generateApiTests = false +// generateModelTests = false +} + +//openApiValidate { +// inputSpec.set("$rootDir/petstore-v3.0-invalid.yaml") +//} +sourceSets { + main { + kotlin { + srcDir("$buildDir/openapi/src/main") + } + } +} + +tasks.compileKotlin { + dependsOn("openApiGenerate") } group = "mu.muse" @@ -55,6 +103,9 @@ dependencies { testRuntimeOnly("org.junit.platform:junit-platform-launcher") implementation(kotlin("stdlib-jdk8")) implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.17.2") + // https://mvnrepository.com/artifact/io.swagger.core.v3/swagger-annotations + implementation("io.swagger.core.v3:swagger-annotations:2.2.22") + implementation("jakarta.validation:jakarta.validation-api:3.1.0") } tasks.named("test") { diff --git a/server/app/src/main/kotlin/mu/muse/rest/EndpointURL.kt b/server/app/src/main/kotlin/mu/muse/rest/EndpointURL.kt index b689acac..cc979c4b 100644 --- a/server/app/src/main/kotlin/mu/muse/rest/EndpointURL.kt +++ b/server/app/src/main/kotlin/mu/muse/rest/EndpointURL.kt @@ -3,7 +3,6 @@ package mu.muse.rest const val AUTH_BASIC_LOGIN = "/api/auth/login" const val API = "/api" -const val API_PROFILE = "$API/profile" const val API_INSTRUMENTS = "$API/instruments" const val API_INSTRUMENT_BY_ID = "$API/instrument/{id:\\d+}" // id must be a number const val API_DELETE_INSTRUMENT_BY_ID = "$API/instrument/{id:\\d+}/delete" // id must be a number diff --git a/server/app/src/main/kotlin/mu/muse/rest/profile/GetProfileEndpoint.kt b/server/app/src/main/kotlin/mu/muse/rest/profile/GetProfileEndpoint.kt index 24eb1357..8f62ad78 100644 --- a/server/app/src/main/kotlin/mu/muse/rest/profile/GetProfileEndpoint.kt +++ b/server/app/src/main/kotlin/mu/muse/rest/profile/GetProfileEndpoint.kt @@ -1,19 +1,26 @@ package mu.muse.rest.profile import mu.muse.domain.user.Username -import mu.muse.rest.API_PROFILE +import mu.muse.rest.api.ProfileApi +import mu.muse.rest.dto.ProfileDetails import mu.muse.usecase.GetProfile -import mu.muse.usecase.dto.ProfileDetails -import org.springframework.web.bind.annotation.GetMapping +import org.springframework.http.ResponseEntity +import org.springframework.security.core.context.SecurityContextHolder import org.springframework.web.bind.annotation.RestController -import java.security.Principal @RestController -class GetProfileEndpoint(private val showProfile: GetProfile) { +class GetProfileEndpoint(private val showProfile: GetProfile) : ProfileApi { - @GetMapping(API_PROFILE) - fun getProfile(principal: Principal): ProfileDetails { + override fun getProfile(): ResponseEntity { + val principal = SecurityContextHolder.getContext().authentication val username = Username.from(principal.name) - return showProfile.execute(username) + val user = showProfile.execute(username) + return ResponseEntity.ok().body( + ProfileDetails( + username = user.username.toStringValue(), + role = user.role.toStringValue(), + fullName = user.fullName.toStringValue(), + ) + ) } } diff --git a/server/app/src/main/kotlin/mu/muse/usecase/GetProfile.kt b/server/app/src/main/kotlin/mu/muse/usecase/GetProfile.kt index 9ea3e5ea..2d4771da 100644 --- a/server/app/src/main/kotlin/mu/muse/usecase/GetProfile.kt +++ b/server/app/src/main/kotlin/mu/muse/usecase/GetProfile.kt @@ -1,11 +1,11 @@ package mu.muse.usecase import mu.muse.common.types.BusinessError +import mu.muse.domain.user.User import mu.muse.domain.user.Username -import mu.muse.usecase.dto.ProfileDetails fun interface GetProfile { - fun execute(username: Username): ProfileDetails + fun execute(username: Username): User } sealed class ShowProfileError : BusinessError { diff --git a/server/app/src/main/kotlin/mu/muse/usecase/dto/ProfileDetails.kt b/server/app/src/main/kotlin/mu/muse/usecase/dto/Username.kt similarity index 76% rename from server/app/src/main/kotlin/mu/muse/usecase/dto/ProfileDetails.kt rename to server/app/src/main/kotlin/mu/muse/usecase/dto/Username.kt index a446502f..fef86bcb 100644 --- a/server/app/src/main/kotlin/mu/muse/usecase/dto/ProfileDetails.kt +++ b/server/app/src/main/kotlin/mu/muse/usecase/dto/Username.kt @@ -2,14 +2,14 @@ package mu.muse.usecase.dto import mu.muse.domain.user.User -data class ProfileDetails( +data class Username( val username: String, val role: String, val fullName: String, ) { companion object { - fun from(user: User): ProfileDetails { - return ProfileDetails( + fun from(user: User): Username { + return Username( username = user.username.toStringValue(), role = user.role.toStringValue(), fullName = user.fullName.toStringValue(), diff --git a/server/app/src/main/kotlin/mu/muse/usecase/scenario/profile/GetProfileUseCase.kt b/server/app/src/main/kotlin/mu/muse/usecase/scenario/profile/GetProfileUseCase.kt index 9065645c..9d6de58c 100644 --- a/server/app/src/main/kotlin/mu/muse/usecase/scenario/profile/GetProfileUseCase.kt +++ b/server/app/src/main/kotlin/mu/muse/usecase/scenario/profile/GetProfileUseCase.kt @@ -1,15 +1,15 @@ package mu.muse.usecase.scenario.profile +import mu.muse.domain.user.User import mu.muse.domain.user.Username import mu.muse.usecase.GetProfile import mu.muse.usecase.ShowProfileError import mu.muse.usecase.access.user.UserExtractor -import mu.muse.usecase.dto.ProfileDetails class GetProfileUseCase(private val userExtractor: UserExtractor) : GetProfile { - override fun execute(username: Username): ProfileDetails { - val user = userExtractor.findByUsername(username) ?: throw ShowProfileError.UserNotFound(username) - return ProfileDetails.from(user) + override fun execute(username: Username): User { + return userExtractor.findByUsername(username) + ?: throw ShowProfileError.UserNotFound(username) } } diff --git a/server/app/src/main/resources/openapi/get-profile.yml b/server/app/src/main/resources/openapi/get-profile.yml new file mode 100644 index 00000000..60ab1d92 --- /dev/null +++ b/server/app/src/main/resources/openapi/get-profile.yml @@ -0,0 +1,43 @@ +openapi: "3.0.0" + +info: + version: 1.0.0 + title: Get Profile +servers: + - url: http://localhost:8080/ + +paths: + /api/profile: + get: + summary: Get Profile Info + operationId: getProfile + tags: + - profile + responses: + "200": + description: Profile Details + content: + application/json: + schema: + $ref: "#/components/schemas/ProfileDetails" + default: + description: server error + content: + application/json: + schema: + $ref: "#/components/schemas/ServerError" + +components: + schemas: + ProfileDetails: + type: object + required: [ username, role, fullName ] + properties: + username: + type: string + role: + type: string + fullName: + type: string + ServerError: + type: object