diff --git a/agent-swagger.json b/agent-swagger.json index a753adf177e398f986cc2a5169faf42a2bd8cec7..ff24b8c63b0afa2da47d9f8fad8f8414577980b5 100644 --- a/agent-swagger.json +++ b/agent-swagger.json @@ -5,6 +5,16 @@ "post": { "operationId": "RestController_createInvitation", "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateInvitationRequestDto" + } + } + } + }, "responses": { "201": { "description": "", @@ -833,6 +843,14 @@ "servers": [], "components": { "schemas": { + "CreateInvitationRequestDto": { + "type": "object", + "properties": { + "goal": { + "type": "string" + } + } + }, "CreateInvitationResponseDto": { "type": "object", "properties": { @@ -1191,14 +1209,14 @@ "type": "string", "example": "6464b521-005a-4379-91e0-a3692b31cafd" }, - "content": { + "message": { "type": "string", "example": "hello world" } }, "required": [ "connectionId", - "content" + "message" ] }, "MessageRecordDto": { diff --git a/apps/agent/deployment/ci-cd/helm/templates/deployment.yaml b/apps/agent/deployment/ci-cd/helm/templates/deployment.yaml index 5f62c324d84fb3f66d556d9079522a97ca795689..d23d200c9d26e3d38b55c94039102dcf701dac78 100644 --- a/apps/agent/deployment/ci-cd/helm/templates/deployment.yaml +++ b/apps/agent/deployment/ci-cd/helm/templates/deployment.yaml @@ -125,10 +125,6 @@ spec: value: {{ .Values.hin.agent.is.rest | quote }} - name: AGENT_IS_SVDX value: {{ .Values.hin.agent.is.svdx | quote }} - - name: AGENT_SVDX_SCHEMA_ID - value: {{ .Values.hin.agent.svdx.schema.id | quote }} - - name: AGENT_SVDX_CRED_DEF_ID - value: {{ .Values.hin.agent.svdx.cred.def.id | quote }} - name: AGENT_SVDX_WEBHOOK_URL value: {{ .Values.hin.agent.svdx.webhook.url | quote }} - name: AGENT_SVDX_BASIC_USER @@ -141,6 +137,8 @@ spec: value: {{ .Values.hin.agent.rete.limit | quote }} - name: ALLOWED_ORIGINS value: {{ .Values.hin.agent.allowedOrigin | quote }} + - name: AGENT_OOB_GOALS + value: {{ .Values.hin.agent.invitationGoals| quote }} {{- end }} {{- if .Values.extraVars }} {{ toYaml .Values.extraVars | indent 8 }} diff --git a/apps/agent/deployment/ci-cd/helm/values.yaml b/apps/agent/deployment/ci-cd/helm/values.yaml index 3f8d1cd8a93f29f6f56c7148f33f92499b41f769..1144237a55c2833f55dd21494604afb476a30634 100644 --- a/apps/agent/deployment/ci-cd/helm/values.yaml +++ b/apps/agent/deployment/ci-cd/helm/values.yaml @@ -153,11 +153,6 @@ hin: basic: user: "" pass: "" - schema: - id: "did:indy:bcovrin:test:5zDb5ptTJLb2LUeDr1LvHH/anoncreds/v0/SCHEMA/demo-hin-schema-dev/0.0.1" - cred: - def: - id: "did:indy:bcovrin:test:5zDb5ptTJLb2LUeDr1LvHH/anoncreds/v0/CLAIM_DEF/102523/demo-hin-cd" webhook: url: "https://did.svdx.pro/ocm/connection" max: @@ -169,6 +164,7 @@ hin: user: "" pass: "" allowedOrigin: "*" + invitationGoals: "connection.exchange" service: diff --git a/apps/agent/src/main.ts b/apps/agent/src/main.ts index 592022b3b0dd67f12f8a8be9e66c6f6b0d7e6e6a..426c955e2ccecee936583850df39e47d385329a0 100644 --- a/apps/agent/src/main.ts +++ b/apps/agent/src/main.ts @@ -8,6 +8,7 @@ import { NestFactory } from "@nestjs/core"; import { AppModule } from "./app/app.module"; import { DocumentBuilder, SwaggerModule } from "@nestjs/swagger"; +import { urlencoded, json } from "express"; import * as fs from "fs"; async function bootstrap() { @@ -18,6 +19,9 @@ async function bootstrap() { origin: origins.length > 1 ? origins : origins[0] || "", methods: "GET,HEAD,PUT,PATCH,POST,DELETE", }); + app.use(json({ limit: "5mb" })); + app.use(urlencoded({ extended: true, limit: "5mb" })); + const globalPrefix = "api"; app.setGlobalPrefix(globalPrefix); const port = process.env.AGENT_PORT || 3001; diff --git a/libs/askar/src/agent.utils.ts b/libs/askar/src/agent.utils.ts index c66a238b5af28210c077f323b354fefe79920a75..61333fba9816d15ffa9c7cefc95702e1405d50d3 100644 --- a/libs/askar/src/agent.utils.ts +++ b/libs/askar/src/agent.utils.ts @@ -291,37 +291,36 @@ export const svdxConnectionStateChangeHandler = async ( return; } - await agent.connections.addConnectionType( - ev.payload.connectionRecord.id, - ev.payload.connectionRecord.theirLabel || "svdx", - ); - - console.log("connection accepted", JSON.stringify(ev, null, 2)); - - const connections = await agent.connections.findAllByConnectionTypes([ - ev.payload.connectionRecord.theirLabel || "svdx", - ]); + const outOfBandId = ev.payload.connectionRecord.outOfBandId; - if (connections.length < 2) { + if (typeof outOfBandId === "undefined") { + console.log(JSON.stringify(ev.payload, null, 2)); + console.log("Out of Band id not found, skipping"); return; } - connections.sort( - (a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime(), - ); + const outOfBandRecord = await agent.oob.findById(outOfBandId); - while (connections.length > 1) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const con = connections.pop()!; + if (!outOfBandRecord) { + console.log(JSON.stringify(ev.payload, null, 2)); + console.log("No out of band record found"); + return; + } - console.log(`deleting ${con.id}`); - await agent.connections.deleteById(con.id); + if ( + !outOfBandRecord.outOfBandInvitation.goal || + !config?.agentOobGoals.includes(outOfBandRecord.outOfBandInvitation.goal) + ) { + console.log(JSON.stringify(ev.payload, null, 2)); + console.log("This connection does not have any goals"); + return; } try { + console.log(`Sending proof request, to ${ev.payload.connectionRecord.id}`); await agent.proofs.requestProof({ protocolVersion: "v2", - connectionId: connections[0].id, + connectionId: ev.payload.connectionRecord.id, proofFormats: { anoncreds: { name: "proof-request", @@ -329,12 +328,6 @@ export const svdxConnectionStateChangeHandler = async ( requested_attributes: { email: { name: "email", - restrictions: [ - { - schema_id: config?.agentSVDXSchemaId, - cred_def_id: config?.agentSVDXCredDefId, - }, - ], }, }, }, diff --git a/libs/askar/src/askar-rest/rest.controller.ts b/libs/askar/src/askar-rest/rest.controller.ts index 6882d252eabb5e7d8124b70d702ce53903151108..d6417ddbe49d54c20045173c0bfa441e489161e3 100644 --- a/libs/askar/src/askar-rest/rest.controller.ts +++ b/libs/askar/src/askar-rest/rest.controller.ts @@ -23,6 +23,7 @@ import { MessageFilterDto, ProofFilterDto, AcceptCredentialDto, + CreateInvitationRequestDto, } from "@ocm-engine/dtos"; import { AllExceptionsHandler } from "./exception.handler"; import { DidResolutionResult } from "@aries-framework/core"; @@ -33,8 +34,10 @@ export class RestController { constructor(private readonly agentService: AgentService) {} @Post("/invitations") - async createInvitation() { - return this.agentService.createInvitation(); + createInvitation( + @Body() createInvitationRequestDto: CreateInvitationRequestDto, + ) { + return this.agentService.createInvitation(createInvitationRequestDto); } @Post("/invitations/accept") diff --git a/libs/askar/src/askar/agent.service.ts b/libs/askar/src/askar/agent.service.ts index 77e661bc85de0b5bd375e93e5465b6d35edbbf87..b56dc2fd704e008b6f20e1c2a9799f92a0494996 100644 --- a/libs/askar/src/askar/agent.service.ts +++ b/libs/askar/src/askar/agent.service.ts @@ -25,6 +25,7 @@ import { AcceptCredentialDto, CredentialFormatDataDto, ProofFormatDataDto, + CreateInvitationRequestDto, } from "@ocm-engine/dtos"; import { AutoAcceptCredential, @@ -33,9 +34,10 @@ import { ConnectionRecord, CredentialExchangeRecord, CredentialState, - ProofExchangeRecord, + OutOfBandRecord, ProofState, Query, + ProofExchangeRecord, } from "@aries-framework/core"; import { AnonCredsRequestedAttribute } from "@aries-framework/anoncreds"; import { uuid } from "@aries-framework/core/build/utils/uuid"; @@ -48,8 +50,27 @@ import { export class AgentService { constructor(private readonly askar: AskarService) {} - createInvitation = async (): Promise<CreateInvitationResponseDto> => { - const outOfBoundRecord = await this.askar.agent.oob.createInvitation(); + createInvitation = async ( + createInvitationRequestDto?: CreateInvitationRequestDto, + ) => { + let outOfBoundRecordPromise: Promise<OutOfBandRecord>; + + if ( + createInvitationRequestDto && + createInvitationRequestDto.goal && + this.askar.agentConfig.agentOobGoals && + this.askar.agentConfig.agentOobGoals.includes( + createInvitationRequestDto.goal, + ) + ) { + outOfBoundRecordPromise = this.askar.agent.oob.createInvitation({ + goal: createInvitationRequestDto.goal, + }); + } else { + outOfBoundRecordPromise = this.askar.agent.oob.createInvitation(); + } + + const outOfBoundRecord = await outOfBoundRecordPromise; const i = new CreateInvitationResponseDto(); i.invitationUrl = outOfBoundRecord.outOfBandInvitation.toUrl({ @@ -866,7 +887,7 @@ export class AgentService { ): Promise<MessageRecordDto> => { const messageRecord = await this.askar.agent.basicMessages.sendMessage( dto.connectionId, - dto.content, + dto.message, ); const connRecord = await this.askar.agent.connections.findById( diff --git a/libs/config/src/config/agent.config.ts b/libs/config/src/config/agent.config.ts index 112fd7a36123674a437cc0f402059f9f97e2b610..d32b23e855b0ec84ba2b0a24ebfdf7d6ac495b48 100644 --- a/libs/config/src/config/agent.config.ts +++ b/libs/config/src/config/agent.config.ts @@ -19,9 +19,11 @@ export const agentConfig = registerAs( parseInt(process.env["AGENT_MAX_MESSAGES"]!) || 10, agentConsumerRateLimit: parseInt(process.env["AGENT_RETE_LIMIT"]!) || 5, agentPort: parseInt(process.env["AGENT_PORT"]!), + agentOobGoals: + typeof process.env["AGENT_OOB_GOALS"] !== undefined + ? process.env["AGENT_OOB_GOALS"]!.split(",") + : [], agentIsSVDX: process.env["AGENT_IS_SVDX"] === "true", - agentSVDXSchemaId: process.env["AGENT_SVDX_SCHEMA_ID"]!, - agentSVDXCredDefId: process.env["AGENT_SVDX_CRED_DEF_ID"]!, agentSVDXWebHook: process.env["AGENT_SVDX_WEBHOOK_URL"]!, agentSVDXBasicUser: process.env["AGENT_SVDX_BASIC_USER"]!, agentSVDXBasicPass: process.env["AGENT_SVDX_BASIC_PASS"]!, diff --git a/libs/config/src/interfaces/agent.config.interface.ts b/libs/config/src/interfaces/agent.config.interface.ts index 317b645a88d15a6b1eac322618bb706fabc12565..59d426060c318d59e638ed5c4e7a279020fa1e9e 100644 --- a/libs/config/src/interfaces/agent.config.interface.ts +++ b/libs/config/src/interfaces/agent.config.interface.ts @@ -12,10 +12,9 @@ export interface IConfAgent { agentConsumerMaxMessagess: number; agentConsumerRateLimit: number; agentPort: number; + agentOobGoals: Array<string>; agentIsSVDX: boolean; - agentSVDXSchemaId: string; - agentSVDXCredDefId: string; agentSVDXWebHook: string; agentSVDXBasicUser: string; agentSVDXBasicPass: string; diff --git a/libs/dtos/src/dtos/requests/create.invitation.request.dto.ts b/libs/dtos/src/dtos/requests/create.invitation.request.dto.ts new file mode 100644 index 0000000000000000000000000000000000000000..9bfad1343dfd48cdcbdb728d759ff3e84e42d32a --- /dev/null +++ b/libs/dtos/src/dtos/requests/create.invitation.request.dto.ts @@ -0,0 +1,8 @@ +import { IsNotEmpty, IsOptional, IsString } from "class-validator"; + +export class CreateInvitationRequestDto { + @IsOptional() + @IsString() + @IsNotEmpty() + goal?: string; +} diff --git a/libs/dtos/src/dtos/requests/make.basic.message.request.dto.ts b/libs/dtos/src/dtos/requests/make.basic.message.request.dto.ts index c17133d97a53de091ee996ad0bc3d2b1d0b29385..a5ab200eb1ceaf52810096ecdc3220df2d93eac0 100644 --- a/libs/dtos/src/dtos/requests/make.basic.message.request.dto.ts +++ b/libs/dtos/src/dtos/requests/make.basic.message.request.dto.ts @@ -9,5 +9,5 @@ export class MakeBasicMessageRequestDto { // @example "hello world" @IsNotEmpty() @IsString() - content: string; + message: string; } diff --git a/libs/dtos/src/index.ts b/libs/dtos/src/index.ts index 7e2e9e486dfc2ebe413f5b59e876b0beb86a80e1..18cb1e41ef1690281c887caa7c98910b4093d3eb 100644 --- a/libs/dtos/src/index.ts +++ b/libs/dtos/src/index.ts @@ -21,6 +21,7 @@ export * from "./dtos/requests/create.credential.definition.request.dto"; export * from "./dtos/requests/offer.credential.request.dto"; export * from "./dtos/requests/request.proof.dto"; export * from "./dtos/requests/make.basic.message.request.dto"; +export * from "./dtos/requests/create.invitation.request.dto"; export * from "./dtos/responses/request.proof.response.dto"; export * from "./dtos/responses/credential.offer.response.dto";