Skip to content

Commit

Permalink
feat(agent): [ATL-2005] implement REST API for credential issuance (#86)
Browse files Browse the repository at this point in the history
* chore(infra): publish Iris docker image in run.sh

* chore(prism-agent): add 'pollux-vc-jwt' dependency

* feat(openapi): add 'validityPeriod' input param and return jwt VC in compact serialization format

* chore(prism-agent): fix JSON marshaller/unmarshaller

* feat(prism-agent): implement minimum jwt VC creation endpoint

* feat(prism-agent): add pollux configuration object

* chore(infra): add necessary docker containers for pollux DB

* chore(pollux): add initial flyway DB migration script

* feat(prism-agent): bind and inject CredentialService into IssueCredentialServiceImpl

* feat(pollux): add credential service and repo methods

* chore(prism-agent): fix pollux DB port config

* chore(pollux): move issuer creation to pollux credential service

* chore(pollux-vc-jwt): fix transitive dependency conflict when imported in prism-agent

* feat(prism-agent): add initial issue credential protocol endpoint

* calculate merkel root in pollux service

* feat(pollux): add methods related to Issue Credential Protocol in credential service

* feat(prism-agent): add new REST api endpoints for issue credential procotol

* feat(pollux): implement 'issue credential record' creation and retrieval

* feat(prism-agent): implement 'issue credential record' creation and retrieval

* publish credentials bulk wip

* chore(pollux): persist State enum as string in DB

* feat(pollux): implement 'accept credential offer' and 'issue credential' in CredentialService

* feat(prism-agent): implement REST endpoints for accept credential offer and issue credential

* feat(prism-agent): return the issue credential record value on update operations

* fix(pollux): ensure current issue record state is valid when accepting offer and issuing credential

* feat(prism-agent): add background job skeleton for issue credential DIDComm exchanges

* feat(prism-agent): add DIDComm service endpoint listener on port 8090

* Finalize publishCredentialBatch function

* chore(pollux-vc-jwt): revert to original dependencies declaration

* chore(prism-agent): extend issue credential record state for DLT publication + add role attribute to record

* chore(pollux): fix vc-jwt project dependencies to get rid of scala 2/3 conflicts in dependent projects

* chore(pollux): comment 'role' attribute in issue credential record for now

* chore(pollux): integrate latest version of 'vc-jwt' lib

* chore(agent): add SLF4J logback implementation

* chore(agent): integrate latest verison of 'vc-jwt' library

* chore(agent): remove 'vc-jwt' lib dependency given it is already a transitive dependency

Co-authored-by: Shota Jolbordi <shota.jolbordi@iohk.io>
  • Loading branch information
bvoiturier and shotexa committed Oct 27, 2022
1 parent cafe7d0 commit 7c1f50a
Show file tree
Hide file tree
Showing 36 changed files with 1,427 additions and 157 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ shell.nix
.envrc
node_modules/
package-lock.json
.dotty-ide-disabled
**/.docker-volumes/*
43 changes: 42 additions & 1 deletion infrastructure/local/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: '3.8'
services:

##########################
# Databases
# Castor Database
##########################
db_castor:
image: postgres:13
Expand Down Expand Up @@ -34,6 +34,39 @@ services:
db_castor_init_delay:
condition: service_completed_successfully

##########################
# Pollux Database
##########################

db_pollux:
image: postgres:13
restart: always
environment:
POSTGRES_DB: pollux
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
ports:
- 5433:5432
volumes:
- pg_data_pollux_db:/var/lib/postgresql/data

# delay to ensure DB is up before applying migrations
db_pollux_init_delay:
image: alpine:3
command: sleep 5
depends_on:
db_pollux:
condition: service_started

db_pollux_init:
image: flyway/flyway:9.3.0-alpine
volumes:
- $PWD/pollux/lib/sql-doobie/src/main/resources/sql:/flyway/sql
command: -url=jdbc:postgresql://db_pollux:5432/pollux?user=postgres&password=postgres migrate
depends_on:
db_pollux_init_delay:
condition: service_completed_successfully

##########################
# Services
##########################
Expand All @@ -55,9 +88,16 @@ services:
CASTOR_DB_NAME: castor
CASTOR_DB_USER: postgres
CASTOR_DB_PASSWORD: postgres
POLLUX_DB_HOST: db_pollux
POLLUX_DB_PORT: 5432
POLLUX_DB_NAME: pollux
POLLUX_DB_USER: postgres
POLLUX_DB_PASSWORD: postgres
depends_on:
db_castor_init:
condition: service_completed_successfully
db_pollux_init:
condition: service_completed_successfully

swagger-ui:
image: swaggerapi/swagger-ui:v4.14.0
Expand All @@ -81,3 +121,4 @@ services:

volumes:
pg_data_castor_db:
pg_data_pollux_db:
1 change: 1 addition & 0 deletions infrastructure/local/run.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ echo "--------------------------------------"

cd mercury/prism-mediator && sbt "project mediator; docker:publishLocal" && cd -
cd prism-agent/service && sbt docker:publishLocal && cd -
cd iris/service && sbt docker:publishLocal && cd -

echo "--------------------------------------"
echo "Bringing up stack using docker-compose"
Expand Down
2 changes: 1 addition & 1 deletion mercury/mercury-library/project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.4.6")
addSbtPlugin("com.github.sbt" % "sbt-release" % "1.1.0")
// addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.9.11")
addSbtPlugin("com.github.sbt" % "sbt-native-packager" % "1.9.11")
addSbtPlugin("com.codecommit" % "sbt-github-packages" % "0.5.3")
3 changes: 3 additions & 0 deletions pollux/lib/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ val commonSettings = Seq(
lazy val root = project
.in(file("."))
.settings(commonSettings)
.settings(
name := "pollux-root"
)
.aggregate(core, `sql-doobie`)

lazy val core = project
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package io.iohk.atala.pollux.core.model

final case class EncodedJWTCredential(batchId: String, credentialId: String, content: String)
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package io.iohk.atala.pollux.core.model

import java.util.UUID

final case class IssueCredentialRecord(
id: UUID,
schemaId: String,
//role: IssueCredentialRecord.Role,
subjectId: String,
validityPeriod: Option[Double] = None,
claims: Map[String, String],
state: IssueCredentialRecord.State
)

object IssueCredentialRecord {

enum Role:
case Issuer extends Role
case Holder extends Role

enum State:
// Issuer has created an offer in a database, but it has not been sent yet (in Issuer DB)
case OfferPending extends State
// Issuer has sent an offer to a holder (in Issuer DB)
case OfferSent extends State
// Holder has received an offer (In Holder DB)
case OfferReceived extends State

// Holder has reviewed and approved the offer (in Holder DB)
case RequestPending extends State
// Holder has sent a request to a an Issuer (in Holder DB)
case RequestSent extends State
// Issuer has received a request from the holder (In Issuer DB)
case RequestReceived extends State

// Holder declined the offer sent by Issuer (Holder DB) or Issuer declined the proposal sent by Holder (Issuer DB)
case ProblemReportPending extends State
// Holder has sent problem report to Issuer (Holder DB) or Issuer has sent problem report to Holder (Issuer DB)
case ProblemReportSent extends State
// Holder has received problem resport from Issuer (Holder DB) or Issuer has received problem report from Holder (Issuer DB)
case ProblemReportReceived extends State

// Issuer has "accepted" a credential request received from a Holder (Issuer DB)
case CredentialPending extends State
// The Issuer has issued (signed) a credential and sent it to Iris. Iris has not confirmed that is has been published on DLT yet (In Issuer DB)
case CredentialPublishQueued extends State
// The credential has been sent to the holder (In Issuer DB)
case CredentialSent extends State
// Iris has notified the Issuer that a credential that it has queued before has been published on DLT (In Issuer DB)
case CredentialPublished extends State
// Holder has received the credential (In Holder DB)
case CredentialReceived extends State
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.iohk.atala.pollux.core.model

import io.iohk.atala.pollux.vc.jwt.W3cCredentialPayload
import io.iohk.atala.prism.crypto.MerkleInclusionProof
import io.iohk.atala.iris.proto.service.IrisOperationId

final case class PublishedBatchData(
operationId: IrisOperationId,
credentialsAnsProofs: Seq[(W3cCredentialPayload, MerkleInclusionProof)]
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.iohk.atala.pollux.core.model.error

sealed trait IssueCredentialError

object IssueCredentialError {
final case class RepositoryError(cause: Throwable) extends IssueCredentialError
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package io.iohk.atala.pollux.core.model.error


sealed trait PublishCredentialBatchError

object PublishCredentialBatchError {
final case class IrisError(cause: Throwable) extends PublishCredentialBatchError
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
package io.iohk.atala.pollux.core.repository

import io.iohk.atala.pollux.core.model.W3CCredential
import io.iohk.atala.pollux.core.model.EncodedJWTCredential
import zio.*

// TODO: replace with actual implementation
import io.iohk.atala.pollux.core.model.IssueCredentialRecord
import java.util.UUID
trait CredentialRepository[F[_]] {
def getCredentials: F[Seq[W3CCredential]]
def createCredentials(batchId: String, credentials: Seq[EncodedJWTCredential]): F[Unit]
def getCredentials(batchId: String): F[Seq[EncodedJWTCredential]]
def createIssueCredentialRecord(record: IssueCredentialRecord): F[Int]
def getIssueCredentialRecords(): F[Seq[IssueCredentialRecord]]
def getIssueCredentialRecord(id: UUID): F[Option[IssueCredentialRecord]]
def updateCredentialRecordState(id: UUID, from: IssueCredentialRecord.State, to: IssueCredentialRecord.State): F[Int]
}

0 comments on commit 7c1f50a

Please sign in to comment.