forked from loafle/openapi-generator-original
Keep old Ktor server generator for backward compatibility (#9365)
This commit is contained in:
parent
53398a0850
commit
ccbb78e1b2
8
bin/configs/kotlin-server-ktor-deprecated.yaml
Normal file
8
bin/configs/kotlin-server-ktor-deprecated.yaml
Normal file
@ -0,0 +1,8 @@
|
||||
generatorName: kotlin-server-deprecated
|
||||
outputDir: samples/server/petstore/kotlin-server-deprecated/ktor
|
||||
library: ktor
|
||||
inputSpec: modules/openapi-generator/src/test/resources/2_0/petstore.yaml
|
||||
templateDir: modules/openapi-generator/src/main/resources/kotlin-server-deprecated
|
||||
additionalProperties:
|
||||
hideGenerationTimestamp: "true"
|
||||
serializableModel: "true"
|
@ -106,6 +106,7 @@ The following generators are available:
|
||||
* [jaxrs-resteasy-eap](generators/jaxrs-resteasy-eap.md)
|
||||
* [jaxrs-spec](generators/jaxrs-spec.md)
|
||||
* [kotlin-server](generators/kotlin-server.md)
|
||||
* [kotlin-server-deprecated](generators/kotlin-server-deprecated.md)
|
||||
* [kotlin-spring](generators/kotlin-spring.md)
|
||||
* [kotlin-vertx (beta)](generators/kotlin-vertx.md)
|
||||
* [nodejs-express-server (beta)](generators/nodejs-express-server.md)
|
||||
|
@ -91,6 +91,7 @@ The following generators are available:
|
||||
* [jaxrs-resteasy-eap](jaxrs-resteasy-eap.md)
|
||||
* [jaxrs-spec](jaxrs-spec.md)
|
||||
* [kotlin-server](kotlin-server.md)
|
||||
* [kotlin-server-deprecated](kotlin-server-deprecated.md)
|
||||
* [kotlin-spring](kotlin-spring.md)
|
||||
* [kotlin-vertx (beta)](kotlin-vertx.md)
|
||||
* [nodejs-express-server (beta)](nodejs-express-server.md)
|
||||
|
214
docs/generators/kotlin-server-deprecated.md
Normal file
214
docs/generators/kotlin-server-deprecated.md
Normal file
@ -0,0 +1,214 @@
|
||||
---
|
||||
title: Config Options for kotlin-server-deprecated
|
||||
sidebar_label: kotlin-server-deprecated
|
||||
---
|
||||
|
||||
These options may be applied as additional-properties (cli) or configOptions (plugins). Refer to [configuration docs](https://openapi-generator.tech/docs/configuration) for more details.
|
||||
|
||||
| Option | Description | Values | Default |
|
||||
| ------ | ----------- | ------ | ------- |
|
||||
|apiSuffix|suffix for api classes| |Api|
|
||||
|artifactId|Generated artifact id (name of jar).| |kotlin-server-deprecated|
|
||||
|artifactVersion|Generated artifact's package version.| |1.0.0|
|
||||
|enumPropertyNaming|Naming convention for enum properties: 'camelCase', 'PascalCase', 'snake_case', 'UPPERCASE', and 'original'| |camelCase|
|
||||
|featureAutoHead|Automatically provide responses to HEAD requests for existing routes that have the GET verb defined.| |true|
|
||||
|featureCORS|Ktor by default provides an interceptor for implementing proper support for Cross-Origin Resource Sharing (CORS). See enable-cors.org.| |false|
|
||||
|featureCompression|Adds ability to compress outgoing content using gzip, deflate or custom encoder and thus reduce size of the response.| |true|
|
||||
|featureConditionalHeaders|Avoid sending content if client already has same content, by checking ETag or LastModified properties.| |false|
|
||||
|featureHSTS|Avoid sending content if client already has same content, by checking ETag or LastModified properties.| |true|
|
||||
|groupId|Generated artifact package's organization (i.e. maven groupId).| |org.openapitools|
|
||||
|library|library template (sub-template)|<dl><dt>**ktor**</dt><dd>ktor framework</dd></dl>|ktor|
|
||||
|modelMutable|Create mutable models| |false|
|
||||
|packageName|Generated artifact package name.| |org.openapitools.server|
|
||||
|parcelizeModels|toggle "@Parcelize" for generated models| |null|
|
||||
|serializableModel|boolean - toggle "implements Serializable" for generated models| |null|
|
||||
|serializationLibrary|What serialization library to use: 'moshi' (default), or 'gson' or 'jackson'| |moshi|
|
||||
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |null|
|
||||
|sortParamsByRequiredFlag|Sort method arguments to place required parameters before optional parameters.| |null|
|
||||
|sourceFolder|source folder for generated code| |src/main/kotlin|
|
||||
|
||||
## IMPORT MAPPING
|
||||
|
||||
| Type/Alias | Imports |
|
||||
| ---------- | ------- |
|
||||
|BigDecimal|java.math.BigDecimal|
|
||||
|Date|java.time.LocalDate|
|
||||
|DateTime|java.time.OffsetDateTime|
|
||||
|File|java.io.File|
|
||||
|LocalDate|java.time.LocalDate|
|
||||
|LocalDateTime|java.time.LocalDateTime|
|
||||
|LocalTime|java.time.LocalTime|
|
||||
|Timestamp|java.sql.Timestamp|
|
||||
|URI|java.net.URI|
|
||||
|UUID|java.util.UUID|
|
||||
|
||||
|
||||
## INSTANTIATION TYPES
|
||||
|
||||
| Type/Alias | Instantiated By |
|
||||
| ---------- | --------------- |
|
||||
|array|kotlin.collections.ArrayList|
|
||||
|list|kotlin.collections.ArrayList|
|
||||
|map|kotlin.collections.HashMap|
|
||||
|
||||
|
||||
## LANGUAGE PRIMITIVES
|
||||
|
||||
<ul class="column-ul">
|
||||
<li>kotlin.Array</li>
|
||||
<li>kotlin.Boolean</li>
|
||||
<li>kotlin.Byte</li>
|
||||
<li>kotlin.ByteArray</li>
|
||||
<li>kotlin.Char</li>
|
||||
<li>kotlin.Double</li>
|
||||
<li>kotlin.Float</li>
|
||||
<li>kotlin.Int</li>
|
||||
<li>kotlin.Long</li>
|
||||
<li>kotlin.Short</li>
|
||||
<li>kotlin.String</li>
|
||||
<li>kotlin.collections.List</li>
|
||||
<li>kotlin.collections.Map</li>
|
||||
<li>kotlin.collections.Set</li>
|
||||
</ul>
|
||||
|
||||
## RESERVED WORDS
|
||||
|
||||
<ul class="column-ul">
|
||||
<li>as</li>
|
||||
<li>break</li>
|
||||
<li>class</li>
|
||||
<li>continue</li>
|
||||
<li>do</li>
|
||||
<li>else</li>
|
||||
<li>false</li>
|
||||
<li>for</li>
|
||||
<li>fun</li>
|
||||
<li>if</li>
|
||||
<li>in</li>
|
||||
<li>interface</li>
|
||||
<li>is</li>
|
||||
<li>null</li>
|
||||
<li>object</li>
|
||||
<li>package</li>
|
||||
<li>return</li>
|
||||
<li>super</li>
|
||||
<li>this</li>
|
||||
<li>throw</li>
|
||||
<li>true</li>
|
||||
<li>try</li>
|
||||
<li>typealias</li>
|
||||
<li>typeof</li>
|
||||
<li>val</li>
|
||||
<li>var</li>
|
||||
<li>when</li>
|
||||
<li>while</li>
|
||||
</ul>
|
||||
|
||||
## FEATURE SET
|
||||
|
||||
|
||||
### Client Modification Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|BasePath|✗|ToolingExtension
|
||||
|Authorizations|✗|ToolingExtension
|
||||
|UserAgent|✗|ToolingExtension
|
||||
|MockServer|✗|ToolingExtension
|
||||
|
||||
### Data Type Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|Custom|✗|OAS2,OAS3
|
||||
|Int32|✓|OAS2,OAS3
|
||||
|Int64|✓|OAS2,OAS3
|
||||
|Float|✓|OAS2,OAS3
|
||||
|Double|✓|OAS2,OAS3
|
||||
|Decimal|✓|ToolingExtension
|
||||
|String|✓|OAS2,OAS3
|
||||
|Byte|✓|OAS2,OAS3
|
||||
|Binary|✓|OAS2,OAS3
|
||||
|Boolean|✓|OAS2,OAS3
|
||||
|Date|✓|OAS2,OAS3
|
||||
|DateTime|✓|OAS2,OAS3
|
||||
|Password|✓|OAS2,OAS3
|
||||
|File|✓|OAS2
|
||||
|Array|✓|OAS2,OAS3
|
||||
|Maps|✓|ToolingExtension
|
||||
|CollectionFormat|✓|OAS2
|
||||
|CollectionFormatMulti|✓|OAS2
|
||||
|Enum|✓|OAS2,OAS3
|
||||
|ArrayOfEnum|✓|ToolingExtension
|
||||
|ArrayOfModel|✓|ToolingExtension
|
||||
|ArrayOfCollectionOfPrimitives|✓|ToolingExtension
|
||||
|ArrayOfCollectionOfModel|✓|ToolingExtension
|
||||
|ArrayOfCollectionOfEnum|✓|ToolingExtension
|
||||
|MapOfEnum|✓|ToolingExtension
|
||||
|MapOfModel|✓|ToolingExtension
|
||||
|MapOfCollectionOfPrimitives|✓|ToolingExtension
|
||||
|MapOfCollectionOfModel|✓|ToolingExtension
|
||||
|MapOfCollectionOfEnum|✓|ToolingExtension
|
||||
|
||||
### Documentation Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|Readme|✓|ToolingExtension
|
||||
|Model|✓|ToolingExtension
|
||||
|Api|✓|ToolingExtension
|
||||
|
||||
### Global Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|Host|✓|OAS2,OAS3
|
||||
|BasePath|✓|OAS2,OAS3
|
||||
|Info|✓|OAS2,OAS3
|
||||
|Schemes|✗|OAS2,OAS3
|
||||
|PartialSchemes|✓|OAS2,OAS3
|
||||
|Consumes|✓|OAS2
|
||||
|Produces|✓|OAS2
|
||||
|ExternalDocumentation|✓|OAS2,OAS3
|
||||
|Examples|✓|OAS2,OAS3
|
||||
|XMLStructureDefinitions|✗|OAS2,OAS3
|
||||
|MultiServer|✗|OAS3
|
||||
|ParameterizedServer|✗|OAS3
|
||||
|ParameterStyling|✗|OAS3
|
||||
|Callbacks|✗|OAS3
|
||||
|LinkObjects|✗|OAS3
|
||||
|
||||
### Parameter Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|Path|✓|OAS2,OAS3
|
||||
|Query|✓|OAS2,OAS3
|
||||
|Header|✓|OAS2,OAS3
|
||||
|Body|✓|OAS2
|
||||
|FormUnencoded|✓|OAS2
|
||||
|FormMultipart|✓|OAS2
|
||||
|Cookie|✗|OAS3
|
||||
|
||||
### Schema Support Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|Simple|✓|OAS2,OAS3
|
||||
|Composite|✓|OAS2,OAS3
|
||||
|Polymorphism|✗|OAS2,OAS3
|
||||
|Union|✗|OAS3
|
||||
|
||||
### Security Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|BasicAuth|✓|OAS2,OAS3
|
||||
|ApiKey|✓|OAS2,OAS3
|
||||
|OpenIDConnect|✗|OAS3
|
||||
|BearerToken|✗|OAS3
|
||||
|OAuth2_Implicit|✓|OAS2,OAS3
|
||||
|OAuth2_Password|✗|OAS2,OAS3
|
||||
|OAuth2_ClientCredentials|✗|OAS2,OAS3
|
||||
|OAuth2_AuthorizationCode|✗|OAS2,OAS3
|
||||
|
||||
### Wire Format Feature
|
||||
| Name | Supported | Defined By |
|
||||
| ---- | --------- | ---------- |
|
||||
|JSON|✓|OAS2,OAS3
|
||||
|XML|✓|OAS2,OAS3
|
||||
|PROTOBUF|✗|ToolingExtension
|
||||
|Custom|✗|OAS2,OAS3
|
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
|
||||
* Copyright 2018 SmartBear Software
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.openapitools.codegen.languages;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.openapitools.codegen.CliOption;
|
||||
import org.openapitools.codegen.CodegenConstants;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.SupportingFile;
|
||||
import org.openapitools.codegen.meta.features.*;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class KotlinServerDeprecatedCodegen extends AbstractKotlinCodegen {
|
||||
|
||||
public static final String DEFAULT_LIBRARY = Constants.KTOR;
|
||||
private final Logger LOGGER = LoggerFactory.getLogger(KotlinServerDeprecatedCodegen.class);
|
||||
private Boolean autoHeadFeatureEnabled = true;
|
||||
private Boolean conditionalHeadersFeatureEnabled = false;
|
||||
private Boolean hstsFeatureEnabled = true;
|
||||
private Boolean corsFeatureEnabled = false;
|
||||
private Boolean compressionFeatureEnabled = true;
|
||||
|
||||
// This is here to potentially warn the user when an option is not supported by the target framework.
|
||||
private Map<String, List<String>> optionsSupportedPerFramework = new ImmutableMap.Builder<String, List<String>>()
|
||||
.put(Constants.KTOR, Arrays.asList(
|
||||
Constants.AUTOMATIC_HEAD_REQUESTS,
|
||||
Constants.CONDITIONAL_HEADERS,
|
||||
Constants.HSTS,
|
||||
Constants.CORS,
|
||||
Constants.COMPRESSION
|
||||
))
|
||||
.build();
|
||||
|
||||
/**
|
||||
* Constructs an instance of `KotlinServerCodegen`.
|
||||
*/
|
||||
public KotlinServerDeprecatedCodegen() {
|
||||
super();
|
||||
|
||||
modifyFeatureSet(features -> features
|
||||
.includeDocumentationFeatures(DocumentationFeature.Readme)
|
||||
.wireFormatFeatures(EnumSet.of(WireFormatFeature.JSON, WireFormatFeature.XML))
|
||||
.securityFeatures(EnumSet.of(
|
||||
SecurityFeature.BasicAuth,
|
||||
SecurityFeature.ApiKey,
|
||||
SecurityFeature.OAuth2_Implicit
|
||||
))
|
||||
.excludeGlobalFeatures(
|
||||
GlobalFeature.XMLStructureDefinitions,
|
||||
GlobalFeature.Callbacks,
|
||||
GlobalFeature.LinkObjects,
|
||||
GlobalFeature.ParameterStyling
|
||||
)
|
||||
.excludeSchemaSupportFeatures(
|
||||
SchemaSupportFeature.Polymorphism
|
||||
)
|
||||
.excludeParameterFeatures(
|
||||
ParameterFeature.Cookie
|
||||
)
|
||||
);
|
||||
|
||||
artifactId = "kotlin-server-deprecated";
|
||||
packageName = "org.openapitools.server";
|
||||
|
||||
// cliOptions default redefinition need to be updated
|
||||
updateOption(CodegenConstants.ARTIFACT_ID, this.artifactId);
|
||||
updateOption(CodegenConstants.PACKAGE_NAME, this.packageName);
|
||||
|
||||
outputFolder = "generated-code" + File.separator + "kotlin-server-deprecated";
|
||||
modelTemplateFiles.put("model.mustache", ".kt");
|
||||
apiTemplateFiles.put("api.mustache", ".kt");
|
||||
embeddedTemplateDir = templateDir = "kotlin-server-deprecated";
|
||||
apiPackage = packageName + ".apis";
|
||||
modelPackage = packageName + ".models";
|
||||
|
||||
supportedLibraries.put(Constants.KTOR, "ktor framework");
|
||||
|
||||
// TODO: Configurable server engine. Defaults to netty in build.gradle.
|
||||
CliOption library = new CliOption(CodegenConstants.LIBRARY, CodegenConstants.LIBRARY_DESC);
|
||||
library.setDefault(DEFAULT_LIBRARY);
|
||||
library.setEnum(supportedLibraries);
|
||||
|
||||
cliOptions.add(library);
|
||||
|
||||
addSwitch(Constants.AUTOMATIC_HEAD_REQUESTS, Constants.AUTOMATIC_HEAD_REQUESTS_DESC, getAutoHeadFeatureEnabled());
|
||||
addSwitch(Constants.CONDITIONAL_HEADERS, Constants.CONDITIONAL_HEADERS_DESC, getConditionalHeadersFeatureEnabled());
|
||||
addSwitch(Constants.HSTS, Constants.HSTS_DESC, getHstsFeatureEnabled());
|
||||
addSwitch(Constants.CORS, Constants.CORS_DESC, getCorsFeatureEnabled());
|
||||
addSwitch(Constants.COMPRESSION, Constants.COMPRESSION_DESC, getCompressionFeatureEnabled());
|
||||
}
|
||||
|
||||
public Boolean getAutoHeadFeatureEnabled() {
|
||||
return autoHeadFeatureEnabled;
|
||||
}
|
||||
|
||||
public void setAutoHeadFeatureEnabled(Boolean autoHeadFeatureEnabled) {
|
||||
this.autoHeadFeatureEnabled = autoHeadFeatureEnabled;
|
||||
}
|
||||
|
||||
public Boolean getCompressionFeatureEnabled() {
|
||||
return compressionFeatureEnabled;
|
||||
}
|
||||
|
||||
public void setCompressionFeatureEnabled(Boolean compressionFeatureEnabled) {
|
||||
this.compressionFeatureEnabled = compressionFeatureEnabled;
|
||||
}
|
||||
|
||||
public Boolean getConditionalHeadersFeatureEnabled() {
|
||||
return conditionalHeadersFeatureEnabled;
|
||||
}
|
||||
|
||||
public void setConditionalHeadersFeatureEnabled(Boolean conditionalHeadersFeatureEnabled) {
|
||||
this.conditionalHeadersFeatureEnabled = conditionalHeadersFeatureEnabled;
|
||||
}
|
||||
|
||||
public Boolean getCorsFeatureEnabled() {
|
||||
return corsFeatureEnabled;
|
||||
}
|
||||
|
||||
public void setCorsFeatureEnabled(Boolean corsFeatureEnabled) {
|
||||
this.corsFeatureEnabled = corsFeatureEnabled;
|
||||
}
|
||||
|
||||
public String getHelp() {
|
||||
return "Generates a Kotlin server.";
|
||||
}
|
||||
|
||||
public Boolean getHstsFeatureEnabled() {
|
||||
return hstsFeatureEnabled;
|
||||
}
|
||||
|
||||
public void setHstsFeatureEnabled(Boolean hstsFeatureEnabled) {
|
||||
this.hstsFeatureEnabled = hstsFeatureEnabled;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return "kotlin-server-deprecated";
|
||||
}
|
||||
|
||||
public CodegenType getTag() {
|
||||
return CodegenType.SERVER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void processOpts() {
|
||||
super.processOpts();
|
||||
|
||||
if (additionalProperties.containsKey(CodegenConstants.LIBRARY)) {
|
||||
this.setLibrary((String) additionalProperties.get(CodegenConstants.LIBRARY));
|
||||
}
|
||||
|
||||
// set default library to "ktor"
|
||||
if (StringUtils.isEmpty(library)) {
|
||||
this.setLibrary(DEFAULT_LIBRARY);
|
||||
additionalProperties.put(CodegenConstants.LIBRARY, DEFAULT_LIBRARY);
|
||||
LOGGER.info("`library` option is empty. Default to " + DEFAULT_LIBRARY);
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(Constants.AUTOMATIC_HEAD_REQUESTS)) {
|
||||
setAutoHeadFeatureEnabled(convertPropertyToBooleanAndWriteBack(Constants.AUTOMATIC_HEAD_REQUESTS));
|
||||
} else {
|
||||
additionalProperties.put(Constants.AUTOMATIC_HEAD_REQUESTS, getAutoHeadFeatureEnabled());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(Constants.CONDITIONAL_HEADERS)) {
|
||||
setConditionalHeadersFeatureEnabled(convertPropertyToBooleanAndWriteBack(Constants.CONDITIONAL_HEADERS));
|
||||
} else {
|
||||
additionalProperties.put(Constants.CONDITIONAL_HEADERS, getConditionalHeadersFeatureEnabled());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(Constants.HSTS)) {
|
||||
setHstsFeatureEnabled(convertPropertyToBooleanAndWriteBack(Constants.HSTS));
|
||||
} else {
|
||||
additionalProperties.put(Constants.HSTS, getHstsFeatureEnabled());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(Constants.CORS)) {
|
||||
setCorsFeatureEnabled(convertPropertyToBooleanAndWriteBack(Constants.CORS));
|
||||
} else {
|
||||
additionalProperties.put(Constants.CORS, getCorsFeatureEnabled());
|
||||
}
|
||||
|
||||
if (additionalProperties.containsKey(Constants.COMPRESSION)) {
|
||||
setCompressionFeatureEnabled(convertPropertyToBooleanAndWriteBack(Constants.COMPRESSION));
|
||||
} else {
|
||||
additionalProperties.put(Constants.COMPRESSION, getCompressionFeatureEnabled());
|
||||
}
|
||||
|
||||
boolean generateApis = additionalProperties.containsKey(CodegenConstants.GENERATE_APIS) && (Boolean) additionalProperties.get(CodegenConstants.GENERATE_APIS);
|
||||
String packageFolder = (sourceFolder + File.separator + packageName).replace(".", File.separator);
|
||||
String resourcesFolder = "src/main/resources"; // not sure this can be user configurable.
|
||||
|
||||
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
|
||||
supportingFiles.add(new SupportingFile("Dockerfile.mustache", "", "Dockerfile"));
|
||||
|
||||
supportingFiles.add(new SupportingFile("build.gradle.mustache", "", "build.gradle"));
|
||||
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
|
||||
supportingFiles.add(new SupportingFile("gradle.properties", "", "gradle.properties"));
|
||||
|
||||
supportingFiles.add(new SupportingFile("AppMain.kt.mustache", packageFolder, "AppMain.kt"));
|
||||
supportingFiles.add(new SupportingFile("Configuration.kt.mustache", packageFolder, "Configuration.kt"));
|
||||
|
||||
if (generateApis) {
|
||||
supportingFiles.add(new SupportingFile("Paths.kt.mustache", packageFolder, "Paths.kt"));
|
||||
}
|
||||
|
||||
supportingFiles.add(new SupportingFile("application.conf.mustache", resourcesFolder, "application.conf"));
|
||||
supportingFiles.add(new SupportingFile("logback.xml", resourcesFolder, "logback.xml"));
|
||||
|
||||
final String infrastructureFolder = (sourceFolder + File.separator + packageName + File.separator + "infrastructure").replace(".", File.separator);
|
||||
|
||||
supportingFiles.add(new SupportingFile("ApiKeyAuth.kt.mustache", infrastructureFolder, "ApiKeyAuth.kt"));
|
||||
}
|
||||
|
||||
public static class Constants {
|
||||
public final static String KTOR = "ktor";
|
||||
public final static String AUTOMATIC_HEAD_REQUESTS = "featureAutoHead";
|
||||
public final static String AUTOMATIC_HEAD_REQUESTS_DESC = "Automatically provide responses to HEAD requests for existing routes that have the GET verb defined.";
|
||||
public final static String CONDITIONAL_HEADERS = "featureConditionalHeaders";
|
||||
public final static String CONDITIONAL_HEADERS_DESC = "Avoid sending content if client already has same content, by checking ETag or LastModified properties.";
|
||||
public final static String HSTS = "featureHSTS";
|
||||
public final static String HSTS_DESC = "Avoid sending content if client already has same content, by checking ETag or LastModified properties.";
|
||||
public final static String CORS = "featureCORS";
|
||||
public final static String CORS_DESC = "Ktor by default provides an interceptor for implementing proper support for Cross-Origin Resource Sharing (CORS). See enable-cors.org.";
|
||||
public final static String COMPRESSION = "featureCompression";
|
||||
public final static String COMPRESSION_DESC = "Adds ability to compress outgoing content using gzip, deflate or custom encoder and thus reduce size of the response.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postProcess() {
|
||||
System.out.println("################################################################################");
|
||||
System.out.println("# Thanks for using OpenAPI Generator. #");
|
||||
System.out.println("# Please consider donation to help us maintain this project \uD83D\uDE4F #");
|
||||
System.out.println("# https://opencollective.com/openapi_generator/donate #");
|
||||
System.out.println("# #");
|
||||
System.out.println("# This generator's contributed by Jim Schubert (https://github.com/jimschubert)#");
|
||||
System.out.println("# Please support his work directly via https://patreon.com/jimschubert \uD83D\uDE4F #");
|
||||
System.out.println("################################################################################");
|
||||
}
|
||||
}
|
@ -44,6 +44,7 @@ org.openapitools.codegen.languages.GraphQLNodeJSExpressServerCodegen
|
||||
org.openapitools.codegen.languages.GroovyClientCodegen
|
||||
org.openapitools.codegen.languages.KotlinClientCodegen
|
||||
org.openapitools.codegen.languages.KotlinServerCodegen
|
||||
org.openapitools.codegen.languages.KotlinServerDeprecatedCodegen
|
||||
org.openapitools.codegen.languages.KotlinSpringServerCodegen
|
||||
org.openapitools.codegen.languages.KotlinVertxServerCodegen
|
||||
org.openapitools.codegen.languages.KtormSchemaCodegen
|
||||
|
84
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/README.mustache
vendored
Normal file
84
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/README.mustache
vendored
Normal file
@ -0,0 +1,84 @@
|
||||
# {{packageName}} - Kotlin Server library for {{appName}}
|
||||
|
||||
## Requires
|
||||
|
||||
* Kotlin 1.1.2
|
||||
* Gradle 3.3
|
||||
|
||||
## Build
|
||||
|
||||
First, create the gradle wrapper script:
|
||||
|
||||
```
|
||||
gradle wrapper
|
||||
```
|
||||
|
||||
Then, run:
|
||||
|
||||
```
|
||||
./gradlew check assemble
|
||||
```
|
||||
|
||||
This runs all tests and packages the library.
|
||||
|
||||
## Features/Implementation Notes
|
||||
|
||||
* Supports JSON inputs/outputs, File inputs, and Form inputs.
|
||||
* 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 name="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}}{{{summary}}}{{/summary}}
|
||||
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
|
||||
{{/generateApiDocs}}
|
||||
|
||||
{{#generateModelDocs}}
|
||||
<a name="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 name="documentation-for-authorization"></a>{{! TODO: optional documentation for authorization? }}
|
||||
## Documentation for Authorization
|
||||
|
||||
{{^authMethods}}
|
||||
All endpoints do not require authorization.
|
||||
{{/authMethods}}
|
||||
{{#authMethods}}
|
||||
{{#last}}
|
||||
Authentication schemes defined for the API:
|
||||
{{/last}}
|
||||
{{/authMethods}}
|
||||
{{#authMethods}}
|
||||
<a name="{{name}}"></a>
|
||||
### {{name}}
|
||||
|
||||
{{#isApiKey}}- **Type**: API key
|
||||
- **API key parameter name**: {{keyParamName}}
|
||||
- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}}
|
||||
{{/isApiKey}}
|
||||
{{#isBasic}}- **Type**: HTTP basic authentication
|
||||
{{/isBasic}}
|
||||
{{#isOAuth}}- **Type**: OAuth
|
||||
- **Flow**: {{flow}}
|
||||
- **Authorization URL**: {{authorizationUrl}}
|
||||
- **Scopes**: {{^scopes}}N/A{{/scopes}}
|
||||
{{#scopes}} - {{scope}}: {{description}}
|
||||
{{/scopes}}
|
||||
{{/isOAuth}}
|
||||
|
||||
{{/authMethods}}
|
65
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/api_doc.mustache
vendored
Normal file
65
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/api_doc.mustache
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
# {{classname}}{{#description}}
|
||||
{{description}}{{/description}}
|
||||
|
||||
All URIs are relative to *{{basePath}}*
|
||||
|
||||
Method | HTTP request | Description
|
||||
------------- | ------------- | -------------
|
||||
{{#operations}}{{#operation}}[**{{operationId}}**]({{classname}}.md#{{operationId}}) | **{{httpMethod}}** {{path}} | {{#summary}}{{summary}}{{/summary}}
|
||||
{{/operation}}{{/operations}}
|
||||
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
<a name="{{operationId}}"></a>
|
||||
# **{{operationId}}**
|
||||
> {{#returnType}}{{returnType}} {{/returnType}}{{operationId}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}})
|
||||
|
||||
{{summary}}{{#notes}}
|
||||
|
||||
{{notes}}{{/notes}}
|
||||
|
||||
### Example
|
||||
```kotlin
|
||||
// Import classes:
|
||||
//import {{{packageName}}}.infrastructure.*
|
||||
//import {{{modelPackage}}}.*
|
||||
|
||||
{{! TODO: Auth method documentation examples}}
|
||||
val apiInstance = {{{classname}}}()
|
||||
{{#allParams}}
|
||||
val {{{paramName}}} : {{{dataType}}} = {{{example}}} // {{{dataType}}} | {{{description}}}
|
||||
{{/allParams}}
|
||||
try {
|
||||
{{#returnType}}val result : {{{returnType}}} = {{/returnType}}apiInstance.{{{operationId}}}({{#allParams}}{{{paramName}}}{{^-last}}, {{/-last}}{{/allParams}}){{#returnType}}
|
||||
println(result){{/returnType}}
|
||||
} catch (e: ClientException) {
|
||||
println("4xx response calling {{{classname}}}#{{{operationId}}}")
|
||||
e.printStackTrace()
|
||||
} catch (e: ServerException) {
|
||||
println("5xx response calling {{{classname}}}#{{{operationId}}}")
|
||||
e.printStackTrace()
|
||||
}
|
||||
```
|
||||
|
||||
### Parameters
|
||||
{{^allParams}}This endpoint does not need any parameter.{{/allParams}}{{#allParams}}{{#-last}}
|
||||
Name | Type | Description | Notes
|
||||
------------- | ------------- | ------------- | -------------{{/-last}}{{/allParams}}
|
||||
{{#allParams}} **{{paramName}}** | {{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}{{#isFile}}**{{dataType}}**{{/isFile}}{{^isFile}}{{#generateModelDocs}}[**{{dataType}}**]({{baseType}}.md){{/generateModelDocs}}{{^generateModelDocs}}**{{dataType}}**{{/generateModelDocs}}{{/isFile}}{{/isPrimitiveType}}| {{description}} |{{^required}} [optional]{{/required}}{{#defaultValue}} [default to {{defaultValue}}]{{/defaultValue}}{{#allowableValues}} [enum: {{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}]{{/allowableValues}}
|
||||
{{/allParams}}
|
||||
|
||||
### Return type
|
||||
|
||||
{{#returnType}}{{#returnTypeIsPrimitive}}**{{returnType}}**{{/returnTypeIsPrimitive}}{{^returnTypeIsPrimitive}}{{#generateModelDocs}}[**{{returnType}}**]({{returnBaseType}}.md){{/generateModelDocs}}{{^generateModelDocs}}**{{returnType}}**{{/generateModelDocs}}{{/returnTypeIsPrimitive}}{{/returnType}}{{^returnType}}null (empty response body){{/returnType}}
|
||||
|
||||
### Authorization
|
||||
|
||||
{{^authMethods}}No authorization required{{/authMethods}}{{#authMethods}}[{{name}}](../README.md#{{name}}){{^-last}}, {{/-last}}{{/authMethods}}
|
||||
|
||||
### HTTP request headers
|
||||
|
||||
- **Content-Type**: {{#consumes}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/consumes}}{{^consumes}}Not defined{{/consumes}}
|
||||
- **Accept**: {{#produces}}{{{mediaType}}}{{^-last}}, {{/-last}}{{/produces}}{{^produces}}Not defined{{/produces}}
|
||||
|
||||
{{/operation}}
|
||||
{{/operations}}
|
15
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/class_doc.mustache
vendored
Normal file
15
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/class_doc.mustache
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
# {{classname}}
|
||||
|
||||
## Properties
|
||||
Name | Type | Description | Notes
|
||||
------------ | ------------- | ------------- | -------------
|
||||
{{#vars}}**{{name}}** | {{#isEnum}}[**inline**](#{{datatypeWithEnum}}){{/isEnum}}{{^isEnum}}{{#isPrimitiveType}}**{{dataType}}**{{/isPrimitiveType}}{{^isPrimitiveType}}[**{{dataType}}**]({{complexType}}.md){{/isPrimitiveType}}{{/isEnum}} | {{description}} | {{^required}} [optional]{{/required}}{{#isReadOnly}} [readonly]{{/isReadOnly}}
|
||||
{{/vars}}
|
||||
{{#vars}}{{#isEnum}}
|
||||
|
||||
<a name="{{{datatypeWithEnum}}}"></a>{{!NOTE: see java's resources "pojo_doc.mustache" once enums are fully implemented}}
|
||||
## Enum: {{baseName}}
|
||||
Name | Value
|
||||
---- | -----{{#allowableValues}}
|
||||
{{name}} | {{#values}}{{.}}{{^-last}}, {{/-last}}{{/values}}{{/allowableValues}}
|
||||
{{/isEnum}}{{/vars}}
|
52
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/data_class.mustache
vendored
Normal file
52
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/data_class.mustache
vendored
Normal file
@ -0,0 +1,52 @@
|
||||
{{#parcelizeModels}}
|
||||
import android.os.Parcelable
|
||||
import kotlinx.parcelize.Parcelize
|
||||
|
||||
{{/parcelizeModels}}
|
||||
{{#serializableModel}}
|
||||
import java.io.Serializable
|
||||
{{/serializableModel}}
|
||||
/**
|
||||
* {{{description}}}
|
||||
{{#vars}}
|
||||
* @param {{name}} {{{description}}}
|
||||
{{/vars}}
|
||||
*/
|
||||
{{#parcelizeModels}}
|
||||
@Parcelize
|
||||
{{/parcelizeModels}}
|
||||
data class {{classname}} (
|
||||
{{#requiredVars}}
|
||||
{{>data_class_req_var}}{{^-last}},
|
||||
{{/-last}}{{/requiredVars}}{{#hasRequired}}{{#hasOptional}},
|
||||
{{/hasOptional}}{{/hasRequired}}{{#optionalVars}}{{>data_class_opt_var}}{{^-last}},
|
||||
{{/-last}}{{/optionalVars}}
|
||||
) {{^serializableModel}}{{#parcelizeModels}} : Parcelable{{/parcelizeModels}}{{/serializableModel}}{{^parcelizeModels}}{{#serializableModel}}: Serializable {{/serializableModel}}{{/parcelizeModels}}{{#parcelizeModels}}{{#serializableModel}} : Parcelable, Serializable {{/serializableModel}}{{/parcelizeModels}}
|
||||
{{#vendorExtensions.x-has-data-class-body}}
|
||||
{
|
||||
{{/vendorExtensions.x-has-data-class-body}}
|
||||
{{#serializableModel}}
|
||||
companion object {
|
||||
private const val serialVersionUID: Long = 123
|
||||
}
|
||||
{{/serializableModel}}
|
||||
{{#hasEnums}}
|
||||
{{#vars}}
|
||||
{{#isEnum}}
|
||||
/**
|
||||
* {{{description}}}
|
||||
* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}}
|
||||
*/
|
||||
enum class {{nameInCamelCase}}(val value: {{dataType}}){
|
||||
{{#allowableValues}}
|
||||
{{#enumVars}}
|
||||
{{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
|
||||
{{/enumVars}}
|
||||
{{/allowableValues}}
|
||||
}
|
||||
{{/isEnum}}
|
||||
{{/vars}}
|
||||
{{/hasEnums}}
|
||||
{{#vendorExtensions.x-has-data-class-body}}
|
||||
}
|
||||
{{/vendorExtensions.x-has-data-class-body}}
|
@ -0,0 +1,4 @@
|
||||
{{#description}}
|
||||
/* {{{description}}} */
|
||||
{{/description}}
|
||||
{{>modelMutable}} {{{name}}}: {{#isEnum}}{{classname}}.{{nameInCamelCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{#defaultvalue}}{{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}null{{/defaultvalue}}
|
@ -0,0 +1,4 @@
|
||||
{{#description}}
|
||||
/* {{{description}}} */
|
||||
{{/description}}
|
||||
{{>modelMutable}} {{{name}}}: {{#isEnum}}{{classname}}.{{nameInCamelCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}
|
9
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/enum_class.mustache
vendored
Normal file
9
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/enum_class.mustache
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
/**
|
||||
* {{{description}}}
|
||||
* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}}
|
||||
*/
|
||||
enum class {{classname}}(val value: {{dataType}}){
|
||||
{{#allowableValues}}{{#enumVars}}
|
||||
{{&name}}({{{value}}}){{^-last}},{{/-last}}{{#-last}};{{/-last}}
|
||||
{{/enumVars}}{{/allowableValues}}
|
||||
}
|
7
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/enum_doc.mustache
vendored
Normal file
7
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/enum_doc.mustache
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
# {{classname}}
|
||||
|
||||
## Enum
|
||||
|
||||
{{#allowableValues}}{{#enumVars}}
|
||||
* `{{name}}` (value: `{{{value}}}`)
|
||||
{{/enumVars}}{{/allowableValues}}
|
@ -0,0 +1,85 @@
|
||||
package {{packageName}}.infrastructure
|
||||
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.application.call
|
||||
import io.ktor.auth.Authentication
|
||||
import io.ktor.auth.AuthenticationFailedCause
|
||||
import io.ktor.auth.AuthenticationPipeline
|
||||
import io.ktor.auth.AuthenticationProvider
|
||||
import io.ktor.auth.Credential
|
||||
import io.ktor.auth.Principal
|
||||
import io.ktor.auth.UnauthorizedResponse
|
||||
import io.ktor.http.auth.HeaderValueEncoding
|
||||
import io.ktor.http.auth.HttpAuthHeader
|
||||
import io.ktor.request.ApplicationRequest
|
||||
import io.ktor.response.respond
|
||||
|
||||
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 a Api Key authentication provider
|
||||
* @param name is the name of the provider, or `null` for a default provider
|
||||
*/
|
||||
class ApiKeyAuthenticationProvider(name: String?) : AuthenticationProvider(name) {
|
||||
internal var authenticationFunction: suspend ApplicationCall.(ApiKeyCredential) -> Principal? = { null }
|
||||
|
||||
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 Authentication.Configuration.apiKeyAuth(name: String? = null, configure: ApiKeyAuthenticationProvider.() -> Unit) {
|
||||
val provider = ApiKeyAuthenticationProvider(name).apply(configure)
|
||||
val apiKeyName = provider.apiKeyName
|
||||
val apiKeyLocation = provider.apiKeyLocation
|
||||
val authenticate = provider.authenticationFunction
|
||||
|
||||
provider.pipeline.intercept(AuthenticationPipeline.RequestAuthentication) { context ->
|
||||
val credentials = call.request.apiKeyAuthenticationCredentials(apiKeyName, apiKeyLocation)
|
||||
val principal = credentials?.let { authenticate(call, it) }
|
||||
|
||||
val cause = when {
|
||||
credentials == null -> AuthenticationFailedCause.NoCredentials
|
||||
principal == null -> AuthenticationFailedCause.InvalidCredentials
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (cause != null) {
|
||||
context.challenge(apiKeyName, cause) {
|
||||
// TODO: Verify correct response structure here.
|
||||
call.respond(UnauthorizedResponse(HttpAuthHeader.Parameterized("API_KEY", mapOf("key" to apiKeyName), HeaderValueEncoding.QUOTED_ALWAYS)))
|
||||
it.complete()
|
||||
}
|
||||
}
|
||||
|
||||
if (principal != null) {
|
||||
context.principal(principal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun ApplicationRequest.apiKeyAuthenticationCredentials(apiKeyName: String, apiKeyLocation: ApiKeyLocation): ApiKeyCredential? {
|
||||
val value: String? = when(apiKeyLocation) {
|
||||
ApiKeyLocation.QUERY -> this.queryParameters[apiKeyName]
|
||||
ApiKeyLocation.HEADER -> this.headers[apiKeyName]
|
||||
}
|
||||
when (value) {
|
||||
null -> return null
|
||||
else -> return ApiKeyCredential(value)
|
||||
}
|
||||
}
|
@ -0,0 +1,145 @@
|
||||
package {{packageName}}
|
||||
|
||||
import com.codahale.metrics.Slf4jReporter
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import io.ktor.application.Application
|
||||
import io.ktor.application.ApplicationStopping
|
||||
import io.ktor.application.install
|
||||
import io.ktor.application.log
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.apache.Apache
|
||||
import io.ktor.config.HoconApplicationConfig
|
||||
{{#featureAutoHead}}
|
||||
import io.ktor.features.AutoHeadResponse
|
||||
{{/featureAutoHead}}
|
||||
{{#featureCompression}}
|
||||
import io.ktor.features.Compression
|
||||
{{/featureCompression}}
|
||||
{{#featureCORS}}
|
||||
import io.ktor.features.CORS
|
||||
{{/featureCORS}}
|
||||
{{#featureConditionalHeaders}}
|
||||
import io.ktor.features.ConditionalHeaders
|
||||
{{/featureConditionalHeaders}}
|
||||
import io.ktor.features.ContentNegotiation
|
||||
import io.ktor.features.DefaultHeaders
|
||||
{{#featureHSTS}}
|
||||
import io.ktor.features.HSTS
|
||||
{{/featureHSTS}}
|
||||
import io.ktor.gson.GsonConverter
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Locations
|
||||
import io.ktor.metrics.Metrics
|
||||
import io.ktor.routing.Routing
|
||||
import java.util.concurrent.TimeUnit
|
||||
import io.ktor.util.KtorExperimentalAPI
|
||||
{{#hasAuthMethods}}
|
||||
import io.ktor.auth.Authentication
|
||||
import io.ktor.auth.oauth
|
||||
import org.openapitools.server.infrastructure.ApiKeyCredential
|
||||
import org.openapitools.server.infrastructure.ApiPrincipal
|
||||
import org.openapitools.server.infrastructure.apiKeyAuth
|
||||
{{/hasAuthMethods}}
|
||||
{{#generateApis}}{{#apiInfo}}{{#apis}}import {{apiPackage}}.{{classname}}
|
||||
{{/apis}}{{/apiInfo}}{{/generateApis}}
|
||||
|
||||
@KtorExperimentalAPI
|
||||
internal val settings = HoconApplicationConfig(ConfigFactory.defaultApplication(HTTP::class.java.classLoader))
|
||||
|
||||
object HTTP {
|
||||
val client = HttpClient(Apache)
|
||||
}
|
||||
|
||||
@KtorExperimentalAPI
|
||||
@KtorExperimentalLocationsAPI
|
||||
fun Application.main() {
|
||||
install(DefaultHeaders)
|
||||
install(Metrics) {
|
||||
val reporter = Slf4jReporter.forRegistry(registry)
|
||||
.outputTo(log)
|
||||
.convertRatesTo(TimeUnit.SECONDS)
|
||||
.convertDurationsTo(TimeUnit.MILLISECONDS)
|
||||
.build()
|
||||
reporter.start(10, TimeUnit.SECONDS)
|
||||
}
|
||||
{{#generateApis}}
|
||||
install(ContentNegotiation) {
|
||||
register(ContentType.Application.Json, GsonConverter())
|
||||
}
|
||||
{{#featureAutoHead}}
|
||||
install(AutoHeadResponse) // see http://ktor.io/features/autoheadresponse.html
|
||||
{{/featureAutoHead}}
|
||||
{{#featureConditionalHeaders}}
|
||||
install(ConditionalHeaders) // see http://ktor.io/features/conditional-headers.html
|
||||
{{/featureConditionalHeaders}}
|
||||
{{#featureHSTS}}
|
||||
install(HSTS, ApplicationHstsConfiguration()) // see http://ktor.io/features/hsts.html
|
||||
{{/featureHSTS}}
|
||||
{{#featureCORS}}
|
||||
install(CORS, ApplicationCORSConfiguration()) // see http://ktor.io/features/cors.html
|
||||
{{/featureCORS}}
|
||||
{{#featureCompression}}
|
||||
install(Compression, ApplicationCompressionConfiguration()) // see http://ktor.io/features/compression.html
|
||||
{{/featureCompression}}
|
||||
install(Locations) // see http://ktor.io/features/locations.html
|
||||
{{#hasAuthMethods}}
|
||||
install(Authentication) {
|
||||
{{#authMethods}}
|
||||
{{#isBasic}}
|
||||
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
|
||||
}
|
||||
}
|
||||
{{/isBasic}}
|
||||
{{#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 = { ApplicationAuthProviders["{{{name}}}"] }
|
||||
urlProvider = { _ ->
|
||||
// TODO: define a callback url here.
|
||||
"/"
|
||||
}
|
||||
}
|
||||
{{/bodyAllowed}}
|
||||
{{/isOAuth}}
|
||||
{{/authMethods}}
|
||||
}
|
||||
{{/hasAuthMethods}}
|
||||
install(Routing) {
|
||||
{{#apiInfo}}
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
{{classname}}()
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
{{/apiInfo}}
|
||||
}
|
||||
|
||||
{{/generateApis}}
|
||||
|
||||
environment.monitor.subscribe(ApplicationStopping)
|
||||
{
|
||||
HTTP.client.close()
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
package {{packageName}}
|
||||
|
||||
// Use this file to hold package-level internal functions that return receiver object passed to the `install` method.
|
||||
import io.ktor.auth.OAuthServerSettings
|
||||
import io.ktor.features.Compression
|
||||
import io.ktor.features.HSTS
|
||||
import io.ktor.features.deflate
|
||||
import io.ktor.features.gzip
|
||||
import io.ktor.features.minimumSize
|
||||
import io.ktor.http.HttpMethod
|
||||
import io.ktor.util.KtorExperimentalAPI
|
||||
import java.time.Duration
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
import {{packageName}}.settings
|
||||
|
||||
{{#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(): CORS.Configuration.() -> 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(): HSTS.Configuration.() -> Unit {
|
||||
return {
|
||||
maxAge = Duration.ofDays(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(): Compression.Configuration.() -> Unit {
|
||||
return {
|
||||
gzip {
|
||||
priority = 1.0
|
||||
}
|
||||
deflate {
|
||||
priority = 10.0
|
||||
minimumSize(1024) // condition
|
||||
}
|
||||
}
|
||||
}
|
||||
{{/featureCompression}}
|
||||
|
||||
// Defines authentication mechanisms used throughout the application.
|
||||
@KtorExperimentalAPI
|
||||
val ApplicationAuthProviders: Map<String, OAuthServerSettings> = listOf<OAuthServerSettings>(
|
||||
{{#authMethods}}
|
||||
{{#isOAuth}}
|
||||
OAuthServerSettings.OAuth2ServerSettings(
|
||||
name = "{{name}}",
|
||||
authorizeUrl = "{{authorizationUrl}}",
|
||||
accessTokenUrl = "{{tokenUrl}}",
|
||||
requestMethod = HttpMethod.Get,
|
||||
{{! TODO: flow, doesn't seem to be supported yet by ktor }}
|
||||
clientId = settings.property("auth.oauth.{{name}}.clientId").getString(),
|
||||
clientSecret = settings.property("auth.oauth.{{name}}.clientSecret").getString(),
|
||||
defaultScopes = listOf({{#scopes}}"{{scope}}"{{^-last}}, {{/-last}}{{/scopes}})
|
||||
){{^-last}},{{/-last}}
|
||||
{{/isOAuth}}
|
||||
{{/authMethods}}
|
||||
// OAuthServerSettings.OAuth2ServerSettings(
|
||||
// name = "facebook",
|
||||
// authorizeUrl = "https://graph.facebook.com/oauth/authorize",
|
||||
// accessTokenUrl = "https://graph.facebook.com/oauth/access_token",
|
||||
// requestMethod = HttpMethod.Post,
|
||||
//
|
||||
// clientId = "settings.property("auth.oauth.facebook.clientId").getString()",
|
||||
// clientSecret = "settings.property("auth.oauth.facebook.clientSecret").getString()",
|
||||
// defaultScopes = listOf("public_profile")
|
||||
// )
|
||||
).associateBy { it.name }
|
||||
|
||||
// Provides an application-level fixed thread pool on which to execute coroutines (mainly)
|
||||
internal val ApplicationExecutors = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 4)
|
@ -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"]
|
@ -0,0 +1,28 @@
|
||||
{{>licenseInfo}}
|
||||
package {{packageName}}
|
||||
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
{{#imports}}import {{import}}
|
||||
{{/imports}}
|
||||
|
||||
{{#apiInfo}}
|
||||
object Paths {
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
{{^bodyAllowed}}
|
||||
/**
|
||||
* {{summary}}
|
||||
* {{#unescapedNotes}}{{.}}{{/unescapedNotes}}
|
||||
{{#allParams}}* @param {{paramName}} {{description}} {{^required}}(optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}
|
||||
{{/allParams}}*/
|
||||
@KtorExperimentalLocationsAPI
|
||||
@Location("{{path}}") class {{operationId}}({{#allParams}}val {{paramName}}: {{{dataType}}}{{^required}}? = null{{/required}}{{#required}}{{#isNullable}}?{{/isNullable}}{{/required}}{{^-last}}, {{/-last}}{{/allParams}})
|
||||
|
||||
{{/bodyAllowed}}
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
}
|
||||
{{/apiInfo}}
|
101
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/libraries/ktor/README.mustache
vendored
Normal file
101
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/libraries/ktor/README.mustache
vendored
Normal file
@ -0,0 +1,101 @@
|
||||
# {{packageName}} - Kotlin Server library for {{appName}}
|
||||
|
||||
{{#unescapedAppDescription}}
|
||||
{{.}}
|
||||
{{/unescapedAppDescription}}
|
||||
|
||||
Generated by OpenAPI Generator {{generatorVersion}}{{^hideGenerationTimestamp}} ({{generatedDate}}){{/hideGenerationTimestamp}}.
|
||||
|
||||
## Requires
|
||||
|
||||
* Kotlin 1.3.21
|
||||
* Gradle 4.9
|
||||
|
||||
## 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 name="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}}{{{summary}}}{{/summary}}
|
||||
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
|
||||
{{/generateApiDocs}}
|
||||
|
||||
{{#generateModelDocs}}
|
||||
<a name="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 name="documentation-for-authorization"></a>{{! TODO: optional documentation for authorization? }}
|
||||
## Documentation for Authorization
|
||||
|
||||
{{^authMethods}}
|
||||
All endpoints do not require authorization.
|
||||
{{/authMethods}}
|
||||
{{#authMethods}}
|
||||
{{#last}}
|
||||
Authentication schemes defined for the API:
|
||||
{{/last}}
|
||||
{{/authMethods}}
|
||||
{{#authMethods}}
|
||||
<a name="{{name}}"></a>
|
||||
### {{name}}
|
||||
|
||||
{{#isApiKey}}- **Type**: API key
|
||||
- **API key parameter name**: {{keyParamName}}
|
||||
- **Location**: {{#isKeyInQuery}}URL query string{{/isKeyInQuery}}{{#isKeyInHeader}}HTTP header{{/isKeyInHeader}}
|
||||
{{/isApiKey}}
|
||||
{{#isBasic}}- **Type**: HTTP basic authentication
|
||||
{{/isBasic}}
|
||||
{{#isOAuth}}- **Type**: OAuth
|
||||
- **Flow**: {{flow}}
|
||||
- **Authorization URL**: {{authorizationUrl}}
|
||||
- **Scopes**: {{^scopes}}N/A{{/scopes}}
|
||||
{{#scopes}} - {{scope}}: {{description}}
|
||||
{{/scopes}}
|
||||
{{/isOAuth}}
|
||||
|
||||
{{/authMethods}}
|
@ -0,0 +1,25 @@
|
||||
{{#hasAuthMethods}}
|
||||
{{>libraries/ktor/_principal}}
|
||||
if (principal == null) {
|
||||
call.respond(HttpStatusCode.Unauthorized)
|
||||
} else {
|
||||
{{#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}}
|
@ -0,0 +1,11 @@
|
||||
{{#authMethods}}
|
||||
{{#isBasic}}
|
||||
val principal = call.authentication.principal<UserIdPrincipal>()
|
||||
{{/isBasic}}
|
||||
{{#isApiKey}}
|
||||
val principal = call.authentication.principal<ApiPrincipal>()
|
||||
{{/isApiKey}}
|
||||
{{#isOAuth}}
|
||||
val principal = call.authentication.principal<OAuthAccessTokenResponse>()
|
||||
{{/isOAuth}}
|
||||
{{/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)
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
{{>licenseInfo}}
|
||||
package {{apiPackage}}
|
||||
|
||||
import com.google.gson.Gson
|
||||
import io.ktor.application.call
|
||||
import io.ktor.auth.UserIdPrincipal
|
||||
import io.ktor.auth.authentication
|
||||
import io.ktor.auth.authenticate
|
||||
import io.ktor.auth.OAuthAccessTokenResponse
|
||||
import io.ktor.auth.OAuthServerSettings
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.delete
|
||||
import io.ktor.locations.get
|
||||
import io.ktor.response.respond
|
||||
import io.ktor.response.respondText
|
||||
import io.ktor.routing.Route
|
||||
import io.ktor.routing.post
|
||||
import io.ktor.routing.put
|
||||
import io.ktor.routing.route
|
||||
|
||||
import {{packageName}}.Paths
|
||||
import {{packageName}}.infrastructure.ApiPrincipal
|
||||
|
||||
|
||||
{{#imports}}import {{import}}
|
||||
{{/imports}}
|
||||
|
||||
{{#operations}}
|
||||
@KtorExperimentalLocationsAPI
|
||||
fun Route.{{classname}}() {
|
||||
val gson = Gson()
|
||||
val empty = mutableMapOf<String, Any?>()
|
||||
{{#operation}}
|
||||
{{#bodyAllowed}}
|
||||
|
||||
route("{{path}}") {
|
||||
{{#hasAuthMethods}}
|
||||
{{#authMethods}}
|
||||
authenticate("{{{name}}}") {
|
||||
{{/authMethods}}
|
||||
{{/hasAuthMethods}}
|
||||
{{#lambda.lowercase}}{{httpMethod}}{{/lambda.lowercase}} {
|
||||
{{#lambda.indented_12}}{{>libraries/ktor/_api_body}}{{/lambda.indented_12}}
|
||||
}
|
||||
{{#hasAuthMethods}}
|
||||
}
|
||||
{{/hasAuthMethods}}
|
||||
}
|
||||
{{/bodyAllowed}}
|
||||
{{^bodyAllowed}}
|
||||
|
||||
{{! NOTE: Locations can be used on routes without body parameters.}}
|
||||
{{#lambda.lowercase}}{{httpMethod}}{{/lambda.lowercase}}<Paths.{{operationId}}> { _: Paths.{{operationId}} ->
|
||||
{{#lambda.indented_8}}{{>libraries/ktor/_api_body}}{{/lambda.indented_8}}
|
||||
}
|
||||
{{/bodyAllowed}}
|
||||
|
||||
{{/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,68 @@
|
||||
group '{{groupId}}'
|
||||
version '{{artifactVersion}}'
|
||||
|
||||
wrapper {
|
||||
gradleVersion = '4.9'
|
||||
distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
|
||||
}
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.21'
|
||||
ext.ktor_version = '1.1.3'
|
||||
ext.shadow_version = '2.0.3'
|
||||
|
||||
repositories {
|
||||
maven { url "https://repo1.maven.org/maven2" }
|
||||
maven {
|
||||
url = "https://plugins.gradle.org/m2/"
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "com.github.jengelman.gradle.plugins:shadow:$shadow_version"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'kotlin'
|
||||
apply plugin: 'application'
|
||||
|
||||
mainClassName = "io.ktor.server.netty.DevelopmentEngine"
|
||||
|
||||
// Initialization order with shadow 2.0.1 and Gradle 4.3 is weird.
|
||||
// See https://github.com/johnrengelman/shadow/issues/336#issuecomment-355402508
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
|
||||
compileKotlin {
|
||||
kotlinOptions.jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
compileTestKotlin {
|
||||
kotlinOptions.jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
baseName = '{{artifactId}}'
|
||||
classifier = null
|
||||
version = null
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { url "https://repo1.maven.org/maven2" }
|
||||
maven { url "https://dl.bintray.com/kotlin/ktor" }
|
||||
maven { url "https://dl.bintray.com/kotlin/kotlinx" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
compile "io.ktor:ktor-server-netty:$ktor_version"
|
||||
compile "io.ktor:ktor-metrics:$ktor_version"
|
||||
compile "io.ktor:ktor-locations:$ktor_version"
|
||||
compile "io.ktor:ktor-gson:$ktor_version"
|
||||
compile "io.ktor:ktor-client-core:$ktor_version"
|
||||
compile "io.ktor:ktor-client-apache:$ktor_version"
|
||||
compile "ch.qos.logback:logback-classic:1.2.1"
|
||||
testCompile group: 'junit', name: 'junit', version: '4.13'
|
||||
}
|
@ -0,0 +1 @@
|
||||
org.gradle.caching=true
|
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* {{{appName}}}
|
||||
* {{{appDescription}}}
|
||||
*
|
||||
* {{#version}}The version of the OpenAPI document: {{{version}}}{{/version}}
|
||||
* {{#infoEmail}}Contact: {{{infoEmail}}}{{/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>
|
11
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/licenseInfo.mustache
vendored
Normal file
11
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/licenseInfo.mustache
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/**
|
||||
* {{{appName}}}
|
||||
* {{{appDescription}}}
|
||||
*
|
||||
* {{#version}}The version of the OpenAPI document: {{{version}}}{{/version}}
|
||||
* {{#infoEmail}}Contact: {{{infoEmail}}}{{/infoEmail}}
|
||||
*
|
||||
* NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech).
|
||||
* https://openapi-generator.tech
|
||||
* Do not edit the class manually.
|
||||
*/
|
11
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/model.mustache
vendored
Normal file
11
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/model.mustache
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
{{>licenseInfo}}
|
||||
package {{modelPackage}}
|
||||
|
||||
{{#imports}}import {{import}}
|
||||
{{/imports}}
|
||||
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
{{#isEnum}}{{>enum_class}}{{/isEnum}}{{^isEnum}}{{>data_class}}{{/isEnum}}
|
||||
{{/model}}
|
||||
{{/models}}
|
1
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/modelMutable.mustache
vendored
Normal file
1
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/modelMutable.mustache
vendored
Normal file
@ -0,0 +1 @@
|
||||
{{#modelMutable}}var{{/modelMutable}}{{^modelMutable}}val{{/modelMutable}}
|
3
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/model_doc.mustache
vendored
Normal file
3
modules/openapi-generator/src/main/resources/kotlin-server-deprecated/model_doc.mustache
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
{{#models}}{{#model}}
|
||||
{{#isEnum}}{{>enum_doc}}{{/isEnum}}{{^isEnum}}{{>class_doc}}{{/isEnum}}
|
||||
{{/model}}{{/models}}
|
@ -0,0 +1 @@
|
||||
rootProject.name = '{{artifactId}}'
|
@ -9,6 +9,7 @@ import org.openapitools.codegen.DefaultGenerator;
|
||||
import org.openapitools.codegen.languages.AbstractKotlinCodegen;
|
||||
import org.openapitools.codegen.languages.KotlinClientCodegen;
|
||||
import org.openapitools.codegen.languages.KotlinServerCodegen;
|
||||
import org.openapitools.codegen.languages.KotlinServerDeprecatedCodegen;
|
||||
import org.openapitools.codegen.languages.KotlinSpringServerCodegen;
|
||||
import org.openapitools.codegen.languages.KotlinVertxServerCodegen;
|
||||
import org.testng.annotations.DataProvider;
|
||||
@ -28,6 +29,7 @@ public class KotlinModelCodegenTest {
|
||||
return new Object[][]{
|
||||
{new KotlinClientCodegen()},
|
||||
{new KotlinServerCodegen()},
|
||||
{new KotlinServerDeprecatedCodegen()},
|
||||
{new KotlinSpringServerCodegen()},
|
||||
{new KotlinVertxServerCodegen()},
|
||||
};
|
||||
|
@ -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,20 @@
|
||||
Dockerfile
|
||||
README.md
|
||||
build.gradle
|
||||
gradle.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/ApiResponse.kt
|
||||
src/main/kotlin/org/openapitools/server/models/Category.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 @@
|
||||
5.2.0-SNAPSHOT
|
@ -0,0 +1,7 @@
|
||||
FROM openjdk:8-jre-alpine
|
||||
|
||||
COPY ./build/libs/kotlin-server-deprecated.jar /root/kotlin-server-deprecated.jar
|
||||
|
||||
WORKDIR /root
|
||||
|
||||
CMD ["java", "-server", "-Xms4g", "-Xmx4g", "-XX:+UseG1GC", "-XX:MaxGCPauseMillis=100", "-XX:+UseStringDeduplication", "-jar", "kotlin-server-deprecated.jar"]
|
104
samples/server/petstore/kotlin-server-deprecated/ktor/README.md
Normal file
104
samples/server/petstore/kotlin-server-deprecated/ktor/README.md
Normal file
@ -0,0 +1,104 @@
|
||||
# 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 5.2.0-SNAPSHOT.
|
||||
|
||||
## Requires
|
||||
|
||||
* Kotlin 1.3.21
|
||||
* Gradle 4.9
|
||||
|
||||
## 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-deprecated.jar`.
|
||||
|
||||
You may also run in docker:
|
||||
|
||||
```
|
||||
docker build -t kotlin-server-deprecated .
|
||||
docker run -p 8080:8080 kotlin-server-deprecated
|
||||
```
|
||||
|
||||
## 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 name="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 name="documentation-for-models"></a>
|
||||
## Documentation for Models
|
||||
|
||||
- [org.openapitools.server.models.ApiResponse](docs/ApiResponse.md)
|
||||
- [org.openapitools.server.models.Category](docs/Category.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 name="documentation-for-authorization"></a>
|
||||
## Documentation for Authorization
|
||||
|
||||
<a name="api_key"></a>
|
||||
### api_key
|
||||
|
||||
- **Type**: API key
|
||||
- **API key parameter name**: api_key
|
||||
- **Location**: HTTP header
|
||||
|
||||
<a name="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
|
||||
|
@ -0,0 +1,68 @@
|
||||
group 'org.openapitools'
|
||||
version '1.0.0'
|
||||
|
||||
wrapper {
|
||||
gradleVersion = '4.9'
|
||||
distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
|
||||
}
|
||||
|
||||
buildscript {
|
||||
ext.kotlin_version = '1.3.21'
|
||||
ext.ktor_version = '1.1.3'
|
||||
ext.shadow_version = '2.0.3'
|
||||
|
||||
repositories {
|
||||
maven { url "https://repo1.maven.org/maven2" }
|
||||
maven {
|
||||
url = "https://plugins.gradle.org/m2/"
|
||||
}
|
||||
}
|
||||
dependencies {
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath "com.github.jengelman.gradle.plugins:shadow:$shadow_version"
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'kotlin'
|
||||
apply plugin: 'application'
|
||||
|
||||
mainClassName = "io.ktor.server.netty.DevelopmentEngine"
|
||||
|
||||
// Initialization order with shadow 2.0.1 and Gradle 4.3 is weird.
|
||||
// See https://github.com/johnrengelman/shadow/issues/336#issuecomment-355402508
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
sourceCompatibility = 1.8
|
||||
|
||||
compileKotlin {
|
||||
kotlinOptions.jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
compileTestKotlin {
|
||||
kotlinOptions.jvmTarget = "1.8"
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
baseName = 'kotlin-server-deprecated'
|
||||
classifier = null
|
||||
version = null
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven { url "https://repo1.maven.org/maven2" }
|
||||
maven { url "https://dl.bintray.com/kotlin/ktor" }
|
||||
maven { url "https://dl.bintray.com/kotlin/kotlinx" }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
compile "io.ktor:ktor-server-netty:$ktor_version"
|
||||
compile "io.ktor:ktor-metrics:$ktor_version"
|
||||
compile "io.ktor:ktor-locations:$ktor_version"
|
||||
compile "io.ktor:ktor-gson:$ktor_version"
|
||||
compile "io.ktor:ktor-client-core:$ktor_version"
|
||||
compile "io.ktor:ktor-client-apache:$ktor_version"
|
||||
compile "ch.qos.logback:logback-classic:1.2.1"
|
||||
testCompile group: 'junit', name: 'junit', version: '4.13'
|
||||
}
|
@ -0,0 +1 @@
|
||||
org.gradle.caching=true
|
@ -0,0 +1 @@
|
||||
rootProject.name = 'kotlin-server-deprecated'
|
@ -0,0 +1,91 @@
|
||||
package org.openapitools.server
|
||||
|
||||
import com.codahale.metrics.Slf4jReporter
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import io.ktor.application.Application
|
||||
import io.ktor.application.ApplicationStopping
|
||||
import io.ktor.application.install
|
||||
import io.ktor.application.log
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.apache.Apache
|
||||
import io.ktor.config.HoconApplicationConfig
|
||||
import io.ktor.features.AutoHeadResponse
|
||||
import io.ktor.features.Compression
|
||||
import io.ktor.features.ContentNegotiation
|
||||
import io.ktor.features.DefaultHeaders
|
||||
import io.ktor.features.HSTS
|
||||
import io.ktor.gson.GsonConverter
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Locations
|
||||
import io.ktor.metrics.Metrics
|
||||
import io.ktor.routing.Routing
|
||||
import java.util.concurrent.TimeUnit
|
||||
import io.ktor.util.KtorExperimentalAPI
|
||||
import io.ktor.auth.Authentication
|
||||
import io.ktor.auth.oauth
|
||||
import org.openapitools.server.infrastructure.ApiKeyCredential
|
||||
import org.openapitools.server.infrastructure.ApiPrincipal
|
||||
import org.openapitools.server.infrastructure.apiKeyAuth
|
||||
import org.openapitools.server.apis.PetApi
|
||||
import org.openapitools.server.apis.StoreApi
|
||||
import org.openapitools.server.apis.UserApi
|
||||
|
||||
|
||||
@KtorExperimentalAPI
|
||||
internal val settings = HoconApplicationConfig(ConfigFactory.defaultApplication(HTTP::class.java.classLoader))
|
||||
|
||||
object HTTP {
|
||||
val client = HttpClient(Apache)
|
||||
}
|
||||
|
||||
@KtorExperimentalAPI
|
||||
@KtorExperimentalLocationsAPI
|
||||
fun Application.main() {
|
||||
install(DefaultHeaders)
|
||||
install(Metrics) {
|
||||
val reporter = Slf4jReporter.forRegistry(registry)
|
||||
.outputTo(log)
|
||||
.convertRatesTo(TimeUnit.SECONDS)
|
||||
.convertDurationsTo(TimeUnit.MILLISECONDS)
|
||||
.build()
|
||||
reporter.start(10, TimeUnit.SECONDS)
|
||||
}
|
||||
install(ContentNegotiation) {
|
||||
register(ContentType.Application.Json, GsonConverter())
|
||||
}
|
||||
install(AutoHeadResponse) // see http://ktor.io/features/autoheadresponse.html
|
||||
install(HSTS, ApplicationHstsConfiguration()) // see http://ktor.io/features/hsts.html
|
||||
install(Compression, ApplicationCompressionConfiguration()) // see http://ktor.io/features/compression.html
|
||||
install(Locations) // see http://ktor.io/features/locations.html
|
||||
install(Authentication) {
|
||||
// "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
|
||||
}
|
||||
}
|
||||
}
|
||||
oauth("petstore_auth") {
|
||||
client = HttpClient(Apache)
|
||||
providerLookup = { ApplicationAuthProviders["petstore_auth"] }
|
||||
urlProvider = { _ ->
|
||||
// TODO: define a callback url here.
|
||||
"/"
|
||||
}
|
||||
}
|
||||
}
|
||||
install(Routing) {
|
||||
PetApi()
|
||||
StoreApi()
|
||||
UserApi()
|
||||
}
|
||||
|
||||
|
||||
environment.monitor.subscribe(ApplicationStopping)
|
||||
{
|
||||
HTTP.client.close()
|
||||
}
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
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.auth.OAuthServerSettings
|
||||
import io.ktor.features.Compression
|
||||
import io.ktor.features.HSTS
|
||||
import io.ktor.features.deflate
|
||||
import io.ktor.features.gzip
|
||||
import io.ktor.features.minimumSize
|
||||
import io.ktor.http.HttpMethod
|
||||
import io.ktor.util.KtorExperimentalAPI
|
||||
import java.time.Duration
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
import org.openapitools.server.settings
|
||||
|
||||
|
||||
/**
|
||||
* 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(): HSTS.Configuration.() -> Unit {
|
||||
return {
|
||||
maxAge = Duration.ofDays(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(): Compression.Configuration.() -> Unit {
|
||||
return {
|
||||
gzip {
|
||||
priority = 1.0
|
||||
}
|
||||
deflate {
|
||||
priority = 10.0
|
||||
minimumSize(1024) // condition
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Defines authentication mechanisms used throughout the application.
|
||||
@KtorExperimentalAPI
|
||||
val ApplicationAuthProviders: Map<String, OAuthServerSettings> = listOf<OAuthServerSettings>(
|
||||
OAuthServerSettings.OAuth2ServerSettings(
|
||||
name = "petstore_auth",
|
||||
authorizeUrl = "http://petstore.swagger.io/api/oauth/dialog",
|
||||
accessTokenUrl = "",
|
||||
requestMethod = HttpMethod.Get,
|
||||
clientId = settings.property("auth.oauth.petstore_auth.clientId").getString(),
|
||||
clientSecret = settings.property("auth.oauth.petstore_auth.clientSecret").getString(),
|
||||
defaultScopes = listOf("write:pets", "read:pets")
|
||||
)
|
||||
// OAuthServerSettings.OAuth2ServerSettings(
|
||||
// name = "facebook",
|
||||
// authorizeUrl = "https://graph.facebook.com/oauth/authorize",
|
||||
// accessTokenUrl = "https://graph.facebook.com/oauth/access_token",
|
||||
// requestMethod = HttpMethod.Post,
|
||||
//
|
||||
// clientId = "settings.property("auth.oauth.facebook.clientId").getString()",
|
||||
// clientSecret = "settings.property("auth.oauth.facebook.clientSecret").getString()",
|
||||
// defaultScopes = listOf("public_profile")
|
||||
// )
|
||||
).associateBy { it.name }
|
||||
|
||||
// Provides an application-level fixed thread pool on which to execute coroutines (mainly)
|
||||
internal val ApplicationExecutors = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 4)
|
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* 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.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.Location
|
||||
|
||||
object Paths {
|
||||
/**
|
||||
* Deletes a pet
|
||||
*
|
||||
* @param petId Pet id to delete
|
||||
* @param apiKey (optional)
|
||||
*/
|
||||
@KtorExperimentalLocationsAPI
|
||||
@Location("/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
|
||||
*/
|
||||
@KtorExperimentalLocationsAPI
|
||||
@Location("/pet/findByStatus") class findPetsByStatus(val status: kotlin.Array<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
|
||||
*/
|
||||
@KtorExperimentalLocationsAPI
|
||||
@Location("/pet/findByTags") class findPetsByTags(val tags: kotlin.Array<kotlin.String>)
|
||||
|
||||
/**
|
||||
* Find pet by ID
|
||||
* Returns a single pet
|
||||
* @param petId ID of pet to return
|
||||
*/
|
||||
@KtorExperimentalLocationsAPI
|
||||
@Location("/pet/{petId}") class getPetById(val petId: kotlin.Long)
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@KtorExperimentalLocationsAPI
|
||||
@Location("/store/order/{orderId}") class deleteOrder(val orderId: kotlin.String)
|
||||
|
||||
/**
|
||||
* Returns pet inventories by status
|
||||
* Returns a map of status codes to quantities
|
||||
*/
|
||||
@KtorExperimentalLocationsAPI
|
||||
@Location("/store/inventory") class getInventory()
|
||||
|
||||
/**
|
||||
* Find purchase order by ID
|
||||
* For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions
|
||||
* @param orderId ID of pet that needs to be fetched
|
||||
*/
|
||||
@KtorExperimentalLocationsAPI
|
||||
@Location("/store/order/{orderId}") class getOrderById(val orderId: kotlin.Long)
|
||||
|
||||
/**
|
||||
* Delete user
|
||||
* This can only be done by the logged in user.
|
||||
* @param username The name that needs to be deleted
|
||||
*/
|
||||
@KtorExperimentalLocationsAPI
|
||||
@Location("/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.
|
||||
*/
|
||||
@KtorExperimentalLocationsAPI
|
||||
@Location("/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
|
||||
*/
|
||||
@KtorExperimentalLocationsAPI
|
||||
@Location("/user/login") class loginUser(val username: kotlin.String, val password: kotlin.String)
|
||||
|
||||
/**
|
||||
* Logs out current logged in user session
|
||||
*
|
||||
*/
|
||||
@KtorExperimentalLocationsAPI
|
||||
@Location("/user/logout") class logoutUser()
|
||||
|
||||
}
|
@ -0,0 +1,228 @@
|
||||
/**
|
||||
* 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.application.call
|
||||
import io.ktor.auth.UserIdPrincipal
|
||||
import io.ktor.auth.authentication
|
||||
import io.ktor.auth.authenticate
|
||||
import io.ktor.auth.OAuthAccessTokenResponse
|
||||
import io.ktor.auth.OAuthServerSettings
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.delete
|
||||
import io.ktor.locations.get
|
||||
import io.ktor.response.respond
|
||||
import io.ktor.response.respondText
|
||||
import io.ktor.routing.Route
|
||||
import io.ktor.routing.post
|
||||
import io.ktor.routing.put
|
||||
import io.ktor.routing.route
|
||||
|
||||
import org.openapitools.server.Paths
|
||||
import org.openapitools.server.infrastructure.ApiPrincipal
|
||||
|
||||
|
||||
import org.openapitools.server.models.ApiResponse
|
||||
import org.openapitools.server.models.Pet
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
fun Route.PetApi() {
|
||||
val gson = Gson()
|
||||
val empty = mutableMapOf<String, Any?>()
|
||||
|
||||
route("/pet") {
|
||||
authenticate("petstore_auth") {
|
||||
post {
|
||||
val principal = call.authentication.principal<OAuthAccessTokenResponse>()
|
||||
|
||||
if (principal == null) {
|
||||
call.respond(HttpStatusCode.Unauthorized)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotImplemented)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delete<Paths.deletePet> { _: Paths.deletePet ->
|
||||
val principal = call.authentication.principal<OAuthAccessTokenResponse>()
|
||||
|
||||
if (principal == null) {
|
||||
call.respond(HttpStatusCode.Unauthorized)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotImplemented)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
get<Paths.findPetsByStatus> { _: Paths.findPetsByStatus ->
|
||||
val principal = call.authentication.principal<OAuthAccessTokenResponse>()
|
||||
|
||||
if (principal == null) {
|
||||
call.respond(HttpStatusCode.Unauthorized)
|
||||
} else {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
get<Paths.findPetsByTags> { _: Paths.findPetsByTags ->
|
||||
val principal = call.authentication.principal<OAuthAccessTokenResponse>()
|
||||
|
||||
if (principal == null) {
|
||||
call.respond(HttpStatusCode.Unauthorized)
|
||||
} else {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
get<Paths.getPetById> { _: Paths.getPetById ->
|
||||
val principal = call.authentication.principal<ApiPrincipal>()
|
||||
|
||||
if (principal == null) {
|
||||
call.respond(HttpStatusCode.Unauthorized)
|
||||
} else {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
route("/pet") {
|
||||
authenticate("petstore_auth") {
|
||||
put {
|
||||
val principal = call.authentication.principal<OAuthAccessTokenResponse>()
|
||||
|
||||
if (principal == null) {
|
||||
call.respond(HttpStatusCode.Unauthorized)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotImplemented)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
route("/pet/{petId}") {
|
||||
authenticate("petstore_auth") {
|
||||
post {
|
||||
val principal = call.authentication.principal<OAuthAccessTokenResponse>()
|
||||
|
||||
if (principal == null) {
|
||||
call.respond(HttpStatusCode.Unauthorized)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotImplemented)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
route("/pet/{petId}/uploadImage") {
|
||||
authenticate("petstore_auth") {
|
||||
post {
|
||||
val principal = call.authentication.principal<OAuthAccessTokenResponse>()
|
||||
|
||||
if (principal == null) {
|
||||
call.respond(HttpStatusCode.Unauthorized)
|
||||
} else {
|
||||
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,99 @@
|
||||
/**
|
||||
* 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.application.call
|
||||
import io.ktor.auth.UserIdPrincipal
|
||||
import io.ktor.auth.authentication
|
||||
import io.ktor.auth.authenticate
|
||||
import io.ktor.auth.OAuthAccessTokenResponse
|
||||
import io.ktor.auth.OAuthServerSettings
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.delete
|
||||
import io.ktor.locations.get
|
||||
import io.ktor.response.respond
|
||||
import io.ktor.response.respondText
|
||||
import io.ktor.routing.Route
|
||||
import io.ktor.routing.post
|
||||
import io.ktor.routing.put
|
||||
import io.ktor.routing.route
|
||||
|
||||
import org.openapitools.server.Paths
|
||||
import org.openapitools.server.infrastructure.ApiPrincipal
|
||||
|
||||
|
||||
import org.openapitools.server.models.Order
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
fun Route.StoreApi() {
|
||||
val gson = Gson()
|
||||
val empty = mutableMapOf<String, Any?>()
|
||||
|
||||
delete<Paths.deleteOrder> { _: Paths.deleteOrder ->
|
||||
call.respond(HttpStatusCode.NotImplemented)
|
||||
}
|
||||
|
||||
|
||||
get<Paths.getInventory> { _: Paths.getInventory ->
|
||||
val principal = call.authentication.principal<ApiPrincipal>()
|
||||
|
||||
if (principal == null) {
|
||||
call.respond(HttpStatusCode.Unauthorized)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotImplemented)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
get<Paths.getOrderById> { _: 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)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
route("/store/order") {
|
||||
post {
|
||||
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,107 @@
|
||||
/**
|
||||
* 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.application.call
|
||||
import io.ktor.auth.UserIdPrincipal
|
||||
import io.ktor.auth.authentication
|
||||
import io.ktor.auth.authenticate
|
||||
import io.ktor.auth.OAuthAccessTokenResponse
|
||||
import io.ktor.auth.OAuthServerSettings
|
||||
import io.ktor.http.ContentType
|
||||
import io.ktor.http.HttpStatusCode
|
||||
import io.ktor.locations.KtorExperimentalLocationsAPI
|
||||
import io.ktor.locations.delete
|
||||
import io.ktor.locations.get
|
||||
import io.ktor.response.respond
|
||||
import io.ktor.response.respondText
|
||||
import io.ktor.routing.Route
|
||||
import io.ktor.routing.post
|
||||
import io.ktor.routing.put
|
||||
import io.ktor.routing.route
|
||||
|
||||
import org.openapitools.server.Paths
|
||||
import org.openapitools.server.infrastructure.ApiPrincipal
|
||||
|
||||
|
||||
import org.openapitools.server.models.User
|
||||
|
||||
@KtorExperimentalLocationsAPI
|
||||
fun Route.UserApi() {
|
||||
val gson = Gson()
|
||||
val empty = mutableMapOf<String, Any?>()
|
||||
|
||||
route("/user") {
|
||||
post {
|
||||
call.respond(HttpStatusCode.NotImplemented)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
route("/user/createWithArray") {
|
||||
post {
|
||||
call.respond(HttpStatusCode.NotImplemented)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
route("/user/createWithList") {
|
||||
post {
|
||||
call.respond(HttpStatusCode.NotImplemented)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delete<Paths.deleteUser> { _: Paths.deleteUser ->
|
||||
call.respond(HttpStatusCode.NotImplemented)
|
||||
}
|
||||
|
||||
|
||||
get<Paths.getUserByName> { _: 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> { _: Paths.loginUser ->
|
||||
call.respond(HttpStatusCode.NotImplemented)
|
||||
}
|
||||
|
||||
|
||||
get<Paths.logoutUser> { _: Paths.logoutUser ->
|
||||
call.respond(HttpStatusCode.NotImplemented)
|
||||
}
|
||||
|
||||
|
||||
route("/user/{username}") {
|
||||
put {
|
||||
call.respond(HttpStatusCode.NotImplemented)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
package org.openapitools.server.infrastructure
|
||||
|
||||
import io.ktor.application.ApplicationCall
|
||||
import io.ktor.application.call
|
||||
import io.ktor.auth.Authentication
|
||||
import io.ktor.auth.AuthenticationFailedCause
|
||||
import io.ktor.auth.AuthenticationPipeline
|
||||
import io.ktor.auth.AuthenticationProvider
|
||||
import io.ktor.auth.Credential
|
||||
import io.ktor.auth.Principal
|
||||
import io.ktor.auth.UnauthorizedResponse
|
||||
import io.ktor.http.auth.HeaderValueEncoding
|
||||
import io.ktor.http.auth.HttpAuthHeader
|
||||
import io.ktor.request.ApplicationRequest
|
||||
import io.ktor.response.respond
|
||||
|
||||
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 a Api Key authentication provider
|
||||
* @param name is the name of the provider, or `null` for a default provider
|
||||
*/
|
||||
class ApiKeyAuthenticationProvider(name: String?) : AuthenticationProvider(name) {
|
||||
internal var authenticationFunction: suspend ApplicationCall.(ApiKeyCredential) -> Principal? = { null }
|
||||
|
||||
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 Authentication.Configuration.apiKeyAuth(name: String? = null, configure: ApiKeyAuthenticationProvider.() -> Unit) {
|
||||
val provider = ApiKeyAuthenticationProvider(name).apply(configure)
|
||||
val apiKeyName = provider.apiKeyName
|
||||
val apiKeyLocation = provider.apiKeyLocation
|
||||
val authenticate = provider.authenticationFunction
|
||||
|
||||
provider.pipeline.intercept(AuthenticationPipeline.RequestAuthentication) { context ->
|
||||
val credentials = call.request.apiKeyAuthenticationCredentials(apiKeyName, apiKeyLocation)
|
||||
val principal = credentials?.let { authenticate(call, it) }
|
||||
|
||||
val cause = when {
|
||||
credentials == null -> AuthenticationFailedCause.NoCredentials
|
||||
principal == null -> AuthenticationFailedCause.InvalidCredentials
|
||||
else -> null
|
||||
}
|
||||
|
||||
if (cause != null) {
|
||||
context.challenge(apiKeyName, cause) {
|
||||
// TODO: Verify correct response structure here.
|
||||
call.respond(UnauthorizedResponse(HttpAuthHeader.Parameterized("API_KEY", mapOf("key" to apiKeyName), HeaderValueEncoding.QUOTED_ALWAYS)))
|
||||
it.complete()
|
||||
}
|
||||
}
|
||||
|
||||
if (principal != null) {
|
||||
context.principal(principal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun ApplicationRequest.apiKeyAuthenticationCredentials(apiKeyName: String, apiKeyLocation: ApiKeyLocation): ApiKeyCredential? {
|
||||
val value: String? = when(apiKeyLocation) {
|
||||
ApiKeyLocation.QUERY -> this.queryParameters[apiKeyName]
|
||||
ApiKeyLocation.HEADER -> this.headers[apiKeyName]
|
||||
}
|
||||
when (value) {
|
||||
null -> return null
|
||||
else -> return ApiKeyCredential(value)
|
||||
}
|
||||
}
|
@ -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 ApiResponse (
|
||||
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,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,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? = null
|
||||
) : 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.Array<kotlin.String>,
|
||||
val id: kotlin.Long? = null,
|
||||
val category: Category? = null,
|
||||
val tags: kotlin.Array<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