-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ATL-1334 feat(pollux): add sandbox project to play with Tapir and sch…
…ema-registry (#62) feat(pollux): add sandbox project to play with Tapir and schema-registry
- Loading branch information
1 parent
f0d1745
commit 496337b
Showing
14 changed files
with
486 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
version = 3.5.8 | ||
maxColumn = 140 | ||
runner.dialect = scala3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
## Quick start | ||
|
||
This is a sandbox project based on tapir template for Scala 3 and ZIO/ZIO-HTTP. | ||
|
||
You can play there with different Tapir features or even run the in-memory schema service. | ||
|
||
You can use the standard commands: | ||
|
||
```shell | ||
sbt compile # build the project | ||
sbt test # run the tests | ||
sbt run # run the application (Main) | ||
``` | ||
|
||
## Links: | ||
|
||
* [tapir documentation](https://tapir.softwaremill.com/en/latest/) | ||
* [tapir github](https://github.com/softwaremill/tapir) | ||
* [bootzooka: template microservice using tapir](https://softwaremill.github.io/bootzooka/) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
val tapirVersion = "1.1.0" | ||
|
||
lazy val rootProject = (project in file(".")).settings( | ||
Seq( | ||
name := "pollux", | ||
version := "0.1.0-SNAPSHOT", | ||
organization := "iohk", | ||
scalaVersion := "3.2.0", | ||
libraryDependencies ++= Seq( | ||
"com.softwaremill.sttp.tapir" %% "tapir-zio-http-server" % tapirVersion, | ||
"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-bundle" % tapirVersion, | ||
"com.softwaremill.sttp.tapir" %% "tapir-json-zio" % tapirVersion, | ||
"ch.qos.logback" % "logback-classic" % "1.4.1", | ||
"com.softwaremill.sttp.tapir" %% "tapir-redoc-bundle" % "1.1.1", | ||
"com.softwaremill.sttp.tapir" %% "tapir-sttp-stub-server" % tapirVersion % Test, | ||
"dev.zio" %% "zio-test" % "2.0.0" % Test, | ||
"dev.zio" %% "zio-test-sbt" % "2.0.0" % Test, | ||
"com.softwaremill.sttp.client3" %% "zio-json" % "3.8.0" % Test | ||
), | ||
testFrameworks := Seq(new TestFramework("zio.test.sbt.ZTestFramework")) | ||
) | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
sbt.version=1.7.1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6") |
40 changes: 40 additions & 0 deletions
40
sandbox/prism-agent-tapir/src/main/scala/io/iohk/atala/pollux/Main.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package io.iohk.atala.pollux | ||
|
||
import io.iohk.atala.pollux.stub.SchemaEndpointsInMemory | ||
import org.slf4j.LoggerFactory | ||
import sttp.tapir.server.interceptor.log.DefaultServerLog | ||
import sttp.tapir.server.ziohttp.{ZioHttpInterpreter, ZioHttpServerOptions} | ||
import zhttp.http.HttpApp | ||
import zhttp.service.server.ServerChannelFactory | ||
import zhttp.service.{EventLoopGroup, Server} | ||
import zio.{Console, Scope, Task, ZIO, ZIOAppArgs, ZIOAppDefault} | ||
|
||
// Here serverEndpoints are interpreted by Tapir into HTTP Server based on ZIO-HTTP Interpreter | ||
object Main extends ZIOAppDefault: | ||
val log = LoggerFactory.getLogger(ZioHttpInterpreter.getClass.getName) | ||
|
||
override def run: ZIO[Any with ZIOAppArgs with Scope, Any, Any] = | ||
val serverOptions: ZioHttpServerOptions[Any] = | ||
ZioHttpServerOptions.customiseInterceptors | ||
.serverLog( | ||
DefaultServerLog[Task]( | ||
doLogWhenReceived = msg => ZIO.succeed(log.debug(msg)), | ||
doLogWhenHandled = (msg, error) => ZIO.succeed(error.fold(log.debug(msg))(err => log.debug(msg, err))), | ||
doLogAllDecodeFailures = (msg, error) => ZIO.succeed(error.fold(log.debug(msg))(err => log.debug(msg, err))), | ||
doLogExceptions = (msg: String, ex: Throwable) => ZIO.succeed(log.debug(msg, ex)), | ||
noLog = ZIO.unit | ||
) | ||
) | ||
.options | ||
val app: HttpApp[Any, Throwable] = ZioHttpInterpreter(serverOptions) | ||
.toHttp(SchemaEndpointsInMemory.all) | ||
|
||
val port = sys.env.get("http.port").map(_.toInt).getOrElse(8080) | ||
|
||
(for | ||
serverStart <- Server(app).withPort(port).make | ||
_ <- Console.printLine(s"Go to http://localhost:${serverStart.port}/docs to open SwaggerUI. Press ENTER key to exit.") | ||
_ <- Console.readLine | ||
yield serverStart) | ||
.provideSomeLayer(EventLoopGroup.auto(0) ++ ServerChannelFactory.auto ++ Scope.default) | ||
.exitCode |
20 changes: 20 additions & 0 deletions
20
...prism-agent-tapir/src/main/scala/io/iohk/atala/pollux/api/CommonEndpointDefinitions.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package io.iohk.atala.pollux.api | ||
|
||
import io.iohk.atala.pollux.models.{BadRequest, FailureResponse, InternalServerError} | ||
import sttp.model.StatusCode | ||
import sttp.tapir.EndpointOutput.OneOf | ||
import sttp.model.StatusCode | ||
import sttp.tapir.EndpointOutput.OneOf | ||
import sttp.tapir.generic.auto.* | ||
import sttp.tapir.json.zio.jsonBody | ||
import sttp.tapir.ztapir.{oneOf, oneOfVariant} | ||
import zio.json.{DeriveJsonDecoder, DeriveJsonEncoder} | ||
|
||
object CommonEndpointDefinitions { | ||
|
||
// This is an example of the common output definition for the endpoint that can be reused in the endpoint definition | ||
val httpErrors: OneOf[FailureResponse, FailureResponse] = oneOf[FailureResponse]( | ||
oneOfVariant(StatusCode.InternalServerError, jsonBody[InternalServerError]), | ||
oneOfVariant(StatusCode.BadRequest, jsonBody[BadRequest]) | ||
) | ||
} |
58 changes: 58 additions & 0 deletions
58
...-tapir/src/main/scala/io/iohk/atala/pollux/api/VerifiableCredentialsSchemaEndpoints.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
package io.iohk.atala.pollux.api | ||
|
||
import io.iohk.atala.pollux.models.{ | ||
BadRequest, | ||
ErrorResponse, | ||
FailureResponse, | ||
InternalServerError, | ||
NotFoundResponse, | ||
UnauthorizedResponse, | ||
UnknownResponse, | ||
VerifiableCredentialsSchema, | ||
VerifiableCredentialsSchemaInput | ||
} | ||
import sttp.tapir.EndpointIO.Info | ||
import sttp.tapir.json.zio.jsonBody | ||
import sttp.tapir.{Endpoint, EndpointInfo, PublicEndpoint, endpoint, oneOf, oneOfDefaultVariant, oneOfVariant, path, stringToPath} | ||
import sttp.tapir.generic.auto.* | ||
import zio.json.{DeriveJsonDecoder, DeriveJsonEncoder} | ||
import sttp.model.StatusCode | ||
import sttp.tapir.statusCode | ||
|
||
import java.util.UUID | ||
|
||
object VerifiableCredentialsSchemaEndpoints { | ||
|
||
val createSchemaEndpoint: PublicEndpoint[VerifiableCredentialsSchemaInput, Unit, VerifiableCredentialsSchema, Any] = | ||
endpoint.post | ||
.in("schema-registry" / "schemas") | ||
.in( | ||
jsonBody[VerifiableCredentialsSchemaInput] | ||
.copy(info = Info.empty.description("Create schema input object with the metadata and attributes")) | ||
) | ||
.out(statusCode(StatusCode.Created)) | ||
.out(jsonBody[VerifiableCredentialsSchema]) | ||
.name("createSchema") | ||
.summary("Publish new schema to the schema registry") | ||
.description( | ||
"Publish the new schema with attributes to the schema registry on behalf of Cloud Agent. Schema will be signed by the keys of Cloud Agent and issued by the DID that corresponds to it" | ||
) | ||
.tag("Schema Registry") | ||
|
||
val getSchemaById: PublicEndpoint[UUID, FailureResponse, VerifiableCredentialsSchema, Any] = | ||
endpoint.get | ||
.in( | ||
"schema-registry" / "schemas" / path[UUID]("id") | ||
.copy(info = Info.empty.description("Schema Id")) | ||
) | ||
.out(jsonBody[VerifiableCredentialsSchema]) | ||
.errorOut( | ||
oneOf[FailureResponse]( | ||
oneOfVariant(StatusCode.NotFound, jsonBody[NotFoundResponse]) | ||
) | ||
) | ||
.name("getSchemaById") | ||
.summary("Fetch the schema from the registry by id") | ||
.description("Fetch the schema by the unique identifier. Verifiable Credential Schema in json format is returned.") | ||
.tag("Schema Registry") | ||
} |
90 changes: 90 additions & 0 deletions
90
sandbox/prism-agent-tapir/src/main/scala/io/iohk/atala/pollux/models/ErrorResponse.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
package io.iohk.atala.pollux.models | ||
|
||
import sttp.model.StatusCode | ||
import sttp.tapir.EndpointOutput.OneOf | ||
import sttp.tapir.generic.auto.* | ||
import sttp.tapir.json.zio.jsonBody | ||
import sttp.tapir.ztapir.{oneOf, oneOfVariant} | ||
import zio.json.{DeriveJsonDecoder, DeriveJsonEncoder} | ||
|
||
sealed trait FailureResponse | ||
|
||
case class NotFoundResponse(msg: String) extends FailureResponse | ||
|
||
object NotFoundResponse { | ||
given encoder: zio.json.JsonEncoder[NotFoundResponse] = DeriveJsonEncoder.gen[NotFoundResponse] | ||
given decoder: zio.json.JsonDecoder[NotFoundResponse] = DeriveJsonDecoder.gen[NotFoundResponse] | ||
} | ||
|
||
case class BadRequest(msg: String, errors: List[String] = List.empty) extends FailureResponse | ||
|
||
object BadRequest { | ||
given encoder: zio.json.JsonEncoder[BadRequest] = DeriveJsonEncoder.gen[BadRequest] | ||
given decoder: zio.json.JsonDecoder[BadRequest] = DeriveJsonDecoder.gen[BadRequest] | ||
} | ||
|
||
case class InternalServerError(msg: String) extends FailureResponse | ||
|
||
object InternalServerError { | ||
given encoder: zio.json.JsonEncoder[InternalServerError] = DeriveJsonEncoder.gen[InternalServerError] | ||
given decoder: zio.json.JsonDecoder[InternalServerError] = DeriveJsonDecoder.gen[InternalServerError] | ||
} | ||
|
||
//An RFC-7807 compliant data structure for reporting errors to the client | ||
case class ErrorResponse(`type`: String, title: String, status: Int, instance: String, details: Option[String]) extends FailureResponse | ||
|
||
object ErrorResponse { | ||
given encoder: zio.json.JsonEncoder[ErrorResponse] = DeriveJsonEncoder.gen[ErrorResponse] | ||
given decoder: zio.json.JsonDecoder[ErrorResponse] = DeriveJsonDecoder.gen[ErrorResponse] | ||
} | ||
|
||
case class UnauthorizedResponse(message: String) extends FailureResponse | ||
|
||
object UnauthorizedResponse { | ||
given encoder: zio.json.JsonEncoder[UnauthorizedResponse] = DeriveJsonEncoder.gen[UnauthorizedResponse] | ||
given decoder: zio.json.JsonDecoder[UnauthorizedResponse] = DeriveJsonDecoder.gen[UnauthorizedResponse] | ||
} | ||
|
||
case class UnknownResponse(message: String) extends FailureResponse | ||
|
||
object UnknownResponse { | ||
given encoder: zio.json.JsonEncoder[UnknownResponse] = DeriveJsonEncoder.gen[UnknownResponse] | ||
given decoder: zio.json.JsonDecoder[UnknownResponse] = DeriveJsonDecoder.gen[UnknownResponse] | ||
} | ||
|
||
// ErrorResponse: | ||
// type: object | ||
// description: An RFC-7807 compliant data structure for reporting errors to the client | ||
// required: | ||
// - type | ||
// - title | ||
// - status | ||
// - instance | ||
// properties: | ||
// type: | ||
// type: string | ||
// description: A URI reference that identifies the problem type. | ||
// example: https://example.org/doc/#model-MalformedEmail | ||
// title: | ||
// type: string | ||
// example: "Malformed email" | ||
// description: |- | ||
// A short, human-readable summary of the problem type. It does not | ||
// change from occurrence to occurrence of the problem. | ||
// status: | ||
// type: integer | ||
// format: int32 | ||
// example: 400 | ||
// description: |- | ||
// The HTTP status code for this occurrence of the problem. | ||
// detail: | ||
// type: string | ||
// description: |- | ||
// A human-readable explanation specific to this occurrence of the problem. | ||
// example: "The received '{}à!è@!.b}' email does not conform to the email format" | ||
// instance: | ||
// type: string | ||
// example: "/problems/d914e" | ||
// description: |- | ||
// A URI reference that identifies the specific occurrence of the problem. | ||
// It may or may not yield further information if dereferenced. |
64 changes: 64 additions & 0 deletions
64
...-agent-tapir/src/main/scala/io/iohk/atala/pollux/models/VerifiableCredentialsSchema.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
package io.iohk.atala.pollux.models | ||
|
||
import zio.json.{DeriveJsonDecoder, DeriveJsonEncoder} | ||
|
||
import java.time.ZonedDateTime | ||
import java.util.UUID | ||
|
||
case class VerifiableCredentialsSchemaInput( | ||
id: Option[UUID], | ||
name: String, | ||
version: String, | ||
description: Option[String], | ||
attributes: List[String], | ||
authored: Option[ZonedDateTime], | ||
tags: List[String] | ||
) | ||
object VerifiableCredentialsSchemaInput { | ||
given encoder: zio.json.JsonEncoder[VerifiableCredentialsSchemaInput] = DeriveJsonEncoder.gen[VerifiableCredentialsSchemaInput] | ||
given decoder: zio.json.JsonDecoder[VerifiableCredentialsSchemaInput] = DeriveJsonDecoder.gen[VerifiableCredentialsSchemaInput] | ||
} | ||
|
||
case class VerifiableCredentialsSchema( | ||
id: UUID, | ||
name: String, | ||
version: String, | ||
tags: List[String], | ||
description: Option[String], | ||
attributes: List[String], | ||
author: String, | ||
authored: ZonedDateTime, | ||
proof: Option[Proof] | ||
) | ||
|
||
object VerifiableCredentialsSchema { | ||
def apply(in: VerifiableCredentialsSchemaInput): VerifiableCredentialsSchema = | ||
VerifiableCredentialsSchema( | ||
id = in.id.getOrElse(UUID.randomUUID()), | ||
name = in.name, | ||
version = in.version, | ||
tags = in.tags, | ||
description = in.description, | ||
attributes = in.attributes, | ||
author = "Prism Agent", | ||
authored = in.authored.getOrElse(ZonedDateTime.now()), | ||
proof = None | ||
) | ||
|
||
given encoder: zio.json.JsonEncoder[VerifiableCredentialsSchema] = DeriveJsonEncoder.gen[VerifiableCredentialsSchema] | ||
given decoder: zio.json.JsonDecoder[VerifiableCredentialsSchema] = DeriveJsonDecoder.gen[VerifiableCredentialsSchema] | ||
} | ||
|
||
case class Proof( | ||
`type`: String, | ||
created: ZonedDateTime, | ||
verificationMethod: String, | ||
proofPurpose: String, | ||
proofValue: String, | ||
domain: Option[String] | ||
) | ||
|
||
object Proof { | ||
given encoder: zio.json.JsonEncoder[Proof] = DeriveJsonEncoder.gen[Proof] | ||
given decoder: zio.json.JsonDecoder[Proof] = DeriveJsonDecoder.gen[Proof] | ||
} |
10 changes: 10 additions & 0 deletions
10
sandbox/prism-agent-tapir/src/main/scala/io/iohk/atala/pollux/services/SchemaService.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package io.iohk.atala.pollux.services | ||
|
||
import io.iohk.atala.pollux.models.* | ||
import zio.Task | ||
import java.util.UUID | ||
|
||
trait SchemaService { | ||
def createSchema(in: VerifiableCredentialsSchemaInput): Task[VerifiableCredentialsSchema] | ||
def getSchemaById(id: UUID): Task[Option[VerifiableCredentialsSchema]] | ||
} |
24 changes: 24 additions & 0 deletions
24
...rism-agent-tapir/src/main/scala/io/iohk/atala/pollux/services/SchemaServiceInMemory.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package io.iohk.atala.pollux.services | ||
import io.iohk.atala.pollux.models.{VerifiableCredentialsSchema, VerifiableCredentialsSchemaInput} | ||
|
||
import java.util.UUID | ||
import scala.collection.mutable | ||
import zio.{Task, ZIO} | ||
|
||
class SchemaServiceInMemory() extends SchemaService { | ||
val storage = mutable.Map[UUID, VerifiableCredentialsSchema]() | ||
|
||
override def createSchema(in: VerifiableCredentialsSchemaInput): Task[VerifiableCredentialsSchema] = { | ||
val schema = VerifiableCredentialsSchema(in) | ||
storage.put(schema.id, schema) | ||
ZIO.succeed(schema) | ||
} | ||
|
||
override def getSchemaById(id: UUID): Task[Option[VerifiableCredentialsSchema]] = { | ||
ZIO.succeed(storage.get(id)) | ||
} | ||
} | ||
|
||
object SchemaServiceInMemory { | ||
val instance = SchemaServiceInMemory() | ||
} |
Oops, something went wrong.