mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-05-12 20:50:55 +00:00
add ktor2 library option to kotlin server generator
This commit is contained in:
parent
b218e238f4
commit
24ddb33d0b
@ -41,6 +41,7 @@ jobs:
|
|||||||
- samples/server/petstore/kotlin-server/javalin
|
- samples/server/petstore/kotlin-server/javalin
|
||||||
- samples/server/petstore/kotlin-server/javalin-6
|
- samples/server/petstore/kotlin-server/javalin-6
|
||||||
- samples/server/petstore/kotlin-server/ktor
|
- samples/server/petstore/kotlin-server/ktor
|
||||||
|
- samples/server/petstore/kotlin-server/ktor2
|
||||||
# comment out due to gradle build failure
|
# comment out due to gradle build failure
|
||||||
# - samples/server/petstore/kotlin-spring-default/
|
# - samples/server/petstore/kotlin-spring-default/
|
||||||
steps:
|
steps:
|
||||||
|
@ -23,6 +23,7 @@ jobs:
|
|||||||
sample:
|
sample:
|
||||||
- samples/server/petstore/kotlin-server/javalin-6
|
- samples/server/petstore/kotlin-server/javalin-6
|
||||||
- samples/server/petstore/kotlin-server/ktor
|
- samples/server/petstore/kotlin-server/ktor
|
||||||
|
- samples/server/petstore/kotlin-server/ktor2
|
||||||
- samples/server/petstore/kotlin-server-required-and-nullable-properties
|
- samples/server/petstore/kotlin-server-required-and-nullable-properties
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
1
.github/workflows/samples-kotlin-server.yaml
vendored
1
.github/workflows/samples-kotlin-server.yaml
vendored
@ -38,6 +38,7 @@ jobs:
|
|||||||
- samples/server/petstore/kotlin-springboot-source-swagger2
|
- samples/server/petstore/kotlin-springboot-source-swagger2
|
||||||
- samples/server/petstore/kotlin-springboot-springfox
|
- samples/server/petstore/kotlin-springboot-springfox
|
||||||
- samples/server/petstore/kotlin-server/ktor
|
- samples/server/petstore/kotlin-server/ktor
|
||||||
|
- samples/server/petstore/kotlin-server/ktor2
|
||||||
- samples/server/petstore/kotlin-server/jaxrs-spec
|
- samples/server/petstore/kotlin-server/jaxrs-spec
|
||||||
- samples/server/petstore/kotlin-server/jaxrs-spec-mutiny
|
- samples/server/petstore/kotlin-server/jaxrs-spec-mutiny
|
||||||
- samples/server/petstore/kotlin-server-modelMutable
|
- samples/server/petstore/kotlin-server-modelMutable
|
||||||
|
8
bin/configs/kotlin-server-ktor2.yaml
Normal file
8
bin/configs/kotlin-server-ktor2.yaml
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
generatorName: kotlin-server
|
||||||
|
outputDir: samples/server/petstore/kotlin-server/ktor2
|
||||||
|
library: ktor2
|
||||||
|
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
|
||||||
|
templateDir: modules/openapi-generator/src/main/resources/kotlin-server
|
||||||
|
additionalProperties:
|
||||||
|
hideGenerationTimestamp: "true"
|
||||||
|
serializableModel: "true"
|
@ -32,7 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|
|||||||
|featureResources|Generates routes in a typed way, for both: constructing URLs and reading the parameters.| |true|
|
|featureResources|Generates routes in a typed way, for both: constructing URLs and reading the parameters.| |true|
|
||||||
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
|
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
|
||||||
|interfaceOnly|Whether to generate only API interface stubs without the server files. This option is currently supported only when using jaxrs-spec library.| |false|
|
|interfaceOnly|Whether to generate only API interface stubs without the server files. This option is currently supported only when using jaxrs-spec library.| |false|
|
||||||
|library|library template (sub-template)|<dl><dt>**ktor**</dt><dd>ktor framework</dd><dt>**jaxrs-spec**</dt><dd>JAX-RS spec only</dd><dt>**javalin5**</dt><dd>Javalin 5</dd><dt>**javalin6**</dt><dd>Javalin 6</dd></dl>|ktor|
|
|library|library template (sub-template)|<dl><dt>**ktor**</dt><dd>ktor framework</dd><dt>**ktor2**</dt><dd>ktor (2.x) framework</dd><dt>**jaxrs-spec**</dt><dd>JAX-RS spec only</dd><dt>**javalin5**</dt><dd>Javalin 5</dd><dt>**javalin6**</dt><dd>Javalin 6</dd></dl>|ktor|
|
||||||
|modelMutable|Create mutable models| |false|
|
|modelMutable|Create mutable models| |false|
|
||||||
|omitGradleWrapper|Whether to omit Gradle wrapper for creating a sub project.| |false|
|
|omitGradleWrapper|Whether to omit Gradle wrapper for creating a sub project.| |false|
|
||||||
|packageName|Generated artifact package name.| |org.openapitools.server|
|
|packageName|Generated artifact package name.| |org.openapitools.server|
|
||||||
|
@ -73,6 +73,16 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen implements BeanVa
|
|||||||
Constants.METRICS,
|
Constants.METRICS,
|
||||||
Constants.OMIT_GRADLE_WRAPPER
|
Constants.OMIT_GRADLE_WRAPPER
|
||||||
))
|
))
|
||||||
|
.put(Constants.KTOR2, Arrays.asList(
|
||||||
|
Constants.AUTOMATIC_HEAD_REQUESTS,
|
||||||
|
Constants.CONDITIONAL_HEADERS,
|
||||||
|
Constants.HSTS,
|
||||||
|
Constants.CORS,
|
||||||
|
Constants.COMPRESSION,
|
||||||
|
Constants.RESOURCES,
|
||||||
|
Constants.METRICS,
|
||||||
|
Constants.OMIT_GRADLE_WRAPPER
|
||||||
|
))
|
||||||
.put(Constants.JAXRS_SPEC, Arrays.asList(
|
.put(Constants.JAXRS_SPEC, Arrays.asList(
|
||||||
USE_BEANVALIDATION,
|
USE_BEANVALIDATION,
|
||||||
Constants.USE_COROUTINES,
|
Constants.USE_COROUTINES,
|
||||||
@ -127,6 +137,7 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen implements BeanVa
|
|||||||
modelPackage = packageName + ".models";
|
modelPackage = packageName + ".models";
|
||||||
|
|
||||||
supportedLibraries.put(Constants.KTOR, "ktor framework");
|
supportedLibraries.put(Constants.KTOR, "ktor framework");
|
||||||
|
supportedLibraries.put(Constants.KTOR2, "ktor (2.x) framework");
|
||||||
supportedLibraries.put(Constants.JAXRS_SPEC, "JAX-RS spec only");
|
supportedLibraries.put(Constants.JAXRS_SPEC, "JAX-RS spec only");
|
||||||
supportedLibraries.put(Constants.JAVALIN5, "Javalin 5");
|
supportedLibraries.put(Constants.JAVALIN5, "Javalin 5");
|
||||||
supportedLibraries.put(Constants.JAVALIN6, "Javalin 6");
|
supportedLibraries.put(Constants.JAVALIN6, "Javalin 6");
|
||||||
@ -323,6 +334,7 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen implements BeanVa
|
|||||||
|
|
||||||
public static class Constants {
|
public static class Constants {
|
||||||
public final static String KTOR = "ktor";
|
public final static String KTOR = "ktor";
|
||||||
|
public final static String KTOR2 = "ktor2";
|
||||||
public final static String JAXRS_SPEC = "jaxrs-spec";
|
public final static String JAXRS_SPEC = "jaxrs-spec";
|
||||||
|
|
||||||
public final static String JAVALIN5 = "javalin5";
|
public final static String JAVALIN5 = "javalin5";
|
||||||
@ -419,6 +431,6 @@ public class KotlinServerCodegen extends AbstractKotlinCodegen implements BeanVa
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isKtor() {
|
private boolean isKtor() {
|
||||||
return Constants.KTOR.equals(library);
|
return Constants.KTOR.equals(library) || Constants.KTOR2.equals(library);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
102
modules/openapi-generator/src/main/resources/kotlin-server/libraries/ktor2/ApiKeyAuth.kt.mustache
vendored
Normal file
102
modules/openapi-generator/src/main/resources/kotlin-server/libraries/ktor2/ApiKeyAuth.kt.mustache
vendored
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
package org.openapitools.server.infrastructure
|
||||||
|
|
||||||
|
import io.ktor.http.auth.*
|
||||||
|
import io.ktor.server.application.*
|
||||||
|
import io.ktor.server.auth.*
|
||||||
|
import io.ktor.server.request.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
|
|
||||||
|
enum class ApiKeyLocation(val location: String) {
|
||||||
|
QUERY("query"),
|
||||||
|
HEADER("header")
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ApiKeyCredential(val value: String) : Credential
|
||||||
|
data class ApiPrincipal(val apiKeyCredential: ApiKeyCredential?) : Principal
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an Api Key authentication provider
|
||||||
|
*/
|
||||||
|
class ApiKeyAuthenticationProvider(configuration: Configuration) : AuthenticationProvider(configuration) {
|
||||||
|
|
||||||
|
private val authenticationFunction = configuration.authenticationFunction
|
||||||
|
|
||||||
|
private val apiKeyName: String = configuration.apiKeyName
|
||||||
|
|
||||||
|
private val apiKeyLocation: ApiKeyLocation = configuration.apiKeyLocation
|
||||||
|
|
||||||
|
override suspend fun onAuthenticate(context: AuthenticationContext) {
|
||||||
|
val call = context.call
|
||||||
|
val credentials = call.request.apiKeyAuthenticationCredentials(apiKeyName, apiKeyLocation)
|
||||||
|
val principal = credentials?.let { authenticationFunction.invoke(call, it) }
|
||||||
|
|
||||||
|
val cause = when {
|
||||||
|
credentials == null -> AuthenticationFailedCause.NoCredentials
|
||||||
|
principal == null -> AuthenticationFailedCause.InvalidCredentials
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cause != null) {
|
||||||
|
context.challenge(apiKeyName, cause) { challenge, call ->
|
||||||
|
call.respond(
|
||||||
|
UnauthorizedResponse(
|
||||||
|
HttpAuthHeader.Parameterized(
|
||||||
|
"API_KEY",
|
||||||
|
mapOf("key" to apiKeyName),
|
||||||
|
HeaderValueEncoding.QUOTED_ALWAYS
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
challenge.complete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (principal != null) {
|
||||||
|
context.principal(principal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Configuration internal constructor(name: String?) : Config(name) {
|
||||||
|
|
||||||
|
internal var authenticationFunction: suspend ApplicationCall.(ApiKeyCredential) -> Principal? = {
|
||||||
|
throw NotImplementedError(
|
||||||
|
"Api Key auth validate function is not specified. Use apiKeyAuth { validate { ... } } to fix."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var apiKeyName: String = ""
|
||||||
|
|
||||||
|
var apiKeyLocation: ApiKeyLocation = ApiKeyLocation.QUERY
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a validation function that will check given [ApiKeyCredential] instance and return [Principal],
|
||||||
|
* or null if credential does not correspond to an authenticated principal
|
||||||
|
*/
|
||||||
|
fun validate(body: suspend ApplicationCall.(ApiKeyCredential) -> Principal?) {
|
||||||
|
authenticationFunction = body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AuthenticationConfig.apiKeyAuth(
|
||||||
|
name: String? = null,
|
||||||
|
configure: ApiKeyAuthenticationProvider.Configuration.() -> Unit
|
||||||
|
) {
|
||||||
|
val configuration = ApiKeyAuthenticationProvider.Configuration(name).apply(configure)
|
||||||
|
val provider = ApiKeyAuthenticationProvider(configuration)
|
||||||
|
register(provider)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApplicationRequest.apiKeyAuthenticationCredentials(
|
||||||
|
apiKeyName: String,
|
||||||
|
apiKeyLocation: ApiKeyLocation
|
||||||
|
): ApiKeyCredential? {
|
||||||
|
val value: String? = when (apiKeyLocation) {
|
||||||
|
ApiKeyLocation.QUERY -> this.queryParameters[apiKeyName]
|
||||||
|
ApiKeyLocation.HEADER -> this.headers[apiKeyName]
|
||||||
|
}
|
||||||
|
return when (value) {
|
||||||
|
null -> null
|
||||||
|
else -> ApiKeyCredential(value)
|
||||||
|
}
|
||||||
|
}
|
139
modules/openapi-generator/src/main/resources/kotlin-server/libraries/ktor2/AppMain.kt.mustache
vendored
Normal file
139
modules/openapi-generator/src/main/resources/kotlin-server/libraries/ktor2/AppMain.kt.mustache
vendored
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
package {{packageName}}
|
||||||
|
|
||||||
|
import io.ktor.server.application.*
|
||||||
|
import io.ktor.serialization.gson.*
|
||||||
|
import io.ktor.http.*
|
||||||
|
{{#featureResources}}
|
||||||
|
import io.ktor.server.resources.*
|
||||||
|
{{/featureResources}}
|
||||||
|
{{#featureCORS}}
|
||||||
|
import io.ktor.server.plugins.cors.routing.*
|
||||||
|
{{/featureCORS}}
|
||||||
|
{{#featureAutoHead}}
|
||||||
|
import io.ktor.server.plugins.autohead.*
|
||||||
|
{{/featureAutoHead}}
|
||||||
|
{{#featureConditionalHeaders}}
|
||||||
|
import io.ktor.server.plugins.conditionalheaders.*
|
||||||
|
{{/featureConditionalHeaders}}
|
||||||
|
{{#featureCompression}}
|
||||||
|
import io.ktor.server.plugins.compression.*
|
||||||
|
{{/featureCompression}}
|
||||||
|
import io.ktor.server.plugins.contentnegotiation.*
|
||||||
|
import io.ktor.server.plugins.defaultheaders.*
|
||||||
|
{{#featureHSTS}}
|
||||||
|
import io.ktor.server.plugins.hsts.*
|
||||||
|
{{/featureHSTS}}
|
||||||
|
{{#featureMetrics}}
|
||||||
|
import com.codahale.metrics.Slf4jReporter
|
||||||
|
import io.ktor.server.metrics.dropwizard.*
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
{{/featureMetrics}}
|
||||||
|
import io.ktor.server.routing.*
|
||||||
|
{{#hasAuthMethods}}
|
||||||
|
import com.typesafe.config.ConfigFactory
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.engine.apache.Apache
|
||||||
|
import io.ktor.server.config.HoconApplicationConfig
|
||||||
|
import io.ktor.server.auth.*
|
||||||
|
import org.openapitools.server.infrastructure.*
|
||||||
|
{{/hasAuthMethods}}
|
||||||
|
{{#generateApis}}{{#apiInfo}}{{#apis}}import {{apiPackage}}.{{classname}}
|
||||||
|
{{/apis}}{{/apiInfo}}{{/generateApis}}
|
||||||
|
|
||||||
|
{{#hasAuthMethods}}
|
||||||
|
internal val settings = HoconApplicationConfig(ConfigFactory.defaultApplication(HTTP::class.java.classLoader))
|
||||||
|
|
||||||
|
object HTTP {
|
||||||
|
val client = HttpClient(Apache)
|
||||||
|
}
|
||||||
|
{{/hasAuthMethods}}
|
||||||
|
|
||||||
|
fun Application.main() {
|
||||||
|
install(DefaultHeaders)
|
||||||
|
{{#featureMetrics}}
|
||||||
|
install(DropwizardMetrics) {
|
||||||
|
val reporter = Slf4jReporter.forRegistry(registry)
|
||||||
|
.outputTo(this@main.log)
|
||||||
|
.convertRatesTo(TimeUnit.SECONDS)
|
||||||
|
.convertDurationsTo(TimeUnit.MILLISECONDS)
|
||||||
|
.build()
|
||||||
|
reporter.start(10, TimeUnit.SECONDS)
|
||||||
|
}
|
||||||
|
{{/featureMetrics}}
|
||||||
|
{{#generateApis}}
|
||||||
|
install(ContentNegotiation) {
|
||||||
|
register(ContentType.Application.Json, GsonConverter())
|
||||||
|
}
|
||||||
|
{{#featureAutoHead}}
|
||||||
|
install(AutoHeadResponse) // see https://ktor.io/docs/autoheadresponse.html
|
||||||
|
{{/featureAutoHead}}
|
||||||
|
{{#featureConditionalHeaders}}
|
||||||
|
install(ConditionalHeaders) // see https://ktor.io/docs/conditional-headers.html
|
||||||
|
{{/featureConditionalHeaders}}
|
||||||
|
{{#featureCompression}}
|
||||||
|
install(Compression, ApplicationCompressionConfiguration()) // see https://ktor.io/docs/compression.html
|
||||||
|
{{/featureCompression}}
|
||||||
|
{{#featureCORS}}
|
||||||
|
install(CORS, ApplicationCORSConfiguration()) // see https://ktor.io/docs/cors.html
|
||||||
|
{{/featureCORS}}
|
||||||
|
{{#featureHSTS}}
|
||||||
|
install(HSTS, ApplicationHstsConfiguration()) // see https://ktor.io/docs/hsts.html
|
||||||
|
{{/featureHSTS}}
|
||||||
|
{{#featureResources}}
|
||||||
|
install(Resources)
|
||||||
|
{{/featureResources}}
|
||||||
|
{{#hasAuthMethods}}
|
||||||
|
install(Authentication) {
|
||||||
|
{{#authMethods}}
|
||||||
|
{{#isBasicBasic}}
|
||||||
|
basic("{{{name}}}") {
|
||||||
|
validate { credentials ->
|
||||||
|
// TODO: "Apply your basic authentication functionality."
|
||||||
|
// Accessible in-method via call.principal<UserIdPrincipal>()
|
||||||
|
if (credentials.name == "Swagger" && "Codegen" == credentials.password) {
|
||||||
|
UserIdPrincipal(credentials.name)
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{/isBasicBasic}}
|
||||||
|
{{#isApiKey}}
|
||||||
|
// "Implement API key auth ({{{name}}}) for parameter name '{{{keyParamName}}}'."
|
||||||
|
apiKeyAuth("{{{name}}}") {
|
||||||
|
validate { apikeyCredential: ApiKeyCredential ->
|
||||||
|
when {
|
||||||
|
apikeyCredential.value == "keyboardcat" -> ApiPrincipal(apikeyCredential)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{/isApiKey}}
|
||||||
|
{{#isOAuth}}
|
||||||
|
{{#bodyAllowed}}
|
||||||
|
{{/bodyAllowed}}
|
||||||
|
{{^bodyAllowed}}
|
||||||
|
oauth("{{name}}") {
|
||||||
|
client = HttpClient(Apache)
|
||||||
|
providerLookup = { applicationAuthProvider(this@main.environment.config) }
|
||||||
|
urlProvider = { _ ->
|
||||||
|
// TODO: define a callback url here.
|
||||||
|
"/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{/bodyAllowed}}
|
||||||
|
{{/isOAuth}}
|
||||||
|
{{/authMethods}}
|
||||||
|
}
|
||||||
|
{{/hasAuthMethods}}
|
||||||
|
install(Routing) {
|
||||||
|
{{#apiInfo}}
|
||||||
|
{{#apis}}
|
||||||
|
{{#operations}}
|
||||||
|
{{classname}}()
|
||||||
|
{{/operations}}
|
||||||
|
{{/apis}}
|
||||||
|
{{/apiInfo}}
|
||||||
|
}
|
||||||
|
|
||||||
|
{{/generateApis}}
|
||||||
|
}
|
@ -0,0 +1,98 @@
|
|||||||
|
package {{packageName}}
|
||||||
|
|
||||||
|
// Use this file to hold package-level internal functions that return receiver object passed to the `install` method.
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.server.auth.*
|
||||||
|
import io.ktor.server.config.*
|
||||||
|
import io.ktor.util.*
|
||||||
|
import java.time.Duration
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
{{#featureCORS}}
|
||||||
|
import io.ktor.server.plugins.cors.routing.*
|
||||||
|
import io.ktor.server.plugins.cors.*
|
||||||
|
{{/featureCORS}}
|
||||||
|
{{#featureCompression}}
|
||||||
|
import io.ktor.server.plugins.compression.*
|
||||||
|
{{/featureCompression}}
|
||||||
|
{{#featureHSTS}}
|
||||||
|
import io.ktor.server.plugins.hsts.*
|
||||||
|
{{/featureHSTS}}
|
||||||
|
|
||||||
|
{{#featureCORS}}
|
||||||
|
/**
|
||||||
|
* Application block for [CORS] configuration.
|
||||||
|
*
|
||||||
|
* This file may be excluded in .openapi-generator-ignore,
|
||||||
|
* and application-specific configuration can be applied in this function.
|
||||||
|
*
|
||||||
|
* See http://ktor.io/features/cors.html
|
||||||
|
*/
|
||||||
|
internal fun ApplicationCORSConfiguration(): CORSConfig.() -> Unit {
|
||||||
|
return {
|
||||||
|
// method(HttpMethod.Options)
|
||||||
|
// header(HttpHeaders.XForwardedProto)
|
||||||
|
// anyHost()
|
||||||
|
// host("my-host")
|
||||||
|
// host("my-host:80")
|
||||||
|
// host("my-host", subDomains = listOf("www"))
|
||||||
|
// host("my-host", schemes = listOf("http", "https"))
|
||||||
|
// allowCredentials = true
|
||||||
|
// maxAge = Duration.ofDays(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{/featureCORS}}
|
||||||
|
{{#featureHSTS}}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application block for [HSTS] configuration.
|
||||||
|
*
|
||||||
|
* This file may be excluded in .openapi-generator-ignore,
|
||||||
|
* and application-specific configuration can be applied in this function.
|
||||||
|
*
|
||||||
|
* See http://ktor.io/features/hsts.html
|
||||||
|
*/
|
||||||
|
internal fun ApplicationHstsConfiguration(): HSTSConfig.() -> Unit {
|
||||||
|
return {
|
||||||
|
maxAgeInSeconds = TimeUnit.DAYS.toSeconds(365)
|
||||||
|
includeSubDomains = true
|
||||||
|
preload = false
|
||||||
|
|
||||||
|
// You may also apply any custom directives supported by specific user-agent. For example:
|
||||||
|
// customDirectives.put("redirectHttpToHttps", "false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{/featureHSTS}}
|
||||||
|
{{#featureCompression}}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application block for [Compression] configuration.
|
||||||
|
*
|
||||||
|
* This file may be excluded in .openapi-generator-ignore,
|
||||||
|
* and application-specific configuration can be applied in this function.
|
||||||
|
*
|
||||||
|
* See http://ktor.io/features/compression.html
|
||||||
|
*/
|
||||||
|
internal fun ApplicationCompressionConfiguration(): CompressionConfig.() -> Unit {
|
||||||
|
return {
|
||||||
|
gzip {
|
||||||
|
priority = 1.0
|
||||||
|
}
|
||||||
|
deflate {
|
||||||
|
priority = 10.0
|
||||||
|
minimumSize(1024) // condition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{/featureCompression}}
|
||||||
|
|
||||||
|
// Defines authentication mechanisms used throughout the application.
|
||||||
|
fun applicationAuthProvider(config: ApplicationConfig): OAuthServerSettings =
|
||||||
|
OAuthServerSettings.OAuth2ServerSettings(
|
||||||
|
name = "petstore_auth",
|
||||||
|
authorizeUrl = "http://petstore.swagger.io/api/oauth/dialog",
|
||||||
|
accessTokenUrl = "",
|
||||||
|
requestMethod = HttpMethod.Get,
|
||||||
|
clientId = config.property("auth.oauth.petstore_auth.clientId").getString(),
|
||||||
|
clientSecret = config.property("auth.oauth.petstore_auth.clientSecret").getString(),
|
||||||
|
defaultScopes = listOf("write:pets", "read:pets")
|
||||||
|
)
|
@ -0,0 +1,7 @@
|
|||||||
|
FROM openjdk:8-jre-alpine
|
||||||
|
|
||||||
|
COPY ./build/libs/{{artifactId}}.jar /root/{{artifactId}}.jar
|
||||||
|
|
||||||
|
WORKDIR /root
|
||||||
|
|
||||||
|
CMD ["java", "-server", "-Xms4g", "-Xmx4g", "-XX:+UseG1GC", "-XX:MaxGCPauseMillis=100", "-XX:+UseStringDeduplication", "-jar", "{{artifactId}}.jar"]
|
31
modules/openapi-generator/src/main/resources/kotlin-server/libraries/ktor2/Paths.kt.mustache
vendored
Normal file
31
modules/openapi-generator/src/main/resources/kotlin-server/libraries/ktor2/Paths.kt.mustache
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{{>licenseInfo}}
|
||||||
|
package {{packageName}}
|
||||||
|
|
||||||
|
import io.ktor.resources.*
|
||||||
|
import kotlinx.serialization.*
|
||||||
|
import {{packageName}}.models.*
|
||||||
|
{{#imports}}import {{import}}
|
||||||
|
{{/imports}}
|
||||||
|
|
||||||
|
{{#apiInfo}}
|
||||||
|
object Paths {
|
||||||
|
{{#apis}}
|
||||||
|
{{#operations}}
|
||||||
|
{{#operation}}
|
||||||
|
/**{{#summary}}
|
||||||
|
* {{.}}{{/summary}}
|
||||||
|
* {{unescapedNotes}}
|
||||||
|
{{#allParams}}* @param {{paramName}} {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}
|
||||||
|
{{/allParams}}*/
|
||||||
|
{{#hasParams}}
|
||||||
|
@Serializable @Resource("{{{path}}}") class {{operationId}}({{#allParams}}val {{paramName}}: {{{dataType}}}{{^required}}? = null{{/required}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}})
|
||||||
|
{{/hasParams}}
|
||||||
|
{{^hasParams}}
|
||||||
|
@Serializable @Resource("{{{path}}}") class {{operationId}}
|
||||||
|
{{/hasParams}}
|
||||||
|
|
||||||
|
{{/operation}}
|
||||||
|
{{/operations}}
|
||||||
|
{{/apis}}
|
||||||
|
}
|
||||||
|
{{/apiInfo}}
|
99
modules/openapi-generator/src/main/resources/kotlin-server/libraries/ktor2/README.mustache
vendored
Normal file
99
modules/openapi-generator/src/main/resources/kotlin-server/libraries/ktor2/README.mustache
vendored
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
# {{packageName}} - Kotlin Server library for {{appName}}
|
||||||
|
|
||||||
|
{{#unescapedAppDescription}}
|
||||||
|
{{.}}
|
||||||
|
{{/unescapedAppDescription}}
|
||||||
|
|
||||||
|
Generated by OpenAPI Generator {{generatorVersion}}{{^hideGenerationTimestamp}} ({{generatedDate}}){{/hideGenerationTimestamp}}.
|
||||||
|
|
||||||
|
## Requires
|
||||||
|
|
||||||
|
* Kotlin 2.0.20
|
||||||
|
* Gradle 8.10.2
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
First, create the gradle wrapper script:
|
||||||
|
|
||||||
|
```
|
||||||
|
gradle wrapper
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, run:
|
||||||
|
|
||||||
|
```
|
||||||
|
./gradlew check assemble
|
||||||
|
```
|
||||||
|
|
||||||
|
This runs all tests and packages the library.
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
The server builds as a fat jar with a main entrypoint. To start the service, run `java -jar ./build/libs/{{artifactId}}.jar`.
|
||||||
|
|
||||||
|
You may also run in docker:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker build -t {{artifactId}} .
|
||||||
|
docker run -p 8080:8080 {{artifactId}}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Features/Implementation Notes
|
||||||
|
|
||||||
|
* Supports JSON inputs/outputs, File inputs, and Form inputs (see ktor documentation for more info).
|
||||||
|
* ~Supports collection formats for query parameters: csv, tsv, ssv, pipes.~
|
||||||
|
* Some Kotlin and Java types are fully qualified to avoid conflicts with types defined in OpenAPI definitions.
|
||||||
|
|
||||||
|
{{#generateApiDocs}}
|
||||||
|
<a id="documentation-for-api-endpoints"></a>
|
||||||
|
## Documentation for API Endpoints
|
||||||
|
|
||||||
|
All URIs are relative to *{{{basePath}}}*
|
||||||
|
|
||||||
|
Class | Method | HTTP request | Description
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}*{{classname}}* | [**{{operationId}}**]({{apiDocPath}}{{classname}}.md#{{operationIdLowerCase}}) | **{{httpMethod}}** {{path}} | {{{summary}}}
|
||||||
|
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
|
||||||
|
{{/generateApiDocs}}
|
||||||
|
|
||||||
|
{{#generateModelDocs}}
|
||||||
|
<a id="documentation-for-models"></a>
|
||||||
|
## Documentation for Models
|
||||||
|
|
||||||
|
{{#modelPackage}}
|
||||||
|
{{#models}}{{#model}} - [{{{modelPackage}}}.{{{classname}}}]({{modelDocPath}}{{{classname}}}.md)
|
||||||
|
{{/model}}{{/models}}
|
||||||
|
{{/modelPackage}}
|
||||||
|
{{^modelPackage}}
|
||||||
|
No model defined in this package
|
||||||
|
{{/modelPackage}}
|
||||||
|
{{/generateModelDocs}}
|
||||||
|
|
||||||
|
<a id="documentation-for-authorization"></a>
|
||||||
|
## Documentation for Authorization
|
||||||
|
|
||||||
|
{{^authMethods}}Endpoints do not require authorization.{{/authMethods}}
|
||||||
|
{{#hasAuthMethods}}Authentication schemes defined for the API:{{/hasAuthMethods}}
|
||||||
|
{{#authMethods}}
|
||||||
|
<a id="{{name}}"></a>
|
||||||
|
### {{name}}
|
||||||
|
|
||||||
|
{{#isApiKey}}- **Type**: API key
|
||||||
|
- **API key parameter name**: {{keyParamName}}
|
||||||
|
- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}}
|
||||||
|
{{/isApiKey}}
|
||||||
|
{{#isBasicBasic}}- **Type**: HTTP basic authentication
|
||||||
|
{{/isBasicBasic}}
|
||||||
|
{{#isBasicBearer}}- **Type**: HTTP Bearer Token authentication{{#bearerFormat}} ({{{.}}}){{/bearerFormat}}
|
||||||
|
{{/isBasicBearer}}
|
||||||
|
{{#isHttpSignature}}- **Type**: HTTP signature authentication
|
||||||
|
{{/isHttpSignature}}
|
||||||
|
{{#isOAuth}}- **Type**: OAuth
|
||||||
|
- **Flow**: {{flow}}
|
||||||
|
- **Authorization URL**: {{authorizationUrl}}
|
||||||
|
- **Scopes**: {{^scopes}}N/A{{/scopes}}
|
||||||
|
{{#scopes}} - {{scope}}: {{description}}
|
||||||
|
{{/scopes}}
|
||||||
|
{{/isOAuth}}
|
||||||
|
|
||||||
|
{{/authMethods}}
|
21
modules/openapi-generator/src/main/resources/kotlin-server/libraries/ktor2/_api_body.mustache
vendored
Normal file
21
modules/openapi-generator/src/main/resources/kotlin-server/libraries/ktor2/_api_body.mustache
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{{#hasAuthMethods}}
|
||||||
|
{{>libraries/ktor/_principal}}
|
||||||
|
{{#examples}}
|
||||||
|
{{#-first}}
|
||||||
|
{{#lambda.indented}}{{>_response}}{{/lambda.indented}}
|
||||||
|
{{/-first}}
|
||||||
|
{{/examples}}
|
||||||
|
{{^examples}}
|
||||||
|
call.respond(HttpStatusCode.NotImplemented)
|
||||||
|
{{/examples}}
|
||||||
|
{{/hasAuthMethods}}
|
||||||
|
{{^hasAuthMethods}}
|
||||||
|
{{#examples}}
|
||||||
|
{{#-first}}
|
||||||
|
{{>libraries/ktor/_response}}
|
||||||
|
{{/-first}}
|
||||||
|
{{/examples}}
|
||||||
|
{{^examples}}
|
||||||
|
call.respond(HttpStatusCode.NotImplemented)
|
||||||
|
{{/examples}}
|
||||||
|
{{/hasAuthMethods}}
|
11
modules/openapi-generator/src/main/resources/kotlin-server/libraries/ktor2/_principal.mustache
vendored
Normal file
11
modules/openapi-generator/src/main/resources/kotlin-server/libraries/ktor2/_principal.mustache
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{{#authMethods}}
|
||||||
|
{{#isBasicBasic}}
|
||||||
|
val principal = call.authentication.principal<UserIdPrincipal>()!!
|
||||||
|
{{/isBasicBasic}}{{^isBasicBasic}}{{#isApiKey}}
|
||||||
|
val principal = call.authentication.principal<ApiPrincipal>()!!
|
||||||
|
{{/isApiKey}}{{^isApiKey}}{{#isOAuth}}
|
||||||
|
val principal = call.authentication.principal<OAuthAccessTokenResponse>()!!
|
||||||
|
{{/isOAuth}}{{^isOAuth}}
|
||||||
|
val principal = null!!
|
||||||
|
{{/isOAuth}}{{/isApiKey}}{{/isBasicBasic}}
|
||||||
|
{{/authMethods}}
|
@ -0,0 +1,8 @@
|
|||||||
|
val exampleContentType = "{{{contentType}}}"
|
||||||
|
val exampleContentString = """{{&example}}"""
|
||||||
|
|
||||||
|
when (exampleContentType) {
|
||||||
|
"application/json" -> call.respond(gson.fromJson(exampleContentString, empty::class.java))
|
||||||
|
"application/xml" -> call.respondText(exampleContentString, ContentType.Text.Xml)
|
||||||
|
else -> call.respondText(exampleContentString)
|
||||||
|
}
|
53
modules/openapi-generator/src/main/resources/kotlin-server/libraries/ktor2/api.mustache
vendored
Normal file
53
modules/openapi-generator/src/main/resources/kotlin-server/libraries/ktor2/api.mustache
vendored
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
{{>licenseInfo}}
|
||||||
|
package {{apiPackage}}
|
||||||
|
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.server.application.*
|
||||||
|
import io.ktor.server.auth.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
|
{{#featureResources}}
|
||||||
|
import {{packageName}}.Paths
|
||||||
|
import io.ktor.server.resources.options
|
||||||
|
import io.ktor.server.resources.get
|
||||||
|
import io.ktor.server.resources.post
|
||||||
|
import io.ktor.server.resources.put
|
||||||
|
import io.ktor.server.resources.delete
|
||||||
|
import io.ktor.server.resources.head
|
||||||
|
import io.ktor.server.resources.patch
|
||||||
|
{{/featureResources}}
|
||||||
|
import io.ktor.server.routing.*
|
||||||
|
import {{packageName}}.infrastructure.ApiPrincipal
|
||||||
|
{{#imports}}import {{import}}
|
||||||
|
{{/imports}}
|
||||||
|
|
||||||
|
{{#operations}}
|
||||||
|
fun Route.{{classname}}() {
|
||||||
|
val gson = Gson()
|
||||||
|
val empty = mutableMapOf<String, Any?>()
|
||||||
|
|
||||||
|
{{#operation}}
|
||||||
|
{{#hasAuthMethods}}
|
||||||
|
{{#authMethods}}
|
||||||
|
authenticate("{{{name}}}") {
|
||||||
|
{{/authMethods}}
|
||||||
|
{{/hasAuthMethods}}
|
||||||
|
{{^featureResources}}
|
||||||
|
route("{{path}}") {
|
||||||
|
{{#lambda.lowercase}}{{httpMethod}}{{/lambda.lowercase}} {
|
||||||
|
{{#lambda.indented_12}}{{>libraries/ktor/_api_body}}{{/lambda.indented_12}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{{/featureResources}}
|
||||||
|
{{#featureResources}}
|
||||||
|
{{#lambda.lowercase}}{{httpMethod}}{{/lambda.lowercase}}<Paths.{{operationId}}> {
|
||||||
|
{{#lambda.indented_8}}{{>libraries/ktor/_api_body}}{{/lambda.indented_8}}
|
||||||
|
}
|
||||||
|
{{/featureResources}}
|
||||||
|
{{#hasAuthMethods}}
|
||||||
|
}
|
||||||
|
{{/hasAuthMethods}}
|
||||||
|
|
||||||
|
{{/operation}}
|
||||||
|
}
|
||||||
|
{{/operations}}
|
@ -0,0 +1,27 @@
|
|||||||
|
ktor {
|
||||||
|
deployment {
|
||||||
|
environment = development
|
||||||
|
port = 8080
|
||||||
|
autoreload = true
|
||||||
|
watch = [ {{packageName}} ]
|
||||||
|
}
|
||||||
|
|
||||||
|
application {
|
||||||
|
modules = [ {{packageName}}.AppMainKt.main ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Typesafe config allows multiple ways to provide configuration values without hard-coding them here.
|
||||||
|
# Please see https://github.com/lightbend/config for details.
|
||||||
|
auth {
|
||||||
|
oauth {
|
||||||
|
{{#authMethods}}
|
||||||
|
{{#isOAuth}}
|
||||||
|
{{name}} {
|
||||||
|
clientId = ""
|
||||||
|
clientSecret = ""
|
||||||
|
}
|
||||||
|
{{/isOAuth}}
|
||||||
|
{{/authMethods}}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
|
||||||
|
val kotlin_version: String by project
|
||||||
|
val logback_version: String by project
|
||||||
|
|
||||||
|
group = "{{groupId}}"
|
||||||
|
version = "{{artifactVersion}}"
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm") version "2.0.20"
|
||||||
|
id("io.ktor.plugin") version "2.3.12"
|
||||||
|
}
|
||||||
|
|
||||||
|
application {
|
||||||
|
mainClass.set("io.ktor.server.netty.EngineMain")
|
||||||
|
|
||||||
|
val isDevelopment: Boolean = project.ext.has("development")
|
||||||
|
applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment")
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("ch.qos.logback:logback-classic:$logback_version")
|
||||||
|
{{#hasAuthMethods}}
|
||||||
|
implementation("com.typesafe:config:1.4.1")
|
||||||
|
{{/hasAuthMethods}}
|
||||||
|
implementation("io.ktor:ktor-server-auth")
|
||||||
|
{{#hasAuthMethods}}
|
||||||
|
implementation("io.ktor:ktor-client-apache")
|
||||||
|
{{/hasAuthMethods}}
|
||||||
|
{{#featureAutoHead}}
|
||||||
|
implementation("io.ktor:ktor-server-auto-head-response")
|
||||||
|
{{/featureAutoHead}}
|
||||||
|
implementation("io.ktor:ktor-server-default-headers")
|
||||||
|
implementation("io.ktor:ktor-server-content-negotiation")
|
||||||
|
implementation("io.ktor:ktor-serialization-gson")
|
||||||
|
{{#featureResources}}
|
||||||
|
implementation("io.ktor:ktor-server-resources")
|
||||||
|
{{/featureResources}}
|
||||||
|
{{#featureHSTS}}
|
||||||
|
implementation("io.ktor:ktor-server-hsts")
|
||||||
|
{{/featureHSTS}}
|
||||||
|
{{#featureCORS}}
|
||||||
|
implementation("io.ktor:ktor-server-cors")
|
||||||
|
{{/featureCORS}}
|
||||||
|
{{#featureConditionalHeaders}}
|
||||||
|
implementation("io.ktor:ktor-server-conditional-headers")
|
||||||
|
{{/featureConditionalHeaders}}
|
||||||
|
{{#featureCompression}}
|
||||||
|
implementation("io.ktor:ktor-server-compression")
|
||||||
|
{{/featureCompression}}
|
||||||
|
{{#featureMetrics}}
|
||||||
|
implementation("io.dropwizard.metrics:metrics-core:4.1.18")
|
||||||
|
implementation("io.ktor:ktor-server-metrics")
|
||||||
|
{{/featureMetrics}}
|
||||||
|
implementation("io.ktor:ktor-server-netty")
|
||||||
|
|
||||||
|
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
@ -0,0 +1,4 @@
|
|||||||
|
kotlin.code.style=official
|
||||||
|
ktor_version=2.3.12
|
||||||
|
kotlin_version=2.0.20
|
||||||
|
logback_version=1.4.14
|
11
modules/openapi-generator/src/main/resources/kotlin-server/libraries/ktor2/licenseInfo.mustache
vendored
Normal file
11
modules/openapi-generator/src/main/resources/kotlin-server/libraries/ktor2/licenseInfo.mustache
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* {{{appName}}}
|
||||||
|
* {{{appDescription}}}
|
||||||
|
*
|
||||||
|
* {{#version}}The version of the OpenAPI document: {{{.}}}{{/version}}
|
||||||
|
* {{#infoEmail}}Contact: {{{.}}}{{/infoEmail}}
|
||||||
|
*
|
||||||
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
* https://openapi-generator.tech
|
||||||
|
* Do not edit the class manually.
|
||||||
|
*/
|
@ -0,0 +1,15 @@
|
|||||||
|
<configuration>
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="trace">
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
</root>
|
||||||
|
|
||||||
|
<logger name="org.eclipse.jetty" level="INFO"/>
|
||||||
|
<logger name="io.netty" level="INFO"/>
|
||||||
|
|
||||||
|
</configuration>
|
@ -0,0 +1,23 @@
|
|||||||
|
# OpenAPI Generator Ignore
|
||||||
|
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
|
||||||
|
|
||||||
|
# Use this file to prevent files from being overwritten by the generator.
|
||||||
|
# The patterns follow closely to .gitignore or .dockerignore.
|
||||||
|
|
||||||
|
# As an example, the C# client generator defines ApiClient.cs.
|
||||||
|
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
|
||||||
|
#ApiClient.cs
|
||||||
|
|
||||||
|
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
|
||||||
|
#foo/*/qux
|
||||||
|
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
|
||||||
|
|
||||||
|
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
|
||||||
|
#foo/**/qux
|
||||||
|
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
|
||||||
|
|
||||||
|
# You can also negate patterns with an exclamation (!).
|
||||||
|
# For example, you can ignore all files in a docs folder with the file extension .md:
|
||||||
|
#docs/*.md
|
||||||
|
# Then explicitly reverse the ignore rule for a single file:
|
||||||
|
#!docs/README.md
|
@ -0,0 +1,21 @@
|
|||||||
|
Dockerfile
|
||||||
|
README.md
|
||||||
|
build.gradle.kts
|
||||||
|
gradle.properties
|
||||||
|
gradle/wrapper/gradle-wrapper.properties
|
||||||
|
settings.gradle
|
||||||
|
src/main/kotlin/org/openapitools/server/AppMain.kt
|
||||||
|
src/main/kotlin/org/openapitools/server/Configuration.kt
|
||||||
|
src/main/kotlin/org/openapitools/server/Paths.kt
|
||||||
|
src/main/kotlin/org/openapitools/server/apis/PetApi.kt
|
||||||
|
src/main/kotlin/org/openapitools/server/apis/StoreApi.kt
|
||||||
|
src/main/kotlin/org/openapitools/server/apis/UserApi.kt
|
||||||
|
src/main/kotlin/org/openapitools/server/infrastructure/ApiKeyAuth.kt
|
||||||
|
src/main/kotlin/org/openapitools/server/models/Category.kt
|
||||||
|
src/main/kotlin/org/openapitools/server/models/ModelApiResponse.kt
|
||||||
|
src/main/kotlin/org/openapitools/server/models/Order.kt
|
||||||
|
src/main/kotlin/org/openapitools/server/models/Pet.kt
|
||||||
|
src/main/kotlin/org/openapitools/server/models/Tag.kt
|
||||||
|
src/main/kotlin/org/openapitools/server/models/User.kt
|
||||||
|
src/main/resources/application.conf
|
||||||
|
src/main/resources/logback.xml
|
@ -0,0 +1 @@
|
|||||||
|
7.11.0-SNAPSHOT
|
7
samples/server/petstore/kotlin-server/ktor2/Dockerfile
Normal file
7
samples/server/petstore/kotlin-server/ktor2/Dockerfile
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
FROM openjdk:8-jre-alpine
|
||||||
|
|
||||||
|
COPY ./build/libs/kotlin-server.jar /root/kotlin-server.jar
|
||||||
|
|
||||||
|
WORKDIR /root
|
||||||
|
|
||||||
|
CMD ["java", "-server", "-Xms4g", "-Xmx4g", "-XX:+UseG1GC", "-XX:MaxGCPauseMillis=100", "-XX:+UseStringDeduplication", "-jar", "kotlin-server.jar"]
|
106
samples/server/petstore/kotlin-server/ktor2/README.md
Normal file
106
samples/server/petstore/kotlin-server/ktor2/README.md
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
# org.openapitools.server - Kotlin Server library for OpenAPI Petstore
|
||||||
|
|
||||||
|
This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||||
|
|
||||||
|
Generated by OpenAPI Generator 7.11.0-SNAPSHOT.
|
||||||
|
|
||||||
|
## Requires
|
||||||
|
|
||||||
|
* Kotlin 2.0.20
|
||||||
|
* Gradle 8.10.2
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
First, create the gradle wrapper script:
|
||||||
|
|
||||||
|
```
|
||||||
|
gradle wrapper
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, run:
|
||||||
|
|
||||||
|
```
|
||||||
|
./gradlew check assemble
|
||||||
|
```
|
||||||
|
|
||||||
|
This runs all tests and packages the library.
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
The server builds as a fat jar with a main entrypoint. To start the service, run `java -jar ./build/libs/kotlin-server.jar`.
|
||||||
|
|
||||||
|
You may also run in docker:
|
||||||
|
|
||||||
|
```
|
||||||
|
docker build -t kotlin-server .
|
||||||
|
docker run -p 8080:8080 kotlin-server
|
||||||
|
```
|
||||||
|
|
||||||
|
## Features/Implementation Notes
|
||||||
|
|
||||||
|
* Supports JSON inputs/outputs, File inputs, and Form inputs (see ktor documentation for more info).
|
||||||
|
* ~Supports collection formats for query parameters: csv, tsv, ssv, pipes.~
|
||||||
|
* Some Kotlin and Java types are fully qualified to avoid conflicts with types defined in OpenAPI definitions.
|
||||||
|
|
||||||
|
<a id="documentation-for-api-endpoints"></a>
|
||||||
|
## Documentation for API Endpoints
|
||||||
|
|
||||||
|
All URIs are relative to *http://petstore.swagger.io/v2*
|
||||||
|
|
||||||
|
Class | Method | HTTP request | Description
|
||||||
|
------------ | ------------- | ------------- | -------------
|
||||||
|
*PetApi* | [**addPet**](docs/PetApi.md#addpet) | **POST** /pet | Add a new pet to the store
|
||||||
|
*PetApi* | [**deletePet**](docs/PetApi.md#deletepet) | **DELETE** /pet/{petId} | Deletes a pet
|
||||||
|
*PetApi* | [**findPetsByStatus**](docs/PetApi.md#findpetsbystatus) | **GET** /pet/findByStatus | Finds Pets by status
|
||||||
|
*PetApi* | [**findPetsByTags**](docs/PetApi.md#findpetsbytags) | **GET** /pet/findByTags | Finds Pets by tags
|
||||||
|
*PetApi* | [**getPetById**](docs/PetApi.md#getpetbyid) | **GET** /pet/{petId} | Find pet by ID
|
||||||
|
*PetApi* | [**updatePet**](docs/PetApi.md#updatepet) | **PUT** /pet | Update an existing pet
|
||||||
|
*PetApi* | [**updatePetWithForm**](docs/PetApi.md#updatepetwithform) | **POST** /pet/{petId} | Updates a pet in the store with form data
|
||||||
|
*PetApi* | [**uploadFile**](docs/PetApi.md#uploadfile) | **POST** /pet/{petId}/uploadImage | uploads an image
|
||||||
|
*StoreApi* | [**deleteOrder**](docs/StoreApi.md#deleteorder) | **DELETE** /store/order/{orderId} | Delete purchase order by ID
|
||||||
|
*StoreApi* | [**getInventory**](docs/StoreApi.md#getinventory) | **GET** /store/inventory | Returns pet inventories by status
|
||||||
|
*StoreApi* | [**getOrderById**](docs/StoreApi.md#getorderbyid) | **GET** /store/order/{orderId} | Find purchase order by ID
|
||||||
|
*StoreApi* | [**placeOrder**](docs/StoreApi.md#placeorder) | **POST** /store/order | Place an order for a pet
|
||||||
|
*UserApi* | [**createUser**](docs/UserApi.md#createuser) | **POST** /user | Create user
|
||||||
|
*UserApi* | [**createUsersWithArrayInput**](docs/UserApi.md#createuserswitharrayinput) | **POST** /user/createWithArray | Creates list of users with given input array
|
||||||
|
*UserApi* | [**createUsersWithListInput**](docs/UserApi.md#createuserswithlistinput) | **POST** /user/createWithList | Creates list of users with given input array
|
||||||
|
*UserApi* | [**deleteUser**](docs/UserApi.md#deleteuser) | **DELETE** /user/{username} | Delete user
|
||||||
|
*UserApi* | [**getUserByName**](docs/UserApi.md#getuserbyname) | **GET** /user/{username} | Get user by user name
|
||||||
|
*UserApi* | [**loginUser**](docs/UserApi.md#loginuser) | **GET** /user/login | Logs user into the system
|
||||||
|
*UserApi* | [**logoutUser**](docs/UserApi.md#logoutuser) | **GET** /user/logout | Logs out current logged in user session
|
||||||
|
*UserApi* | [**updateUser**](docs/UserApi.md#updateuser) | **PUT** /user/{username} | Updated user
|
||||||
|
|
||||||
|
|
||||||
|
<a id="documentation-for-models"></a>
|
||||||
|
## Documentation for Models
|
||||||
|
|
||||||
|
- [org.openapitools.server.models.Category](docs/Category.md)
|
||||||
|
- [org.openapitools.server.models.ModelApiResponse](docs/ModelApiResponse.md)
|
||||||
|
- [org.openapitools.server.models.Order](docs/Order.md)
|
||||||
|
- [org.openapitools.server.models.Pet](docs/Pet.md)
|
||||||
|
- [org.openapitools.server.models.Tag](docs/Tag.md)
|
||||||
|
- [org.openapitools.server.models.User](docs/User.md)
|
||||||
|
|
||||||
|
|
||||||
|
<a id="documentation-for-authorization"></a>
|
||||||
|
## Documentation for Authorization
|
||||||
|
|
||||||
|
|
||||||
|
Authentication schemes defined for the API:
|
||||||
|
<a id="petstore_auth"></a>
|
||||||
|
### petstore_auth
|
||||||
|
|
||||||
|
- **Type**: OAuth
|
||||||
|
- **Flow**: implicit
|
||||||
|
- **Authorization URL**: http://petstore.swagger.io/api/oauth/dialog
|
||||||
|
- **Scopes**:
|
||||||
|
- write:pets: modify pets in your account
|
||||||
|
- read:pets: read your pets
|
||||||
|
|
||||||
|
<a id="api_key"></a>
|
||||||
|
### api_key
|
||||||
|
|
||||||
|
- **Type**: API key
|
||||||
|
- **API key parameter name**: api_key
|
||||||
|
- **Location**: HTTP header
|
||||||
|
|
41
samples/server/petstore/kotlin-server/ktor2/build.gradle.kts
Normal file
41
samples/server/petstore/kotlin-server/ktor2/build.gradle.kts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
|
||||||
|
val kotlin_version: String by project
|
||||||
|
val logback_version: String by project
|
||||||
|
|
||||||
|
group = "org.openapitools"
|
||||||
|
version = "1.0.0"
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm") version "2.0.20"
|
||||||
|
id("io.ktor.plugin") version "2.3.12"
|
||||||
|
}
|
||||||
|
|
||||||
|
application {
|
||||||
|
mainClass.set("io.ktor.server.netty.EngineMain")
|
||||||
|
|
||||||
|
val isDevelopment: Boolean = project.ext.has("development")
|
||||||
|
applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment")
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("ch.qos.logback:logback-classic:$logback_version")
|
||||||
|
implementation("com.typesafe:config:1.4.1")
|
||||||
|
implementation("io.ktor:ktor-server-auth")
|
||||||
|
implementation("io.ktor:ktor-client-apache")
|
||||||
|
implementation("io.ktor:ktor-server-auto-head-response")
|
||||||
|
implementation("io.ktor:ktor-server-default-headers")
|
||||||
|
implementation("io.ktor:ktor-server-content-negotiation")
|
||||||
|
implementation("io.ktor:ktor-serialization-gson")
|
||||||
|
implementation("io.ktor:ktor-server-resources")
|
||||||
|
implementation("io.ktor:ktor-server-hsts")
|
||||||
|
implementation("io.ktor:ktor-server-compression")
|
||||||
|
implementation("io.dropwizard.metrics:metrics-core:4.1.18")
|
||||||
|
implementation("io.ktor:ktor-server-metrics")
|
||||||
|
implementation("io.ktor:ktor-server-netty")
|
||||||
|
|
||||||
|
testImplementation("org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version")
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
kotlin.code.style=official
|
||||||
|
ktor_version=2.3.12
|
||||||
|
kotlin_version=2.0.20
|
||||||
|
logback_version=1.4.14
|
5
samples/server/petstore/kotlin-server/ktor2/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
samples/server/petstore/kotlin-server/ktor2/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
distributionBase=GRADLE_USER_HOME
|
||||||
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
|
||||||
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
zipStorePath=wrapper/dists
|
@ -0,0 +1 @@
|
|||||||
|
rootProject.name = 'kotlin-server'
|
@ -0,0 +1,75 @@
|
|||||||
|
package org.openapitools.server
|
||||||
|
|
||||||
|
import io.ktor.server.application.*
|
||||||
|
import io.ktor.serialization.gson.*
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.server.resources.*
|
||||||
|
import io.ktor.server.plugins.autohead.*
|
||||||
|
import io.ktor.server.plugins.compression.*
|
||||||
|
import io.ktor.server.plugins.contentnegotiation.*
|
||||||
|
import io.ktor.server.plugins.defaultheaders.*
|
||||||
|
import io.ktor.server.plugins.hsts.*
|
||||||
|
import com.codahale.metrics.Slf4jReporter
|
||||||
|
import io.ktor.server.metrics.dropwizard.*
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import io.ktor.server.routing.*
|
||||||
|
import com.typesafe.config.ConfigFactory
|
||||||
|
import io.ktor.client.HttpClient
|
||||||
|
import io.ktor.client.engine.apache.Apache
|
||||||
|
import io.ktor.server.config.HoconApplicationConfig
|
||||||
|
import io.ktor.server.auth.*
|
||||||
|
import org.openapitools.server.infrastructure.*
|
||||||
|
import org.openapitools.server.apis.PetApi
|
||||||
|
import org.openapitools.server.apis.StoreApi
|
||||||
|
import org.openapitools.server.apis.UserApi
|
||||||
|
|
||||||
|
|
||||||
|
internal val settings = HoconApplicationConfig(ConfigFactory.defaultApplication(HTTP::class.java.classLoader))
|
||||||
|
|
||||||
|
object HTTP {
|
||||||
|
val client = HttpClient(Apache)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Application.main() {
|
||||||
|
install(DefaultHeaders)
|
||||||
|
install(DropwizardMetrics) {
|
||||||
|
val reporter = Slf4jReporter.forRegistry(registry)
|
||||||
|
.outputTo(this@main.log)
|
||||||
|
.convertRatesTo(TimeUnit.SECONDS)
|
||||||
|
.convertDurationsTo(TimeUnit.MILLISECONDS)
|
||||||
|
.build()
|
||||||
|
reporter.start(10, TimeUnit.SECONDS)
|
||||||
|
}
|
||||||
|
install(ContentNegotiation) {
|
||||||
|
register(ContentType.Application.Json, GsonConverter())
|
||||||
|
}
|
||||||
|
install(AutoHeadResponse) // see https://ktor.io/docs/autoheadresponse.html
|
||||||
|
install(Compression, ApplicationCompressionConfiguration()) // see https://ktor.io/docs/compression.html
|
||||||
|
install(HSTS, ApplicationHstsConfiguration()) // see https://ktor.io/docs/hsts.html
|
||||||
|
install(Resources)
|
||||||
|
install(Authentication) {
|
||||||
|
oauth("petstore_auth") {
|
||||||
|
client = HttpClient(Apache)
|
||||||
|
providerLookup = { applicationAuthProvider(this@main.environment.config) }
|
||||||
|
urlProvider = { _ ->
|
||||||
|
// TODO: define a callback url here.
|
||||||
|
"/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// "Implement API key auth (api_key) for parameter name 'api_key'."
|
||||||
|
apiKeyAuth("api_key") {
|
||||||
|
validate { apikeyCredential: ApiKeyCredential ->
|
||||||
|
when {
|
||||||
|
apikeyCredential.value == "keyboardcat" -> ApiPrincipal(apikeyCredential)
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
install(Routing) {
|
||||||
|
PetApi()
|
||||||
|
StoreApi()
|
||||||
|
UserApi()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
package org.openapitools.server
|
||||||
|
|
||||||
|
// Use this file to hold package-level internal functions that return receiver object passed to the `install` method.
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.server.auth.*
|
||||||
|
import io.ktor.server.config.*
|
||||||
|
import io.ktor.util.*
|
||||||
|
import java.time.Duration
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
import io.ktor.server.plugins.compression.*
|
||||||
|
import io.ktor.server.plugins.hsts.*
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application block for [HSTS] configuration.
|
||||||
|
*
|
||||||
|
* This file may be excluded in .openapi-generator-ignore,
|
||||||
|
* and application-specific configuration can be applied in this function.
|
||||||
|
*
|
||||||
|
* See http://ktor.io/features/hsts.html
|
||||||
|
*/
|
||||||
|
internal fun ApplicationHstsConfiguration(): HSTSConfig.() -> Unit {
|
||||||
|
return {
|
||||||
|
maxAgeInSeconds = TimeUnit.DAYS.toSeconds(365)
|
||||||
|
includeSubDomains = true
|
||||||
|
preload = false
|
||||||
|
|
||||||
|
// You may also apply any custom directives supported by specific user-agent. For example:
|
||||||
|
// customDirectives.put("redirectHttpToHttps", "false")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Application block for [Compression] configuration.
|
||||||
|
*
|
||||||
|
* This file may be excluded in .openapi-generator-ignore,
|
||||||
|
* and application-specific configuration can be applied in this function.
|
||||||
|
*
|
||||||
|
* See http://ktor.io/features/compression.html
|
||||||
|
*/
|
||||||
|
internal fun ApplicationCompressionConfiguration(): CompressionConfig.() -> Unit {
|
||||||
|
return {
|
||||||
|
gzip {
|
||||||
|
priority = 1.0
|
||||||
|
}
|
||||||
|
deflate {
|
||||||
|
priority = 10.0
|
||||||
|
minimumSize(1024) // condition
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defines authentication mechanisms used throughout the application.
|
||||||
|
fun applicationAuthProvider(config: ApplicationConfig): OAuthServerSettings =
|
||||||
|
OAuthServerSettings.OAuth2ServerSettings(
|
||||||
|
name = "petstore_auth",
|
||||||
|
authorizeUrl = "http://petstore.swagger.io/api/oauth/dialog",
|
||||||
|
accessTokenUrl = "",
|
||||||
|
requestMethod = HttpMethod.Get,
|
||||||
|
clientId = config.property("auth.oauth.petstore_auth.clientId").getString(),
|
||||||
|
clientSecret = config.property("auth.oauth.petstore_auth.clientSecret").getString(),
|
||||||
|
defaultScopes = listOf("write:pets", "read:pets")
|
||||||
|
)
|
@ -0,0 +1,164 @@
|
|||||||
|
/**
|
||||||
|
* OpenAPI Petstore
|
||||||
|
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0.0
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
* https://openapi-generator.tech
|
||||||
|
* Do not edit the class manually.
|
||||||
|
*/
|
||||||
|
package org.openapitools.server
|
||||||
|
|
||||||
|
import io.ktor.resources.*
|
||||||
|
import kotlinx.serialization.*
|
||||||
|
import org.openapitools.server.models.*
|
||||||
|
|
||||||
|
object Paths {
|
||||||
|
/**
|
||||||
|
* Add a new pet to the store
|
||||||
|
*
|
||||||
|
* @param pet Pet object that needs to be added to the store
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/pet") class addPet(val pet: Pet)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes a pet
|
||||||
|
*
|
||||||
|
* @param petId Pet id to delete
|
||||||
|
* @param apiKey (optional)
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/pet/{petId}") class deletePet(val petId: kotlin.Long, val apiKey: kotlin.String? = null)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds Pets by status
|
||||||
|
* Multiple status values can be provided with comma separated strings
|
||||||
|
* @param status Status values that need to be considered for filter
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/pet/findByStatus") class findPetsByStatus(val status: kotlin.collections.List<kotlin.String>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds Pets by tags
|
||||||
|
* Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.
|
||||||
|
* @param tags Tags to filter by
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/pet/findByTags") class findPetsByTags(val tags: kotlin.collections.List<kotlin.String>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find pet by ID
|
||||||
|
* Returns a single pet
|
||||||
|
* @param petId ID of pet to return
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/pet/{petId}") class getPetById(val petId: kotlin.Long)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update an existing pet
|
||||||
|
*
|
||||||
|
* @param pet Pet object that needs to be added to the store
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/pet") class updatePet(val pet: Pet)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a pet in the store with form data
|
||||||
|
*
|
||||||
|
* @param petId ID of pet that needs to be updated
|
||||||
|
* @param name Updated name of the pet (optional)
|
||||||
|
* @param status Updated status of the pet (optional)
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/pet/{petId}") class updatePetWithForm(val petId: kotlin.Long, val name: kotlin.String? = null, val status: kotlin.String? = null)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* uploads an image
|
||||||
|
*
|
||||||
|
* @param petId ID of pet to update
|
||||||
|
* @param additionalMetadata Additional data to pass to server (optional)
|
||||||
|
* @param file file to upload (optional)
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/pet/{petId}/uploadImage") class uploadFile(val petId: kotlin.Long, val additionalMetadata: kotlin.String? = null, val file: java.io.File? = null)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete purchase order by ID
|
||||||
|
* For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors
|
||||||
|
* @param orderId ID of the order that needs to be deleted
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/store/order/{orderId}") class deleteOrder(val orderId: kotlin.String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns pet inventories by status
|
||||||
|
* Returns a map of status codes to quantities
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/store/inventory") class getInventory
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find purchase order by ID
|
||||||
|
* For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions
|
||||||
|
* @param orderId ID of pet that needs to be fetched
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/store/order/{orderId}") class getOrderById(val orderId: kotlin.Long)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Place an order for a pet
|
||||||
|
*
|
||||||
|
* @param order order placed for purchasing the pet
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/store/order") class placeOrder(val order: Order)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create user
|
||||||
|
* This can only be done by the logged in user.
|
||||||
|
* @param user Created user object
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/user") class createUser(val user: User)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates list of users with given input array
|
||||||
|
*
|
||||||
|
* @param user List of user object
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/user/createWithArray") class createUsersWithArrayInput(val user: kotlin.collections.List<User>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates list of users with given input array
|
||||||
|
*
|
||||||
|
* @param user List of user object
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/user/createWithList") class createUsersWithListInput(val user: kotlin.collections.List<User>)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete user
|
||||||
|
* This can only be done by the logged in user.
|
||||||
|
* @param username The name that needs to be deleted
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/user/{username}") class deleteUser(val username: kotlin.String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get user by user name
|
||||||
|
*
|
||||||
|
* @param username The name that needs to be fetched. Use user1 for testing.
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/user/{username}") class getUserByName(val username: kotlin.String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs user into the system
|
||||||
|
*
|
||||||
|
* @param username The user name for login
|
||||||
|
* @param password The password for login in clear text
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/user/login") class loginUser(val username: kotlin.String, val password: kotlin.String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logs out current logged in user session
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/user/logout") class logoutUser
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updated user
|
||||||
|
* This can only be done by the logged in user.
|
||||||
|
* @param username name that need to be deleted
|
||||||
|
* @param user Updated user object
|
||||||
|
*/
|
||||||
|
@Serializable @Resource("/user/{username}") class updateUser(val username: kotlin.String, val user: User)
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,282 @@
|
|||||||
|
/**
|
||||||
|
* OpenAPI Petstore
|
||||||
|
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0.0
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
* https://openapi-generator.tech
|
||||||
|
* Do not edit the class manually.
|
||||||
|
*/
|
||||||
|
package org.openapitools.server.apis
|
||||||
|
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.server.application.*
|
||||||
|
import io.ktor.server.auth.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
|
import org.openapitools.server.Paths
|
||||||
|
import io.ktor.server.resources.options
|
||||||
|
import io.ktor.server.resources.get
|
||||||
|
import io.ktor.server.resources.post
|
||||||
|
import io.ktor.server.resources.put
|
||||||
|
import io.ktor.server.resources.delete
|
||||||
|
import io.ktor.server.resources.head
|
||||||
|
import io.ktor.server.resources.patch
|
||||||
|
import io.ktor.server.routing.*
|
||||||
|
import org.openapitools.server.infrastructure.ApiPrincipal
|
||||||
|
import org.openapitools.server.models.ModelApiResponse
|
||||||
|
import org.openapitools.server.models.Pet
|
||||||
|
|
||||||
|
fun Route.PetApi() {
|
||||||
|
val gson = Gson()
|
||||||
|
val empty = mutableMapOf<String, Any?>()
|
||||||
|
|
||||||
|
authenticate("petstore_auth") {
|
||||||
|
post<Paths.addPet> {
|
||||||
|
|
||||||
|
val principal = call.authentication.principal<OAuthAccessTokenResponse>()!!
|
||||||
|
|
||||||
|
|
||||||
|
val exampleContentType = "application/json"
|
||||||
|
val exampleContentString = """{
|
||||||
|
"photoUrls" : [ "photoUrls", "photoUrls" ],
|
||||||
|
"name" : "doggie",
|
||||||
|
"id" : 0,
|
||||||
|
"category" : {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 6
|
||||||
|
},
|
||||||
|
"tags" : [ {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 1
|
||||||
|
}, {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 1
|
||||||
|
} ],
|
||||||
|
"status" : "available"
|
||||||
|
}"""
|
||||||
|
|
||||||
|
when (exampleContentType) {
|
||||||
|
"application/json" -> call.respond(gson.fromJson(exampleContentString, empty::class.java))
|
||||||
|
"application/xml" -> call.respondText(exampleContentString, ContentType.Text.Xml)
|
||||||
|
else -> call.respondText(exampleContentString)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate("petstore_auth") {
|
||||||
|
delete<Paths.deletePet> {
|
||||||
|
|
||||||
|
val principal = call.authentication.principal<OAuthAccessTokenResponse>()!!
|
||||||
|
|
||||||
|
|
||||||
|
call.respond(HttpStatusCode.NotImplemented)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate("petstore_auth") {
|
||||||
|
get<Paths.findPetsByStatus> {
|
||||||
|
|
||||||
|
val principal = call.authentication.principal<OAuthAccessTokenResponse>()!!
|
||||||
|
|
||||||
|
|
||||||
|
val exampleContentType = "application/json"
|
||||||
|
val exampleContentString = """[ {
|
||||||
|
"photoUrls" : [ "photoUrls", "photoUrls" ],
|
||||||
|
"name" : "doggie",
|
||||||
|
"id" : 0,
|
||||||
|
"category" : {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 6
|
||||||
|
},
|
||||||
|
"tags" : [ {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 1
|
||||||
|
}, {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 1
|
||||||
|
} ],
|
||||||
|
"status" : "available"
|
||||||
|
}, {
|
||||||
|
"photoUrls" : [ "photoUrls", "photoUrls" ],
|
||||||
|
"name" : "doggie",
|
||||||
|
"id" : 0,
|
||||||
|
"category" : {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 6
|
||||||
|
},
|
||||||
|
"tags" : [ {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 1
|
||||||
|
}, {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 1
|
||||||
|
} ],
|
||||||
|
"status" : "available"
|
||||||
|
} ]"""
|
||||||
|
|
||||||
|
when (exampleContentType) {
|
||||||
|
"application/json" -> call.respond(gson.fromJson(exampleContentString, empty::class.java))
|
||||||
|
"application/xml" -> call.respondText(exampleContentString, ContentType.Text.Xml)
|
||||||
|
else -> call.respondText(exampleContentString)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate("petstore_auth") {
|
||||||
|
get<Paths.findPetsByTags> {
|
||||||
|
|
||||||
|
val principal = call.authentication.principal<OAuthAccessTokenResponse>()!!
|
||||||
|
|
||||||
|
|
||||||
|
val exampleContentType = "application/json"
|
||||||
|
val exampleContentString = """[ {
|
||||||
|
"photoUrls" : [ "photoUrls", "photoUrls" ],
|
||||||
|
"name" : "doggie",
|
||||||
|
"id" : 0,
|
||||||
|
"category" : {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 6
|
||||||
|
},
|
||||||
|
"tags" : [ {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 1
|
||||||
|
}, {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 1
|
||||||
|
} ],
|
||||||
|
"status" : "available"
|
||||||
|
}, {
|
||||||
|
"photoUrls" : [ "photoUrls", "photoUrls" ],
|
||||||
|
"name" : "doggie",
|
||||||
|
"id" : 0,
|
||||||
|
"category" : {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 6
|
||||||
|
},
|
||||||
|
"tags" : [ {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 1
|
||||||
|
}, {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 1
|
||||||
|
} ],
|
||||||
|
"status" : "available"
|
||||||
|
} ]"""
|
||||||
|
|
||||||
|
when (exampleContentType) {
|
||||||
|
"application/json" -> call.respond(gson.fromJson(exampleContentString, empty::class.java))
|
||||||
|
"application/xml" -> call.respondText(exampleContentString, ContentType.Text.Xml)
|
||||||
|
else -> call.respondText(exampleContentString)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate("api_key") {
|
||||||
|
get<Paths.getPetById> {
|
||||||
|
|
||||||
|
val principal = call.authentication.principal<ApiPrincipal>()!!
|
||||||
|
|
||||||
|
|
||||||
|
val exampleContentType = "application/json"
|
||||||
|
val exampleContentString = """{
|
||||||
|
"photoUrls" : [ "photoUrls", "photoUrls" ],
|
||||||
|
"name" : "doggie",
|
||||||
|
"id" : 0,
|
||||||
|
"category" : {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 6
|
||||||
|
},
|
||||||
|
"tags" : [ {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 1
|
||||||
|
}, {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 1
|
||||||
|
} ],
|
||||||
|
"status" : "available"
|
||||||
|
}"""
|
||||||
|
|
||||||
|
when (exampleContentType) {
|
||||||
|
"application/json" -> call.respond(gson.fromJson(exampleContentString, empty::class.java))
|
||||||
|
"application/xml" -> call.respondText(exampleContentString, ContentType.Text.Xml)
|
||||||
|
else -> call.respondText(exampleContentString)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate("petstore_auth") {
|
||||||
|
put<Paths.updatePet> {
|
||||||
|
|
||||||
|
val principal = call.authentication.principal<OAuthAccessTokenResponse>()!!
|
||||||
|
|
||||||
|
|
||||||
|
val exampleContentType = "application/json"
|
||||||
|
val exampleContentString = """{
|
||||||
|
"photoUrls" : [ "photoUrls", "photoUrls" ],
|
||||||
|
"name" : "doggie",
|
||||||
|
"id" : 0,
|
||||||
|
"category" : {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 6
|
||||||
|
},
|
||||||
|
"tags" : [ {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 1
|
||||||
|
}, {
|
||||||
|
"name" : "name",
|
||||||
|
"id" : 1
|
||||||
|
} ],
|
||||||
|
"status" : "available"
|
||||||
|
}"""
|
||||||
|
|
||||||
|
when (exampleContentType) {
|
||||||
|
"application/json" -> call.respond(gson.fromJson(exampleContentString, empty::class.java))
|
||||||
|
"application/xml" -> call.respondText(exampleContentString, ContentType.Text.Xml)
|
||||||
|
else -> call.respondText(exampleContentString)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate("petstore_auth") {
|
||||||
|
post<Paths.updatePetWithForm> {
|
||||||
|
|
||||||
|
val principal = call.authentication.principal<OAuthAccessTokenResponse>()!!
|
||||||
|
|
||||||
|
|
||||||
|
call.respond(HttpStatusCode.NotImplemented)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate("petstore_auth") {
|
||||||
|
post<Paths.uploadFile> {
|
||||||
|
|
||||||
|
val principal = call.authentication.principal<OAuthAccessTokenResponse>()!!
|
||||||
|
|
||||||
|
|
||||||
|
val exampleContentType = "application/json"
|
||||||
|
val exampleContentString = """{
|
||||||
|
"code" : 0,
|
||||||
|
"type" : "type",
|
||||||
|
"message" : "message"
|
||||||
|
}"""
|
||||||
|
|
||||||
|
when (exampleContentType) {
|
||||||
|
"application/json" -> call.respond(gson.fromJson(exampleContentString, empty::class.java))
|
||||||
|
"application/xml" -> call.respondText(exampleContentString, ContentType.Text.Xml)
|
||||||
|
else -> call.respondText(exampleContentString)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,89 @@
|
|||||||
|
/**
|
||||||
|
* OpenAPI Petstore
|
||||||
|
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0.0
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
* https://openapi-generator.tech
|
||||||
|
* Do not edit the class manually.
|
||||||
|
*/
|
||||||
|
package org.openapitools.server.apis
|
||||||
|
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.server.application.*
|
||||||
|
import io.ktor.server.auth.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
|
import org.openapitools.server.Paths
|
||||||
|
import io.ktor.server.resources.options
|
||||||
|
import io.ktor.server.resources.get
|
||||||
|
import io.ktor.server.resources.post
|
||||||
|
import io.ktor.server.resources.put
|
||||||
|
import io.ktor.server.resources.delete
|
||||||
|
import io.ktor.server.resources.head
|
||||||
|
import io.ktor.server.resources.patch
|
||||||
|
import io.ktor.server.routing.*
|
||||||
|
import org.openapitools.server.infrastructure.ApiPrincipal
|
||||||
|
import org.openapitools.server.models.Order
|
||||||
|
|
||||||
|
fun Route.StoreApi() {
|
||||||
|
val gson = Gson()
|
||||||
|
val empty = mutableMapOf<String, Any?>()
|
||||||
|
|
||||||
|
delete<Paths.deleteOrder> {
|
||||||
|
call.respond(HttpStatusCode.NotImplemented)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate("api_key") {
|
||||||
|
get<Paths.getInventory> {
|
||||||
|
|
||||||
|
val principal = call.authentication.principal<ApiPrincipal>()!!
|
||||||
|
|
||||||
|
|
||||||
|
call.respond(HttpStatusCode.NotImplemented)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get<Paths.getOrderById> {
|
||||||
|
val exampleContentType = "application/json"
|
||||||
|
val exampleContentString = """{
|
||||||
|
"petId" : 6,
|
||||||
|
"quantity" : 1,
|
||||||
|
"id" : 0,
|
||||||
|
"shipDate" : "2000-01-23T04:56:07.000+00:00",
|
||||||
|
"complete" : false,
|
||||||
|
"status" : "placed"
|
||||||
|
}"""
|
||||||
|
|
||||||
|
when (exampleContentType) {
|
||||||
|
"application/json" -> call.respond(gson.fromJson(exampleContentString, empty::class.java))
|
||||||
|
"application/xml" -> call.respondText(exampleContentString, ContentType.Text.Xml)
|
||||||
|
else -> call.respondText(exampleContentString)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
post<Paths.placeOrder> {
|
||||||
|
val exampleContentType = "application/json"
|
||||||
|
val exampleContentString = """{
|
||||||
|
"petId" : 6,
|
||||||
|
"quantity" : 1,
|
||||||
|
"id" : 0,
|
||||||
|
"shipDate" : "2000-01-23T04:56:07.000+00:00",
|
||||||
|
"complete" : false,
|
||||||
|
"status" : "placed"
|
||||||
|
}"""
|
||||||
|
|
||||||
|
when (exampleContentType) {
|
||||||
|
"application/json" -> call.respond(gson.fromJson(exampleContentString, empty::class.java))
|
||||||
|
"application/xml" -> call.respondText(exampleContentString, ContentType.Text.Xml)
|
||||||
|
else -> call.respondText(exampleContentString)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,127 @@
|
|||||||
|
/**
|
||||||
|
* OpenAPI Petstore
|
||||||
|
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0.0
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
* https://openapi-generator.tech
|
||||||
|
* Do not edit the class manually.
|
||||||
|
*/
|
||||||
|
package org.openapitools.server.apis
|
||||||
|
|
||||||
|
import com.google.gson.Gson
|
||||||
|
import io.ktor.http.*
|
||||||
|
import io.ktor.server.application.*
|
||||||
|
import io.ktor.server.auth.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
|
import org.openapitools.server.Paths
|
||||||
|
import io.ktor.server.resources.options
|
||||||
|
import io.ktor.server.resources.get
|
||||||
|
import io.ktor.server.resources.post
|
||||||
|
import io.ktor.server.resources.put
|
||||||
|
import io.ktor.server.resources.delete
|
||||||
|
import io.ktor.server.resources.head
|
||||||
|
import io.ktor.server.resources.patch
|
||||||
|
import io.ktor.server.routing.*
|
||||||
|
import org.openapitools.server.infrastructure.ApiPrincipal
|
||||||
|
import org.openapitools.server.models.User
|
||||||
|
|
||||||
|
fun Route.UserApi() {
|
||||||
|
val gson = Gson()
|
||||||
|
val empty = mutableMapOf<String, Any?>()
|
||||||
|
|
||||||
|
authenticate("api_key") {
|
||||||
|
post<Paths.createUser> {
|
||||||
|
|
||||||
|
val principal = call.authentication.principal<ApiPrincipal>()!!
|
||||||
|
|
||||||
|
|
||||||
|
call.respond(HttpStatusCode.NotImplemented)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate("api_key") {
|
||||||
|
post<Paths.createUsersWithArrayInput> {
|
||||||
|
|
||||||
|
val principal = call.authentication.principal<ApiPrincipal>()!!
|
||||||
|
|
||||||
|
|
||||||
|
call.respond(HttpStatusCode.NotImplemented)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate("api_key") {
|
||||||
|
post<Paths.createUsersWithListInput> {
|
||||||
|
|
||||||
|
val principal = call.authentication.principal<ApiPrincipal>()!!
|
||||||
|
|
||||||
|
|
||||||
|
call.respond(HttpStatusCode.NotImplemented)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate("api_key") {
|
||||||
|
delete<Paths.deleteUser> {
|
||||||
|
|
||||||
|
val principal = call.authentication.principal<ApiPrincipal>()!!
|
||||||
|
|
||||||
|
|
||||||
|
call.respond(HttpStatusCode.NotImplemented)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get<Paths.getUserByName> {
|
||||||
|
val exampleContentType = "application/json"
|
||||||
|
val exampleContentString = """{
|
||||||
|
"firstName" : "firstName",
|
||||||
|
"lastName" : "lastName",
|
||||||
|
"password" : "password",
|
||||||
|
"userStatus" : 6,
|
||||||
|
"phone" : "phone",
|
||||||
|
"id" : 0,
|
||||||
|
"email" : "email",
|
||||||
|
"username" : "username"
|
||||||
|
}"""
|
||||||
|
|
||||||
|
when (exampleContentType) {
|
||||||
|
"application/json" -> call.respond(gson.fromJson(exampleContentString, empty::class.java))
|
||||||
|
"application/xml" -> call.respondText(exampleContentString, ContentType.Text.Xml)
|
||||||
|
else -> call.respondText(exampleContentString)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
get<Paths.loginUser> {
|
||||||
|
call.respond(HttpStatusCode.NotImplemented)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate("api_key") {
|
||||||
|
get<Paths.logoutUser> {
|
||||||
|
|
||||||
|
val principal = call.authentication.principal<ApiPrincipal>()!!
|
||||||
|
|
||||||
|
|
||||||
|
call.respond(HttpStatusCode.NotImplemented)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
authenticate("api_key") {
|
||||||
|
put<Paths.updateUser> {
|
||||||
|
|
||||||
|
val principal = call.authentication.principal<ApiPrincipal>()!!
|
||||||
|
|
||||||
|
|
||||||
|
call.respond(HttpStatusCode.NotImplemented)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,102 @@
|
|||||||
|
package org.openapitools.server.infrastructure
|
||||||
|
|
||||||
|
import io.ktor.http.auth.*
|
||||||
|
import io.ktor.server.application.*
|
||||||
|
import io.ktor.server.auth.*
|
||||||
|
import io.ktor.server.request.*
|
||||||
|
import io.ktor.server.response.*
|
||||||
|
|
||||||
|
enum class ApiKeyLocation(val location: String) {
|
||||||
|
QUERY("query"),
|
||||||
|
HEADER("header")
|
||||||
|
}
|
||||||
|
|
||||||
|
data class ApiKeyCredential(val value: String) : Credential
|
||||||
|
data class ApiPrincipal(val apiKeyCredential: ApiKeyCredential?) : Principal
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents an Api Key authentication provider
|
||||||
|
*/
|
||||||
|
class ApiKeyAuthenticationProvider(configuration: Configuration) : AuthenticationProvider(configuration) {
|
||||||
|
|
||||||
|
private val authenticationFunction = configuration.authenticationFunction
|
||||||
|
|
||||||
|
private val apiKeyName: String = configuration.apiKeyName
|
||||||
|
|
||||||
|
private val apiKeyLocation: ApiKeyLocation = configuration.apiKeyLocation
|
||||||
|
|
||||||
|
override suspend fun onAuthenticate(context: AuthenticationContext) {
|
||||||
|
val call = context.call
|
||||||
|
val credentials = call.request.apiKeyAuthenticationCredentials(apiKeyName, apiKeyLocation)
|
||||||
|
val principal = credentials?.let { authenticationFunction.invoke(call, it) }
|
||||||
|
|
||||||
|
val cause = when {
|
||||||
|
credentials == null -> AuthenticationFailedCause.NoCredentials
|
||||||
|
principal == null -> AuthenticationFailedCause.InvalidCredentials
|
||||||
|
else -> null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cause != null) {
|
||||||
|
context.challenge(apiKeyName, cause) { challenge, call ->
|
||||||
|
call.respond(
|
||||||
|
UnauthorizedResponse(
|
||||||
|
HttpAuthHeader.Parameterized(
|
||||||
|
"API_KEY",
|
||||||
|
mapOf("key" to apiKeyName),
|
||||||
|
HeaderValueEncoding.QUOTED_ALWAYS
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
challenge.complete()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (principal != null) {
|
||||||
|
context.principal(principal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Configuration internal constructor(name: String?) : Config(name) {
|
||||||
|
|
||||||
|
internal var authenticationFunction: suspend ApplicationCall.(ApiKeyCredential) -> Principal? = {
|
||||||
|
throw NotImplementedError(
|
||||||
|
"Api Key auth validate function is not specified. Use apiKeyAuth { validate { ... } } to fix."
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
var apiKeyName: String = ""
|
||||||
|
|
||||||
|
var apiKeyLocation: ApiKeyLocation = ApiKeyLocation.QUERY
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a validation function that will check given [ApiKeyCredential] instance and return [Principal],
|
||||||
|
* or null if credential does not correspond to an authenticated principal
|
||||||
|
*/
|
||||||
|
fun validate(body: suspend ApplicationCall.(ApiKeyCredential) -> Principal?) {
|
||||||
|
authenticationFunction = body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun AuthenticationConfig.apiKeyAuth(
|
||||||
|
name: String? = null,
|
||||||
|
configure: ApiKeyAuthenticationProvider.Configuration.() -> Unit
|
||||||
|
) {
|
||||||
|
val configuration = ApiKeyAuthenticationProvider.Configuration(name).apply(configure)
|
||||||
|
val provider = ApiKeyAuthenticationProvider(configuration)
|
||||||
|
register(provider)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ApplicationRequest.apiKeyAuthenticationCredentials(
|
||||||
|
apiKeyName: String,
|
||||||
|
apiKeyLocation: ApiKeyLocation
|
||||||
|
): ApiKeyCredential? {
|
||||||
|
val value: String? = when (apiKeyLocation) {
|
||||||
|
ApiKeyLocation.QUERY -> this.queryParameters[apiKeyName]
|
||||||
|
ApiKeyLocation.HEADER -> this.headers[apiKeyName]
|
||||||
|
}
|
||||||
|
return when (value) {
|
||||||
|
null -> null
|
||||||
|
else -> ApiKeyCredential(value)
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* OpenAPI Petstore
|
||||||
|
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0.0
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
* https://openapi-generator.tech
|
||||||
|
* Do not edit the class manually.
|
||||||
|
*/
|
||||||
|
package org.openapitools.server.models
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
/**
|
||||||
|
* A category for a pet
|
||||||
|
* @param id
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
data class Category(
|
||||||
|
val id: kotlin.Long? = null,
|
||||||
|
val name: kotlin.String? = null
|
||||||
|
) : Serializable
|
||||||
|
{
|
||||||
|
companion object {
|
||||||
|
private const val serialVersionUID: Long = 123
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* OpenAPI Petstore
|
||||||
|
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0.0
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
* https://openapi-generator.tech
|
||||||
|
* Do not edit the class manually.
|
||||||
|
*/
|
||||||
|
package org.openapitools.server.models
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
/**
|
||||||
|
* Describes the result of uploading an image resource
|
||||||
|
* @param code
|
||||||
|
* @param type
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
data class ModelApiResponse(
|
||||||
|
val code: kotlin.Int? = null,
|
||||||
|
val type: kotlin.String? = null,
|
||||||
|
val message: kotlin.String? = null
|
||||||
|
) : Serializable
|
||||||
|
{
|
||||||
|
companion object {
|
||||||
|
private const val serialVersionUID: Long = 123
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
|||||||
|
/**
|
||||||
|
* OpenAPI Petstore
|
||||||
|
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0.0
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
* https://openapi-generator.tech
|
||||||
|
* Do not edit the class manually.
|
||||||
|
*/
|
||||||
|
package org.openapitools.server.models
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
/**
|
||||||
|
* An order for a pets from the pet store
|
||||||
|
* @param id
|
||||||
|
* @param petId
|
||||||
|
* @param quantity
|
||||||
|
* @param shipDate
|
||||||
|
* @param status Order Status
|
||||||
|
* @param complete
|
||||||
|
*/
|
||||||
|
data class Order(
|
||||||
|
val id: kotlin.Long? = null,
|
||||||
|
val petId: kotlin.Long? = null,
|
||||||
|
val quantity: kotlin.Int? = null,
|
||||||
|
val shipDate: java.time.OffsetDateTime? = null,
|
||||||
|
/* Order Status */
|
||||||
|
val status: Order.Status? = null,
|
||||||
|
val complete: kotlin.Boolean? = false
|
||||||
|
) : Serializable
|
||||||
|
{
|
||||||
|
companion object {
|
||||||
|
private const val serialVersionUID: Long = 123
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Order Status
|
||||||
|
* Values: placed,approved,delivered
|
||||||
|
*/
|
||||||
|
enum class Status(val value: kotlin.String){
|
||||||
|
placed("placed"),
|
||||||
|
approved("approved"),
|
||||||
|
delivered("delivered");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
|||||||
|
/**
|
||||||
|
* OpenAPI Petstore
|
||||||
|
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0.0
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
* https://openapi-generator.tech
|
||||||
|
* Do not edit the class manually.
|
||||||
|
*/
|
||||||
|
package org.openapitools.server.models
|
||||||
|
|
||||||
|
import org.openapitools.server.models.Category
|
||||||
|
import org.openapitools.server.models.Tag
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
/**
|
||||||
|
* A pet for sale in the pet store
|
||||||
|
* @param name
|
||||||
|
* @param photoUrls
|
||||||
|
* @param id
|
||||||
|
* @param category
|
||||||
|
* @param tags
|
||||||
|
* @param status pet status in the store
|
||||||
|
*/
|
||||||
|
data class Pet(
|
||||||
|
val name: kotlin.String,
|
||||||
|
val photoUrls: kotlin.collections.List<kotlin.String>,
|
||||||
|
val id: kotlin.Long? = null,
|
||||||
|
val category: Category? = null,
|
||||||
|
val tags: kotlin.collections.List<Tag>? = null,
|
||||||
|
/* pet status in the store */
|
||||||
|
val status: Pet.Status? = null
|
||||||
|
) : Serializable
|
||||||
|
{
|
||||||
|
companion object {
|
||||||
|
private const val serialVersionUID: Long = 123
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* pet status in the store
|
||||||
|
* Values: available,pending,sold
|
||||||
|
*/
|
||||||
|
enum class Status(val value: kotlin.String){
|
||||||
|
available("available"),
|
||||||
|
pending("pending"),
|
||||||
|
sold("sold");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
|||||||
|
/**
|
||||||
|
* OpenAPI Petstore
|
||||||
|
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0.0
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
* https://openapi-generator.tech
|
||||||
|
* Do not edit the class manually.
|
||||||
|
*/
|
||||||
|
package org.openapitools.server.models
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
/**
|
||||||
|
* A tag for a pet
|
||||||
|
* @param id
|
||||||
|
* @param name
|
||||||
|
*/
|
||||||
|
data class Tag(
|
||||||
|
val id: kotlin.Long? = null,
|
||||||
|
val name: kotlin.String? = null
|
||||||
|
) : Serializable
|
||||||
|
{
|
||||||
|
companion object {
|
||||||
|
private const val serialVersionUID: Long = 123
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* OpenAPI Petstore
|
||||||
|
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||||
|
*
|
||||||
|
* The version of the OpenAPI document: 1.0.0
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||||
|
* https://openapi-generator.tech
|
||||||
|
* Do not edit the class manually.
|
||||||
|
*/
|
||||||
|
package org.openapitools.server.models
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.Serializable
|
||||||
|
/**
|
||||||
|
* A User who is purchasing from the pet store
|
||||||
|
* @param id
|
||||||
|
* @param username
|
||||||
|
* @param firstName
|
||||||
|
* @param lastName
|
||||||
|
* @param email
|
||||||
|
* @param password
|
||||||
|
* @param phone
|
||||||
|
* @param userStatus User Status
|
||||||
|
*/
|
||||||
|
data class User(
|
||||||
|
val id: kotlin.Long? = null,
|
||||||
|
val username: kotlin.String? = null,
|
||||||
|
val firstName: kotlin.String? = null,
|
||||||
|
val lastName: kotlin.String? = null,
|
||||||
|
val email: kotlin.String? = null,
|
||||||
|
val password: kotlin.String? = null,
|
||||||
|
val phone: kotlin.String? = null,
|
||||||
|
/* User Status */
|
||||||
|
val userStatus: kotlin.Int? = null
|
||||||
|
) : Serializable
|
||||||
|
{
|
||||||
|
companion object {
|
||||||
|
private const val serialVersionUID: Long = 123
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
|||||||
|
ktor {
|
||||||
|
deployment {
|
||||||
|
environment = development
|
||||||
|
port = 8080
|
||||||
|
autoreload = true
|
||||||
|
watch = [ org.openapitools.server ]
|
||||||
|
}
|
||||||
|
|
||||||
|
application {
|
||||||
|
modules = [ org.openapitools.server.AppMainKt.main ]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Typesafe config allows multiple ways to provide configuration values without hard-coding them here.
|
||||||
|
# Please see https://github.com/lightbend/config for details.
|
||||||
|
auth {
|
||||||
|
oauth {
|
||||||
|
petstore_auth {
|
||||||
|
clientId = ""
|
||||||
|
clientSecret = ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
<configuration>
|
||||||
|
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
<encoder>
|
||||||
|
<pattern>%d{YYYY-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
|
||||||
|
</encoder>
|
||||||
|
</appender>
|
||||||
|
|
||||||
|
<root level="trace">
|
||||||
|
<appender-ref ref="STDOUT"/>
|
||||||
|
</root>
|
||||||
|
|
||||||
|
<logger name="org.eclipse.jetty" level="INFO"/>
|
||||||
|
<logger name="io.netty" level="INFO"/>
|
||||||
|
|
||||||
|
</configuration>
|
Loading…
x
Reference in New Issue
Block a user