diff --git a/apps/gateway/src/app/managers/attestation.controller.ts b/apps/gateway/src/app/managers/attestation.controller.ts index 88140a189570219c7d9f3fa5af5614d19f701ee5..536fc82cb7564ea2e17f888c4dcf3bd3ddc9d6b8 100644 --- a/apps/gateway/src/app/managers/attestation.controller.ts +++ b/apps/gateway/src/app/managers/attestation.controller.ts @@ -1,12 +1,4 @@ -import { - BadRequestException, - Body, - Controller, - Get, - Param, - Post, - UseFilters, -} from "@nestjs/common"; +import { Body, Controller, Get, Param, Post, UseFilters } from "@nestjs/common"; import { AllExceptionsHandler } from "../exception.handler"; import { AttestationManagerClient } from "@ocm-engine/clients"; import { diff --git a/apps/gateway/src/app/managers/proof.controller.ts b/apps/gateway/src/app/managers/proof.controller.ts index 8b5b1347f4ee5330ffb72ecded4789dc31b5a2a2..86e8a2999b23b7709918fdcd98719d1b894b87f6 100644 --- a/apps/gateway/src/app/managers/proof.controller.ts +++ b/apps/gateway/src/app/managers/proof.controller.ts @@ -1,18 +1,14 @@ -import { - BadRequestException, - Body, - Controller, - Get, - Param, - Post, - UseFilters, -} from "@nestjs/common"; +import { Body, Controller, Get, Param, Post, UseFilters } from "@nestjs/common"; import { AcceptProofRequestDto, + DeclineProofRequestDto, GatewayAcceptedResponseDto, + GetProofRequestDto, GetSchemaRequestDto, IssueProofRequestDto, PROOF_ACCEPT, + PROOF_DECLINE, + PROOF_GET, PROOF_ISSUE, PROOF_LIST, } from "@ocm-engine/dtos"; @@ -76,6 +72,55 @@ export class ProofController { }); } + @Get("/credentials/proof/:proof_record_id") + @ApiResponse({ + status: 200, + description: + "Request is accepted for execution, the response id will match the event id received from the web socket", + type: GatewayAcceptedResponseDto, + }) + @ApiInternalServerErrorResponse({ + description: + "Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.", + content: { + "application/json": { + schema: { + type: "object", + properties: { + statusCode: { + type: "number", + example: 500, + }, + + message: { + type: "string", + example: "connect ECONNREFUSED 0.0.0.0.0:1919", + }, + }, + }, + }, + }, + }) + @ApiOperation({ + summary: "Get a single proof record by providing proof record id.", + description: + "Method get proof by id. Status - request-receive. The id of the response will be matched when you receive event from the websocket", + tags: ["Credentials Proof"], + }) + getProofById(@Param("proof_record_id") proofRecordId: string) { + const data = new GetProofRequestDto(); + data.proofRecordId = proofRecordId; + + return this.pmClient.sendPayload<GetProofRequestDto>({ + pattern: "proofs", + payload: { + source: "/credentials/proof/:proof_record_id", + data, + type: PROOF_GET, + }, + }); + } + @Post("/credentials/proof/issue") @ApiResponse({ status: 201, @@ -150,7 +195,7 @@ export class ProofController { }); } - @Post(`/credentials/proof/:proof_record_id/accept`) + @Post(`/credentials/proof/accept`) @ApiResponse({ status: 201, description: @@ -185,16 +230,62 @@ export class ProofController { "Method accept credential proof. The id of the response will be matched when you receive event from the websocket", tags: ["Credentials Proof"], }) - acceptProof(@Param("proof_record_id") proofRecordId: string) { - const data = new AcceptProofRequestDto(); + acceptProof(@Body() acceptProofRequestDto: AcceptProofRequestDto) { + return this.pmClient.sendPayload<AcceptProofRequestDto>({ + pattern: "proofs", + payload: { + source: "/credentials/proofs/accept", + data: acceptProofRequestDto, + type: PROOF_ACCEPT, + }, + }); + } + + @Post("/credentials/proof/:proof_record_id/decline") + @ApiResponse({ + status: 200, + description: + "Request is accepted for execution, the response id will match the event id received from the web socket", + type: GatewayAcceptedResponseDto, + }) + @ApiInternalServerErrorResponse({ + description: + "Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.", + content: { + "application/json": { + schema: { + type: "object", + properties: { + statusCode: { + type: "number", + example: 500, + }, + + message: { + type: "string", + example: "connect ECONNREFUSED 0.0.0.0.0:1919", + }, + }, + }, + }, + }, + }) + @ApiOperation({ + summary: "Decline a proof request.", + description: + "Method to decline a proof request by id. Status - request-receive. The id of the response will be matched when you receive event from the websocket", + tags: ["Credentials Proof"], + }) + declineProofRequest(@Param("proof_record_id") proofRecordId: string) { + const data = new DeclineProofRequestDto(); data.proofRecordId = proofRecordId; - return this.pmClient.sendPayload<AcceptProofRequestDto>({ + return this.pmClient.sendPayload<DeclineProofRequestDto>({ pattern: "proofs", payload: { - source: "/credentials/proofs/:id/accept", + source: "/credentials/proof/:proof_record_id/decline", data, - type: PROOF_ACCEPT, + type: PROOF_DECLINE, }, }); } diff --git a/apps/proof-manager/src/app/app.controller.ts b/apps/proof-manager/src/app/app.controller.ts index b7e41ea0dda88da0b3225d4bdacb1ba6b9af0f2c..8f80bb48ed6abd241e156069437b38519f8e79a9 100644 --- a/apps/proof-manager/src/app/app.controller.ts +++ b/apps/proof-manager/src/app/app.controller.ts @@ -3,6 +3,7 @@ import { Body, Controller, Logger } from "@nestjs/common"; import { ProducerService } from "@ocm-engine/nats"; import { MessagePattern, RpcException } from "@nestjs/microservices"; import { + AcceptProofRequestDto, CloudEventDto, GatewayAcceptedResponseDto, makeEvent, @@ -19,7 +20,7 @@ export class AppController { async create( @Body() payload: { - data: null; + data: null | AcceptProofRequestDto; type: ProofEvent; source: string; }, diff --git a/gateway-swagger.json b/gateway-swagger.json index 0da4211542ced768ce3d3628b3b896e7011415af..9455a2b3d686feb26229f0a60333303da6c4a592 100644 --- a/gateway-swagger.json +++ b/gateway-swagger.json @@ -1 +1 @@ -{"openapi":"3.0.0","paths":{"/api/v1/invitations":{"post":{"operationId":"ConnectionController_createInvitation","summary":"Create invitation for connection","description":"Method will create invitation url. The id of the response will be matched when you receive event from the websocket","tags":["Connections"],"parameters":[],"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to connection manager. This error shows that connection manager could not convert request to event or connection manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:4312"}}}}}}}}},"/api/v1/invitations/accept":{"post":{"operationId":"ConnectionController_acceptInvitation","summary":"Accept invitation for connection","description":"Method will accept the invitation and will return connection thought the websocket. The id of the response will be matched when you receive event from the websocket","tags":["Connections"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvitationResponseDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["invitationUrl must be a string","invitationUrl should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to connection manager. This error shows that connection manager could not convert request to event or connection manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:4312"}}}}}}}}},"/api/v1/connections":{"get":{"operationId":"ConnectionController_list","summary":"List all connections","description":"The id of the response will be matched when you receive event from the websocket","tags":["Connections"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to connection manager. This error shows that connection manager could not convert request to event or connection manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:4312"}}}}}}}}},"/api/v1/connections/{id}":{"get":{"operationId":"ConnectionController_getById","summary":"Get connection by id","description":"The method will search for connection id, if not found null will be returned. The id of the response will be matched when you receive event from the websocket","tags":["Connections"],"parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to connection manager. This error shows that connection manager could not convert request to event or connection manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:4312"}}}}}}}}},"/api/v1/schemas":{"post":{"operationId":"AttestationController_createSchema","summary":"Create schema","description":"Method will create schema. The id of the response will be matched when you receive event from the websocket","tags":["Schema"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSchemaRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["name must be a string","name should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}},"get":{"operationId":"AttestationController_listSchema","summary":"List all schemas","description":"Method will fetch all schemas. The id of the response will be matched when you receive event from the websocket","tags":["Schema"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/schemas-by-id":{"post":{"operationId":"AttestationController_getSchemaById","summary":"Get schema by id","description":"Method will fetch specific schema or return null. The id of the response will be matched when you receive event from the websocket","tags":["Schema"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSchemaRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["schemaId must be a string","schemaId should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/definition":{"post":{"operationId":"AttestationController_createCredentialDefinition","summary":"Create credential definition","description":"Method create credential definition. The id of the response will be matched when you receive event from the websocket","tags":["Credentials"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCredentialDefinitionRequsetDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["schemaId must be a string","schemaId should not be empty","tag must be a string","tag should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/issue":{"post":{"operationId":"AttestationController_issueCredential","summary":"Issue credential","description":"Method issue credential, it will create an offer and send it to specified receiver (connectionId). The id of the response will be matched when you receive event from the websocket","tags":["Credentials"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueCredentialRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["connectionId must be a string","connectionId should not be empty","credentialDefinitionId must be a string","credentialDefinitionId should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials":{"get":{"operationId":"AttestationController_credentials","summary":"List all credential","description":"Method list credential definition no filters applied. The id of the response will be matched when you receive event from the websocket","tags":["Credentials"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/offers":{"get":{"operationId":"AttestationController_getCredentialOffers","summary":"List unaccepted credential offers","description":"Method list offers that are received, but not accepted. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Offers"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/offers/{credential_record_id}/accept":{"post":{"operationId":"AttestationController_acceptCredential","summary":"Accept credential offers","description":"Method list accept credential offer. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Offers"],"parameters":[{"name":"credential_record_id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"201":{"description":""},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/messages":{"post":{"operationId":"AttestationController_sendMeesage","summary":"Send basic message","description":"Method will send basic message to a connection. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Offers"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MakeBasicMessageRequestDto"}}}},"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"201":{"description":""},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["connectionId must be a string","connectionId should not be empty","message must be a string","message should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/proof":{"get":{"operationId":"ProofController_proofs","summary":"List received unaccepted proofs","description":"Method list all received unaccepted proofs. Status - request-receive. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Proof"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1919"}}}}}}}}},"/api/v1/credentials/proof/issue":{"post":{"operationId":"ProofController_issueProof","summary":"Issue proof for credential","description":"Method will issue proof. If connection id is not passed, the proof will be OOB. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Proof"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueProofRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["attributes must contain at least 1 elements","attributes must be an array"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1919"}}}}}}}}},"/api/v1/credentials/proof/{proof_record_id}/accept":{"post":{"operationId":"ProofController_acceptProof","summary":"Accept credential proof","description":"Method accept credential proof. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Proof"],"parameters":[{"name":"proof_record_id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1919"}}}}}}}}}},"info":{"title":"OCM Gateway","description":"OCM ENGINE GATEWAY API","version":"1.0","contact":{}},"tags":[],"servers":[{"url":"http://0.0.0.0:8081"}],"components":{"schemas":{"CloudEventDto":{"type":"object","properties":{}},"GatewayAcceptedResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"80633e6d-c606-4539-a3df-287fedd09253"}},"required":["id"]},"CreateInvitationResponseDto":{"type":"object","properties":{"invitationUrl":{"type":"string","description":"A list of user's roles","example":"http://0.0.0.0:8001?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiIzYWExNGIzNC04YTk5LTQxY2UtYTY3NC1jODUxYmVhMTIxMWEiLCJsYWJlbCI6IkRFeGNWYXNkX0FHRU5UXzQ1IiwiYWNjZXB0IjpbImRpZGNvbW0vYWlwMSIsImRpZGNvbW0vYWlwMjtlbnY9cmZjMTkiXSwiaGFuZHNoYWtlX3Byb3RvY29scyI6WyJodHRwczovL2RpZGNvbW0ub3JnL2RpZGV4Y2hhbmdlLzEuMCIsImh0dHBzOi8vZGlkY29tbS5vcmcvY29ubmVjdGlvbnMvMS4wIl0sInNlcnZpY2VzIjpbeyJpZCI6IiNpbmxpbmUtMCIsInNlcnZpY2VFbmRwb2ludCI6Imh0dHA6Ly8wLjAuMC4wOjgwMDEiLCJ0eXBlIjoiZGlkLWNvbW11bmljYXRpb24iLCJyZWNpcGllbnRLZXlzIjpbImRpZDprZXk6ejZNa3VFcHllc1pNa3k0a1BpQzhEOEplZERlcm55YTFuaTREMUF3ZmdnWWt6YmR4Il0sInJvdXRpbmdLZXlzIjpbXX1dfQ"}},"required":["invitationUrl"]},"CreateSchemaRequestDto":{"type":"object","properties":{"name":{"type":"string","example":"my test schema"},"attributes":{"example":["first_name, last_name"],"type":"array","items":{"type":"string"}},"version":{"type":"string","example":"1.0.2","pattern":"/^(\\d+\\.)?(\\d+\\.)?(\\*|\\d+)$/"}},"required":["name","attributes","version"]},"GetSchemaRequestDto":{"type":"object","properties":{"schemaId":{"type":"string","example":"did:indy:LEDNGER:SXM76gQwRnjkgoz2oBnGjd/anoncreds/v0/SCHEMA/test schema/1.0.2"}},"required":["schemaId"]},"CreateCredentialDefinitionRequsetDto":{"type":"object","properties":{"schemaId":{"type":"string"},"tag":{"type":"string"}},"required":["schemaId","tag"]},"IssueCredentialAttributes":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}},"required":["name","value"]},"IssueCredentialRequestDto":{"type":"object","properties":{"connectionId":{"type":"string","example":"6464b521-005a-4379-91e0-a3692b31cafd"},"credentialDefinitionId":{"type":"string"},"attributes":{"type":"array","items":{"$ref":"#/components/schemas/IssueCredentialAttributes"}}},"required":["connectionId","credentialDefinitionId","attributes"]},"MakeBasicMessageRequestDto":{"type":"object","properties":{"connectionId":{"type":"string","example":"6464b521-005a-4379-91e0-a3692b31cafd"},"message":{"type":"string","example":"hello world"}},"required":["connectionId","message"]},"IssueProofAttribute":{"type":"object","properties":{"attributeName":{"type":"string"},"credentialDefinitionId":{"type":"string"},"schemaId":{"type":"string"}},"required":["attributeName","credentialDefinitionId","schemaId"]},"IssueProofRequestDto":{"type":"object","properties":{"connectionId":{"type":"string","example":"6464b521-005a-4379-91e0-a3692b31cafd"},"attributes":{"type":"array","items":{"$ref":"#/components/schemas/IssueProofAttribute"}}},"required":["attributes"]}}}} \ No newline at end of file +{"openapi":"3.0.0","paths":{"/api/v1/invitations":{"post":{"operationId":"ConnectionController_createInvitation","summary":"Create invitation for connection","description":"Method will create invitation url. The id of the response will be matched when you receive event from the websocket","tags":["Connections"],"parameters":[],"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to connection manager. This error shows that connection manager could not convert request to event or connection manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:4312"}}}}}}}}},"/api/v1/invitations/accept":{"post":{"operationId":"ConnectionController_acceptInvitation","summary":"Accept invitation for connection","description":"Method will accept the invitation and will return connection thought the websocket. The id of the response will be matched when you receive event from the websocket","tags":["Connections"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvitationResponseDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["invitationUrl must be a string","invitationUrl should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to connection manager. This error shows that connection manager could not convert request to event or connection manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:4312"}}}}}}}}},"/api/v1/connections":{"get":{"operationId":"ConnectionController_list","summary":"List all connections","description":"The id of the response will be matched when you receive event from the websocket","tags":["Connections"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to connection manager. This error shows that connection manager could not convert request to event or connection manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:4312"}}}}}}}}},"/api/v1/connections/{id}":{"get":{"operationId":"ConnectionController_getById","summary":"Get connection by id","description":"The method will search for connection id, if not found null will be returned. The id of the response will be matched when you receive event from the websocket","tags":["Connections"],"parameters":[{"name":"id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to connection manager. This error shows that connection manager could not convert request to event or connection manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:4312"}}}}}}}}},"/api/v1/schemas":{"post":{"operationId":"AttestationController_createSchema","summary":"Create schema","description":"Method will create schema. The id of the response will be matched when you receive event from the websocket","tags":["Schema"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSchemaRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["name must be a string","name should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}},"get":{"operationId":"AttestationController_listSchema","summary":"List all schemas","description":"Method will fetch all schemas. The id of the response will be matched when you receive event from the websocket","tags":["Schema"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/schemas-by-id":{"post":{"operationId":"AttestationController_getSchemaById","summary":"Get schema by id","description":"Method will fetch specific schema or return null. The id of the response will be matched when you receive event from the websocket","tags":["Schema"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSchemaRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["schemaId must be a string","schemaId should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/definition":{"post":{"operationId":"AttestationController_createCredentialDefinition","summary":"Create credential definition","description":"Method create credential definition. The id of the response will be matched when you receive event from the websocket","tags":["Credentials"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCredentialDefinitionRequsetDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["schemaId must be a string","schemaId should not be empty","tag must be a string","tag should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/issue":{"post":{"operationId":"AttestationController_issueCredential","summary":"Issue credential","description":"Method issue credential, it will create an offer and send it to specified receiver (connectionId). The id of the response will be matched when you receive event from the websocket","tags":["Credentials"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueCredentialRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["connectionId must be a string","connectionId should not be empty","credentialDefinitionId must be a string","credentialDefinitionId should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials":{"get":{"operationId":"AttestationController_credentials","summary":"List all credential","description":"Method list credential definition no filters applied. The id of the response will be matched when you receive event from the websocket","tags":["Credentials"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/offers":{"get":{"operationId":"AttestationController_getCredentialOffers","summary":"List unaccepted credential offers","description":"Method list offers that are received, but not accepted. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Offers"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/offers/{credential_record_id}/accept":{"post":{"operationId":"AttestationController_acceptCredential","summary":"Accept credential offers","description":"Method list accept credential offer. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Offers"],"parameters":[{"name":"credential_record_id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"201":{"description":""},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/messages":{"post":{"operationId":"AttestationController_sendMeesage","summary":"Send basic message","description":"Method will send basic message to a connection. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Offers"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MakeBasicMessageRequestDto"}}}},"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"201":{"description":""},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["connectionId must be a string","connectionId should not be empty","message must be a string","message should not be empty"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to attestation manager. This error shows that attestation manager could not convert request to event or attestation manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1234"}}}}}}}}},"/api/v1/credentials/proof":{"get":{"operationId":"ProofController_proofs","summary":"List received unaccepted proofs","description":"Method list all received unaccepted proofs. Status - request-receive. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Proof"],"parameters":[],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1919"}}}}}}}}},"/api/v1/credentials/proof/{proof_record_id}":{"get":{"operationId":"ProofController_getProofById","summary":"Get a single proof record by providing proof record id.","description":"Method get proof by id. Status - request-receive. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Proof"],"parameters":[{"name":"proof_record_id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1919"}}}}}}}}},"/api/v1/credentials/proof/issue":{"post":{"operationId":"ProofController_issueProof","summary":"Issue proof for credential","description":"Method will issue proof. If connection id is not passed, the proof will be OOB. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Proof"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueProofRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":400},"message":{"type":"array","example":["attributes must contain at least 1 elements","attributes must be an array"]},"error":{"type":"string","example":"Bad Request"}}}}}},"500":{"description":"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1919"}}}}}}}}},"/api/v1/credentials/proof/accept":{"post":{"operationId":"ProofController_acceptProof","summary":"Accept credential proof","description":"Method accept credential proof. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Proof"],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptProofRequestDto"}}}},"responses":{"201":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"500":{"description":"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1919"}}}}}}}}},"/api/v1/credentials/proof/{proof_record_id}/decline":{"post":{"operationId":"ProofController_declineProofRequest","summary":"Decline a proof request.","description":"Method to decline a proof request by id. Status - request-receive. The id of the response will be matched when you receive event from the websocket","tags":["Credentials Proof"],"parameters":[{"name":"proof_record_id","required":true,"in":"path","schema":{"type":"string"}}],"responses":{"200":{"description":"Request is accepted for execution, the response id will match the event id received from the web socket","content":{"application/json":{"schema":{"$ref":"#/components/schemas/GatewayAcceptedResponseDto"}}}},"201":{"description":""},"500":{"description":"Error in sending data to proof manager. This error shows that proof manager could not convert request to event or proof manager could not send the event to the broker.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"number","example":500},"message":{"type":"string","example":"connect ECONNREFUSED 0.0.0.0.0:1919"}}}}}}}}}},"info":{"title":"OCM Gateway","description":"OCM ENGINE GATEWAY API","version":"1.0","contact":{}},"tags":[],"servers":[{"url":"http://undefined:NaN"}],"components":{"schemas":{"CloudEventDto":{"type":"object","properties":{}},"GatewayAcceptedResponseDto":{"type":"object","properties":{"id":{"type":"string","example":"80633e6d-c606-4539-a3df-287fedd09253"}},"required":["id"]},"CreateInvitationResponseDto":{"type":"object","properties":{"invitationUrl":{"type":"string","description":"A list of user's roles","example":"http://0.0.0.0:8001?oob=eyJAdHlwZSI6Imh0dHBzOi8vZGlkY29tbS5vcmcvb3V0LW9mLWJhbmQvMS4xL2ludml0YXRpb24iLCJAaWQiOiIzYWExNGIzNC04YTk5LTQxY2UtYTY3NC1jODUxYmVhMTIxMWEiLCJsYWJlbCI6IkRFeGNWYXNkX0FHRU5UXzQ1IiwiYWNjZXB0IjpbImRpZGNvbW0vYWlwMSIsImRpZGNvbW0vYWlwMjtlbnY9cmZjMTkiXSwiaGFuZHNoYWtlX3Byb3RvY29scyI6WyJodHRwczovL2RpZGNvbW0ub3JnL2RpZGV4Y2hhbmdlLzEuMCIsImh0dHBzOi8vZGlkY29tbS5vcmcvY29ubmVjdGlvbnMvMS4wIl0sInNlcnZpY2VzIjpbeyJpZCI6IiNpbmxpbmUtMCIsInNlcnZpY2VFbmRwb2ludCI6Imh0dHA6Ly8wLjAuMC4wOjgwMDEiLCJ0eXBlIjoiZGlkLWNvbW11bmljYXRpb24iLCJyZWNpcGllbnRLZXlzIjpbImRpZDprZXk6ejZNa3VFcHllc1pNa3k0a1BpQzhEOEplZERlcm55YTFuaTREMUF3ZmdnWWt6YmR4Il0sInJvdXRpbmdLZXlzIjpbXX1dfQ"}},"required":["invitationUrl"]},"CreateSchemaRequestDto":{"type":"object","properties":{"name":{"type":"string","example":"my test schema"},"attributes":{"example":["first_name, last_name"],"type":"array","items":{"type":"string"}},"version":{"type":"string","example":"1.0.2","pattern":"/^(\\d+\\.)?(\\d+\\.)?(\\*|\\d+)$/"}},"required":["name","attributes","version"]},"GetSchemaRequestDto":{"type":"object","properties":{"schemaId":{"type":"string","example":"did:indy:LEDNGER:SXM76gQwRnjkgoz2oBnGjd/anoncreds/v0/SCHEMA/test schema/1.0.2"}},"required":["schemaId"]},"CreateCredentialDefinitionRequsetDto":{"type":"object","properties":{"schemaId":{"type":"string"},"tag":{"type":"string"}},"required":["schemaId","tag"]},"IssueCredentialAttributes":{"type":"object","properties":{"name":{"type":"string"},"value":{"type":"string"}},"required":["name","value"]},"IssueCredentialRequestDto":{"type":"object","properties":{"connectionId":{"type":"string","example":"6464b521-005a-4379-91e0-a3692b31cafd"},"credentialDefinitionId":{"type":"string"},"attributes":{"type":"array","items":{"$ref":"#/components/schemas/IssueCredentialAttributes"}}},"required":["connectionId","credentialDefinitionId","attributes"]},"MakeBasicMessageRequestDto":{"type":"object","properties":{"connectionId":{"type":"string","example":"6464b521-005a-4379-91e0-a3692b31cafd"},"message":{"type":"string","example":"hello world"}},"required":["connectionId","message"]},"IssueProofAttribute":{"type":"object","properties":{"attributeName":{"type":"string"},"credentialDefinitionId":{"type":"string"},"schemaId":{"type":"string"}},"required":["attributeName","credentialDefinitionId","schemaId"]},"IssueProofRequestDto":{"type":"object","properties":{"connectionId":{"type":"string","example":"6464b521-005a-4379-91e0-a3692b31cafd"},"attributes":{"type":"array","items":{"$ref":"#/components/schemas/IssueProofAttribute"}}},"required":["attributes"]},"AcceptProofRequestDto":{"type":"object","properties":{"proofRecordId":{"type":"string"},"proofUrl":{"type":"string"}},"required":["proofRecordId","proofUrl"]}}}} \ No newline at end of file diff --git a/libs/askar/src/agent.utils.ts b/libs/askar/src/agent.utils.ts index 30de9c76e6f7304812caf2060d5e391e770dc9ad..9bca784c0838eac47a45b12ac1ca83e3b0f23673 100644 --- a/libs/askar/src/agent.utils.ts +++ b/libs/askar/src/agent.utils.ts @@ -2,15 +2,18 @@ import { Agent, AutoAcceptCredential, AutoAcceptProof, + BaseEvent, ConnectionsModule, ConnectionStateChangedEvent, CredentialsModule, DidExchangeRole, DidsModule, + EncryptedMessage, Key, KeyDidResolver, KeyType, PeerDidResolver, + ProofEventTypes, ProofsModule, ProofState, ProofStateChangedEvent, @@ -40,6 +43,25 @@ import { ariesAskar } from "@hyperledger/aries-askar-nodejs"; import { Key as C, KeyAlgs } from "@hyperledger/aries-askar-shared"; import { IConfAgent } from "@ocm-engine/config"; import axios from "axios"; +import { + catchError, + filter, + lastValueFrom, + map, + Observable, + ReplaySubject, + Subject, + take, + timeout, +} from "rxjs"; +import { SubjectInboundTransport } from "./askar/transports/agent.subject.inbound.transport"; +import { SubjectOutboundTransport } from "./askar/transports/agent.subject.outbound.transport"; + +export type EventReplaySubject = ReplaySubject<BaseEvent>; +export type SubjectMessage = { + message: EncryptedMessage; + replySubject?: Subject<SubjectMessage>; +}; export const importDidsToWallet = async ( agent: Agent, @@ -147,6 +169,36 @@ export const getAskarAnonCredsIndyModules = (networks: any) => { } as const; }; +export const setupEventReplaySubjects = ( + agents: Agent[], + eventTypes: string[], +): ReplaySubject<BaseEvent>[] => { + const replaySubjects: EventReplaySubject[] = []; + + for (const agent of agents) { + const replaySubject = new ReplaySubject<BaseEvent>(); + + for (const eventType of eventTypes) { + agent.events.observable(eventType).subscribe(replaySubject); + } + + replaySubjects.push(replaySubject); + } + + return replaySubjects; +}; + +export const setupSubjectTransports = (agents: Agent[]) => { + const subjectMap: Record<string, Subject<SubjectMessage>> = {}; + + for (const agent of agents) { + const messages = new Subject<SubjectMessage>(); + subjectMap[agent.config.endpoints[0]] = messages; + agent.registerInboundTransport(new SubjectInboundTransport(messages)); + agent.registerOutboundTransport(new SubjectOutboundTransport(subjectMap)); + } +}; + export const svdxProofStateChangeHandler = async ( ev: ProofStateChangedEvent, agent: Agent, @@ -272,3 +324,64 @@ export const svdxConnectionStateChangeHandler = async ( console.log("failed to issue credential"); } }; + +export const isProofStateChangedEvent = ( + e: BaseEvent, +): e is ProofStateChangedEvent => e.type === ProofEventTypes.ProofStateChanged; + +export const waitForProofExchangeRecordSubject = ( + subject: ReplaySubject<BaseEvent> | Observable<BaseEvent>, + { + threadId, + parentThreadId, + state, + previousState, + timeoutMs = 10000, + count = 1, + }: { + threadId?: string; + parentThreadId?: string; + state?: ProofState; + previousState?: ProofState | null; + timeoutMs?: number; + count?: number; + }, +) => { + const observable: Observable<BaseEvent> = + subject instanceof ReplaySubject ? subject.asObservable() : subject; + return lastValueFrom( + observable.pipe( + filter(isProofStateChangedEvent), + filter( + (e) => + previousState === undefined || + e.payload.previousState === previousState, + ), + filter( + (e) => + threadId === undefined || e.payload.proofRecord.threadId === threadId, + ), + filter( + (e) => + parentThreadId === undefined || + e.payload.proofRecord.parentThreadId === parentThreadId, + ), + filter( + (e) => state === undefined || e.payload.proofRecord.state === state, + ), + timeout(timeoutMs), + catchError(() => { + throw new Error( + `ProofStateChangedEvent event not emitted within specified timeout: ${timeoutMs} + previousState: ${previousState}, + threadId: ${threadId}, + parentThreadId: ${parentThreadId}, + state: ${state} + }`, + ); + }), + take(count), + map((e) => e.payload.proofRecord), + ), + ); +}; diff --git a/libs/askar/src/askar-nats/event.handler.service.ts b/libs/askar/src/askar-nats/event.handler.service.ts index 0561068736ff1ec96d3331c210a49683aaa24096..b1a634a6b3b166e1bcb849a4e5d0e6c53a0f87f4 100644 --- a/libs/askar/src/askar-nats/event.handler.service.ts +++ b/libs/askar/src/askar-nats/event.handler.service.ts @@ -21,13 +21,17 @@ import { IssueCredentialRequestDto, IssueProofRequestDto, MakeBasicMessageRequestDto, + DeclineProofRequestDto, MESSAGE_MAKE, PROOF_ACCEPT, PROOF_ISSUE, PROOF_LIST, + PROOF_GET, SCHEMA_CREATE, SCHEMA_GET, SCHEMA_LIST, + GetProofRequestDto, + PROOF_DECLINE, } from "@ocm-engine/dtos"; import asyncRetry from "async-retry"; @@ -108,9 +112,22 @@ export class EventHandlerService { data = await this.agentService.proofs(); break; + case PROOF_GET: + dto = event.data as GetProofRequestDto; + data = await this.agentService.getProofById(dto.proofRecordId); + break; + case PROOF_ACCEPT: - dto = event.data as AcceptProofRequestDto; - data = await this.agentService.acceptProof(dto.proofRecordId); + data = await this.agentService.acceptProof( + event.data as AcceptProofRequestDto, + ); + break; + + case PROOF_DECLINE: + dto = event.data as DeclineProofRequestDto; + data = await this.agentService.declineProofRequest( + dto.proofRecordId, + ); break; case MESSAGE_MAKE: diff --git a/libs/askar/src/askar-rest/rest.controller.ts b/libs/askar/src/askar-rest/rest.controller.ts index 53c82aa8e4766e73ed88f97bd58377d6f4800d24..8227d7dd6ab466a4ce94aa370eb68f31f7c8a1b5 100644 --- a/libs/askar/src/askar-rest/rest.controller.ts +++ b/libs/askar/src/askar-rest/rest.controller.ts @@ -8,6 +8,8 @@ import { IssueProofRequestDto, CreateSchemaRequestDto, MakeBasicMessageRequestDto, + AcceptProofRequestDto, + GetProofRequestDto, } from "@ocm-engine/dtos"; import { AllExceptionsHandler } from "./exception.handler"; @@ -77,9 +79,19 @@ export class RestController { return this.agentService.issueProof(issueProofDto); } - @Post(`/credential/proof/:proof_record_id/accept`) - acceptProof(@Param("proof_record_id") proofRecordId: string) { - return this.agentService.acceptProof(proofRecordId); + @Get("credential/proof/:proof_record_id") + getProof(@Param("proof_record_id") data: GetProofRequestDto) { + return this.agentService.getProofById(data.proofRecordId); + } + + @Post(`/credential/proof/accept`) + acceptProof(@Body() acceptProofRequestDto: AcceptProofRequestDto) { + return this.agentService.acceptProof(acceptProofRequestDto); + } + + @Post(`/credential/proof/:proof_record_id/decline`) + declineProofRequest(@Param("proof_record_id") proofRecordId: string) { + return this.agentService.declineProofRequest(proofRecordId); } @Post("/resolve") @@ -88,7 +100,7 @@ export class RestController { } @Post("/messages") - async sendMeesage(@Body() message: MakeBasicMessageRequestDto) { + sendMeesage(@Body() message: MakeBasicMessageRequestDto) { return this.agentService.sendMessage(message); } } diff --git a/libs/askar/src/askar/agent.event.listener.servce.ts b/libs/askar/src/askar/agent-event-listener.service.ts similarity index 97% rename from libs/askar/src/askar/agent.event.listener.servce.ts rename to libs/askar/src/askar/agent-event-listener.service.ts index 08c4fec6be11ee782da60f2ba85f6e9dea9a0666..9cb3722871aefcae414e07427051dfe572d6fc69 100644 --- a/libs/askar/src/askar/agent.event.listener.servce.ts +++ b/libs/askar/src/askar/agent-event-listener.service.ts @@ -23,9 +23,9 @@ import { } from "../agent.utils"; @Injectable() -export class AgentEventListenerServce implements OnModuleInit { +export class AgentEventListenerService implements OnModuleInit { private agentConfig: IConfAgent | undefined; - private readonly logger: Logger = new Logger(AgentEventListenerServce.name); + private readonly logger: Logger = new Logger(AgentEventListenerService.name); constructor( private readonly gatewayClient: GatewayClient, diff --git a/libs/askar/src/askar/agent.service.ts b/libs/askar/src/askar/agent.service.ts index 7f95b64e4903789f93afeb894af29d5dc6223e2a..15ace71407fc3eae827b46e1bfcfebabcf9458d6 100644 --- a/libs/askar/src/askar/agent.service.ts +++ b/libs/askar/src/askar/agent.service.ts @@ -2,6 +2,7 @@ import { Injectable } from "@nestjs/common"; import { AskarService } from "./askar.service"; import { AcceptInvitationResponseDto, + AcceptProofRequestDto, ConnectionNotFoundError, CreateCredentialDefinitionRequsetDto, CreateCredentialDefinitionResponseDto, @@ -13,16 +14,21 @@ import { IssueCredentialResponseDto, IssueProofRequestDto, IssueProofResponseDto, + GetProofByIdResponseDto, MakeBasicMessageRequestDto, MakeBasicMessageResponseDto, SchemaNotCreatedError, + DeclineProofResponseDto, } from "@ocm-engine/dtos"; import { + AutoAcceptProof, CredentialState, - ProofExchangeRecord, + JsonEncoder, ProofState, } from "@aries-framework/core"; import { AnonCredsRequestedAttribute } from "@aries-framework/anoncreds"; +import { uuid } from "@aries-framework/core/build/utils/uuid"; +import { waitForProofExchangeRecordSubject } from "../agent.utils"; @Injectable() export class AgentService { @@ -228,11 +234,11 @@ export class AgentService { }; issueProof = async (issueProofDto: IssueProofRequestDto) => { - let exchangeRecord: ProofExchangeRecord; + console.log(JSON.stringify(issueProofDto, null, 2)); const requestedAttributes: Record<string, AnonCredsRequestedAttribute> = {}; for (const attr of issueProofDto.attributes) { - requestedAttributes[attr.attributeName] = { + requestedAttributes[uuid()] = { name: attr.attributeName, restrictions: [ { @@ -244,32 +250,45 @@ export class AgentService { } if (!issueProofDto.connectionId) { - const { proofRecord } = await this.askar.agent.proofs.createRequest({ - protocolVersion: "v2", - proofFormats: { - anoncreds: { - name: "proof-request", - version: "1.0", - requested_attributes: requestedAttributes, + console.log("connection Id not detected, creating oob proof"); + const { proofRecord, message } = + await this.askar.agent.proofs.createRequest({ + protocolVersion: "v2", + proofFormats: { + anoncreds: { + name: "proof-request", + version: "1.0", + requested_attributes: requestedAttributes, + }, }, - }, - }); + autoAcceptProof: AutoAcceptProof.ContentApproved, + }); - exchangeRecord = proofRecord; - } else { - exchangeRecord = await this.askar.agent.proofs.requestProof({ - protocolVersion: "v2", - connectionId: issueProofDto.connectionId, - proofFormats: { - anoncreds: { - name: "proof-request", - version: "1.0", - requested_attributes: requestedAttributes, - }, - }, - }); + console.log({ proofRecord }); + const { invitationUrl } = + await this.askar.agent.oob.createLegacyConnectionlessInvitation({ + recordId: proofRecord.id, + message, + domain: this.askar.agentConfig.agentPeerAddress, + }); + + return { proofUrl: invitationUrl }; } + console.log(`${issueProofDto.connectionId} detected, issuing proof`); + + const exchangeRecord = await this.askar.agent.proofs.requestProof({ + protocolVersion: "v2", + connectionId: issueProofDto.connectionId, + proofFormats: { + anoncreds: { + name: "proof-request", + version: "1.0", + requested_attributes: requestedAttributes, + }, + }, + }); + const response = new IssueProofResponseDto(); response.proofId = exchangeRecord.id; response.connectionId = exchangeRecord.connectionId; @@ -300,25 +319,102 @@ export class AgentService { return response; }; - acceptProof = async (proofRecordId: string) => { + getProofById = async (proofRecordId: string) => { + const proofRecord = await this.askar.agent.proofs.findById(proofRecordId); + + if (!proofRecord) { + return proofRecord; + } + + const proofResponse = new GetProofByIdResponseDto(); + + proofResponse.proofId = proofRecord.id; + proofResponse.connectionId = proofRecord.connectionId; + proofResponse.state = proofRecord.state; + proofResponse.updatedAt = proofRecord.updatedAt; + proofResponse.createdAt = proofRecord.createdAt; + + return proofResponse; + }; + + acceptProof = async (acceptProofDto: AcceptProofRequestDto) => { + if (acceptProofDto.proofUrl) { + return this.acceptOobProof(acceptProofDto.proofUrl); + } + return this.acceptConnectionProof(acceptProofDto.proofId); + }; + + acceptOobProof = async (url: string) => { + const param = url.split("d_m=")[1]; + + const t = JsonEncoder.fromBase64(param); + + await this.askar.agent.receiveMessage(t); + + const record = await waitForProofExchangeRecordSubject(this.askar.agentR, { + state: ProofState.RequestReceived, + }); + + const requestedCredentials = + await this.askar.agent.proofs.selectCredentialsForRequest({ + proofRecordId: record.id, + }); + + const acceptedRecord = await this.askar.agent.proofs.acceptRequest({ + proofRecordId: record.id, + proofFormats: requestedCredentials.proofFormats, + }); + + const response = new IssueProofResponseDto(); + + response.proofId = acceptedRecord.id; + response.state = acceptedRecord.state; + response.updatedAt = acceptedRecord.updatedAt; + response.createdAt = acceptedRecord.createdAt; + + return acceptedRecord; + }; + + acceptConnectionProof = async (proofRecordId: string) => { + console.log(`accepting proof request for ${proofRecordId}`); const requestedCredentials = await this.askar.agent.proofs.selectCredentialsForRequest({ proofRecordId, }); + console.log(JSON.stringify(requestedCredentials, null, 2)); + const proof = await this.askar.agent.proofs.acceptRequest({ proofRecordId, proofFormats: requestedCredentials.proofFormats, }); - const t = new IssueProofResponseDto(); - t.proofId = proof.id; - t.connectionId = proof.connectionId; - t.state = proof.state; - t.updatedAt = proof.updatedAt; - t.createdAt = proof.createdAt; + console.log(JSON.stringify(proof, null, 2)); + + const response = new IssueProofResponseDto(); + response.proofId = proof.id; + response.connectionId = proof.connectionId; + response.state = proof.state; + response.updatedAt = proof.updatedAt; + response.createdAt = proof.createdAt; + + return response; + }; + + declineProofRequest = async (proofRecordId: string) => { + const resultFromDecline = await this.askar.agent.proofs.declineRequest({ + proofRecordId, + // sendProblemReport: false, // REVIEW: do we have a use case for this key? + }); + + const declineResponse = new DeclineProofResponseDto(); + declineResponse.proofId = resultFromDecline.id; + declineResponse.connectionId = resultFromDecline.connectionId; + declineResponse.state = resultFromDecline.state; + declineResponse.updatedAt = resultFromDecline.updatedAt; + declineResponse.createdAt = resultFromDecline.createdAt; - return t; + return declineResponse; }; resolve = async (did: string) => { diff --git a/libs/askar/src/askar/askar.module.ts b/libs/askar/src/askar/askar.module.ts index 05a8706a87d787f04c2509461d5db4e9463974e0..c2f542cef457dd735b3ff5514299703b737bf903 100644 --- a/libs/askar/src/askar/askar.module.ts +++ b/libs/askar/src/askar/askar.module.ts @@ -3,7 +3,7 @@ import { AskarService } from "./askar.service"; import { AgentService } from "./agent.service"; import { ConfigModule } from "@nestjs/config"; import { LedgersModule } from "@ocm-engine/ledgers"; -import { AgentEventListenerServce } from "./agent.event.listener.servce"; +import { AgentEventListenerService } from "./agent-event-listener.service"; import { GatewayClient } from "@ocm-engine/clients"; @Global() @@ -12,7 +12,7 @@ import { GatewayClient } from "@ocm-engine/clients"; providers: [ AgentService, AskarService, - AgentEventListenerServce, + AgentEventListenerService, GatewayClient, ], exports: [AgentService, AskarService], diff --git a/libs/askar/src/askar/askar.service.ts b/libs/askar/src/askar/askar.service.ts index e07eb52a9f77a1f1b57ff7e0df2acdeebf9ec5e8..27c5307f0866f3cd1b07980fcac62b63759a9c91 100644 --- a/libs/askar/src/askar/askar.service.ts +++ b/libs/askar/src/askar/askar.service.ts @@ -7,10 +7,12 @@ import { import { Agent, + BaseEvent, ConsoleLogger, HttpOutboundTransport, InitConfig, LogLevel, + ProofEventTypes, TypedArrayEncoder, WsOutboundTransport, } from "@aries-framework/core"; @@ -22,12 +24,16 @@ import { generateKey, getAskarAnonCredsIndyModules, importDidsToWallet, + setupEventReplaySubjects, + setupSubjectTransports, } from "../agent.utils"; import { IConfAgent } from "@ocm-engine/config"; +import { ReplaySubject } from "rxjs"; @Injectable() export class AskarService implements OnModuleInit, OnModuleDestroy { public agent: Agent<ReturnType<typeof getAskarAnonCredsIndyModules>>; + public agentR: ReplaySubject<BaseEvent>; public agentConfig: IConfAgent; private readonly logger: Logger = new Logger(AskarService.name); @@ -73,6 +79,14 @@ export class AskarService implements OnModuleInit, OnModuleDestroy { this.agent.registerOutboundTransport(new WsOutboundTransport()); this.agent.registerOutboundTransport(new HttpOutboundTransport()); + setupSubjectTransports([this.agent]); + + const [agentR] = setupEventReplaySubjects( + [this.agent], + [ProofEventTypes.ProofStateChanged], + ); + + this.agentR = agentR; this.logger.log("Agent setup completed"); } diff --git a/libs/askar/src/askar/transports/agent.subject.inbound.transport.ts b/libs/askar/src/askar/transports/agent.subject.inbound.transport.ts new file mode 100644 index 0000000000000000000000000000000000000000..1a78cda63b11033b8eb096daec3831d1fdfc264d --- /dev/null +++ b/libs/askar/src/askar/transports/agent.subject.inbound.transport.ts @@ -0,0 +1,80 @@ +import { + Agent, + AgentContext, + EncryptedMessage, + InboundTransport, + MessageReceiver, + TransportService, + TransportSession, +} from "@aries-framework/core"; +import { Subject, Subscription } from "rxjs"; +import { uuid } from "@aries-framework/core/build/utils/uuid"; +import { SubjectMessage } from "../../agent.utils"; + +class SubjectTransportSession implements TransportSession { + public id: string; + public readonly type = "subject"; + private replySubject: Subject<SubjectMessage>; + + public constructor(id: string, replySubject: Subject<SubjectMessage>) { + this.id = id; + this.replySubject = replySubject; + } + + public async send( + agentContext: AgentContext, + encryptedMessage: EncryptedMessage, + ): Promise<void> { + this.replySubject.next({ message: encryptedMessage }); + } + + public async close(): Promise<void> { + this.replySubject.complete(); + } +} + +export class SubjectInboundTransport implements InboundTransport { + public readonly ourSubject: Subject<SubjectMessage>; + private subscription?: Subscription; + + public constructor(ourSubject = new Subject<SubjectMessage>()) { + this.ourSubject = ourSubject; + } + + public async start(agent: Agent) { + this.subscribe(agent); + } + + public async stop() { + this.subscription?.unsubscribe(); + } + + private subscribe(agent: Agent) { + const logger = agent.config.logger; + const transportService = agent.dependencyManager.resolve(TransportService); + const messageReceiver = agent.dependencyManager.resolve(MessageReceiver); + + this.subscription = this.ourSubject.subscribe({ + next: async ({ message, replySubject }: SubjectMessage) => { + logger.test("Received message"); + + let session: SubjectTransportSession | undefined; + if (replySubject) { + session = new SubjectTransportSession( + `subject-session-${uuid()}`, + replySubject, + ); + + // When the subject is completed (e.g. when the session is closed), we need to + // remove the session from the transport service so it won't be used for sending messages + // in the future. + replySubject.subscribe({ + complete: () => session && transportService.removeSession(session), + }); + } + + await messageReceiver.receiveMessage(message, { session }); + }, + }); + } +} diff --git a/libs/askar/src/askar/transports/agent.subject.outbound.transport.ts b/libs/askar/src/askar/transports/agent.subject.outbound.transport.ts new file mode 100644 index 0000000000000000000000000000000000000000..4c3d77c2471c4935018874a66e9c13df20329586 --- /dev/null +++ b/libs/askar/src/askar/transports/agent.subject.outbound.transport.ts @@ -0,0 +1,80 @@ +import { + Agent, + AriesFrameworkError, + InjectionSymbols, + MessageReceiver, + OutboundPackage, + OutboundTransport, +} from "@aries-framework/core"; +import { Logger } from "@nestjs/common"; +import { Subject, take, takeUntil } from "rxjs"; +import { SubjectMessage } from "../../agent.utils"; + +export class SubjectOutboundTransport implements OutboundTransport { + private logger!: Logger; + private subjectMap: { [key: string]: Subject<SubjectMessage> | undefined }; + private agent!: Agent; + private stop$!: Subject<boolean>; + + public supportedSchemes = ["rxjs", "wss"]; + + public constructor(subjectMap: { + [key: string]: Subject<SubjectMessage> | undefined; + }) { + this.subjectMap = subjectMap; + } + + public async start(agent: Agent): Promise<void> { + this.agent = agent; + + this.logger = agent.dependencyManager.resolve(InjectionSymbols.Logger); + this.stop$ = agent.dependencyManager.resolve(InjectionSymbols.Stop$); + } + + public async stop(): Promise<void> { + // No logic needed + } + + public async sendMessage(outboundPackage: OutboundPackage) { + const messageReceiver = + this.agent.dependencyManager.resolve(MessageReceiver); + this.logger.debug( + `Sending outbound message to endpoint ${outboundPackage.endpoint}`, + { + endpoint: outboundPackage.endpoint, + }, + ); + const { payload, endpoint } = outboundPackage; + + if (!endpoint) { + throw new AriesFrameworkError( + "Cannot send message to subject without endpoint", + ); + } + + const subject = this.subjectMap[endpoint]; + + if (!subject) { + throw new AriesFrameworkError( + `No subject found for endpoint ${endpoint}`, + ); + } + + // Create a replySubject just for this session. Both ends will be able to close it, + // mimicking a transport like http or websocket. Close session automatically when agent stops + const replySubject = new Subject<SubjectMessage>(); + this.stop$ + .pipe(take(1)) + .subscribe(() => !replySubject.closed && replySubject.complete()); + + replySubject.pipe(takeUntil(this.stop$)).subscribe({ + next: async ({ message }: SubjectMessage) => { + this.logger.debug("Received message"); + + await messageReceiver.receiveMessage(message); + }, + }); + + subject.next({ message: payload, replySubject }); + } +} diff --git a/libs/dtos/src/dtos/requests/accept.proof.request.dto.ts b/libs/dtos/src/dtos/requests/accept.proof.request.dto.ts index 848258238ee20537fbefc58b906bbcf2d7119cc8..5483583ebef614b46ee6cae700136126f61f8f26 100644 --- a/libs/dtos/src/dtos/requests/accept.proof.request.dto.ts +++ b/libs/dtos/src/dtos/requests/accept.proof.request.dto.ts @@ -1,7 +1,13 @@ -import { IsNotEmpty, IsString } from "class-validator"; +import { IsNotEmpty, IsString, ValidateIf } from "class-validator"; export class AcceptProofRequestDto { @IsString() @IsNotEmpty() - proofRecordId: string; + @ValidateIf((o) => o.proofUrl === undefined) + proofId: string; + + @IsString() + @IsNotEmpty() + @ValidateIf((o) => o.proofId === undefined) + proofUrl: string; } diff --git a/libs/dtos/src/dtos/requests/decline.proof.request.dto.ts b/libs/dtos/src/dtos/requests/decline.proof.request.dto.ts new file mode 100644 index 0000000000000000000000000000000000000000..2b37d7f4d915c4c193426f7c04d7d1db1ca80da4 --- /dev/null +++ b/libs/dtos/src/dtos/requests/decline.proof.request.dto.ts @@ -0,0 +1,10 @@ +import { IsBoolean, IsNotEmpty, IsString } from "class-validator"; + +export class DeclineProofRequestDto { + @IsString() + @IsNotEmpty() + proofRecordId: string; + + @IsBoolean() + sendProblemReport?: boolean; +} \ No newline at end of file diff --git a/libs/dtos/src/dtos/requests/get.proof.request.dto.ts b/libs/dtos/src/dtos/requests/get.proof.request.dto.ts new file mode 100644 index 0000000000000000000000000000000000000000..fdc7f72fdfbf960f6c20d4d36366cfb9afbfc7fc --- /dev/null +++ b/libs/dtos/src/dtos/requests/get.proof.request.dto.ts @@ -0,0 +1,7 @@ +import { IsNotEmpty, IsString } from "class-validator"; + +export class GetProofRequestDto { + @IsString() + @IsNotEmpty() + proofRecordId: string; +} diff --git a/libs/dtos/src/dtos/responses/decline.proof.response.dto.ts b/libs/dtos/src/dtos/responses/decline.proof.response.dto.ts new file mode 100644 index 0000000000000000000000000000000000000000..e8e4885995ca4ff29db1dc4ac39b0bd8183389d3 --- /dev/null +++ b/libs/dtos/src/dtos/responses/decline.proof.response.dto.ts @@ -0,0 +1,25 @@ +import { + IsDateString, + IsNotEmpty, + IsString +} from "class-validator"; + +export class DeclineProofResponseDto { + @IsString() + @IsNotEmpty() + proofId: string; + + @IsString() + connectionId?: string; + + @IsString() + @IsNotEmpty() + state: string; + + @IsDateString() + updatedAt?: Date; + + @IsNotEmpty() + @IsDateString() + createdAt: Date; +} \ No newline at end of file diff --git a/libs/dtos/src/dtos/responses/get.proof.response.dto.ts b/libs/dtos/src/dtos/responses/get.proof.response.dto.ts new file mode 100644 index 0000000000000000000000000000000000000000..d044786caa05eadd9a57eb1836369f03ffbbc2e4 --- /dev/null +++ b/libs/dtos/src/dtos/responses/get.proof.response.dto.ts @@ -0,0 +1,25 @@ +import { + IsDateString, + IsNotEmpty, + IsString +} from "class-validator"; + +export class GetProofByIdResponseDto { + @IsString() + @IsNotEmpty() + proofId: string; + + @IsString() + connectionId?: string; + + @IsString() + @IsNotEmpty() + state: string; + + @IsDateString() + updatedAt?: Date; + + @IsNotEmpty() + @IsDateString() + createdAt: Date; +} diff --git a/libs/dtos/src/events/dtoToEventTransformer.ts b/libs/dtos/src/events/dtoToEventTransformer.ts index cde079ed94ef10f8e5f83a9badd32af348e51030..a120dee89f47017180b2ffa1d8a3eeab2bf48fd9 100644 --- a/libs/dtos/src/events/dtoToEventTransformer.ts +++ b/libs/dtos/src/events/dtoToEventTransformer.ts @@ -17,6 +17,10 @@ import { IssueProofRequestDto } from "../dtos/requests/issue.proof.request.dto"; import { AcceptCredentialOfferRequestDto } from "../dtos/requests/accept.credential.offer.request.dto"; import { MakeBasicMessageResponseDto } from "../dtos/responses/make.basic.message.response.dto"; import { MakeBasicMessageRequestDto } from "../dtos/requests/make.basic.message.request.dto"; +import { AcceptProofRequestDto } from "../dtos/requests/accept.proof.request.dto"; +import { GetProofByIdResponseDto } from "../dtos/responses/get.proof.response.dto"; +import { DeclineProofRequestDto } from '../dtos/requests/decline.proof.request.dto'; +import { DeclineProofResponseDto } from "../dtos/responses/decline.proof.response.dto"; export const makeEvent = (payload: { data: @@ -26,8 +30,12 @@ export const makeEvent = (payload: { | CreateInvitationResponseDto | GetConnectionRequestDto | CreateSchemaRequestDto + | AcceptProofRequestDto + | DeclineProofRequestDto + | DeclineProofResponseDto | CreateSchemaRequestDto | CreateCredentialDefinitionRequsetDto + | GetProofByIdResponseDto | IssueCredentialRequestDto | MakeBasicMessageResponseDto | MakeBasicMessageRequestDto; diff --git a/libs/dtos/src/events/types.ts b/libs/dtos/src/events/types.ts index f19e1b6c62fdfb057e40f735a4e762454006e0b7..f226768c0a49887a8e3d4d1e9352301176f59d01 100644 --- a/libs/dtos/src/events/types.ts +++ b/libs/dtos/src/events/types.ts @@ -48,16 +48,25 @@ export const CRED_EVENTS: CredentialEvent[] = [ CRED_OFFER_ACCEPT, ]; -export type ProofEvent = "proofs.list" | "proofs.accept" | "proofs.issue"; +export type ProofEvent = + | "proofs.list" + | "proofs.accept" + | "proofs.issue" + | "proofs.get" + | "proofs.decline" export const PROOF_LIST = "proofs.list"; +export const PROOF_GET = "proofs.get" export const PROOF_ACCEPT = "proofs.accept"; export const PROOF_ISSUE = "proofs.issue"; +export const PROOF_DECLINE = "proofs.decline" export const PROOF_EVENTS: ProofEvent[] = [ PROOF_ACCEPT, PROOF_LIST, PROOF_ISSUE, + PROOF_GET, + PROOF_DECLINE, ]; export type BasicMessageEvent = "messages.make"; diff --git a/libs/dtos/src/index.ts b/libs/dtos/src/index.ts index e699d9fee52649b12387d27ab349fd61feaf4a10..ce0ac84aac42b0426913d8f6ed022b7e085fc050 100644 --- a/libs/dtos/src/index.ts +++ b/libs/dtos/src/index.ts @@ -8,6 +8,8 @@ export * from "./dtos/requests/get.schema.request.dto"; export * from "./dtos/requests/accept.credential.offer.request.dto"; export * from "./dtos/requests/accept.proof.request.dto"; export * from "./dtos/requests/make.basic.message.request.dto"; +export * from "./dtos/requests/get.proof.request.dto"; +export * from "./dtos/requests/decline.proof.request.dto"; export * from "./dtos/responses/create.invitation.response.dto"; export * from "./dtos/responses/accept.invitation.response.dto"; @@ -17,6 +19,8 @@ export * from "./dtos/responses/issue.credential.response.dto"; export * from "./dtos/responses/issue.proof.response.dto"; export * from "./dtos/responses/gateway.accepted.response.dto"; export * from "./dtos/responses/make.basic.message.response.dto"; +export * from "./dtos/responses/get.proof.response.dto"; +export * from "./dtos/responses/decline.proof.response.dto"; export * from "./errors/connection.not.found.error"; export * from "./errors/schema.not.created.error"; diff --git a/package.json b/package.json index 1e94baaca7f1934074d4d47753c7ec0922c192b2..9979d29e05059f82ce25ba14d6862250ac668218 100644 --- a/package.json +++ b/package.json @@ -27,8 +27,8 @@ "infra:holder": "cd compose && docker-compose --profile holder up -d --build", "infra:issuer:stop": "cd compose && docker-compose --profile issuer stop", "infra:holder:stop": "cd compose && docker-compose --profile holder stop", - "infra:local": "cd compose && docker-compose -f=docker-compose.infra.yml up -d", - "infra:local:stop": "cd compose && docker-compose -f=docker-compose.infra.yml stop", + "infra:local": "cd compose && docker-compose -f docker-compose.infra.yml up -d", + "infra:local:stop": "cd compose && docker-compose -f docker-compose.infra.yml stop", "infra:simple": "cd compose && docker-compose -f docker-compose.simple.yml up -d" }, "private": true,