Skip to content

Commit

Permalink
Fix OpenAPI security schema (#2813) (#2893)
Browse files Browse the repository at this point in the history
  • Loading branch information
987Nabil authored Jun 11, 2024
1 parent dc0e883 commit abdaf0b
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 19 deletions.
2 changes: 1 addition & 1 deletion project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ object Dependencies {
val ZioVersion = "2.1.1"
val ZioCliVersion = "0.5.0"
val ZioJsonVersion = "0.6.2"
val ZioSchemaVersion = "1.2.0"
val ZioSchemaVersion = "1.2.1"
val SttpVersion = "3.3.18"
val ZioConfigVersion = "4.0.2"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import zio.Chunk
import zio.json.ast._

import zio.schema._
import zio.schema.annotation.{fieldName, noDiscriminator}
import zio.schema.annotation.{caseName, discriminatorName, fieldName, noDiscriminator}
import zio.schema.codec.JsonCodec
import zio.schema.codec.json._

Expand Down Expand Up @@ -1271,8 +1271,8 @@ object OpenAPI {
*/
final case class XML(name: String, namespace: URI, prefix: String, attribute: Boolean = false, wrapped: Boolean)

@discriminatorName("type")
sealed trait SecurityScheme {
def `type`: String
def description: Option[Doc]
}

Expand All @@ -1291,9 +1291,8 @@ object OpenAPI {
* @param in
* The location of the API key.
*/
final case class ApiKey(description: Option[Doc], name: String, in: ApiKey.In) extends SecurityScheme {
override def `type`: String = "apiKey"
}
@caseName("apiKey")
final case class ApiKey(description: Option[Doc], name: String, in: ApiKey.In) extends SecurityScheme

object ApiKey {
sealed trait In extends Product with Serializable
Expand All @@ -1319,11 +1318,8 @@ object OpenAPI {
* Bearer tokens are usually generated by an authorization server, so this
* information is primarily for documentation purposes.
*/
final case class Http(description: Option[Doc], scheme: String, bearerFormat: Option[String])
extends SecurityScheme {
override def `type`: String = "http"

}
@caseName("http")
final case class Http(description: Option[Doc], scheme: String, bearerFormat: Option[String]) extends SecurityScheme

/**
* @param description
Expand All @@ -1332,21 +1328,17 @@ object OpenAPI {
* An object containing configuration information for the flow types
* supported.
*/
final case class OAuth2(description: Option[Doc], flows: OAuthFlows) extends SecurityScheme {
override def `type`: String = "oauth2"

}
@caseName("oauth2")
final case class OAuth2(description: Option[Doc], flows: OAuthFlows) extends SecurityScheme

/**
* @param description
* A short description for security scheme.
* @param openIdConnectUrl
* OpenId Connect URL to discover OAuth2 configuration values.
*/
final case class OpenIdConnect(description: Option[Doc], openIdConnectUrl: URI) extends SecurityScheme {
override def `type`: String = "openIdConnect"

}
@caseName("openIdConnect")
final case class OpenIdConnect(description: Option[Doc], openIdConnectUrl: URI) extends SecurityScheme

/**
* Allows configuration of the supported OAuth Flows.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package zio.http.endpoint.openapi

import scala.collection.immutable.ListMap

import zio.json.ast.Json
import zio.test._

import zio.http.endpoint.openapi.OpenAPI.SecurityScheme._

object OpenAPISpec extends ZIOSpecDefault {

def toJsonAst(str: String): Json =
Json.decoder.decodeJson(str).toOption.get

def toJsonAst(api: OpenAPI): Json =
toJsonAst(api.toJson)

val spec = suite("OpenAPISpec")(
test("auth schema serialization") {
import OpenAPI._
val securitySchemes: ListMap[Key, ReferenceOr[SecurityScheme]] = ListMap(
Key.fromString("apiKeyAuth").get -> ReferenceOr.Or(
SecurityScheme.ApiKey(
None,
"Authorization",
ApiKey.In.Header,
),
),
)

val openApi = OpenAPI.empty.copy(
security = List(SecurityRequirement(Map("apiKeyAuth" -> List.empty))),
components = Some(OpenAPI.Components(securitySchemes = securitySchemes)),
)
val json = openApi.toJsonPretty
val expected = """{
| "openapi" : "3.1.0",
| "info" : {
| "title" : "",
| "version" : ""
| },
| "components" : {
| "securitySchemes" : {
| "apiKeyAuth" :
| {
| "type" : "apiKey",
| "name" : "Authorization",
| "in" : "Header"
| }
| }
| },
| "security" : [
| {
| "securitySchemes" : {
| "apiKeyAuth" : []
| }
| }
| ]
|}""".stripMargin

assertTrue(toJsonAst(json) == toJsonAst(expected))
},
)
}

0 comments on commit abdaf0b

Please sign in to comment.