Skip to content

Commit

Permalink
feat(pollux): schema registry lookup and verification policies REST A…
Browse files Browse the repository at this point in the history
…PI ATL-1334 (#168)

* feat(pollux): implement schema-registry in-memory using Tapir
* feat(pollux) Add pagination request for VC Schema + Specs
* feat(pollux) Add VerificationPolicy entity and REST API
  • Loading branch information
yshyn-iohk authored Nov 28, 2022
1 parent d6d7224 commit d75b36b
Show file tree
Hide file tree
Showing 22 changed files with 1,032 additions and 121 deletions.
5 changes: 4 additions & 1 deletion infrastructure/local/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,10 @@ services:
POLLUX_DB_NAME: pollux
POLLUX_DB_USER: postgres
POLLUX_DB_PASSWORD: postgres

ports:
- "8085:8085"
- "8080:8080"

swagger-ui:
image: swaggerapi/swagger-ui:v4.14.0
environment:
Expand Down
12 changes: 9 additions & 3 deletions prism-agent/service/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import sbtghpackages.GitHubPackagesPlugin.autoImport._
import sbtrelease.ReleasePlugin.autoImport.ReleaseTransformations._

// Custom keys
val apiBaseDirectory = settingKey[File]("The base directory for PrismAgent API specifications")
val apiBaseDirectory =
settingKey[File]("The base directory for PrismAgent API specifications")

inThisBuild(
Seq(
Expand Down Expand Up @@ -53,8 +54,13 @@ lazy val server = project
Compile / sourceGenerators += openApiGenerateClasses,
openApiGeneratorSpec := apiBaseDirectory.value / "http/prism-agent-openapi-spec.yaml",
openApiGeneratorConfig := baseDirectory.value / "openapi/generator-config/config.yaml",
openApiGeneratorImportMapping := Seq("DidOperationType", "DidOperationStatus")
.map(model => (model, s"io.iohk.atala.agent.server.http.model.OASModelPatches.$model"))
openApiGeneratorImportMapping := Seq(
"DidOperationType",
"DidOperationStatus"
)
.map(model =>
(model, s"io.iohk.atala.agent.server.http.model.OASModelPatches.$model")
)
.toMap,
Docker / maintainer := "[email protected]",
Docker / dockerUsername := Some("input-output-hk"),
Expand Down
2 changes: 2 additions & 0 deletions prism-agent/service/project/Dependencies.scala
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ object Dependencies {

private lazy val tapirRedocBundle = "com.softwaremill.sttp.tapir" %% "tapir-redoc-bundle" % Versions.tapir
private lazy val tapirSttpStubServer = "com.softwaremill.sttp.tapir" %% "tapir-sttp-stub-server" % Versions.tapir % Test
private lazy val sttpClient3ZioJson = "com.softwaremill.sttp.client3" %% "zio-json" % "3.8.0" % Test


// Dependency Modules
Expand All @@ -80,6 +81,7 @@ object Dependencies {
tapirJsonZio,
tapirRedocBundle,
tapirSttpStubServer,
sttpClient3ZioJson,
tapirZioHttpServer,
tapirHttp4sServerZio,
http4sBlazeServer)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,13 @@ import io.iohk.atala.pollux.sql.repository.{Migrations => PolluxMigrations}
import io.iohk.atala.connect.sql.repository.{Migrations => ConnectMigrations}

object Main extends ZIOAppDefault {
def agentLayer(peer: PeerDID): ZLayer[Any, Nothing, AgentServiceAny] = ZLayer.succeed(
io.iohk.atala.mercury.AgentServiceAny(
new DIDComm(UniversalDidResolver, peer.getSecretResolverInMemory),
peer.did
def agentLayer(peer: PeerDID): ZLayer[Any, Nothing, AgentServiceAny] =
ZLayer.succeed(
io.iohk.atala.mercury.AgentServiceAny(
new DIDComm(UniversalDidResolver, peer.getSecretResolverInMemory),
peer.did
)
)
)

override def run: ZIO[Any, Throwable, Unit] =
for {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import io.iohk.atala.castor.core.service.{DIDService, DIDServiceImpl}
import io.iohk.atala.pollux.core.service.CredentialServiceImpl
import io.iohk.atala.castor.core.util.DIDOperationValidator
import io.iohk.atala.castor.sql.repository.{JdbcDIDOperationRepository, TransactorLayer}
import io.iohk.atala.castor.sql.repository.{DbConfig => CastorDbConfig}
import io.iohk.atala.castor.sql.repository.DbConfig as CastorDbConfig
import io.iohk.atala.iris.proto.service.IrisServiceGrpc
import io.iohk.atala.iris.proto.service.IrisServiceGrpc.IrisServiceStub
import io.iohk.atala.pollux.core.repository.CredentialRepository
Expand All @@ -65,17 +65,17 @@ import zio.config.typesafe.TypesafeConfigSource
import zio.config.{ReadError, read}
import zio.interop.catz.*
import zio.stream.ZStream
import zhttp.http._
import zhttp.http.*
import zhttp.service.Server

import java.util.concurrent.Executors

import io.iohk.atala.mercury._
import io.iohk.atala.mercury.model._
import io.iohk.atala.mercury.model.error._
import io.iohk.atala.mercury.protocol.issuecredential._
import io.iohk.atala.mercury.*
import io.iohk.atala.mercury.model.*
import io.iohk.atala.mercury.model.error.*
import io.iohk.atala.mercury.protocol.issuecredential.*
import io.iohk.atala.pollux.core.model.error.IssueCredentialError
import io.iohk.atala.pollux.core.model.error.IssueCredentialError.RepositoryError

import java.io.IOException
import cats.implicits.*
import io.iohk.atala.pollux.schema.SchemaRegistryServerEndpoints
Expand All @@ -87,6 +87,8 @@ import io.iohk.atala.connect.sql.repository.JdbcConnectionRepository
import io.iohk.atala.mercury.protocol.connection.ConnectionRequest
import io.iohk.atala.mercury.protocol.connection.ConnectionResponse
import io.iohk.atala.connect.core.model.error.ConnectionError
import io.iohk.atala.pollux.schema.{SchemaRegistryServerEndpoints, VerificationPolicyServerEndpoints}
import io.iohk.atala.pollux.service.{SchemaRegistryServiceInMemory, VerificationPolicyServiceInMemory}

object Modules {

Expand All @@ -101,13 +103,18 @@ object Modules {
lazy val zioApp = {
val zioHttpServerApp = for {
allSchemaRegistryEndpoints <- SchemaRegistryServerEndpoints.all
allEndpoints = ZHttpEndpoints.withDocumentations[Task](allSchemaRegistryEndpoints)
allVerificationPolicyEndpoints <- VerificationPolicyServerEndpoints.all
allEndpoints = ZHttpEndpoints.withDocumentations[Task](
allSchemaRegistryEndpoints ++ allVerificationPolicyEndpoints
)
appConfig <- ZIO.service[AppConfig]
httpServer <- ZHttp4sBlazeServer.start(allEndpoints, port = appConfig.agent.httpEndpoint.http.port)
} yield httpServer

zioHttpServerApp
.provideLayer(SchemaRegistryServiceInMemory.layer ++ SystemModule.configLayer)
.provideLayer(
SchemaRegistryServiceInMemory.layer ++ VerificationPolicyServiceInMemory.layer ++ SystemModule.configLayer
)
.unit
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.iohk.atala.api.http

import sttp.model.StatusCode
import sttp.tapir.EndpointOutput.OneOf
import sttp.tapir.Schema
import sttp.tapir.generic.auto.*
import sttp.tapir.json.zio.jsonBody
import zio.json.{DeriveJsonDecoder, DeriveJsonEncoder}
Expand All @@ -13,20 +14,23 @@ 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]
given schema: Schema[NotFoundResponse] = Schema.derived
}

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]
given schema: Schema[BadRequest] = Schema.derived
}

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]
given schema: Schema[InternalServerError] = Schema.derived
}

//An RFC-7807 compliant data structure for reporting errors to the client
Expand All @@ -36,4 +40,5 @@ case class ErrorResponse(`type`: String, title: String, status: Int, instance: S
object ErrorResponse {
given encoder: zio.json.JsonEncoder[ErrorResponse] = DeriveJsonEncoder.gen[ErrorResponse]
given decoder: zio.json.JsonDecoder[ErrorResponse] = DeriveJsonDecoder.gen[ErrorResponse]
given schema: Schema[ErrorResponse] = Schema.derived
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package io.iohk.atala.api.http.codec

import io.iohk.atala.api.http.model.Order
import io.iohk.atala.api.http.model.Order.Direction
import sttp.tapir.Codec.PlainCodec
import sttp.tapir.{Codec, DecodeResult}

import java.util.Base64

object OrderCodec {
implicit def orderCodec: PlainCodec[Order] = {
def decode(s: String): DecodeResult[Order] =
try {
val s2 = new String(Base64.getDecoder.decode(s))
val order = s2.split(".", 2) match {
case Array() => Order.empty
case Array(field) => Order(field)
case Array(field, "") => Order(field)
case Array(field, direction) =>
Order(field, Some(Direction.valueOf(direction)))
case _ => sys.error("impossible")
}
DecodeResult.Value(order)
} catch {
case e: Exception => DecodeResult.Error(s, e)
}

def encode(order: Order): String =
Base64.getEncoder
.encodeToString(
s"${order.field}.${order.direction.getOrElse(Order.DefaultDirection).toString}"
.getBytes("UTF-8")
)

Codec.string.mapDecode(decode)(encode)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.iohk.atala.api.http.model

import sttp.tapir.Codec.PlainCodec
import sttp.tapir.generic.auto.*
import sttp.tapir.{Codec, DecodeResult, Schema}

import java.util.Base64

case class Order(field: String, direction: Option[Order.Direction] = None)

object Order {
val DefaultDirection = Direction.Ascending
val empty = Order("")

enum Direction(kind: String):
case Ascending extends Direction("asc")
case Descending extends Direction("desc")

import io.iohk.atala.api.http.codec.OrderCodec.orderCodec
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.iohk.atala.api.http.model

import sttp.tapir.Codec.PlainCodec
import sttp.tapir.generic.auto.*
import sttp.tapir.{Codec, DecodeResult, Schema}
import zio.json.{DeriveJsonDecoder, DeriveJsonEncoder}

import java.time.ZonedDateTime
import java.util.{Base64, UUID}
import scala.util.Try

case class Pagination(
offset: Option[Int] = Some(0),
limit: Option[Int] = Some(10)
)

This file was deleted.

Loading

0 comments on commit d75b36b

Please sign in to comment.