From dc8d86b1ba87d747c5ac0089573ddd8c2ab62f5e Mon Sep 17 00:00:00 2001 From: bvoiturier Date: Tue, 29 Nov 2022 12:41:55 +0100 Subject: [PATCH 1/5] feat(prism-agent): add connect/issue doc + allow local execution of multiple Prism Agent instances (#178) * chore(prism-agent): do not link DIDComm service port variable to DIDComm service URL variable * chore(infra): add docker-compose config for Connect + only expose th main http port * chore(infra): add HAProxy config for DIDComm service endpoint * chore(prism-agent): bump version number to 0.6.0-SNAPSHOT * docs(prism-agent): add basic documentation on executing Connect and Issue flows * docs(prism-agent): add links in main README.md --- infrastructure/local/docker-compose.yml | 48 +++++++++----- infrastructure/local/haproxy/haproxy.cfg | 16 +++-- prism-agent/service/README.md | 7 ++ prism-agent/service/connect.md | 51 +++++++++++++++ prism-agent/service/issue.md | 65 +++++++++++++++++++ .../io/iohk/atala/agent/server/Main.scala | 2 +- prism-agent/service/version.sbt | 2 +- 7 files changed, 170 insertions(+), 21 deletions(-) create mode 100644 prism-agent/service/connect.md create mode 100644 prism-agent/service/issue.md diff --git a/infrastructure/local/docker-compose.yml b/infrastructure/local/docker-compose.yml index c48c0f7194..842766fae4 100644 --- a/infrastructure/local/docker-compose.yml +++ b/infrastructure/local/docker-compose.yml @@ -12,8 +12,6 @@ services: POSTGRES_DB: castor POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres - ports: - - 5432:5432 volumes: - pg_data_castor_db:/var/lib/postgresql/data @@ -36,8 +34,6 @@ services: POSTGRES_DB: pollux POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres - ports: - - 5433:5432 volumes: - pg_data_pollux_db:/var/lib/postgresql/data @@ -49,6 +45,28 @@ services: db_pollux: condition: service_started + ########################## + # Connect Database + ########################## + + db_connect: + image: postgres:13 + restart: always + environment: + POSTGRES_DB: connect + POSTGRES_USER: postgres + POSTGRES_PASSWORD: postgres + volumes: + - pg_data_connect_db:/var/lib/postgresql/data + + # delay to ensure DB is up before applying migrations + db_connect_init_delay: + image: alpine:3 + command: sleep 5 + depends_on: + db_connect: + condition: service_started + ########################## # Iris Database ########################## @@ -60,8 +78,6 @@ services: POSTGRES_DB: iris POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres - ports: - - 5434:5432 volumes: - pg_data_iris_db:/var/lib/postgresql/data @@ -78,12 +94,10 @@ services: # Services ########################## mediator: - image: ghcr.io/input-output-hk/mercury-mediator:0.1.0-SNAPSHOT + image: ghcr.io/input-output-hk/mercury-mediator:0.2.0 iris: - image: ghcr.io/input-output-hk/iris-service:0.1.0-SNAPSHOT - ports: - - 8081:8081 + image: ghcr.io/input-output-hk/iris-service:0.1.0 environment: IRIS_DB_HOST: db_iris IRIS_DB_PORT: 5432 @@ -91,7 +105,7 @@ services: IRIS_DB_USER: postgres prism-agent: - image: ghcr.io/input-output-hk/prism-agent:0.2.0-SNAPSHOT + image: ghcr.io/input-output-hk/prism-agent:0.6.0-SNAPSHOT environment: IRIS_HOST: iris IRIS_PORT: 8081 @@ -105,9 +119,12 @@ services: POLLUX_DB_NAME: pollux POLLUX_DB_USER: postgres POLLUX_DB_PASSWORD: postgres - ports: - - "8085:8085" - - "8080:8080" + CONNECT_DB_HOST: db_connect + CONNECT_DB_PORT: 5432 + CONNECT_DB_NAME: connect + CONNECT_DB_USER: postgres + CONNECT_DB_PASSWORD: postgres + DIDCOMM_SERVICE_URL: http://host.docker.internal:${PORT}/didcomm/ swagger-ui: image: swaggerapi/swagger-ui:v4.14.0 @@ -121,7 +138,7 @@ services: haproxy: image: haproxy:2.6.5 ports: - - "80:80" # Http + - "${PORT}:80" # Http depends_on: - mediator - prism-agent @@ -132,4 +149,5 @@ services: volumes: pg_data_castor_db: pg_data_pollux_db: + pg_data_connect_db: pg_data_iris_db: diff --git a/infrastructure/local/haproxy/haproxy.cfg b/infrastructure/local/haproxy/haproxy.cfg index 9437b6acb0..8701458eda 100644 --- a/infrastructure/local/haproxy/haproxy.cfg +++ b/infrastructure/local/haproxy/haproxy.cfg @@ -24,10 +24,11 @@ frontend https-in option httplog option logasap - use_backend mediator if { path_beg -i /mediator } - use_backend swagger-ui if { path_beg -i /apidocs } - use_backend prism-agent if { path_beg -i /prism-agent } - use_backend prism-agent-tapir if { path_beg -i /tapir } + use_backend mediator if { path_beg -i /mediator } + use_backend swagger-ui if { path_beg -i /apidocs } + use_backend prism-agent if { path_beg -i /prism-agent } + use_backend prism-agent-didcomm if { path_beg -i /didcomm } + use_backend prism-agent-tapir if { path_beg -i /tapir } backend mediator balance roundrobin @@ -43,6 +44,13 @@ backend prism-agent option forwardfor server s1 prism-agent:8080 maxconn 32 +backend prism-agent-didcomm + balance roundrobin + http-request set-uri %[url,regsub(^/didcomm,,)] if { path_beg /didcomm } + option httpclose + option forwardfor + server s1 prism-agent:8090 maxconn 32 + backend prism-agent-tapir balance roundrobin http-request set-uri %[url,regsub(^/tapir,,)] if { path_beg /tapir } diff --git a/prism-agent/service/README.md b/prism-agent/service/README.md index 7834ef3728..9e3fcb2d97 100644 --- a/prism-agent/service/README.md +++ b/prism-agent/service/README.md @@ -47,7 +47,14 @@ Similar to [Indy Wallet SDK - secret API](https://github.com/hyperledger/indy-sd *it does not expose a private-key* for external use, instead it provide functions to perform cryptographic actions using internally stored private-keys. --- +## Connect flow +Basic documentation on how to execute the Connect flow from command line can be found [here](./connect.md). +--- +## Issue flow +Basic documentation on how to execute the Issue flow from the command line can be found [here](./issue.md). + +--- ## Known limitations ### Castor `worker` process embedded inside `prism-agent` runnable diff --git a/prism-agent/service/connect.md b/prism-agent/service/connect.md new file mode 100644 index 0000000000..806b7f926a --- /dev/null +++ b/prism-agent/service/connect.md @@ -0,0 +1,51 @@ +### Running multiple instances of Prism Agent +--- + +#### Starting an instance for `Inviter` on port `8080` + +```bash +# From the root directory +PORT=8080 docker-compose -p inviter -f infrastructure/local/docker-compose.yml up +``` + +#### Starting an instance for `Invitee` on port `8090` + +```bash +# From the root directory +PORT=8090 docker-compose -p invitee -f infrastructure/local/docker-compose.yml up +``` + +### Executing the `Connect` flow +--- + +- **Inviter** - Create a connection record containing the invitation +```bash +curl -X 'POST' \ + 'http://localhost:8080/prism-agent/connections' \ + -H 'Content-Type: application/json' \ + -d '{ + "label": "Connect with Alice" + }' | jq +``` + +- **Inviter** - Retrieving the list of connections +```bash +curl -X 'GET' 'http://localhost:8080/prism-agent/connections' | jq +``` + +- **Invitee** - Accept OOB invitation + +Replace `{RAW_INVITATION}` with the value of the '_oob' query string parameter from the invitation URL above +```bash +curl -X 'POST' \ + 'http://localhost:8090/prism-agent/connection-invitations' \ + -H 'Content-Type: application/json' \ + -d '{ + "invitation": "{RAW_INVITATION}" + }' | jq +``` + +- **Invitee** - Retrieving the list of connections +```bash +curl -X 'GET' 'http://localhost:8090/prism-agent/connections' | jq +``` diff --git a/prism-agent/service/issue.md b/prism-agent/service/issue.md new file mode 100644 index 0000000000..ab727b85c8 --- /dev/null +++ b/prism-agent/service/issue.md @@ -0,0 +1,65 @@ +### Running multiple instances of Prism Agent +--- + +#### Starting an instance for `Issuer` on port `8080` + +```bash +# From the root directory +PORT=8080 docker-compose -p issuer -f infrastructure/local/docker-compose.yml up +``` + +#### Starting an instance for `Holder` on port `8090` + +```bash +# From the root directory +PORT=8090 docker-compose -p holder -f infrastructure/local/docker-compose.yml up +``` + +### Executing the `Issue` flow +--- + +- **Issuer** - Initiate a new issue credential flow + +Replace `{SUBJECT_ID}` with the DID of the holder displayed at startup in the his Prism Agent console logs +```bash +curl -X 'POST' \ + 'http://localhost:8080/prism-agent/issue-credentials/credential-offers' \ + -H 'accept: application/json' \ + -H 'Content-Type: application/json' \ + -d '{ + "schemaId": "schema:1234", + "subjectId": "{SUBJECT_ID}", + "validityPeriod": 3600, + "automaticIssuance": false, + "awaitConfirmation": false, + "claims": { + "firstname": "Alice", + "lastname": "Wonderland", + "birthdate": "01/01/2000" + } + }' | jq +``` + +- **Holder** - Retrieving the list of issue records +```bash +curl -X 'GET' 'http://localhost:8090/prism-agent/issue-credentials/records' | jq +``` + +- **Holder** - Accepting the credential offer + +Replace `{RECORD_ID}` with the UUID of the record from the previous list +```bash +curl -X 'POST' 'http://localhost:8090/prism-agent/issue-credentials/records/{RECORD_ID}/accept-offer' | jq +``` + +- **Issuer** - Retrieving the list of issue records +```bash +curl -X 'GET' 'http://localhost:8080/prism-agent/issue-credentials/records' | jq +``` + +- **Issuer** - Issuing the credential + +Replace `{RECORD_ID}` with the UUID of the record from the previous list +```bash +curl -X 'POST' 'http://localhost:8080/prism-agent/issue-credentials/records/{RECORD_ID}/issue-credential' | jq +``` \ No newline at end of file diff --git a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/Main.scala b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/Main.scala index 04c267982e..07a0ca1c45 100644 --- a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/Main.scala +++ b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/Main.scala @@ -67,7 +67,7 @@ object Main extends ZIOAppDefault { .provide(RepoModule.connectDbConfigLayer >>> ConnectMigrations.layer) agentDID <- for { - peer <- ZIO.succeed(PeerDID.makePeerDid(serviceEndpoint = Some(s"$didCommServiceUrl:$didCommServicePort"))) + peer <- ZIO.succeed(PeerDID.makePeerDid(serviceEndpoint = Some(didCommServiceUrl))) _ <- ZIO.logInfo(s"New DID: ${peer.did}") *> ZIO.logInfo(s"JWK for KeyAgreement: ${peer.jwkForKeyAgreement.toJSONString}") *> ZIO.logInfo(s"JWK for KeyAuthentication: ${peer.jwkForKeyAuthentication.toJSONString}") diff --git a/prism-agent/service/version.sbt b/prism-agent/service/version.sbt index 0908091720..5bf12846b2 100644 --- a/prism-agent/service/version.sbt +++ b/prism-agent/service/version.sbt @@ -1 +1 @@ -ThisBuild / version := "0.5.0-SNAPSHOT" +ThisBuild / version := "0.6.0-SNAPSHOT" From ca5f8c02da8bd8f8834f8f648f7b47cbbc053360 Mon Sep 17 00:00:00 2001 From: atala-dev Date: Tue, 29 Nov 2022 12:01:45 +0000 Subject: [PATCH 2/5] chore(release): cut prism-agent image 0.6.0 release [skip ci] # [prism-agent-v0.6.0](https://github.com/input-output-hk/atala-prism-building-blocks/compare/prism-agent-v0.5.0...prism-agent-v0.6.0) (2022-11-29) ### Features * **prism-agent:** add connect/issue doc + allow local execution of multiple Prism Agent instances ([#178](https://github.com/input-output-hk/atala-prism-building-blocks/issues/178)) ([dc8d86b](https://github.com/input-output-hk/atala-prism-building-blocks/commit/dc8d86b1ba87d747c5ac0089573ddd8c2ab62f5e)) --- prism-agent/service/CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/prism-agent/service/CHANGELOG.md b/prism-agent/service/CHANGELOG.md index c77b4ff1ec..1ed4da9b73 100644 --- a/prism-agent/service/CHANGELOG.md +++ b/prism-agent/service/CHANGELOG.md @@ -1,3 +1,10 @@ +# [prism-agent-v0.6.0](https://github.com/input-output-hk/atala-prism-building-blocks/compare/prism-agent-v0.5.0...prism-agent-v0.6.0) (2022-11-29) + + +### Features + +* **prism-agent:** add connect/issue doc + allow local execution of multiple Prism Agent instances ([#178](https://github.com/input-output-hk/atala-prism-building-blocks/issues/178)) ([dc8d86b](https://github.com/input-output-hk/atala-prism-building-blocks/commit/dc8d86b1ba87d747c5ac0089573ddd8c2ab62f5e)) + # [prism-agent-v0.5.0](https://github.com/input-output-hk/atala-prism-building-blocks/compare/prism-agent-v0.4.0...prism-agent-v0.5.0) (2022-11-28) From e5d1810a157db7036490a0721404c7af0b825266 Mon Sep 17 00:00:00 2001 From: Fabio Pinheiro Date: Tue, 29 Nov 2022 12:51:06 +0000 Subject: [PATCH 3/5] feat(mercury): New DidValidator (#180) --- .../iohk/atala/resolvers/DidValidator.scala | 44 +++++++++++++++++++ .../atala/resolvers/DidValidatorSpec.scala | 31 +++++++++++++ 2 files changed, 75 insertions(+) create mode 100644 mercury/mercury-library/resolver/src/main/scala/io/iohk/atala/resolvers/DidValidator.scala create mode 100644 mercury/mercury-library/resolver/src/test/scala/io/iohk/atala/resolvers/DidValidatorSpec.scala diff --git a/mercury/mercury-library/resolver/src/main/scala/io/iohk/atala/resolvers/DidValidator.scala b/mercury/mercury-library/resolver/src/main/scala/io/iohk/atala/resolvers/DidValidator.scala new file mode 100644 index 0000000000..3180e4da50 --- /dev/null +++ b/mercury/mercury-library/resolver/src/main/scala/io/iohk/atala/resolvers/DidValidator.scala @@ -0,0 +1,44 @@ +package io.iohk.atala.resolvers + +import io.iohk.atala.mercury.model.DidId + +object DidValidator extends DidValidator +trait DidValidator { + val regexAny = "^did:(.*):(.*)$".r + + /** Ex: did:prism:66940961cc0f6a884ff5876992991b994ca518aa34b3bacfd15f2b51a7b042cf + */ + val regexPRISM = "^did:prism:(.*)$".r + + /** Ex: + * did:peer:2.Ez6LSeSTchYyPTBk131pKECXWP7t1CYG2RMgRE2KWoiWi962w.Vz6MkmLJC9YyMerhFD831jrbVAo8rHXiBvDV6UKnt8xzQY7MJ.SeyJ0IjoiZG0iLCJzIjoiaHR0cDovL2xvY2FsaG9zdEw5OTk5IiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfQ + */ + val regexPeer = + "^did:peer:(([01](z)([1-9a-km-zA-HJ-NP-Z]{46,47}))|(2((\\.[AEVID](z)([1-9a-km-zA-HJ-NP-Z]{46,47}))+(\\.(S)[0-9a-zA-Z=]*)?)))$".r + + def isDidPRISM(did: String) = did match { + case regexPRISM(id) => true + case _ => false + } + def isDidPeer(did: String) = did match { + case regexPeer(id, _*) => true + case _ => false + } + + def validDID(did: DidId): Boolean = validDID(did.value) + def validDID(did: String): Boolean = did match { + case regexAny(method, id) => true + case _ => false + } + + def supportedDid(did: DidId): Boolean = supportedDid(did.value) + def supportedDid(did: String): Boolean = did match + case regexPRISM(id) => true + case regexPeer(id, _*) => true + case regexAny("example", "alice") => true // for debug + case regexAny("example", "mediator") => true // for debug + case regexAny("example", "bob") => true // for debug + case regexAny(method, id) => false + case _ => false // NOT a DID + +} diff --git a/mercury/mercury-library/resolver/src/test/scala/io/iohk/atala/resolvers/DidValidatorSpec.scala b/mercury/mercury-library/resolver/src/test/scala/io/iohk/atala/resolvers/DidValidatorSpec.scala new file mode 100644 index 0000000000..0949b9f9e1 --- /dev/null +++ b/mercury/mercury-library/resolver/src/test/scala/io/iohk/atala/resolvers/DidValidatorSpec.scala @@ -0,0 +1,31 @@ +package io.iohk.atala.resolvers + +import munit.* + +/** resolver/testOnly io.iohk.atala.resolvers.DidValidatorSpec + */ +class DidValidatorSpec extends ZSuite { + val exPRISM = "did:prism:66940961cc0f6a884ff5876992991b994ca518aa34b3bacfd15f2b51a7b042cf" + val exPeer = + "did:peer:2.Ez6LSeSTchYyPTBk131pKECXWP7t1CYG2RMgRE2KWoiWi962w.Vz6MkmLJC9YyMerhFD831jrbVAo8rHXiBvDV6UKnt8xzQY7MJ.SeyJ0IjoiZG0iLCJzIjoiaHR0cDovL2xvY2FsaG9zdEw5OTk5IiwiciI6W10sImEiOlsiZGlkY29tbS92MiJdfQ" + + test("validDID") { + assertEquals(DidValidator.validDID(exPRISM), true) + assertEquals(DidValidator.validDID(exPeer), true) + assertEquals(DidValidator.validDID("did:test:ola"), true) + } + + test("supportedDid") { + assertEquals(DidValidator.supportedDid(exPRISM), true) + assertEquals(DidValidator.supportedDid(exPeer), true) + assertEquals(DidValidator.supportedDid("did:test:ola"), false) + } + + test("isDidPRISM and isDidPeer") { + assertEquals(DidValidator.isDidPRISM(exPRISM), true) + assertEquals(DidValidator.isDidPeer(exPRISM), false) + + assertEquals(DidValidator.isDidPRISM(exPeer), false) + assertEquals(DidValidator.isDidPeer(exPeer), true) + } +} From 79170f8722053de9e477118f3f9443c97f27c512 Mon Sep 17 00:00:00 2001 From: yshyn-iohk Date: Tue, 29 Nov 2022 19:59:53 +0800 Subject: [PATCH 4/5] feat(pollux): cleanup the OAS from Issue Credentials and other unused tags --- .../service/api/http/pollux/schemas.yaml | 120 -------- .../api/http/prism-agent-openapi-spec.yaml | 286 ++---------------- 2 files changed, 29 insertions(+), 377 deletions(-) diff --git a/prism-agent/service/api/http/pollux/schemas.yaml b/prism-agent/service/api/http/pollux/schemas.yaml index c943525d68..d48f05427f 100644 --- a/prism-agent/service/api/http/pollux/schemas.yaml +++ b/prism-agent/service/api/http/pollux/schemas.yaml @@ -244,126 +244,6 @@ components: count: type: integer -# - - W3CCredentialInput: - description: |- - Credential input object based on which the new instance of the verifiable credentials is created. - Object contains the minimal set of the fields required to create the credentials for the given subject. - All other required fields of the verifiable credential depend on the context of the cloud agent - required: - - subjectId - - claims - properties: - schemaId: - type: string - description: "Identity of the Verifiable Credentials Schema associated with this object" - example: "did:example:MDP8AsFhHzhwUvGNuYkX7T;id=06e126d1-fa44-4882-a243-1e326fbe21db;version=1.0" - subjectId: - type: string - description: "Subject DID of the verifiable credentials object" - example: "did:prism:subjectofverifiablecredentials" - validityPeriod: - type: number - description: "The validity period in seconds of the verifiable credential" - example: 3600 - claims: - type: object - additionalProperties: - type: string - description: "Clams associated with given credentials object (for now it's just a key/value, later should be more complex" - - W3CCredential: - description: "Verifiable Credential Object according to W3C specification" - required: ["id", "type", "issuer", "issuanceDate", "credentialSubject"] - properties: - id: - type: string - description: "Credential id or url that can be used to get the status of revoke the credential" - example: "http://example.edu/credentials/1872" - type: - type: string - description: "Credential type according to W3C specification. Must include VerifiableCredentials and type of concrete credentials" - example: '["VerifiableCredential", "AlumniCredential"]' - issuer: - type: string - description: "Issuer DID" - example: "did:prism:issuerdid" - issuanceDate: - type: string - description: "Datetime in ISO format that corresponds to the date of issuance" - example: "2010-01-01T19:23:24Z" - credentialSubject: - type: object - description: "Credentials subject DID and claims according to the schema object" - additionalProperties: - type: string - example: - id: "did:prism:subject12345" - alumni_of: "University" - degree: "master of openapi specification" - proof: - $ref: "#/components/schemas/W3CProof" - - W3CCredentialsPaginated: - description: "Paginated response that contains an array of the credential objects" - properties: - data: - type: array - items: - $ref: "#/components/schemas/W3CCredential" - offset: - type: integer - limit: - type: integer - count: - type: integer - - W3CIssuanceBatch: - description: "An issuance batch object that is associated with thelist of verifiable credentials" - properties: - id: - type: string - description: "Issuance batch id" - count: - type: integer - description: "Count of the verifiable credentials object in the batch" - actions: - type: array - items: - $ref: "#/components/schemas/W3CIssuanceBatchAction" - - W3CIssuanceBatchAction: - description: "Action performed on the list of credentials associated with the issuance batch" - properties: - action: - description: "Action name" - type: string - enum: ["sign", "issue", "send"] - example: "issue" - id: - description: "Action id for tracking" - type: string - example: "uid" - status: - description: "Action status" - type: string - enum: ["scheduled", "pending", "completed", "failed"] - - W3CIssuanceBatchPaginated: - description: "Paginated response that contains an array of the issuance-batch objects" - properties: - data: - type: array - items: - $ref: "#/components/schemas/W3CIssuanceBatch" - offset: - type: integer - limit: - type: integer - count: - type: integer - W3CCredentialStatus: description: Verifiable Credential revocation status required: diff --git a/prism-agent/service/api/http/prism-agent-openapi-spec.yaml b/prism-agent/service/api/http/prism-agent-openapi-spec.yaml index 716c57a397..e14c4241de 100644 --- a/prism-agent/service/api/http/prism-agent-openapi-spec.yaml +++ b/prism-agent/service/api/http/prism-agent-openapi-spec.yaml @@ -17,7 +17,7 @@ components: in: header name: apikey security: - - ApiKeyAuth: [] + - ApiKeyAuth: [ ] tags: # Castor - name: DID @@ -31,12 +31,6 @@ tags: # Pollux - name: Schema Registry description: Schema Registry REST API - - name: Issue Credentials - description: Verifiable Credentials creation and issuance REST API - - name: Verify Credentials - description: Verifiable Credentials verification REST API - - name: Revocation - description: Verifiable Credentials revocation REST API - name: Present Proof description: Present Proof REST API # Connect @@ -372,7 +366,7 @@ paths: # ---------------------------------- /schema-registry/schemas: post: - tags: ["Schema Registry"] + tags: [ "Schema Registry" ] operationId: createSchema summary: Publish new schema to the schema registry description: |- @@ -397,7 +391,7 @@ paths: "401": description: Client is unauthorized to call the API get: - tags: ["Schema Registry"] + tags: [ "Schema Registry" ] operationId: fetchSchemasByQuery summary: Fetch schemas by query description: |- @@ -436,7 +430,7 @@ paths: $ref: "./pollux/schemas.yaml#/components/schemas/W3CSchemaPaginated" /schema-registry/schemas/{id}: get: - tags: ["Schema Registry"] + tags: [ "Schema Registry" ] operationId: getSchemaById summary: Fetch the schema from the registry by id description: |- @@ -458,11 +452,11 @@ paths: $ref: "./pollux/schemas.yaml#/components/schemas/W3CSchema" "404": description: Schema is not found by id -## Issue Credential Protocol + ## Issue Credential Protocol /issue-credentials/credential-offers: post: - tags: ["Issue Credentials Protocol"] + tags: [ "Issue Credentials Protocol" ] operationId: createCredentialOffer summary: As a VC issuer, create a new credential offer to be sent to a VC holder requestBody: @@ -471,7 +465,7 @@ paths: content: application/json: schema: - $ref: ./pollux/schemas.yaml#/components/schemas/CreateIssueCredentialRecordRequest + $ref: ./pollux/schemas.yaml#/components/schemas/CreateIssueCredentialRecordRequest responses: "201": description: The issue credential record @@ -488,7 +482,7 @@ paths: /issue-credentials/records: get: - tags: ["Issue Credentials Protocol"] + tags: [ "Issue Credentials Protocol" ] operationId: getCredentialRecords summary: Get credential records responses: @@ -507,7 +501,7 @@ paths: /issue-credentials/records/{recordId}: get: - tags: ["Issue Credentials Protocol"] + tags: [ "Issue Credentials Protocol" ] operationId: getCredentialRecord summary: Get a credential record by Id parameters: @@ -528,7 +522,7 @@ paths: /issue-credentials/records/{recordId}/accept-offer: post: - tags: ["Issue Credentials Protocol"] + tags: [ "Issue Credentials Protocol" ] operationId: acceptCredentialOffer summary: As a VC holder, accept a credential offer received from an issuer parameters: @@ -539,17 +533,17 @@ paths: content: application/json: schema: - $ref: ./pollux/schemas.yaml#/components/schemas/IssueCredentialRecord + $ref: ./pollux/schemas.yaml#/components/schemas/IssueCredentialRecord "404": description: There is no issue credential record maatching the given 'recordId'. content: application/json: schema: - $ref: "./pollux/schemas.yaml#/components/schemas/ErrorResponse" + $ref: "./pollux/schemas.yaml#/components/schemas/ErrorResponse" /issue-credentials/records/{recordId}/issue-credential: post: - tags: ["Issue Credentials Protocol"] + tags: [ "Issue Credentials Protocol" ] operationId: issueCredential summary: As a VC issuer, issue the VC for the specified issue credential record parameters: @@ -560,239 +554,17 @@ paths: content: application/json: schema: - $ref: ./pollux/schemas.yaml#/components/schemas/IssueCredentialRecord + $ref: ./pollux/schemas.yaml#/components/schemas/IssueCredentialRecord "404": description: There is no issue credential record maatching the given 'recordId'. content: application/json: schema: - $ref: "./pollux/schemas.yaml#/components/schemas/ErrorResponse" -## - - /issue-credentials/credentials: - post: - tags: ["Issue Credentials"] - operationId: createCredentials - summary: Create a new instances of Verifiable Credentials objects - description: |- - New credentials are created and stored by Pollux backend in the database - Credentials can be fetched either by issuance batchId or credential id - Any other manipulations and the issuance protocols execution can be performed on this object - requestBody: - description: CredentialInput object with the metadata and claims - required: true - content: - application/json: - schema: - type: object - required: ["credentials"] - properties: - credentials: - type: array - items: - $ref: "./pollux/schemas.yaml#/components/schemas/W3CCredentialInput" - example: - - subjectId: "did:prism:subject123" - schemaId: "unique schema id" - claims: - alumni_of: "University" - degree: "Master" - responses: - "201": - description: "Array of created verifiable credentials objects" - content: - application/json: - schema: - type: object - properties: - batchId: - type: string - description: "BatchId of the current set of credentials" - count: - type: integer - description: "Total count of the credential object in a given batch" - credentials: - type: array - items: - $ref: "./pollux/schemas.yaml#/components/schemas/JWTCompactSerialisation" - - get: - tags: ["Issue Credentials"] - operationId: getCredentialsByBatchId - summary: Returns the list of the credentials associated with the given batchId - description: Returns the list of the credentials associated with the given batchId - parameters: - - in: query - name: batchId - description: "Issuance batchId associated with the set of credentials" - required: true - schema: - type: string - - in: query - name: offset - description: "Offset pagination parameter" - required: false - schema: - type: integer - - in: query - name: limit - description: "Limit pagination parameter" - required: false - schema: - type: integer - responses: - "200": - description: "Paginated response of the verifiable credentials objects" - content: - application/json: - schema: - $ref: "./pollux/schemas.yaml#/components/schemas/W3CCredentialsPaginated" - /issue-credentials/credentials/{id}: - get: - tags: ["Issue Credentials"] - operationId: getCredentialById - summary: Fetch the credential by id - description: |- - Fetch the credential by id - parameters: - - in: path - name: id - schema: - type: string - required: true - description: Identifier of the credential - example: "06e126d1-fa44-4882-a243-1e326fbe21db" - responses: - "200": - description: Successful response, instance of Verifiable Credential is returned - content: - application/json: - schema: - $ref: "./pollux/schemas.yaml#/components/schemas/W3CCredential" - "404": - description: Schema is not found by id - put: - tags: ["Issue Credentials"] - operationId: updateCredentialById - summary: Update the credential by id - description: Update the credential by id - parameters: - - in: path - name: id - schema: - type: string - required: true - description: Identifier of the credential - example: "06e126d1-fa44-4882-a243-1e326fbe21db" - requestBody: - content: - application/json: - schema: - $ref: "./pollux/schemas.yaml#/components/schemas/W3CCredentialInput" - required: true - responses: - "200": - description: "Credential was updated successfully" - content: - application/json: - schema: - $ref: "./pollux/schemas.yaml#/components/schemas/W3CCredential" - delete: - tags: ["Issue Credentials"] - operationId: deleteCredentialById - summary: Delete the credential by id - description: Delete the credential by id - parameters: - - in: path - name: id - schema: - type: string - required: true - description: Identifier of the credential - example: "06e126d1-fa44-4882-a243-1e326fbe21db" - responses: - "204": - description: "Credential was deleted" - /issue-credentials/issuance-batches: - get: - tags: ["Issue Credentials"] - operationId: getIssuanceBatches - summary: Fetch the available list of issuance-batches - description: Fetch the list of issuance-batches - parameters: - - in: query - name: limit - schema: - type: integer - - in: query - name: offset - schema: - type: integer - responses: - "200": - description: Returns the paginated list of issuance-batch objects - content: - application/json: - schema: - $ref: "./pollux/schemas.yaml#/components/schemas/W3CIssuanceBatchPaginated" - /issue-credentials/issuance-batches/{batchId}/actions: - post: - tags: ["Issue Credentials"] - summary: "Submit the list of actions performed on the credentials associated with the issuance-batch" - operationId: "submitIssuanceBatchActions" - description: |- - List of action is submitted, actions are scheduled and IDs are returned for tracking the status - Each action is executed asynchronously in the sequential order according to the state of the issuance batch - Sign -> Issue -> Send - parameters: - - in: path - name: batchId - description: "The batchId of the issuance-batch object" - schema: - type: string - required: true - requestBody: - content: - application/json: - schema: - type: array - items: - $ref: "./pollux/schemas.yaml#/components/schemas/W3CIssuanceBatchAction" - required: true - responses: - "200": - description: "Returns the set of actions performed on the issuance-batch" - content: - application/json: - schema: - type: array - items: - $ref: "./pollux/schemas.yaml#/components/schemas/W3CIssuanceBatchAction" - get: - tags: ["Issue Credentials"] - operationId: "getIssuanceBatchActions" - summary: "Fetch the actions performed on the issuance-batch" - description: "Fetch the actions performed on the issuance-batch" - parameters: - - in: path - name: batchId - description: "The batchId of the issuance-batch object" - schema: - type: string - required: true - responses: - "200": - description: "Returns the set of actions performed on the issuance-batch" - content: - application/json: - schema: - type: array - items: - $ref: "./pollux/schemas.yaml#/components/schemas/W3CIssuanceBatchAction" + $ref: "./pollux/schemas.yaml#/components/schemas/ErrorResponse" /revocation-registry/credential-status/{id}: get: - tags: ["Revocation Registry"] + tags: [ "Revocation Registry" ] operationId: getCredentialRevocationStatusById summary: Get credentials revocation status by credential id description: Get credentials revocation status by credential id @@ -813,7 +585,7 @@ paths: $ref: "./pollux/schemas.yaml#/components/schemas/W3CCredentialStatus" /revocation-registry/revoke: post: - tags: ["Revocation Registry"] + tags: [ "Revocation Registry" ] operationId: revokeCredentialById summary: Revoke credential by id description: Revoke credential by id @@ -838,7 +610,7 @@ paths: /revocation-registry/operations/{id}: get: - tags: ["Revocation Registry"] + tags: [ "Revocation Registry" ] operationId: getRevocationOperationStatusById summary: Get revocation operation status by id description: Get revocation operation status by id @@ -858,7 +630,7 @@ paths: /present-proof/verifiable-presentations: post: - tags: ["Present Proof"] + tags: [ "Present Proof" ] operationId: createVerifiablePresentation summary: Create new instance of VerifiablePresentation description: Verifier creates the instance of Verifiable Presentation object to be used in present proof communication protocol with Prover @@ -879,7 +651,7 @@ paths: # TODO: Add other corner cases and error responses get: - tags: ["Present Proof"] + tags: [ "Present Proof" ] operationId: fetchPresentationByQuery summary: Fetch presentation by query description: Fetch presentation by query @@ -911,7 +683,7 @@ paths: $ref: "./pollux/schemas.yaml#/components/schemas/W3CPresentationPaginated" /present-proof/verifiable-presentations/{id}: get: - tags: ["Present Proof"] + tags: [ "Present Proof" ] operationId: getPresentationById summary: Fetch the presentation from the collection by id description: Fetch the presentation from the collection by id @@ -936,7 +708,7 @@ paths: # ---------------------------------- /connections: post: - tags: ["Connections Management"] + tags: [ "Connections Management" ] operationId: createConnection summary: Creates new connection and returns an invitation. description: |- @@ -966,7 +738,7 @@ paths: $ref: "./connect/schemas.yaml#/components/schemas/ErrorResponse" get: - tags: ["Connections Management"] + tags: [ "Connections Management" ] operationId: getConnections summary: Returns a list of connections. responses: @@ -981,11 +753,11 @@ paths: content: application/json: schema: - $ref: "./connect/schemas.yaml#/components/schemas/ErrorResponse" - + $ref: "./connect/schemas.yaml#/components/schemas/ErrorResponse" + /connections/{connectionId}: get: - tags: ["Connections Management"] + tags: [ "Connections Management" ] parameters: - $ref: "./connect/schemas.yaml#/components/parameters/connectionId" operationId: getConnection @@ -1004,7 +776,7 @@ paths: schema: $ref: "./connect/schemas.yaml#/components/schemas/ErrorResponse" delete: - tags: ["Connections Management"] + tags: [ "Connections Management" ] parameters: - $ref: "./connect/schemas.yaml#/components/parameters/connectionId" operationId: deleteConnection @@ -1018,9 +790,9 @@ paths: /connection-invitations: post: - tags: ["Connections Management"] + tags: [ "Connections Management" ] operationId: acceptConnectionInvitation - summary: Accepts externally received invitation. + summary: Accepts externally received invitation. description: Creates new connection state record in `pending` state. It is assumed that application would first decode and validate the invitation. When it is accepted in the application side, it should be submitted in raw format to this API. requestBody: required: true From 16d5fdbadf20c1597bf42b4e366f71623804dfc4 Mon Sep 17 00:00:00 2001 From: yshyn-iohk Date: Tue, 29 Nov 2022 22:14:35 +0800 Subject: [PATCH 5/5] feat(pollux): cleanup the code of IssueCredentialApi --- .../io/iohk/atala/agent/server/Modules.scala | 13 +- .../atala/agent/server/http/HttpRoutes.scala | 10 +- .../IssueCredentialsApiMarshallerImpl.scala | 49 ----- .../server/http/marshaller/JsonSupport.scala | 10 - .../IssueCredentialsApiServiceImpl.scala | 206 ------------------ ...sueCredentialsProtocolApiServiceImpl.scala | 1 - 6 files changed, 6 insertions(+), 283 deletions(-) delete mode 100644 prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/marshaller/IssueCredentialsApiMarshallerImpl.scala delete mode 100644 prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/service/IssueCredentialsApiServiceImpl.scala diff --git a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/Modules.scala b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/Modules.scala index f13d3f3d78..59661f6ffa 100644 --- a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/Modules.scala +++ b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/Modules.scala @@ -13,7 +13,6 @@ import io.iohk.atala.agent.server.http.marshaller.{ DIDAuthenticationApiMarshallerImpl, DIDOperationsApiMarshallerImpl, DIDRegistrarApiMarshallerImpl, - IssueCredentialsApiMarshallerImpl, ConnectionsManagementApiMarshallerImpl } import io.iohk.atala.agent.server.http.service.{ @@ -21,7 +20,6 @@ import io.iohk.atala.agent.server.http.service.{ DIDAuthenticationApiServiceImpl, DIDOperationsApiServiceImpl, DIDRegistrarApiServiceImpl, - IssueCredentialsApiServiceImpl, ConnectionsManagementApiServiceImpl } import io.iohk.atala.castor.core.repository.DIDOperationRepository @@ -30,7 +28,6 @@ import io.iohk.atala.agent.openapi.api.{ DIDAuthenticationApi, DIDOperationsApi, DIDRegistrarApi, - IssueCredentialsApi, ConnectionsManagementApi } import io.iohk.atala.castor.sql.repository.{JdbcDIDOperationRepository, TransactorLayer} @@ -378,13 +375,6 @@ object HttpModule { (apiServiceLayer ++ apiMarshallerLayer) >>> ZLayer.fromFunction(new DIDRegistrarApi(_, _)) } - val issueCredentialsApiLayer: RLayer[DidComm, IssueCredentialsApi] = { - val serviceLayer = AppModule.credentialServiceLayer - val apiServiceLayer = serviceLayer >>> IssueCredentialsApiServiceImpl.layer - val apiMarshallerLayer = IssueCredentialsApiMarshallerImpl.layer - (apiServiceLayer ++ apiMarshallerLayer) >>> ZLayer.fromFunction(new IssueCredentialsApi(_, _)) - } - val issueCredentialsProtocolApiLayer: RLayer[DidComm, IssueCredentialsProtocolApi] = { val serviceLayer = AppModule.credentialServiceLayer val apiServiceLayer = serviceLayer >>> IssueCredentialsProtocolApiServiceImpl.layer @@ -400,7 +390,8 @@ object HttpModule { } val layers = - didApiLayer ++ didOperationsApiLayer ++ didAuthenticationApiLayer ++ didRegistrarApiLayer ++ issueCredentialsApiLayer ++ issueCredentialsProtocolApiLayer ++ connectionsManagementApiLayer + didApiLayer ++ didOperationsApiLayer ++ didAuthenticationApiLayer ++ didRegistrarApiLayer ++ + issueCredentialsProtocolApiLayer ++ connectionsManagementApiLayer } object RepoModule { diff --git a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/HttpRoutes.scala b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/HttpRoutes.scala index e355797cca..dde4c952e1 100644 --- a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/HttpRoutes.scala +++ b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/HttpRoutes.scala @@ -7,18 +7,17 @@ import io.iohk.atala.agent.openapi.api.{ DIDAuthenticationApi, DIDOperationsApi, DIDRegistrarApi, - IssueCredentialsApi, + IssueCredentialsProtocolApi, ConnectionsManagementApi } import zio.* -import io.iohk.atala.agent.openapi.api.IssueCredentialsProtocolApi import akka.http.scaladsl.server.Route object HttpRoutes { def routes: URIO[ - DIDApi & DIDOperationsApi & DIDAuthenticationApi & DIDRegistrarApi & IssueCredentialsApi & - IssueCredentialsProtocolApi & ConnectionsManagementApi, + DIDApi & DIDOperationsApi & DIDAuthenticationApi & DIDRegistrarApi & IssueCredentialsProtocolApi & + ConnectionsManagementApi, Route ] = for { @@ -26,10 +25,9 @@ object HttpRoutes { didOperationsApi <- ZIO.service[DIDOperationsApi] didAuthApi <- ZIO.service[DIDAuthenticationApi] disRegistrarApi <- ZIO.service[DIDRegistrarApi] - issueCredentialApi <- ZIO.service[IssueCredentialsApi] issueCredentialsProtocolApi <- ZIO.service[IssueCredentialsProtocolApi] connectionsManagementApi <- ZIO.service[ConnectionsManagementApi] - } yield didApi.route ~ didOperationsApi.route ~ didAuthApi.route ~ disRegistrarApi.route ~ issueCredentialApi.route ~ issueCredentialsProtocolApi.route ~ connectionsManagementApi.route ~ additionalRoute + } yield didApi.route ~ didOperationsApi.route ~ didAuthApi.route ~ disRegistrarApi.route ~ issueCredentialsProtocolApi.route ~ connectionsManagementApi.route ~ additionalRoute private def additionalRoute: Route = { // swagger-ui expects this particular header when resolving relative $ref diff --git a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/marshaller/IssueCredentialsApiMarshallerImpl.scala b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/marshaller/IssueCredentialsApiMarshallerImpl.scala deleted file mode 100644 index 4c3ac94cbb..0000000000 --- a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/marshaller/IssueCredentialsApiMarshallerImpl.scala +++ /dev/null @@ -1,49 +0,0 @@ -package io.iohk.atala.agent.server.http.marshaller - -import akka.http.scaladsl.marshalling.ToEntityMarshaller -import akka.http.scaladsl.unmarshalling.FromEntityUnmarshaller -import io.iohk.atala.agent.openapi.api.IssueCredentialsApiMarshaller -import io.iohk.atala.agent.openapi.model.{ - CreateCredentialsRequest, - W3CIssuanceBatchAction, - W3CCredentialInput, - W3CCredentialsPaginated, - W3CCredential, - W3CIssuanceBatchPaginated, - CreateCredentials201Response -} -import spray.json.RootJsonFormat -import zio.* - -object IssueCredentialsApiMarshallerImpl extends JsonSupport { - - val layer: ULayer[IssueCredentialsApiMarshaller] = ZLayer.succeed { - new IssueCredentialsApiMarshaller { - - implicit def fromEntityUnmarshallerCreateCredentialsRequest: FromEntityUnmarshaller[CreateCredentialsRequest] = - summon[RootJsonFormat[CreateCredentialsRequest]] - - implicit def fromEntityUnmarshallerW3CIssuanceBatchActionList - : FromEntityUnmarshaller[Seq[W3CIssuanceBatchAction]] = summon[RootJsonFormat[Seq[W3CIssuanceBatchAction]]] - - implicit def fromEntityUnmarshallerW3CCredentialInput: FromEntityUnmarshaller[W3CCredentialInput] = - summon[RootJsonFormat[W3CCredentialInput]] - - implicit def toEntityMarshallerW3CCredentialsPaginated: ToEntityMarshaller[W3CCredentialsPaginated] = - summon[RootJsonFormat[W3CCredentialsPaginated]] - - implicit def toEntityMarshallerW3CCredential: ToEntityMarshaller[W3CCredential] = - summon[RootJsonFormat[W3CCredential]] - - implicit def toEntityMarshallerW3CIssuanceBatchPaginated: ToEntityMarshaller[W3CIssuanceBatchPaginated] = - summon[RootJsonFormat[W3CIssuanceBatchPaginated]] - - implicit def toEntityMarshallerW3CIssuanceBatchActionarray: ToEntityMarshaller[Seq[W3CIssuanceBatchAction]] = - summon[RootJsonFormat[Seq[W3CIssuanceBatchAction]]] - - implicit def toEntityMarshallerCreateCredentials201Response: ToEntityMarshaller[CreateCredentials201Response] = - summon[RootJsonFormat[CreateCredentials201Response]] - } - } - -} diff --git a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/marshaller/JsonSupport.scala b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/marshaller/JsonSupport.scala index a78d2ebae5..78190d505b 100644 --- a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/marshaller/JsonSupport.scala +++ b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/marshaller/JsonSupport.scala @@ -77,20 +77,10 @@ trait JsonSupport extends SprayJsonSupport with DefaultJsonProtocol { // // Pollux - given RootJsonFormat[CreateCredentials201Response] = jsonFormat3(CreateCredentials201Response.apply) - given RootJsonFormat[CreateCredentialsRequest] = jsonFormat1(CreateCredentialsRequest.apply) given RootJsonFormat[RevocationStatus] = jsonFormat2(RevocationStatus.apply) - given RootJsonFormat[W3CCredential] = jsonFormat6(W3CCredential.apply) -// given RootJsonFormat[W3CCredentialCredentialSubject] = jsonFormat1(W3CCredentialCredentialSubject.apply) - given RootJsonFormat[W3CCredentialInput] = jsonFormat4(W3CCredentialInput.apply) -// given RootJsonFormat[W3CCredentialInputClaims] = jsonFormat1(W3CCredentialInputClaims.apply) given RootJsonFormat[W3CCredentialRevocationRequest] = jsonFormat1(W3CCredentialRevocationRequest.apply) given RootJsonFormat[W3CCredentialRevocationResponse] = jsonFormat2(W3CCredentialRevocationResponse.apply) - given RootJsonFormat[W3CCredentialsPaginated] = jsonFormat4(W3CCredentialsPaginated.apply) given RootJsonFormat[W3CCredentialStatus] = jsonFormat2(W3CCredentialStatus.apply) - given RootJsonFormat[W3CIssuanceBatch] = jsonFormat3(W3CIssuanceBatch.apply) - given RootJsonFormat[W3CIssuanceBatchAction] = jsonFormat3(W3CIssuanceBatchAction.apply) - given RootJsonFormat[W3CIssuanceBatchPaginated] = jsonFormat4(W3CIssuanceBatchPaginated.apply) given RootJsonFormat[W3CPresentation] = jsonFormat1(W3CPresentation.apply) given RootJsonFormat[W3CPresentationInput] = jsonFormat1(W3CPresentationInput.apply) given RootJsonFormat[W3CPresentationPaginated] = jsonFormat4(W3CPresentationPaginated.apply) diff --git a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/service/IssueCredentialsApiServiceImpl.scala b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/service/IssueCredentialsApiServiceImpl.scala deleted file mode 100644 index 1fa8dd18fc..0000000000 --- a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/service/IssueCredentialsApiServiceImpl.scala +++ /dev/null @@ -1,206 +0,0 @@ -package io.iohk.atala.agent.server.http.service - -import akka.http.scaladsl.marshalling.ToEntityMarshaller -import akka.http.scaladsl.server.Route -import io.circe.* -import io.iohk.atala.agent.openapi.api.IssueCredentialsApiService -import io.iohk.atala.agent.openapi.model.* -import io.iohk.atala.agent.server.http.marshaller.IssueCredentialsApiMarshallerImpl -import io.iohk.atala.pollux.vc.jwt.* -import zio.* - -import java.security.spec.ECGenParameterSpec -import java.security.{KeyPairGenerator, SecureRandom} -import java.time.{Instant, OffsetDateTime, OffsetTime} -import java.util.{Base64, UUID} -import cats.implicits.* -import io.circe.* -import io.circe.generic.auto.* -import io.circe.syntax.* -import io.circe.{Decoder, Encoder, HCursor, Json} -import io.circe.parser.decode -import io.iohk.atala.pollux.core.service.CredentialService -import io.iohk.atala.pollux.core.model.EncodedJWTCredential - -// TODO: replace with actual implementation -class IssueCredentialsApiServiceImpl(service: CredentialService)(using runtime: Runtime[Any]) - extends IssueCredentialsApiService - with AkkaZioSupport { - - private val issuer = service.createIssuer - - case class Schema(context: String, `type`: String) - private val defaultSchemas = Set( - Schema("https://www.w3.org/2018/credentials/v1", "VerifiableCredential") - ) - private val mockSchemas = Map( - "06e126d1-fa44-4882-a243-1e326fbe21db" -> Schema( - "https://www.w3.org/2018/credentials/examples/v1", - "UniversityDegreeCredential" - ) - ) - - private val mockW3Credential = W3CCredential( - id = "fsdf234t523fdf3", - `type` = "University degree", - issuer = "University of applied science", - issuanceDate = "21/09/2022", - credentialSubject = Map("id" -> "University degree for smth"), - proof = Some( - W3CProof( - `type` = "proof", - created = "21/09/2022", - verificationMethod = "verificationMethod", - proofPurpose = "proofPurpose", - proofValue = "proofValue", - domain = Some("domain") - ) - ) - ) - - private val mockCredentialResponse = CreateCredentials201Response( - batchId = Some("1"), - count = Some(1), - credentials = Some( - Seq("") - ) - ) - - private val mockW3CCredentialsPaginated = W3CCredentialsPaginated( - data = Some(Seq(mockW3Credential)), - offset = Some(1), - limit = Some(1), - count = Some(1) - ) - - private val mockW3CIssuanceBatchAction = W3CIssuanceBatchAction( - action = Some("abc"), - id = Some("abc"), - status = Some("abc") - ) - - private val mockW3CIssuanceBatch = W3CIssuanceBatch( - id = Some("asdf23fsdf"), - count = Some(1), - actions = Some(Seq(mockW3CIssuanceBatchAction)) - ) - - private val mockW3CIssuanceBatchPaginated = W3CIssuanceBatchPaginated( - data = Some(Seq(mockW3CIssuanceBatch)), - offset = Some(1), - limit = Some(1), - count = Some(1) - ) - - private[this] def createPayload(input: W3CCredentialInput, issuer: Issuer): (UUID, W3cCredentialPayload) = { - val now = Instant.now() - val credentialId = UUID.randomUUID() - val claims = input.claims.map(kv => kv._1 -> Json.fromString(kv._2)) - val schemas = defaultSchemas ++ input.schemaId.flatMap(mockSchemas.get) - credentialId -> W3cCredentialPayload( - `@context` = schemas.map(_.context), - maybeId = Some(s"https://atala.io/prism/credentials/${credentialId.toString}"), - `type` = schemas.map(_.`type`), - issuer = issuer.did, - issuanceDate = now, - maybeExpirationDate = input.validityPeriod.map(sec => now.plusSeconds(sec.toLong)), - maybeCredentialSchema = None, - credentialSubject = claims.updated("id", Json.fromString(input.subjectId)).asJson, - maybeCredentialStatus = None, - maybeRefreshService = None, - maybeEvidence = None, - maybeTermsOfUse = None - ) - } - - /** Code: 201, Message: Array of created verifiable credentials objects, DataType: CreateCredentials201Response - */ - def createCredentials(createCredentialsRequest: CreateCredentialsRequest)(implicit - toEntityMarshallerCreateCredentials201Response: ToEntityMarshaller[CreateCredentials201Response] - ): Route = - onZioSuccess(ZIO.unit) { _ => - val credentials = createCredentialsRequest.credentials.map { input => - val (uuid, payload) = createPayload(input, issuer) - uuid.toString -> payload.toJwtCredentialPayload - } - val batchId = UUID.randomUUID().toString - // service.createCredentials( - // batchId, - // credentials.map { case (id, jwt) => EncodedJWTCredential(batchId, id, jwt) } - // ) - val resp = CreateCredentials201Response( - Some(batchId), - Some(credentials.size), - Some(credentials.map(c => JwtCredential.encodeJwt(c._2, issuer).value)) - ) - - createCredentials201(resp) - } - - /** Code: 204, Message: Credential was deleted - */ - def deleteCredentialById(id: String): Route = - onZioSuccess(ZIO.unit) { _ => deleteCredentialById204 } - - /** Code: 200, Message: Successful response, instance of Verifiable Credential is returned, DataType: W3CCredential - * Code: 404, Message: Schema is not found by id - */ - def getCredentialById(id: String)(implicit - toEntityMarshallerW3CCredential: ToEntityMarshaller[W3CCredential] - ): Route = - onZioSuccess(ZIO.unit) { _ => getCredentialById200(mockW3Credential) } - - /** Code: 200, Message: Paginated response of the verifiable credentials objects, DataType: W3CCredentialsPaginated - */ - def getCredentialsByBatchId(batchId: String, offset: Option[Int], limit: Option[Int])(implicit - toEntityMarshallerW3CCredentialsPaginated: ToEntityMarshaller[W3CCredentialsPaginated] - ): Route = - onZioSuccess(ZIO.unit) { _ => - getCredentialsByBatchId200(mockW3CCredentialsPaginated) - } - - /** Code: 200, Message: Returns the set of actions performed on the issuance-batch, DataType: - * Seq[W3CIssuanceBatchAction] - */ - def getIssuanceBatchActions(batchId: String)(implicit - toEntityMarshallerW3CIssuanceBatchActionarray: ToEntityMarshaller[Seq[W3CIssuanceBatchAction]] - ): Route = - onZioSuccess(ZIO.unit) { _ => getIssuanceBatchActions200(Seq(mockW3CIssuanceBatchAction)) } - - /** Code: 200, Message: Returns the paginated list of issuance-batch objects, DataType: W3CIssuanceBatchPaginated - */ - def getIssuanceBatches(limit: Option[Int], offset: Option[Int])(implicit - toEntityMarshallerW3CIssuanceBatchPaginated: ToEntityMarshaller[W3CIssuanceBatchPaginated] - ): Route = - onZioSuccess(ZIO.unit) { _ => - getIssuanceBatches200(mockW3CIssuanceBatchPaginated) - } - - /** Code: 200, Message: Returns the set of actions performed on the issuance-batch, DataType: - * Seq[W3CIssuanceBatchAction] - */ - def submitIssuanceBatchActions(batchId: String, w3CIssuanceBatchAction: Seq[W3CIssuanceBatchAction])(implicit - toEntityMarshallerW3CIssuanceBatchActionarray: ToEntityMarshaller[Seq[W3CIssuanceBatchAction]] - ): Route = - onZioSuccess(ZIO.unit) { _ => - submitIssuanceBatchActions200(Seq(mockW3CIssuanceBatchAction)) - } - - /** Code: 200, Message: Credential was updated successfully, DataType: W3CCredential - */ - def updateCredentialById(id: String, w3CCredentialInput: W3CCredentialInput)(implicit - toEntityMarshallerW3CCredential: ToEntityMarshaller[W3CCredential] - ): Route = - onZioSuccess(ZIO.unit) { _ => - updateCredentialById200(mockW3Credential) - } -} - -object IssueCredentialsApiServiceImpl { - val layer: URLayer[CredentialService, IssueCredentialsApiService] = ZLayer.fromZIO { - for { - rt <- ZIO.runtime[Any] - svc <- ZIO.service[CredentialService] - } yield IssueCredentialsApiServiceImpl(svc)(using rt) - } -} diff --git a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/service/IssueCredentialsProtocolApiServiceImpl.scala b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/service/IssueCredentialsProtocolApiServiceImpl.scala index 7d900587d2..8802689ad9 100644 --- a/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/service/IssueCredentialsProtocolApiServiceImpl.scala +++ b/prism-agent/service/server/src/main/scala/io/iohk/atala/agent/server/http/service/IssueCredentialsProtocolApiServiceImpl.scala @@ -3,7 +3,6 @@ package io.iohk.atala.agent.server.http.service import akka.http.scaladsl.server.Directives.* import akka.http.scaladsl.marshalling.ToEntityMarshaller import akka.http.scaladsl.server.Route -import io.iohk.atala.agent.openapi.api.IssueCredentialsApi import io.iohk.atala.agent.openapi.api.IssueCredentialsProtocolApiService import zio.* import io.iohk.atala.pollux.core.service.CredentialService