feat: v2-alpha (#112)

There are still some bugs, still some outstanding features, but I don't want to hold this back any longer, that way I can keep the future PRs much more focused
This commit is contained in:
Ryan Brink
2022-01-02 23:15:15 -05:00
committed by GitHub
parent d66880f9b2
commit c29567114d
229 changed files with 9172 additions and 7233 deletions

View File

@ -0,0 +1,9 @@
# Module kompendium-auth
This module is responsible for providing wrappers around ktor-auth configuration blocks, allowing users to document
their API authentication with minimal modifications to their existing configuration.
# Package io.bkbn.kompendium.auth
Base package that is responsible for setting up required authentication route handlers along with exposing
wrapper methods for each ktor-auth authentication mechanism.

View File

@ -1,78 +1,18 @@
plugins {
`java-library`
`maven-publish`
signing
id("io.bkbn.sourdough.library")
}
dependencies {
implementation(platform("org.jetbrains.kotlin:kotlin-bom"))
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation(libs.bundles.ktor)
implementation(libs.bundles.ktorAuth)
// IMPLEMENTATION
val ktorVersion: String by project
implementation(projects.kompendiumCore)
implementation(group = "io.ktor", name = "ktor-server-core", version = ktorVersion)
implementation(group = "io.ktor", name = "ktor-auth", version = ktorVersion)
implementation(group = "io.ktor", name = "ktor-auth-jwt", version = ktorVersion)
testImplementation(libs.ktor.jackson)
testImplementation("org.jetbrains.kotlin:kotlin-test")
testImplementation("org.jetbrains.kotlin:kotlin-test-junit")
testImplementation(libs.jackson.module.kotlin)
testImplementation(libs.ktor.server.test.host)
}
java {
withSourcesJar()
withJavadocJar()
}
publishing {
repositories {
maven {
name = "GithubPackages"
url = uri("https://maven.pkg.github.com/bkbnio/kompendium")
credentials {
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
}
}
publications {
create<MavenPublication>("kompendium") {
from(components["kotlin"])
artifact(tasks.sourcesJar)
artifact(tasks.javadocJar)
groupId = project.group.toString()
artifactId = project.name.toLowerCase()
version = project.version.toString()
pom {
name.set("Kompendium")
description.set("A minimally invasive OpenAPI spec generator for Ktor")
url.set("https://github.com/bkbnio/Kompendium")
licenses {
license {
name.set("MIT License")
url.set("https://mit-license.org/")
}
}
developers {
developer {
id.set("bkbnio")
name.set("Ryan Brink")
email.set("admin@bkbn.io")
}
}
scm {
connection.set("scm:git:git://github.com/bkbnio/Kompendium.git")
developerConnection.set("scm:git:ssh://github.com/bkbnio/Kompendium.git")
url.set("https://github.com/bkbnio/Kompendium.git")
}
}
}
}
}
signing {
val signingKey: String? by project
val signingPassword: String? by project
useInMemoryPgpKeys(signingKey, signingPassword)
sign(publishing.publications)
// TESTING
testImplementation(testFixtures(projects.kompendiumCore))
}

View File

@ -1,53 +0,0 @@
package io.bkbn.kompendium.auth
import io.ktor.auth.Authentication
import io.ktor.auth.basic
import io.ktor.auth.BasicAuthenticationProvider
import io.ktor.auth.jwt.jwt
import io.ktor.auth.jwt.JWTAuthenticationProvider
import io.bkbn.kompendium.Kompendium
import io.bkbn.kompendium.models.oas.OpenApiSpecSchemaSecurity
import io.ktor.auth.AuthenticationRouteSelector
object KompendiumAuth {
init {
Kompendium.addCustomRouteHandler(AuthenticationRouteSelector::class) { route, tail ->
calculate(route.parent, tail)
}
}
fun Authentication.Configuration.notarizedBasic(
name: String? = null,
configure: BasicAuthenticationProvider.Configuration.() -> Unit
) {
Kompendium.openApiSpec.components.securitySchemes[name ?: "default"] = OpenApiSpecSchemaSecurity(
type = "http",
scheme = "basic"
)
basic(name, configure)
}
fun Authentication.Configuration.notarizedJwt(
name: String? = null,
header: String? = null,
scheme: String? = null,
configure: JWTAuthenticationProvider.Configuration.() -> Unit
) {
if (header == null || header == "Authorization") {
Kompendium.openApiSpec.components.securitySchemes[name ?: "default"] = OpenApiSpecSchemaSecurity(
type = "http",
scheme = scheme ?: "bearer"
)
} else {
Kompendium.openApiSpec.components.securitySchemes[name ?: "default"] = OpenApiSpecSchemaSecurity(
type = "apiKey",
name = header,
`in` = "header"
)
}
jwt(name, configure)
}
// TODO support other authentication providers (e.g., oAuth)?
}

View File

@ -0,0 +1,40 @@
package io.bkbn.kompendium.auth
import io.bkbn.kompendium.auth.configuration.ApiKeyConfiguration
import io.bkbn.kompendium.auth.configuration.BasicAuthConfiguration
import io.bkbn.kompendium.auth.configuration.JwtAuthConfiguration
import io.bkbn.kompendium.auth.configuration.OAuthConfiguration
import io.bkbn.kompendium.auth.configuration.SecurityConfiguration
import io.bkbn.kompendium.core.Kompendium
import io.bkbn.kompendium.oas.security.ApiKeyAuth
import io.bkbn.kompendium.oas.security.BasicAuth
import io.bkbn.kompendium.oas.security.BearerAuth
import io.bkbn.kompendium.oas.security.OAuth
import io.ktor.application.feature
import io.ktor.auth.authenticate
import io.ktor.routing.Route
import io.ktor.routing.application
object Notarized {
fun Route.notarizedAuthenticate(
vararg configurations: SecurityConfiguration,
optional: Boolean = false,
build: Route.() -> Unit
): Route {
val configurationNames = configurations.map { it.name }.toTypedArray()
val feature = application.feature(Kompendium)
configurations.forEach { config ->
feature.config.spec.components.securitySchemes[config.name] = when (config) {
is ApiKeyConfiguration -> ApiKeyAuth(config.location, config.keyName)
is BasicAuthConfiguration -> BasicAuth()
is JwtAuthConfiguration -> BearerAuth(config.bearerFormat)
is OAuthConfiguration -> OAuth(config.description, config.flows)
}
}
return authenticate(*configurationNames, optional = optional, build = build)
}
}

View File

@ -0,0 +1,8 @@
package io.bkbn.kompendium.auth.configuration
import io.bkbn.kompendium.oas.security.ApiKeyAuth
interface ApiKeyConfiguration : SecurityConfiguration {
val location: ApiKeyAuth.ApiKeyLocation
val keyName: String
}

View File

@ -0,0 +1,3 @@
package io.bkbn.kompendium.auth.configuration
interface BasicAuthConfiguration : SecurityConfiguration

View File

@ -0,0 +1,6 @@
package io.bkbn.kompendium.auth.configuration
interface JwtAuthConfiguration : SecurityConfiguration {
val bearerFormat: String
get() = "JWT"
}

View File

@ -0,0 +1,9 @@
package io.bkbn.kompendium.auth.configuration
import io.bkbn.kompendium.oas.security.OAuth
interface OAuthConfiguration: SecurityConfiguration {
val flows: OAuth.Flows
val description: String?
get() = null
}

View File

@ -0,0 +1,5 @@
package io.bkbn.kompendium.auth.configuration
sealed interface SecurityConfiguration {
val name: String
}

View File

@ -1,201 +1,69 @@
package io.bkbn.kompendium.auth
import com.fasterxml.jackson.annotation.JsonInclude
import com.fasterxml.jackson.databind.SerializationFeature
import io.ktor.application.Application
import io.ktor.application.call
import io.ktor.application.install
import io.ktor.auth.Authentication
import io.ktor.auth.UserIdPrincipal
import io.ktor.auth.authenticate
import io.ktor.features.ContentNegotiation
import io.ktor.http.ContentType
import io.ktor.http.HttpMethod
import io.ktor.http.HttpStatusCode
import io.ktor.jackson.jackson
import io.ktor.response.respondText
import io.ktor.routing.route
import io.ktor.routing.routing
import io.ktor.server.testing.handleRequest
import io.ktor.server.testing.withTestApplication
import kotlin.test.AfterTest
import kotlin.test.assertEquals
import org.junit.Test
import io.bkbn.kompendium.Kompendium
import io.bkbn.kompendium.Notarized.notarizedGet
import io.bkbn.kompendium.auth.KompendiumAuth.notarizedBasic
import io.bkbn.kompendium.auth.KompendiumAuth.notarizedJwt
import io.bkbn.kompendium.auth.util.TestData
import io.bkbn.kompendium.auth.util.TestParams
import io.bkbn.kompendium.auth.util.TestResponse
import io.bkbn.kompendium.models.meta.MethodInfo
import io.bkbn.kompendium.models.meta.ResponseInfo
import io.bkbn.kompendium.routes.openApi
import io.bkbn.kompendium.routes.redoc
import io.bkbn.kompendium.auth.configuration.BasicAuthConfiguration
import io.bkbn.kompendium.auth.configuration.JwtAuthConfiguration
import io.bkbn.kompendium.auth.configuration.OAuthConfiguration
import io.bkbn.kompendium.auth.util.AuthConfigName
import io.bkbn.kompendium.auth.util.configBasicAuth
import io.bkbn.kompendium.auth.util.configJwtAuth
import io.bkbn.kompendium.auth.util.notarizedAuthRoute
import io.bkbn.kompendium.auth.util.setupOauth
import io.bkbn.kompendium.core.fixtures.TestHelpers.openApiTest
import io.bkbn.kompendium.oas.security.OAuth
import io.kotest.core.spec.style.DescribeSpec
internal class KompendiumAuthTest {
@AfterTest
fun `reset kompendium`() {
Kompendium.resetSchema()
}
@Test
fun `Notarized Get with basic authentication records all expected information`() {
withTestApplication({
configModule()
configBasicAuth()
docs()
notarizedAuthenticatedGetModule(TestData.AuthConfigName.Basic)
}) {
// do
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
// expect
val expected = TestData.getFileSnapshot("notarized_basic_authenticated_get.json").trim()
assertEquals(expected, json, "The received json spec should match the expected content")
}
}
@Test
fun `Notarized Get with jwt authentication records all expected information`() {
withTestApplication({
configModule()
configJwtAuth()
docs()
notarizedAuthenticatedGetModule(TestData.AuthConfigName.JWT)
}) {
// do
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
// expect
val expected = TestData.getFileSnapshot("notarized_jwt_authenticated_get.json").trim()
assertEquals(expected, json, "The received json spec should match the expected content")
}
}
@Test
fun `Notarized Get with jwt authentication and custom scheme records all expected information`() {
withTestApplication({
configModule()
configJwtAuth(scheme = "oauth")
docs()
notarizedAuthenticatedGetModule(TestData.AuthConfigName.JWT)
}) {
// do
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
// expect
val expected = TestData.getFileSnapshot("notarized_jwt_custom_scheme_authenticated_get.json").trim()
assertEquals(expected, json, "The received json spec should match the expected content")
}
}
@Test
fun `Notarized Get with jwt authentication and custom header records all expected information`() {
withTestApplication({
configModule()
configJwtAuth(header = "x-api-key")
docs()
notarizedAuthenticatedGetModule(TestData.AuthConfigName.JWT)
}) {
// do
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
// expect
val expected = TestData.getFileSnapshot("notarized_jwt_custom_header_authenticated_get.json").trim()
assertEquals(expected, json, "The received json spec should match the expected content")
}
}
@Test
fun `Notarized Get with multiple jwt schemes records all expected information`() {
withTestApplication({
configModule()
install(Authentication) {
notarizedJwt("jwt1", header = "x-api-key-1") {
realm = "Ktor server"
}
notarizedJwt("jwt2", header = "x-api-key-2") {
realm = "Ktor server"
}
class KompendiumAuthTest : DescribeSpec({
describe("Basic Authentication") {
it("Can create a notarized basic authentication record with all expected information") {
// arrange
val authConfig = object : BasicAuthConfiguration {
override val name: String = AuthConfigName.Basic
}
docs()
notarizedAuthenticatedGetModule("jwt1", "jwt2")
}) {
// do
val json = handleRequest(HttpMethod.Get, "/openapi.json").response.content
// expect
val expected = TestData.getFileSnapshot("notarized_multiple_jwt_authenticated_get.json").trim()
assertEquals(expected, json, "The received json spec should match the expected content")
}
}
private fun Application.configModule() {
install(ContentNegotiation) {
jackson(ContentType.Application.Json) {
enable(SerializationFeature.INDENT_OUTPUT)
setSerializationInclusion(JsonInclude.Include.NON_NULL)
// act
openApiTest("notarized_basic_authenticated_get.json") {
configBasicAuth()
notarizedAuthRoute(authConfig)
}
}
}
describe("JWT Authentication") {
it("Can create a simple notarized JWT route") {
// arrange
val authConfig = object : JwtAuthConfiguration {
override val name: String = AuthConfigName.JWT
}
private fun Application.configBasicAuth() {
install(Authentication) {
notarizedBasic(TestData.AuthConfigName.Basic) {
realm = "Ktor Server"
validate { credentials ->
if (credentials.name == credentials.password) {
UserIdPrincipal(credentials.name)
} else {
null
}
}
// act
openApiTest("notarized_jwt_authenticated_get.json") {
configJwtAuth()
notarizedAuthRoute(authConfig)
}
}
}
private fun Application.configJwtAuth(
header: String? = null,
scheme: String? = null
) {
install(Authentication) {
notarizedJwt(TestData.AuthConfigName.JWT, header, scheme) {
realm = "Ktor server"
}
}
}
private fun Application.notarizedAuthenticatedGetModule(vararg authenticationConfigName: String) {
routing {
authenticate(*authenticationConfigName) {
route(TestData.getRoutePath) {
notarizedGet(testGetInfo(*authenticationConfigName)) {
call.respondText { "hey dude ‼️ congratz on the get request" }
}
}
}
}
}
private val oas = Kompendium.openApiSpec.copy()
private fun Application.docs() {
routing {
openApi(oas)
redoc(oas)
}
}
private companion object {
val testGetResponse = ResponseInfo<TestResponse>(HttpStatusCode.OK, "A Successful Endeavor")
fun testGetInfo(vararg security: String) =
MethodInfo.GetInfo<TestParams, TestResponse>(
summary = "Another get test",
description = "testing more",
responseInfo = testGetResponse,
securitySchemes = security.toSet()
describe("OAuth Authentication") {
it("Can create an Oauth schema with all possible flows") {
// arrange
val flows = OAuth.Flows(
implicit = OAuth.Flows.Implicit(
"https://accounts.google.com/o/oauth2/auth",
scopes = mapOf("test" to "is a cool scope", "this" to "is also cool")
),
authorizationCode = OAuth.Flows.AuthorizationCode("https://accounts.google.com/o/oauth2/auth"),
password = OAuth.Flows.Password("https://accounts.google.com/o/oauth2/auth"),
clientCredentials = OAuth.Flows.ClientCredential("https://accounts.google.com/token")
)
val authConfig = object : OAuthConfiguration {
override val flows: OAuth.Flows = flows
override val name: String = AuthConfigName.OAuth
}
// act
openApiTest("notarized_oauth_all_flows.json") {
setupOauth()
notarizedAuthRoute(authConfig)
}
}
}
}
})

View File

@ -1,18 +0,0 @@
package io.bkbn.kompendium.auth.util
import java.io.File
object TestData {
object AuthConfigName {
const val Basic = "basic"
const val JWT = "jwt"
}
const val getRoutePath = "/test"
fun getFileSnapshot(fileName: String): String {
val snapshotPath = "src/test/resources"
val file = File("$snapshotPath/$fileName")
return file.readText()
}
}

View File

@ -1,19 +0,0 @@
package io.bkbn.kompendium.auth.util
import io.bkbn.kompendium.annotations.KompendiumField
import io.bkbn.kompendium.annotations.KompendiumParam
import io.bkbn.kompendium.annotations.ParamType
data class TestParams(
@KompendiumParam(ParamType.PATH) val a: String,
@KompendiumParam(ParamType.QUERY) val aa: Int
)
data class TestRequest(
@KompendiumField(name = "field_name")
val b: Double,
val aaa: List<Long>
)
data class TestResponse(val c: String)

View File

@ -0,0 +1,92 @@
package io.bkbn.kompendium.auth.util
import io.bkbn.kompendium.auth.Notarized.notarizedAuthenticate
import io.bkbn.kompendium.auth.configuration.SecurityConfiguration
import io.bkbn.kompendium.core.Notarized.notarizedGet
import io.bkbn.kompendium.core.fixtures.TestParams
import io.bkbn.kompendium.core.fixtures.TestResponse
import io.bkbn.kompendium.core.fixtures.TestResponseInfo
import io.bkbn.kompendium.core.metadata.method.GetInfo
import io.ktor.application.Application
import io.ktor.application.call
import io.ktor.application.install
import io.ktor.auth.Authentication
import io.ktor.auth.OAuthServerSettings
import io.ktor.auth.UserIdPrincipal
import io.ktor.auth.basic
import io.ktor.auth.jwt.jwt
import io.ktor.auth.oauth
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO
import io.ktor.http.HttpMethod
import io.ktor.response.respondText
import io.ktor.routing.route
import io.ktor.routing.routing
fun Application.setupOauth() {
install(Authentication) {
oauth("oauth") {
urlProvider = { "http://localhost:8080/callback" }
client = HttpClient(CIO)
providerLookup = {
OAuthServerSettings.OAuth2ServerSettings(
name = "google",
authorizeUrl = "https://accounts.google.com/o/oauth2/auth",
accessTokenUrl = "https://accounts.google.com/o/oauth2/token",
requestMethod = HttpMethod.Post,
clientId = System.getenv("GOOGLE_CLIENT_ID"),
clientSecret = System.getenv("GOOGLE_CLIENT_SECRET"),
defaultScopes = listOf("https://www.googleapis.com/auth/userinfo.profile")
)
}
}
}
}
fun Application.configBasicAuth() {
install(Authentication) {
basic(AuthConfigName.Basic) {
realm = "Ktor Server"
validate { credentials ->
if (credentials.name == credentials.password) {
UserIdPrincipal(credentials.name)
} else {
null
}
}
}
}
}
fun Application.notarizedAuthRoute(authConfig: SecurityConfiguration) {
routing {
notarizedAuthenticate(authConfig) {
route("/test") { notarizedGet(testGetInfo(authConfig.name)) {
call.respondText { "hey dude ‼️ congratz on the get request" }
}
}
}
}
}
fun Application.configJwtAuth() {
install(Authentication) {
jwt(AuthConfigName.JWT) {
realm = "Ktor server"
}
}
}
fun testGetInfo(vararg security: String) =
GetInfo<TestParams, TestResponse>(
summary = "Another get test",
description = "testing more",
responseInfo = TestResponseInfo.testGetResponse,
securitySchemes = security.toSet()
)
object AuthConfigName {
const val Basic = "basic"
const val JWT = "jwt"
const val OAuth = "oauth"
}

View File

@ -1,75 +1,94 @@
{
"openapi" : "3.0.3",
"info" : { },
"servers" : [ ],
"paths" : {
"/test" : {
"get" : {
"tags" : [ ],
"summary" : "Another get test",
"description" : "testing more",
"parameters" : [ {
"name" : "a",
"in" : "path",
"schema" : {
"type" : "string"
"openapi": "3.0.3",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/test": {
"get": {
"tags": [],
"summary": "Another get test",
"description": "testing more",
"parameters": [
{
"name": "a",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
},
"required" : true,
"deprecated" : false
}, {
"name" : "aa",
"in" : "query",
"schema" : {
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
} ],
"responses" : {
"200" : {
"description" : "A Successful Endeavor",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/TestResponse"
{
"name": "aa",
"in": "query",
"schema": {
"format": "int32",
"type": "integer"
},
"required": true,
"deprecated": false
}
],
"responses": {
"200": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"properties": {
"c": {
"type": "string"
}
},
"required": [
"c"
],
"type": "object"
}
}
}
}
},
"deprecated" : false,
"security" : [ {
"basic" : [ ]
} ]
}
}
},
"components" : {
"schemas" : {
"String" : {
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
"deprecated": false,
"security": [
{
"basic": []
}
}
},
"Int" : {
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : {
"basic" : {
"type" : "http",
"scheme" : "basic"
]
}
}
},
"security" : [ ],
"tags" : [ ]
"components": {
"securitySchemes": {
"basic": {
"type": "http",
"scheme": "basic"
}
}
},
"security": [],
"tags": []
}

View File

@ -1,75 +1,95 @@
{
"openapi" : "3.0.3",
"info" : { },
"servers" : [ ],
"paths" : {
"/test" : {
"get" : {
"tags" : [ ],
"summary" : "Another get test",
"description" : "testing more",
"parameters" : [ {
"name" : "a",
"in" : "path",
"schema" : {
"type" : "string"
"openapi": "3.0.3",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/test": {
"get": {
"tags": [],
"summary": "Another get test",
"description": "testing more",
"parameters": [
{
"name": "a",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
},
"required" : true,
"deprecated" : false
}, {
"name" : "aa",
"in" : "query",
"schema" : {
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
} ],
"responses" : {
"200" : {
"description" : "A Successful Endeavor",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/TestResponse"
{
"name": "aa",
"in": "query",
"schema": {
"format": "int32",
"type": "integer"
},
"required": true,
"deprecated": false
}
],
"responses": {
"200": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"properties": {
"c": {
"type": "string"
}
},
"required": [
"c"
],
"type": "object"
}
}
}
}
},
"deprecated" : false,
"security" : [ {
"jwt" : [ ]
} ]
}
}
},
"components" : {
"schemas" : {
"String" : {
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
"deprecated": false,
"security": [
{
"jwt": []
}
}
},
"Int" : {
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : {
"jwt" : {
"type" : "http",
"scheme" : "bearer"
]
}
}
},
"security" : [ ],
"tags" : [ ]
"components": {
"securitySchemes": {
"jwt": {
"bearerFormat": "JWT",
"type": "http",
"scheme": "bearer"
}
}
},
"security": [],
"tags": []
}

View File

@ -1,76 +0,0 @@
{
"openapi" : "3.0.3",
"info" : { },
"servers" : [ ],
"paths" : {
"/test" : {
"get" : {
"tags" : [ ],
"summary" : "Another get test",
"description" : "testing more",
"parameters" : [ {
"name" : "a",
"in" : "path",
"schema" : {
"type" : "string"
},
"required" : true,
"deprecated" : false
}, {
"name" : "aa",
"in" : "query",
"schema" : {
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
} ],
"responses" : {
"200" : {
"description" : "A Successful Endeavor",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/TestResponse"
}
}
}
}
},
"deprecated" : false,
"security" : [ {
"jwt" : [ ]
} ]
}
}
},
"components" : {
"schemas" : {
"String" : {
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
}
},
"Int" : {
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : {
"jwt" : {
"type" : "apiKey",
"name" : "x-api-key",
"in" : "header"
}
}
},
"security" : [ ],
"tags" : [ ]
}

View File

@ -1,75 +0,0 @@
{
"openapi" : "3.0.3",
"info" : { },
"servers" : [ ],
"paths" : {
"/test" : {
"get" : {
"tags" : [ ],
"summary" : "Another get test",
"description" : "testing more",
"parameters" : [ {
"name" : "a",
"in" : "path",
"schema" : {
"type" : "string"
},
"required" : true,
"deprecated" : false
}, {
"name" : "aa",
"in" : "query",
"schema" : {
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
} ],
"responses" : {
"200" : {
"description" : "A Successful Endeavor",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/TestResponse"
}
}
}
}
},
"deprecated" : false,
"security" : [ {
"jwt" : [ ]
} ]
}
}
},
"components" : {
"schemas" : {
"String" : {
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
}
},
"Int" : {
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : {
"jwt" : {
"type" : "http",
"scheme" : "oauth"
}
}
},
"security" : [ ],
"tags" : [ ]
}

View File

@ -1,82 +0,0 @@
{
"openapi" : "3.0.3",
"info" : { },
"servers" : [ ],
"paths" : {
"/test" : {
"get" : {
"tags" : [ ],
"summary" : "Another get test",
"description" : "testing more",
"parameters" : [ {
"name" : "a",
"in" : "path",
"schema" : {
"type" : "string"
},
"required" : true,
"deprecated" : false
}, {
"name" : "aa",
"in" : "query",
"schema" : {
"type" : "integer",
"format" : "int32"
},
"required" : true,
"deprecated" : false
} ],
"responses" : {
"200" : {
"description" : "A Successful Endeavor",
"content" : {
"application/json" : {
"schema" : {
"$ref" : "#/components/schemas/TestResponse"
}
}
}
}
},
"deprecated" : false,
"security" : [ {
"jwt1" : [ ],
"jwt2" : [ ]
} ]
}
}
},
"components" : {
"schemas" : {
"String" : {
"type" : "string"
},
"TestResponse" : {
"type" : "object",
"properties" : {
"c" : {
"$ref" : "#/components/schemas/String"
}
}
},
"Int" : {
"type" : "integer",
"format" : "int32"
}
},
"securitySchemes" : {
"jwt1" : {
"type" : "apiKey",
"name" : "x-api-key-1",
"in" : "header"
},
"jwt2" : {
"type" : "apiKey",
"name" : "x-api-key-2",
"in" : "header"
}
}
},
"security" : [ ],
"tags" : [ ]
}

View File

@ -0,0 +1,114 @@
{
"openapi": "3.0.3",
"info": {
"title": "Test API",
"version": "1.33.7",
"description": "An amazing, fully-ish 😉 generated API spec",
"termsOfService": "https://example.com",
"contact": {
"name": "Homer Simpson",
"url": "https://gph.is/1NPUDiM",
"email": "chunkylover53@aol.com"
},
"license": {
"name": "MIT",
"url": "https://github.com/bkbnio/kompendium/blob/main/LICENSE"
}
},
"servers": [
{
"url": "https://myawesomeapi.com",
"description": "Production instance of my API"
},
{
"url": "https://staging.myawesomeapi.com",
"description": "Where the fun stuff happens"
}
],
"paths": {
"/test": {
"get": {
"tags": [],
"summary": "Another get test",
"description": "testing more",
"parameters": [
{
"name": "a",
"in": "path",
"schema": {
"type": "string"
},
"required": true,
"deprecated": false
},
{
"name": "aa",
"in": "query",
"schema": {
"format": "int32",
"type": "integer"
},
"required": true,
"deprecated": false
}
],
"responses": {
"200": {
"description": "A Successful Endeavor",
"content": {
"application/json": {
"schema": {
"properties": {
"c": {
"type": "string"
}
},
"required": [
"c"
],
"type": "object"
}
}
}
}
},
"deprecated": false,
"security": [
{
"oauth": []
}
]
}
}
},
"components": {
"securitySchemes": {
"oauth": {
"flows": {
"implicit": {
"authorizationUrl": "https://accounts.google.com/o/oauth2/auth",
"scopes": {
"test": "is a cool scope",
"this": "is also cool"
}
},
"authorizationCode": {
"authorizationUrl": "https://accounts.google.com/o/oauth2/auth",
"scopes": {}
},
"password": {
"tokenUrl": "https://accounts.google.com/o/oauth2/auth",
"scopes": {}
},
"clientCredentials": {
"tokenUrl": "https://accounts.google.com/token",
"scopes": {}
}
},
"type": "oauth2"
}
}
},
"security": [],
"tags": []
}