Skip to content

Commit

Permalink
feat(prism-agent): migrate connect endpoints to Tapir (#493)
Browse files Browse the repository at this point in the history
* chore(prism-agent): create connection controller and in/out classes

* chore(prism-agent): add tapir encoder/decoder and schema

* chore(prism-agent): add endpoints and server endpoints declaration

* chore(prism-agent): add connection controller layer

* chore(prism-agent): register tapir endpoints

* chore(prism-agent): add Tapir validator to Annotation class

* chore(prism-agent): move documentation from static OAS and add necessary validators

* chore(prism-agent): migrate remaining 'connect' endpoints to Tapir

* chore(prism-agent): get rid of 'connect' Akka Http endpoints implementation

* chore(infra): change APISIX config to use Tapir endpoints for 'connect'

* chore(prism-agent): scalafmtAll

* Update prism-agent/service/server/src/main/scala/io/iohk/atala/connect/controller/http/Connection.scala

Co-authored-by: Yurii Shynbuiev - IOHK <[email protected]>

* chore(infra): fix 'prism-agent' healthcheck URL

---------

Co-authored-by: Yurii Shynbuiev - IOHK <[email protected]>
  • Loading branch information
bvoiturier and yshyn-iohk authored Apr 4, 2023
1 parent 8384fe3 commit 876dd9e
Show file tree
Hide file tree
Showing 19 changed files with 795 additions and 304 deletions.
10 changes: 10 additions & 0 deletions infrastructure/shared/apisix/conf/apisix.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ routes:
plugins:
proxy-rewrite:
regex_uri: ["^/prism-agent/(.*)", "/$1"]
- uri: /prism-agent/connections*
upstream_id: 4
plugins:
proxy-rewrite:
regex_uri: ["^/prism-agent/connections(/.*)?", "/connections$1"]
- uri: /prism-agent/connection-invitations
upstream_id: 4
plugins:
proxy-rewrite:
regex_uri: ["^/prism-agent/connection-invitations", "/connection-invitations"]
- uri: /didcomm
upstream_id: 3
plugins:
Expand Down
2 changes: 1 addition & 1 deletion infrastructure/shared/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ services:
prism-node:
condition: service_started
healthcheck:
test: ["CMD", "curl", "-f", "http://prism-agent:8080/connections"]
test: ["CMD", "curl", "-f", "http://prism-agent:8085/connections"]
interval: 30s
timeout: 10s
retries: 5
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import io.circe.generic.auto.*
import io.circe.parser.*
import io.circe.syntax.*
import io.iohk.atala.agent.server.health.HealthInfo
import io.iohk.atala.connect.controller.ConnectionControllerImpl

import java.security.Security

Expand Down Expand Up @@ -154,7 +155,8 @@ object AgentApp extends ZIOAppDefault {
HttpModule.layers,
RepoModule.credentialSchemaServiceLayer,
AppModule.manageDIDServiceLayer,
RepoModule.verificationPolicyServiceLayer
RepoModule.verificationPolicyServiceLayer,
ConnectionControllerImpl.layer
)
} yield app

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,123 +5,88 @@ import akka.actor.setup.ActorSystemSetup
import akka.actor.typed.ActorSystem
import akka.actor.typed.scaladsl.Behaviors
import akka.http.scaladsl.server.Route
import doobie.util.transactor.Transactor
import io.iohk.atala.agent.server.http.{HttpRoutes, HttpServer, ZHttp4sBlazeServer, ZHttpEndpoints}
import io.iohk.atala.castor.core.service.{DIDService, DIDServiceImpl}
import io.iohk.atala.castor.core.util.DIDOperationValidator
import io.iohk.atala.agent.server.http.marshaller.{
ConnectionsManagementApiMarshallerImpl,
DIDApiMarshallerImpl,
DIDRegistrarApiMarshallerImpl
}
import io.iohk.atala.agent.server.http.service.{ConnectionsManagementApiServiceImpl, DIDApiServiceImpl}
import io.iohk.atala.agent.openapi.api.{ConnectionsManagementApi, DIDApi, DIDRegistrarApi}
import cats.effect.std.Dispatcher
import cats.implicits.*
import com.typesafe.config.ConfigFactory
import doobie.util.transactor.Transactor
import io.circe.{DecodingFailure, ParsingFailure}
import io.grpc.ManagedChannelBuilder
import io.iohk.atala.agent.openapi.api.*
import io.iohk.atala.agent.server.config.AppConfig
import io.iohk.atala.agent.walletapi.service.ManagedDIDService
import io.iohk.atala.agent.walletapi.model.error.DIDSecretStorageError
import io.iohk.atala.agent.server.config.{AgentConfig, AppConfig}
import io.iohk.atala.agent.server.http.marshaller.*
import io.iohk.atala.agent.server.http.service.*
import io.iohk.atala.agent.server.http.{HttpRoutes, HttpServer}
import io.iohk.atala.pollux.core.service.{
CredentialSchemaService,
CredentialSchemaServiceImpl,
CredentialService,
CredentialServiceImpl,
PresentationService,
PresentationServiceImpl,
VerificationPolicyService,
VerificationPolicyServiceImpl
}
import io.iohk.atala.pollux.credentialschema.controller.{CredentialSchemaController, CredentialSchemaControllerImpl}
import io.iohk.atala.agent.server.http.{HttpRoutes, HttpServer, ZHttp4sBlazeServer, ZHttpEndpoints}
import io.iohk.atala.agent.server.jobs.*
import io.iohk.atala.agent.server.sql.DbConfig as AgentDbConfig
import io.iohk.atala.agent.walletapi.model.error.DIDSecretStorageError
import io.iohk.atala.agent.walletapi.service.ManagedDIDService
import io.iohk.atala.agent.walletapi.sql.{JdbcDIDNonSecretStorage, JdbcDIDSecretStorage}
import io.iohk.atala.castor.core.service.{DIDService, DIDServiceImpl}
import io.iohk.atala.castor.core.util.DIDOperationValidator
import io.iohk.atala.connect.controller.{ConnectionController, ConnectionControllerImpl, ConnectionServerEndpoints}
import io.iohk.atala.connect.core.model.error.ConnectionServiceError
import io.iohk.atala.connect.core.repository.ConnectionRepository
import io.iohk.atala.connect.core.service.{ConnectionService, ConnectionServiceImpl}
import io.iohk.atala.connect.sql.repository.{JdbcConnectionRepository, DbConfig as ConnectDbConfig}
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
import io.iohk.atala.mercury.*
import io.iohk.atala.mercury.DidOps.*
import io.iohk.atala.mercury.model.*
import io.iohk.atala.mercury.model.error.*
import io.iohk.atala.mercury.protocol.connection.{ConnectionRequest, ConnectionResponse}
import io.iohk.atala.mercury.protocol.issuecredential.*
import io.iohk.atala.mercury.protocol.presentproof.*
import io.iohk.atala.pollux.core.model.error.CredentialServiceError.RepositoryError
import io.iohk.atala.pollux.core.model.error.{CredentialServiceError, PresentationError}
import io.iohk.atala.pollux.core.repository.{CredentialRepository, PresentationRepository}
import io.iohk.atala.pollux.core.service.*
import io.iohk.atala.pollux.credentialschema.controller.*
import io.iohk.atala.pollux.credentialschema.{SchemaRegistryServerEndpoints, VerificationPolicyServerEndpoints}
import io.iohk.atala.pollux.sql.repository.{
JdbcCredentialRepository,
JdbcCredentialSchemaRepository,
JdbcPresentationRepository,
JdbcVerificationPolicyRepository,
DbConfig as PolluxDbConfig
}
import io.iohk.atala.connect.sql.repository.DbConfig as ConnectDbConfig
import io.iohk.atala.agent.server.sql.DbConfig as AgentDbConfig
import io.iohk.atala.agent.server.jobs.*
import io.iohk.atala.pollux.vc.jwt.{PrismDidResolver, DidResolver as JwtDidResolver}
import io.iohk.atala.prism.protos.node_api.NodeServiceGrpc
import io.iohk.atala.resolvers.{DIDResolver, UniversalDidResolver}
import org.didcommx.didcomm.DIDComm
import org.didcommx.didcomm.model.UnpackParams
import org.didcommx.didcomm.secret.{Secret, SecretResolver}
import zhttp.http.*
import zhttp.service.Server
import zio.*
import zio.config.typesafe.TypesafeConfigSource
import zio.config.{ReadError, read}
import zio.interop.catz.*
import zio.stream.ZStream
import zhttp.http.*
import zhttp.service.Server

import java.util.concurrent.Executors
import io.iohk.atala.mercury.*
import io.iohk.atala.mercury.DidOps.*
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.CredentialServiceError.RepositoryError
import io.iohk.atala.prism.protos.node_api.NodeServiceGrpc

import java.io.IOException
import cats.implicits.*
import io.iohk.atala.pollux.credentialschema.SchemaRegistryServerEndpoints
import io.iohk.atala.pollux.core.repository.PresentationRepository
import io.iohk.atala.pollux.core.model.error.PresentationError
import io.iohk.atala.pollux.core.model.error.CredentialServiceError
import io.iohk.atala.connect.core.service.ConnectionService
import io.iohk.atala.connect.core.service.ConnectionServiceImpl
import io.iohk.atala.connect.core.repository.ConnectionRepository
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.ConnectionServiceError
import io.iohk.atala.pollux.credentialschema.{SchemaRegistryServerEndpoints, VerificationPolicyServerEndpoints}
import io.iohk.atala.connect.core.model.error.ConnectionServiceError
import io.iohk.atala.mercury.protocol.presentproof.*
import io.iohk.atala.agent.server.config.AgentConfig
import org.didcommx.didcomm.DIDComm
import io.iohk.atala.resolvers.UniversalDidResolver
import org.didcommx.didcomm.secret.SecretResolver
import org.didcommx.didcomm.model.UnpackParams
import org.didcommx.didcomm.secret.Secret
import io.circe.ParsingFailure
import io.circe.DecodingFailure
import io.iohk.atala.agent.walletapi.sql.{JdbcDIDNonSecretStorage, JdbcDIDSecretStorage}
import io.iohk.atala.resolvers.DIDResolver
import io.iohk.atala.pollux.vc.jwt.DidResolver as JwtDidResolver
import io.iohk.atala.pollux.vc.jwt.PrismDidResolver
import io.iohk.atala.mercury.DidAgent
import io.iohk.atala.pollux.credentialschema.controller.{
CredentialSchemaController,
VerificationPolicyController,
VerificationPolicyControllerImpl,
VerificationPolicyControllerInMemory
}
import java.util.concurrent.Executors

object Modules {

def app(port: Int): RIO[
DidOps & DidAgent & ManagedDIDService & AppConfig & DIDRegistrarApi & IssueCredentialsProtocolApi &
ConnectionsManagementApi & DIDApi & PresentProofApi & ActorSystem[Nothing],
DidOps & DidAgent & ManagedDIDService & AppConfig & DIDRegistrarApi & IssueCredentialsProtocolApi & DIDApi &
PresentProofApi & ActorSystem[Nothing],
Unit
] = {
val httpServerApp = HttpRoutes.routes.flatMap(HttpServer.start(port, _))

httpServerApp.unit
}

lazy val zioApp: RIO[CredentialSchemaController & VerificationPolicyController & AppConfig, Unit] = {
lazy val zioApp
: RIO[CredentialSchemaController & VerificationPolicyController & ConnectionController & AppConfig, Unit] = {
val zioHttpServerApp = for {
allSchemaRegistryEndpoints <- SchemaRegistryServerEndpoints.all
allVerificationPolicyEndpoints <- VerificationPolicyServerEndpoints.all
allConnectionEndpoints <- ConnectionServerEndpoints.all
allEndpoints = ZHttpEndpoints.withDocumentations[Task](
allSchemaRegistryEndpoints ++ allVerificationPolicyEndpoints
allSchemaRegistryEndpoints ++ allVerificationPolicyEndpoints ++ allConnectionEndpoints
)
appConfig <- ZIO.service[AppConfig]
httpServer <- ZHttp4sBlazeServer.start(allEndpoints, port = appConfig.agent.httpEndpoint.http.port)
Expand Down Expand Up @@ -205,7 +170,8 @@ object Modules {
.unit

private[this] def extractFirstRecipientDid(jsonMessage: String): IO[ParsingFailure | DecodingFailure, String] = {
import io.circe._, io.circe.parser._
import io.circe.*
import io.circe.parser.*
val doc = parse(jsonMessage).getOrElse(Json.Null)
val cursor = doc.hcursor
ZIO.fromEither(
Expand Down Expand Up @@ -525,17 +491,9 @@ object HttpModule {
(apiServiceLayer ++ apiMarshallerLayer) >>> ZLayer.fromFunction(new PresentProofApi(_, _))
}

val connectionsManagementApiLayer
: RLayer[DidOps & DidAgent & ManagedDIDService & AppConfig, ConnectionsManagementApi] = {
val serviceLayer = AppModule.connectionServiceLayer
val apiServiceLayer = serviceLayer >>> ConnectionsManagementApiServiceImpl.layer
val apiMarshallerLayer = ConnectionsManagementApiMarshallerImpl.layer
(apiServiceLayer ++ apiMarshallerLayer) >>> ZLayer.fromFunction(new ConnectionsManagementApi(_, _))
}

val layers =
didApiLayer ++ didRegistrarApiLayer ++
issueCredentialsProtocolApiLayer ++ connectionsManagementApiLayer ++ presentProofProtocolApiLayer
issueCredentialsProtocolApiLayer ++ presentProofProtocolApiLayer
}

object RepoModule {
Expand Down Expand Up @@ -638,4 +596,5 @@ object RepoModule {
JdbcVerificationPolicyRepository.layer >+>
VerificationPolicyServiceImpl.layer >+>
VerificationPolicyControllerImpl.layer

}
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,24 @@ package io.iohk.atala.agent.server.http

import akka.http.scaladsl.model.ContentType
import akka.http.scaladsl.server.Directives.*
import io.iohk.atala.agent.openapi.api.{
PresentProofApi,
DIDApi,
DIDRegistrarApi,
IssueCredentialsProtocolApi,
ConnectionsManagementApi
}
import zio.*
import akka.http.scaladsl.server.Route
import io.iohk.atala.agent.openapi.api.{DIDApi, DIDRegistrarApi, IssueCredentialsProtocolApi, PresentProofApi}
import zio.*

object HttpRoutes {

def routes: URIO[
DIDApi & DIDRegistrarApi & IssueCredentialsProtocolApi & ConnectionsManagementApi & PresentProofApi,
DIDApi & DIDRegistrarApi & IssueCredentialsProtocolApi & PresentProofApi,
Route
] =
for {
didApi <- ZIO.service[DIDApi]
disRegistrarApi <- ZIO.service[DIDRegistrarApi]
issueCredentialsProtocolApi <- ZIO.service[IssueCredentialsProtocolApi]
connectionsManagementApi <- ZIO.service[ConnectionsManagementApi]
presentProofApi <- ZIO.service[PresentProofApi]
} yield didApi.route ~
disRegistrarApi.route ~
issueCredentialsProtocolApi.route ~
connectionsManagementApi.route ~
presentProofApi.route ~
additionalRoute

Expand Down

This file was deleted.

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

import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport
import io.iohk.atala.agent.openapi.model.*
import io.iohk.atala.agent.server.http.model.OASModelPatches
import spray.json.{
DefaultJsonProtocol,
DeserializationException,
Expand All @@ -13,9 +14,8 @@ import spray.json.{
jsonWriter
}

import java.util.UUID
import java.time.OffsetDateTime
import io.iohk.atala.agent.server.http.model.OASModelPatches
import java.util.UUID

object JsonSupport extends JsonSupport

Expand Down Expand Up @@ -84,13 +84,6 @@ trait JsonSupport extends SprayJsonSupport with DefaultJsonProtocol {
given RootJsonFormat[RequestPresentationAction] = jsonFormat2(RequestPresentationAction.apply)
given RootJsonFormat[PresentationStatusPage] = jsonFormat6(PresentationStatusPage.apply)

// Connections Management
given RootJsonFormat[CreateConnectionRequest] = jsonFormat1(CreateConnectionRequest.apply)
given RootJsonFormat[AcceptConnectionInvitationRequest] = jsonFormat1(AcceptConnectionInvitationRequest.apply)
given RootJsonFormat[ConnectionsPage] = jsonFormat6(ConnectionsPage.apply)
given RootJsonFormat[Connection] = jsonFormat11(Connection.apply)
given RootJsonFormat[ConnectionInvitation] = jsonFormat4(ConnectionInvitation.apply)

// Manual model patches
given RootJsonFormat[OASModelPatches.DIDDocument] = jsonFormat10(OASModelPatches.DIDDocument.apply)
given RootJsonFormat[OASModelPatches.DIDResolutionResult] = jsonFormat4(OASModelPatches.DIDResolutionResult.apply)
Expand Down
Loading

0 comments on commit 876dd9e

Please sign in to comment.