Skip to content

Commit

Permalink
feat: Support out of band verification (#59)
Browse files Browse the repository at this point in the history
* feat: Support Out-Of-Band verification

Signed-off-by: KulkarniShashank <[email protected]>

* Added the qrcode package in package.json

Signed-off-by: KulkarniShashank <[email protected]>

* Added the QR code for the out-of-band verification

Signed-off-by: KulkarniShashank <[email protected]>

* change the error message on the dto

Signed-off-by: KulkarniShashank <[email protected]>

---------

Signed-off-by: KulkarniShashank <[email protected]>
  • Loading branch information
KulkarniShashank committed Sep 11, 2024
1 parent 11ada5a commit ff55663
Show file tree
Hide file tree
Showing 16 changed files with 507 additions and 97 deletions.
5 changes: 5 additions & 0 deletions apps/agent-service/src/agent-service.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,4 +96,9 @@ export class AgentServiceController {
async getAgentHealth(payload: { user: user, orgId: number }): Promise<object> {
return this.agentServiceService.getAgentHealthDetails(payload.orgId);
}

@MessagePattern({ cmd: 'agent-send-out-of-band-proof-request' })
async sendOutOfBandProofRequest(payload: { proofRequestPayload: ISendProofRequestPayload, url: string, apiKey: string }): Promise<object> {
return this.agentServiceService.sendOutOfBandProofRequest(payload.proofRequestPayload, payload.url, payload.apiKey);
}
}
22 changes: 17 additions & 5 deletions apps/agent-service/src/agent-service.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -851,17 +851,29 @@ export class AgentServiceService {
}
if (orgAgentDetails.agentEndPoint) {
const data = await this.commonService
.httpGet(`${orgAgentDetails.agentEndPoint}/agent`, { headers: { 'x-api-key': '' } })
.then(async response => response);
.httpGet(`${orgAgentDetails.agentEndPoint}/agent`, { headers: { 'x-api-key': '' } })
.then(async response => response);
return data;
} else {
throw new NotFoundException(ResponseMessages.agent.error.agentUrl);
}
throw new NotFoundException(ResponseMessages.agent.error.agentUrl);
}

} catch (error) {
this.logger.error(`Agent health details : ${JSON.stringify(error)}`);
throw new RpcException(error);
}
}

async sendOutOfBandProofRequest(proofRequestPayload: ISendProofRequestPayload, url: string, apiKey: string): Promise<object> {
try {
const sendProofRequest = await this.commonService
.httpPost(url, proofRequestPayload, { headers: { 'x-api-key': apiKey } })
.then(async response => response);
return sendProofRequest;
} catch (error) {
this.logger.error(`Error in send out of band proof request in agent service : ${JSON.stringify(error)}`);
throw new RpcException(error);
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ export interface IAttributes {
}
export interface ISendProofRequestPayload {
comment: string;
connectionId: string;
connectionId?: string;
proofFormats: IProofFormats;
autoAcceptProof: string;
}
Expand Down
66 changes: 56 additions & 10 deletions apps/api-gateway/src/verification/dto/request-proof.dto.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IsArray, IsNotEmpty, IsNumber, IsObject, IsOptional, IsString, MaxLength } from 'class-validator';
import { IsArray, IsEmail, IsNotEmpty, IsNumber, IsObject, IsOptional, IsString, MaxLength } from 'class-validator';
import { toLowerCase, trim } from '@credebl/common/cast.helper';
import { ApiProperty } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
Expand All @@ -7,19 +7,19 @@ import { Transform } from 'class-transformer';
class IProofRequestAttribute {
@IsString()
attributeName: string;

@IsString()
condition?: string;

@IsString()
value?: string;
value?: string;

@IsString()
credDefId?: string;

@IsString()
schemaId: string;
}
}

export class RequestProof {
@ApiProperty()
Expand Down Expand Up @@ -54,13 +54,59 @@ export class RequestProof {
@IsNotEmpty({ message: 'please provide orgId' })
orgId: number;

@IsString({ message: 'autoAcceptProof must be in string' })
@IsNotEmpty({ message: 'please provide valid autoAcceptProof' })
@IsString({ message: 'auto accept proof must be in string' })
@IsNotEmpty({ message: 'please provide valid auto accept proof' })
@IsOptional()
autoAcceptProof: string;

@IsString({ message: 'protocolVersion must be in string' })
@IsNotEmpty({ message: 'please provide valid protocolVersion' })
@IsNotEmpty({ message: 'please provide valid protocol version' })
@IsOptional()
protocolVersion: string;
}

export class OutOfBandRequestProof {
@ApiProperty({
'example': [
{
attributeName: 'attributeName',
condition: '>=',
value: 'predicates',
credDefId: '',
schemaId: ''
}
]
})
@IsArray({ message: 'attributes must be in array' })
@IsObject({ each: true })
@IsNotEmpty({ message: 'please provide valid attributes' })
attributes: IProofRequestAttribute[];

@ApiProperty({ example: 'string' })
@IsNotEmpty({ message: 'Please provide valid emailId' })
@Transform(({ value }) => trim(value))
@Transform(({ value }) => toLowerCase(value))
@IsNotEmpty({ message: 'Email is required.' })
@MaxLength(256, { message: 'Email must be at most 256 character.' })
@IsEmail()
emailId: string;

@ApiProperty()
@IsOptional()
comment: string;

@ApiProperty()
@IsNumber()
@IsNotEmpty({ message: 'please provide orgId' })
orgId: number;

@IsString({ message: 'autoAcceptProof must be in string' })
@IsNotEmpty({ message: 'please provide valid auto accept proof' })
@IsOptional()
autoAcceptProof: string;

@IsString({ message: 'protocol version must be in string' })
@IsNotEmpty({ message: 'please provide valid protocol version' })
@IsOptional()
protocolVersion: string;
}
34 changes: 33 additions & 1 deletion apps/api-gateway/src/verification/verification.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { Controller, Logger, Post, Body, Get, Query, HttpStatus, Res, UseGuards,
import { ApiResponseDto } from '../dtos/apiResponse.dto';
import { UnauthorizedErrorDto } from '../dtos/unauthorized-error.dto';
import { ForbiddenErrorDto } from '../dtos/forbidden-error.dto';
import { RequestProof } from './dto/request-proof.dto';
import { OutOfBandRequestProof, RequestProof } from './dto/request-proof.dto';
import { GetUser } from '../authz/decorators/get-user.decorator';
import { VerificationService } from './verification.service';
import IResponseType from '@credebl/common/interfaces/response.interface';
Expand Down Expand Up @@ -205,5 +205,37 @@ export class VerificationController {
};
return res.status(HttpStatus.CREATED).json(finalResponse);
}

/**
* Out-Of-Band Proof Presentation
* @param user
* @param outOfBandRequestProof
* @returns Get out-of-band requested proof presentation details
*/
@Post('/proofs/create-request-oob')
@ApiTags('verifications')
@ApiOperation({
summary: `Sends a out-of-band proof request`,
description: `Sends a out-of-band proof request`
})
@ApiResponse({ status: 201, description: 'Success', type: ApiResponseDto })
@ApiUnauthorizedResponse({ status: 401, description: 'Unauthorized', type: UnauthorizedErrorDto })
@ApiForbiddenResponse({ status: 403, description: 'Forbidden', type: ForbiddenErrorDto })
@ApiBody({ type: OutOfBandRequestProof })
@Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.VERIFIER)
@UseGuards(AuthGuard('jwt'), OrgRolesGuard)
async sendOutOfBandPresentationRequest(
@Res() res: Response,
@GetUser() user: IUserRequest,
@Body() outOfBandRequestProof: OutOfBandRequestProof
): Promise<object> {
const sendProofRequest = await this.verificationService.sendOutOfBandPresentationRequest(outOfBandRequestProof, user);
const finalResponse: IResponseType = {
statusCode: HttpStatus.CREATED,
message: ResponseMessages.verification.success.fetch,
data: sendProofRequest.response
};
return res.status(HttpStatus.CREATED).json(finalResponse);
}
}

13 changes: 12 additions & 1 deletion apps/api-gateway/src/verification/verification.service.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Injectable, Inject } from '@nestjs/common';
import { ClientProxy } from '@nestjs/microservices';
import { BaseService } from 'libs/service/base.service';
import { RequestProof } from './dto/request-proof.dto';
import { OutOfBandRequestProof, RequestProof } from './dto/request-proof.dto';
import { IUserRequest } from '@credebl/user-request/user-request.interface';
import { WebhookPresentationProof } from './dto/webhook-proof.dto';

Expand Down Expand Up @@ -64,4 +64,15 @@ export class VerificationService extends BaseService {
const payload = { id, proofPresentationPayload };
return this.sendNats(this.verificationServiceProxy, 'webhook-proof-presentation', payload);
}

/**
* Out-Of-Band Proof Presentation
* @param user
* @param outOfBandRequestProof
* @returns Get out-of-band requested proof presentation details
*/
sendOutOfBandPresentationRequest(outOfBandRequestProof: OutOfBandRequestProof, user: IUserRequest): Promise<{ response: object }> {
const payload = { outOfBandRequestProof, user };
return this.sendNats(this.verificationServiceProxy, 'send-out-of-band-proof-request', payload);
}
}
5 changes: 3 additions & 2 deletions apps/verification/src/interfaces/verification.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,12 @@ interface IProofRequestAttribute {

export interface IRequestProof {
orgId: number;
connectionId: string;
connectionId?: string;
attributes: IProofRequestAttribute[];
comment: string;
autoAcceptProof: string;
protocolVersion: string;
emailId?: string
}

export interface IGetAllProofPresentations {
Expand Down Expand Up @@ -68,7 +69,7 @@ interface IRequestedRestriction {
export interface ISendProofRequestPayload {
protocolVersion: string;
comment: string;
connectionId: string;
connectionId?: string;
proofFormats: IProofFormats;
autoAcceptProof: string;
}
Expand Down
35 changes: 33 additions & 2 deletions apps/verification/src/repositories/verification.repository.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { ResponseMessages } from "@credebl/common/response-messages";
import { PrismaService } from "@credebl/prisma-service";
import { Injectable, Logger, NotFoundException } from "@nestjs/common";
import { Injectable, InternalServerErrorException, Logger, NotFoundException } from "@nestjs/common";
// eslint-disable-next-line camelcase
import { org_agents, presentations } from "@prisma/client";
import { org_agents, organisation, platform_config, presentations } from "@prisma/client";
import { IWebhookProofPresentation } from "../interfaces/verification.interface";


Expand Down Expand Up @@ -63,4 +63,35 @@ export class VerificationRepository {
throw error;
}
}

/**
* Get platform config details
* @returns
*/
// eslint-disable-next-line camelcase
async getPlatformConfigDetails(): Promise<platform_config> {
try {

return this.prisma.platform_config.findFirst();

} catch (error) {
this.logger.error(`[getPlatformConfigDetails] - error: ${JSON.stringify(error)}`);
throw new InternalServerErrorException(error);
}
}

/**
* Get organization details
* @returns
*/
async getOrganization(orgId: number): Promise<organisation> {
try {

return this.prisma.organisation.findFirst({ where: { id: orgId } });

} catch (error) {
this.logger.error(`[getOrganization] - error: ${JSON.stringify(error)}`);
throw new InternalServerErrorException(error);
}
}
}
5 changes: 5 additions & 0 deletions apps/verification/src/verification.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,4 +53,9 @@ export class VerificationController {
async webhookProofPresentation(payload: { id: string, proofPresentationPayload: IWebhookProofPresentation }): Promise<presentations> {
return this.verificationService.webhookProofPresentation(payload.id, payload.proofPresentationPayload);
}

@MessagePattern({ cmd: 'send-out-of-band-proof-request' })
async sendOutOfBandPresentationRequest(payload: { outOfBandRequestProof: IRequestProof, user: IUserRequest }): Promise<boolean> {
return this.verificationService.sendOutOfBandPresentationRequest(payload.outOfBandRequestProof);
}
}
Loading

0 comments on commit ff55663

Please sign in to comment.