Skip to content

Commit

Permalink
Feat/verification w3c with connection (#690)
Browse files Browse the repository at this point in the history
* Add: w3c verification with connection

Signed-off-by: Krishna <krishna.waske@ayanworks.com>

* Added: validations

Signed-off-by: Krishna <krishna.waske@ayanworks.com>

* Remove commented code

Signed-off-by: Krishna <krishna.waske@ayanworks.com>

* fix: sonarlint issues

Signed-off-by: Krishna <krishna.waske@ayanworks.com>

* fix: sonarlint issues

Signed-off-by: Krishna <krishna.waske@ayanworks.com>

* Add: validations

Signed-off-by: Krishna <krishna.waske@ayanworks.com>

---------

Signed-off-by: Krishna <krishna.waske@ayanworks.com>
Signed-off-by: KulkarniShashank <shashank.kulkarni@ayanworks.com>
  • Loading branch information
GHkrishna authored and KulkarniShashank committed Sep 11, 2024
1 parent 6871a2a commit a30a686
Show file tree
Hide file tree
Showing 6 changed files with 314 additions and 146 deletions.
34 changes: 33 additions & 1 deletion apps/agent-service/src/interface/agent-service.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,40 @@ export interface IAgentStatus {
isInitialized: boolean;
}

export interface ISchema {
uri:string;
}
export interface IFields {
path: string[];
}
export interface IConstraints {
fields: IFields[];
}

export interface IInputDescriptors {

id:string;
name?:string;
purpose?:string;
schema:ISchema[];
constraints?:IConstraints;

}

export interface IProofRequestPresentationDefinition {
id:string;
name: string;
input_descriptors:IInputDescriptors[];
}

export interface IPresentationExchange {
presentationDefinition:IProofRequestPresentationDefinition;

}

interface IProofFormats {
indy: IndyProof;
indy?: IndyProof;
presentationExchange? : IPresentationExchange;
}

interface IndyProof {
Expand Down
268 changes: 175 additions & 93 deletions apps/api-gateway/src/verification/dto/request-proof.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Transform, Type } from 'class-transformer';
import { AutoAccept } from '@credebl/enum/enum';
import { IProofFormats } from '../interfaces/verification.interface';
import { ProofRequestType } from '../enum/verification.enum';


export class ProofRequestAttribute {
Expand Down Expand Up @@ -69,6 +70,128 @@ class ProofPayload {
protocolVersion: string;
}

export class Fields {
@ApiProperty()
@IsArray()
@IsNotEmpty({ message: 'path is required.' })
path: string[];
}

export class Constraints {
@ApiProperty({type: () => [Fields]})
@IsOptional()
@IsNotEmpty({ message: 'Fields are required.' })
@ValidateNested()
@Type(() => Fields)
fields: Fields[];
}


export class Schema {
@ApiProperty()
@IsNotEmpty({ message: 'uri is required.' })
@IsString()
uri:string;

}
export class InputDescriptors {
@ApiProperty()
@IsNotEmpty({ message: 'id is required.' })
@IsString()
id:string;

@ApiProperty()
@IsString()
@IsOptional()
@IsNotEmpty({ message: 'name is required.' })
name:string;

@ApiProperty()
@IsString()
@IsOptional()
@IsNotEmpty({ message: 'purpose is required.' })
purpose:string;


@ApiProperty({type: () => [Schema]})
@IsNotEmpty({ message: 'schema is required.' })
@ValidateNested()
@Type(() => Schema)
schema:Schema[];


@ApiProperty({type: () => Constraints})
@IsOptional()
@IsNotEmpty({ message: 'Constraints are required.' })
@ValidateNested()
@Type(() => Constraints)
constraints:Constraints;

}

export class ProofRequestPresentationDefinition {

@IsString()
@IsNotEmpty({ message: 'id is required.' })
id: string;

@IsString()
@IsOptional()
name: string;

@ApiProperty({type: () => [InputDescriptors]})
@IsNotEmpty({ message: 'inputDescriptors is required.' })
@IsArray({ message: 'inputDescriptors must be an array' })
@IsObject({ each: true })
@Type(() => InputDescriptors)
@ValidateNested()
// eslint-disable-next-line camelcase
input_descriptors:InputDescriptors[];
}

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

export class IndyDto {
@ApiProperty({
'example': {
'attributes': [
{
attributeName: 'attributeName',
condition: '>=',
value: 'predicates',
credDefId: 'string',
schemaId: 'string'
}
]
},
type: () => [ProofRequestAttributeDto]
})
@ValidateNested()
@IsObject({ each: true })
@IsNotEmpty({ message: 'please provide valid attributes' })
@Type(() => ProofRequestAttributeDto)
indy: ProofRequestAttributeDto;
}

export class RequestProofDto extends ProofPayload {
@ApiProperty()
@IsString()
Expand All @@ -78,29 +201,67 @@ export class RequestProofDto extends ProofPayload {
connectionId: string;

@ApiProperty({
'example': [
'example':
{
'indy': [
{
attributeName: 'attributeName',
condition: '>=',
value: 'predicates',
credDefId: 'string',
schemaId: 'string'
}
]
},
type: () => [IndyDto]
})
@IsOptional()
@ValidateNested()
@IsObject({ message: 'ProofFormatDto must be an object' })
@IsNotEmpty({ message: 'ProofFormatDto must not be empty' })
@Type(() => IndyDto)
proofFormats?: IndyDto;

@ApiProperty({
'example':
{
attributeName: 'attributeName',
condition: '>=',
value: 'predicates',
credDefId: 'string',
schemaId: 'string'
}
],
type: () => [ProofRequestAttribute]
id: '32f54163-7166-48f1-93d8-ff217bdb0653',
inputDescriptors: [
{
'id': 'healthcare_input_1',
'name': 'Medical History',
'schema': [
{
'uri': 'https://health-schemas.org/1.0.1/medical_history.json'
}

],
'constraints': {
'fields': [
{
'path': ['$.PatientID']
}
]
}
}
]
},
type: () => [ProofRequestPresentationDefinition]
})
@IsArray({ message: 'attributes must be in array' })
@IsOptional()
@ValidateNested()
@IsObject({ each: true })
@IsNotEmpty({ message: 'please provide valid attributes' })
@Type(() => ProofRequestAttribute)
attributes: ProofRequestAttribute[];
@IsObject({ message: 'presentationDefinition must be an object' })
@IsNotEmpty({ message: 'presentationDefinition must not be empty' })
@Type(() => ProofRequestPresentationDefinition)
presentationDefinition?:ProofRequestPresentationDefinition;

@ApiPropertyOptional()
@IsOptional()
@IsString({ message: 'comment must be in string' })
comment: string;

type:ProofRequestType;

orgId: string;

@ApiPropertyOptional()
Expand Down Expand Up @@ -156,85 +317,6 @@ export class OutOfBandRequestProof extends ProofPayload {
autoAcceptProof: string;
}

export class Fields {
@ApiProperty()
@IsArray()
@IsNotEmpty({ message: 'path is required.' })
path: string[];
}

export class Constraints {
@ApiProperty({type: () => [Fields]})
@IsOptional()
@IsNotEmpty({ message: 'Fields are required.' })
@ValidateNested()
@Type(() => Fields)
fields: Fields[];
}


export class Schema {
@ApiProperty()
@IsNotEmpty({ message: 'uri is required.' })
@IsString()
uri:string;

}
export class InputDescriptors {
@ApiProperty()
@IsNotEmpty({ message: 'id is required.' })
@IsString()
id:string;

@ApiProperty()
@IsString()
@IsOptional()
@IsNotEmpty({ message: 'name is required.' })
name:string;

@ApiProperty()
@IsString()
@IsOptional()
@IsNotEmpty({ message: 'purpose is required.' })
purpose:string;


@ApiProperty({type: () => [Schema]})
@IsNotEmpty({ message: 'schema is required.' })
@ValidateNested()
@Type(() => Schema)
schema:Schema[];


@ApiProperty({type: () => Constraints})
@IsOptional()
@IsNotEmpty({ message: 'Constraints are required.' })
@ValidateNested()
@Type(() => Constraints)
constraints:Constraints;

}

export class ProofRequestPresentationDefinition {

@IsString()
@IsNotEmpty({ message: 'id is required.' })
id: string;

@IsString()
@IsOptional()
name: string;

@ApiProperty({type: () => [InputDescriptors]})
@IsNotEmpty({ message: 'inputDescriptors is required.' })
@IsArray({ message: 'inputDescriptors must be an array' })
@IsObject({ each: true })
@Type(() => InputDescriptors)
@ValidateNested()
// eslint-disable-next-line camelcase
input_descriptors:InputDescriptors[];
}

export class SendProofRequestPayload {

@ApiPropertyOptional()
Expand Down
26 changes: 22 additions & 4 deletions apps/api-gateway/src/verification/verification.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,19 +170,35 @@ export class VerificationController {
@ApiResponse({ status: HttpStatus.OK, description: 'Success', type: ApiResponseDto })
@ApiUnauthorizedResponse({ status: HttpStatus.UNAUTHORIZED, description: 'Unauthorized', type: UnauthorizedErrorDto })
@ApiForbiddenResponse({ status: HttpStatus.FORBIDDEN, description: 'Forbidden', type: ForbiddenErrorDto })
@ApiBody({ type: RequestProofDto })
@ApiBody({ type: RequestProofDto })@ApiQuery({
name: 'requestType',
enum: ProofRequestType
})
@ApiBearerAuth()
@UseGuards(AuthGuard('jwt'), OrgRolesGuard)
@Roles(OrgRoles.OWNER, OrgRoles.ADMIN, OrgRoles.VERIFIER)
async sendPresentationRequest(
@Res() res: Response,
@User() user: IUserRequest,
@Param('orgId', new ParseUUIDPipe({exceptionFactory: (): Error => { throw new BadRequestException(`Invalid format for orgId`); }})) orgId: string,
@Body() requestProof: RequestProofDto
@Body() requestProof: RequestProofDto,
@Query('requestType') requestType:ProofRequestType = ProofRequestType.INDY
): Promise<Response> {

const attributeArray = [];
for (const attrData of requestProof.attributes) {
if (requestType === ProofRequestType.INDY) {
if (!requestProof.proofFormats) {
throw new BadRequestException(`type: ${requestType} requires proofFormats`);
}
}

if (requestType === ProofRequestType.PRESENTATIONEXCHANGE) {
if (!requestProof.presentationDefinition) {
throw new BadRequestException(`type: ${requestType} requires presentationDefinition`);
}
}
if (requestProof.proofFormats) {
const attributeArray = [];
for (const attrData of requestProof.proofFormats.indy.attributes) {
if (0 === attributeArray.length) {
attributeArray.push(Object.values(attrData)[0]);
} else if (!attributeArray.includes(Object.values(attrData)[0])) {
Expand All @@ -192,8 +208,10 @@ export class VerificationController {
}

}
}

requestProof.orgId = orgId;
requestProof.type = requestType;
const proofData = await this.verificationService.sendProofRequest(requestProof, user);
const finalResponse: IResponse = {
statusCode: HttpStatus.CREATED,
Expand Down
Loading

0 comments on commit a30a686

Please sign in to comment.