Skip to content
This repository has been archived by the owner on Apr 10, 2019. It is now read-only.

Commit

Permalink
#3, feature: Initial swagger -> ast conversion for security definitions
Browse files Browse the repository at this point in the history
  • Loading branch information
slavaschmidt committed Mar 5, 2016
1 parent 5b51d0f commit 995046f
Show file tree
Hide file tree
Showing 11 changed files with 75 additions and 22 deletions.
21 changes: 11 additions & 10 deletions compiler/src/main/scala/de/zalando/apifirst/ast.scala
Original file line number Diff line number Diff line change
Expand Up @@ -222,23 +222,23 @@ case object ParameterPlace extends Enumeration {
object Security {
type OAuth2Scopes = Map[String, String]
sealed trait Definition {
def description: String
def description: Option[String]
}
case class Basic(description: String) extends Definition
case class ApiKey(description: String, name: String, in: ParameterPlace) extends Definition {
case class Basic(description: Option[String]) extends Definition
case class ApiKey(description: Option[String], name: String, in: ParameterPlace) extends Definition {
require(in == ParameterPlace.QUERY || in == ParameterPlace.HEADER)
require(name.nonEmpty)
}
case class OAuth2Implicit(description: String, authorizationUrl: URL, scopes: OAuth2Scopes) extends Definition {
case class OAuth2Implicit(description: Option[String], authorizationUrl: URL, scopes: OAuth2Scopes) extends Definition {
require(authorizationUrl != null)
}
case class OAuth2Password(description: String, tokenUrl: URL, scopes: OAuth2Scopes) extends Definition {
case class OAuth2Password(description: Option[String], tokenUrl: URL, scopes: OAuth2Scopes) extends Definition {
require(tokenUrl != null)
}
case class OAuth2Application(description: String, tokenUrl: URL, scopes: OAuth2Scopes) extends Definition {
case class OAuth2Application(description: Option[String], tokenUrl: URL, scopes: OAuth2Scopes) extends Definition {
require(tokenUrl != null)
}
case class OAuth2AccessCode(description: String, authorizationUrl: URL, tokenUrl: URL, scopes: OAuth2Scopes) extends Definition {
case class OAuth2AccessCode(description: Option[String], authorizationUrl: URL, tokenUrl: URL, scopes: OAuth2Scopes) extends Definition {
require(tokenUrl != null)
require(authorizationUrl != null)
}
Expand Down Expand Up @@ -277,7 +277,7 @@ object Application {
errorMapping: Map[String, Seq[Class[Exception]]], // can be empty for swagger specification
resultTypes: Map[Int, ParameterRef],
defaultResult: Option[ParameterRef],
security: Set[Security.Definition] = Set.empty
security: Set[String] = Set.empty
) {
def asReference = (path.prepend("paths") / verb.toString.toLowerCase).ref
}
Expand All @@ -289,14 +289,15 @@ object Application {
type TypeLookupTable = Map[Reference, Domain.Type]
type DiscriminatorLookupTable = Map[Reference, Reference]

type SecurityDefinitionsDable = Map[String, Security.Definition]
type SecurityDefinitionsTable = Map[String, Security.Definition]

case class StrictModel(calls: Seq[ApiCall],
typeDefs: TypeLookupTable,
params: ParameterLookupTable,
discriminators: DiscriminatorLookupTable,
basePath: String,
packageName: Option[String]) {
packageName: Option[String],
securityDefinitionsTable: SecurityDefinitionsTable) {
def findParameter(ref: ParameterRef): Parameter = params(ref)
def findParameter(name: Reference): Option[Parameter] = params.find(_._1.name == name).map(_._2)
def findType(ref: Reference) = typeDefs(ref)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class ScalaGenerator(val strictModel: StrictModel) extends PlayScalaControllerAn

val denotationTable = AstScalaPlayEnricher(strictModel)

val StrictModel(modelCalls, modelTypes, modelParameters, discriminators, _, overridenPackageName) = strictModel
val StrictModel(modelCalls, modelTypes, modelParameters, discriminators, _, overridenPackageName, _) = strictModel

val testsTemplateName = "play_scala_test"
val validatorsTemplateName = "play_validation"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ trait ParameterNaming {

object ModelConverter extends ParameterNaming {

def fromModel(base: URI, model: SwaggerModel, file: Option[File] = None, keyPrefix: String = "x-api-first", autoConvert: Boolean = true) = {
def fromModel(base: URI, model: SwaggerModel, file: Option[File] = None,
keyPrefix: String = "x-api-first", autoConvert: Boolean = true) = {
val converter = new TypeConverter(base, model, keyPrefix)
val typeDefs = converter.convert
val discriminators = converter.discriminators.toMap
Expand All @@ -30,7 +31,9 @@ object ModelConverter extends ParameterNaming {
val inheritedPackageName = apiCalls.headOption collect {
case h if apiCalls.seq.forall { _.handler.packageName == h.handler.packageName } => h.handler.packageName
}
StrictModel(apiCalls, typeDefs.toMap, inlineParameters, discriminators, model.basePath, packageName orElse inheritedPackageName)
val securityDefinitions = SecurityConverter.convertDefinitions(model.securityDefinitions)
StrictModel(apiCalls, typeDefs.toMap, inlineParameters, discriminators,
model.basePath, packageName orElse inheritedPackageName, securityDefinitions)
}

}
44 changes: 44 additions & 0 deletions compiler/src/main/scala/de/zalando/swagger/SecurityConverter.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package de.zalando.swagger

import java.net.URL

import de.zalando.apifirst.Application.SecurityDefinitionsTable
import de.zalando.apifirst.{ParameterPlace, Security}
import de.zalando.swagger.strictModel._

/**
* @author slasch
* @since 05.03.2016
*/
object SecurityConverter {

def convertDefinitions(swaggerDefinitions: SecurityDefinitions): SecurityDefinitionsTable =
if (swaggerDefinitions == null) Map.empty
else swaggerDefinitions.collect {
case (name, basic: BasicAuthenticationSecurity) =>
name -> Security.Basic(Option(basic.description))
case (name, apiKey: ApiKeySecurity) =>
require(apiKey.name != null && apiKey.name.nonEmpty)
require(apiKey.in != null && apiKey.in.nonEmpty)
val place = ParameterPlace.withName(apiKey.in.toLowerCase)
require(place == ParameterPlace.HEADER || place == ParameterPlace.QUERY)
name -> Security.ApiKey(Option(apiKey.description), apiKey.name, place)
case (name, oauth: Oauth2ImplicitSecurity) =>
val authorizationUrl = new URL(oauth.authorizationUrl)
name -> Security.OAuth2Implicit(Option(oauth.description), authorizationUrl, oauth.scopes)
case (name, oauth: Oauth2PasswordSecurity) =>
val tokenUrl = new URL(oauth.tokenUrl)
name -> Security.OAuth2Password(Option(oauth.description), tokenUrl, oauth.scopes)
case (name, oauth: Oauth2ApplicationSecurity) =>
val tokenUrl = new URL(oauth.tokenUrl)
name -> Security.OAuth2Application(Option(oauth.description), tokenUrl, oauth.scopes)
case (name, oauth: Oauth2AccessCodeSecurity) =>
val authorizationUrl = new URL(oauth.authorizationUrl)
val tokenUrl = new URL(oauth.tokenUrl)
name -> Security.OAuth2AccessCode(Option(oauth.description), authorizationUrl, tokenUrl, oauth.scopes)
}
}




Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ class ParameterDereferencerTest extends FunSpec with MustMatchers {
)

def checkExpectations[T](types: TypeLookupTable)(params: ParameterLookupTable = parametersFromTypes(types)): Unit = {
val model = StrictModel(Nil, types, params, Map.empty, "", None)
val model = StrictModel(Nil, types, params, Map.empty, "", None, Map.empty)
val result = ParameterDereferencer(model)
types.foreach { t => result.typeDefs.contains(t._1) mustBe true }
result.typeDefs.size mustBe (types.size + params.count(! _._2.typeName.isInstanceOf[TypeRef]))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class TypeDeduplicatorTest extends FunSpec with MustMatchers with ExpectedResult
)

val expectedTypes = types - reference1
val model = StrictModel(Nil, types, params, discriminators, "", None)
val model = StrictModel(Nil, types, params, discriminators, "", None, Map.empty)
val result = TypeDeduplicator(model)
result.typeDefs mustBe expectedTypes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import scala.language.implicitConversions
*/
class TypeFlattenerTest extends FunSpec with MustMatchers with ExpectedResults {

implicit def types2model(types: TypeLookupTable): StrictModel = StrictModel.apply(Nil, types, Map.empty, Map.empty, "", None)
implicit def types2model(types: TypeLookupTable): StrictModel =
StrictModel.apply(Nil, types, Map.empty, Map.empty, "", None, Map.empty)

private val noMeta = TypeMeta(None)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import scala.language.implicitConversions
*/
class AstScalaPlayEnricherTest extends FunSpec with MustMatchers {

implicit def types2model(types: TypeLookupTable): StrictModel = StrictModel.apply(Nil, types, Map.empty, Map.empty, "", None)
implicit def types2model(types: TypeLookupTable): StrictModel =
StrictModel.apply(Nil, types, Map.empty, Map.empty, "", None, Map.empty)

describe("AstScalaPlayEnricher") {
it("should generate nothing for empty model") {
Expand Down Expand Up @@ -57,7 +58,7 @@ class AstScalaPlayEnricherTest extends FunSpec with MustMatchers {
val discriminators: DiscriminatorLookupTable = Map(
"definitions" / "Pet" -> "definitions" / "Pet" / "petType"
)
val strictModel = StrictModel(Nil, model, Map.empty, discriminators, "", None)
val strictModel = StrictModel(Nil, model, Map.empty, discriminators, "", None, Map.empty)

val result = AstScalaPlayEnricher(strictModel)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import scala.language.implicitConversions
*/
class ScalaGeneratorsTest extends FunSpec with MustMatchers {

implicit def types2model(types: TypeLookupTable): StrictModel = StrictModel.apply(Nil, types, Map.empty, Map.empty, "", None)
implicit def types2model(types: TypeLookupTable): StrictModel =
StrictModel.apply(Nil, types, Map.empty, Map.empty, "", None, Map.empty)

describe("ScalaGeneratorTest") {
it("should generate nothing for empty model") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ import scala.language.implicitConversions
*/
class ScalaModelGeneratorTest extends FunSpec with MustMatchers {

implicit def types2model(types: TypeLookupTable): StrictModel = StrictModel.apply(Nil, types, Map.empty, Map.empty, "", None)
implicit def types2model(types: TypeLookupTable): StrictModel =
StrictModel.apply(Nil, types, Map.empty, Map.empty, "", None, Map.empty)

describe("ScalaGeneratorTest") {
it("should generate nothing for empty model") {
Expand Down Expand Up @@ -156,7 +157,8 @@ class ScalaModelGeneratorTest extends FunSpec with MustMatchers {
val discriminators: DiscriminatorLookupTable = Map(
"definitions" / "Pet" -> "definitions" / "Pet" / "petType"
)
val strictModel = StrictModel(Nil, model, Map.empty, discriminators, "", Some("overriden.package.scala"))
val strictModel =
StrictModel(Nil, model, Map.empty, discriminators, "", Some("overriden.package.scala"), Map.empty)

val result = new ScalaGenerator(strictModel).generateModel("test.scala", "test.scala")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import play.routes.compiler.{DynamicPart, StaticPart}
*/
class RuleGeneratorTest extends FunSpec with MustMatchers {

implicit val model = StrictModel(Nil, Map.empty, Map.empty, Map.empty, "/base/", None)
implicit val model = StrictModel(Nil, Map.empty, Map.empty, Map.empty, "/base/", None, Map.empty)

val routes = Map(
"/" -> Nil
Expand Down

0 comments on commit 995046f

Please sign in to comment.