Skip to content

Commit

Permalink
feat(openapi-generator): add openapi-generator for server and refacto…
Browse files Browse the repository at this point in the history
…r get profile endpoint to use it
  • Loading branch information
bas-kirill committed Aug 20, 2024
1 parent d4090f2 commit f81cbac
Show file tree
Hide file tree
Showing 8 changed files with 121 additions and 18 deletions.
3 changes: 3 additions & 0 deletions server/.editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
51 changes: 51 additions & 0 deletions server/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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>("test") {
Expand Down
1 change: 0 additions & 1 deletion server/app/src/main/kotlin/mu/muse/rest/EndpointURL.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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<ProfileDetails> {
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(),
)
)
}
}
4 changes: 2 additions & 2 deletions server/app/src/main/kotlin/mu/muse/usecase/GetProfile.kt
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
}
}
43 changes: 43 additions & 0 deletions server/app/src/main/resources/openapi/get-profile.yml
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit f81cbac

Please sign in to comment.