fix: spec and docs behind auth (#284)

This commit is contained in:
Ryan Brink
2022-08-13 10:34:01 -07:00
committed by GitHub
parent 90b1f47dbb
commit 2e29b46f0f
4 changed files with 119 additions and 12 deletions

View File

@ -5,6 +5,7 @@
### Added
### Changed
- Can now put redoc route behind authentication
### Remove

View File

@ -3,7 +3,7 @@ package io.bkbn.kompendium.core.routes
import io.ktor.http.HttpStatusCode
import io.ktor.server.application.call
import io.ktor.server.html.respondHtml
import io.ktor.server.routing.Routing
import io.ktor.server.routing.Route
import io.ktor.server.routing.get
import io.ktor.server.routing.route
import kotlinx.html.body
@ -20,7 +20,7 @@ import kotlinx.html.unsafe
* @param pageTitle Webpage title you wish to be displayed on your docs
* @param specUrl url to point ReDoc to the OpenAPI json document
*/
fun Routing.redoc(pageTitle: String = "Docs", specUrl: String = "/openapi.json") {
fun Route.redoc(pageTitle: String = "Docs", specUrl: String = "/openapi.json") {
route("/docs") {
get {
call.respondHtml(HttpStatusCode.OK) {

View File

@ -30,10 +30,6 @@ import io.ktor.server.routing.route
import io.ktor.server.routing.routing
import kotlinx.serialization.json.Json
/**
* Application entrypoint. Run this and head on over to `localhost:8081/docs`
* to see a very simple yet beautifully documented API
*/
fun main() {
embeddedServer(
Netty,
@ -43,7 +39,6 @@ fun main() {
}
private fun Application.mainModule() {
// Installs Simple JSON Content Negotiation
install(ContentNegotiation) {
json(Json {
serializersModule = KompendiumSerializersModule.module
@ -75,10 +70,6 @@ private fun Application.mainModule() {
routing {
redoc(pageTitle = "Simple API Docs")
authenticate("basic") {
// This adds ReDoc support at the `/docs` endpoint.
// By default, it will point at the `/openapi.json` created by Kompendium
// Route with a get handler
route("/{id}") {
idDocumentation()
get {
@ -89,7 +80,6 @@ private fun Application.mainModule() {
}
}
// Documentation for our route
private fun Route.idDocumentation() {
install(NotarizedRoute()) {
parameters = listOf(

View File

@ -0,0 +1,116 @@
package io.bkbn.kompendium.playground
import io.bkbn.kompendium.core.attribute.KompendiumAttributes
import io.bkbn.kompendium.core.metadata.GetInfo
import io.bkbn.kompendium.core.plugin.NotarizedApplication
import io.bkbn.kompendium.core.plugin.NotarizedRoute
import io.bkbn.kompendium.core.routes.redoc
import io.bkbn.kompendium.json.schema.definition.TypeDefinition
import io.bkbn.kompendium.oas.component.Components
import io.bkbn.kompendium.oas.payload.Parameter
import io.bkbn.kompendium.oas.security.BasicAuth
import io.bkbn.kompendium.oas.serialization.KompendiumSerializersModule
import io.bkbn.kompendium.playground.util.ExampleResponse
import io.bkbn.kompendium.playground.util.Util.baseSpec
import io.ktor.http.HttpStatusCode
import io.ktor.serialization.kotlinx.json.json
import io.ktor.server.application.Application
import io.ktor.server.application.call
import io.ktor.server.application.install
import io.ktor.server.auth.Authentication
import io.ktor.server.auth.UserIdPrincipal
import io.ktor.server.auth.authenticate
import io.ktor.server.auth.basic
import io.ktor.server.engine.embeddedServer
import io.ktor.server.netty.Netty
import io.ktor.server.plugins.contentnegotiation.ContentNegotiation
import io.ktor.server.response.respond
import io.ktor.server.routing.Route
import io.ktor.server.routing.application
import io.ktor.server.routing.get
import io.ktor.server.routing.route
import io.ktor.server.routing.routing
import kotlinx.serialization.json.Json
fun main() {
embeddedServer(
Netty,
port = 8081,
module = Application::mainModule
).start(wait = true)
}
private fun Application.mainModule() {
install(ContentNegotiation) {
json(Json {
serializersModule = KompendiumSerializersModule.module
encodeDefaults = true
explicitNulls = false
})
}
install(Authentication) {
basic("basic") {
realm = "Ktor Server"
validate { credentials ->
if (credentials.name == credentials.password) {
UserIdPrincipal(credentials.name)
} else {
null
}
}
}
}
install(NotarizedApplication()) {
spec = baseSpec.copy(
components = Components(
securitySchemes = mutableMapOf(
"basic" to BasicAuth()
)
)
)
openApiJson = {
authenticate("basic") {
route("/openapi.json") {
get {
call.respond(HttpStatusCode.OK, this@route.application.attributes[KompendiumAttributes.openApiSpec])
}
}
}
}
}
routing {
authenticate("basic") {
redoc(pageTitle = "Simple API Docs")
route("/{id}") {
idDocumentation()
get {
call.respond(HttpStatusCode.OK, ExampleResponse(true))
}
}
}
}
}
private fun Route.idDocumentation() {
install(NotarizedRoute()) {
parameters = listOf(
Parameter(
name = "id",
`in` = Parameter.Location.path,
schema = TypeDefinition.STRING
)
)
get = GetInfo.builder {
summary("Get user by id")
description("A very neat endpoint!")
security = mapOf(
"basic" to emptyList()
)
response {
responseCode(HttpStatusCode.OK)
responseType<ExampleResponse>()
description("Will return whether or not the user is real 😱")
}
}
}
}