Skip to content

Commit

Permalink
Add multiple attributes in single proof request (#531)
Browse files Browse the repository at this point in the history
* feat:add multiple attributes in single proof request

Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>

* feat:add multiple attributes in single proof request

Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>

* fix: verification issue

Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>

* fix: verification issue while verifying credebtials

Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>

---------

Signed-off-by: pranalidhanavade <pranali.dhanavade@ayanworks.com>
Signed-off-by: KulkarniShashank <shashank.kulkarni@ayanworks.com>
  • Loading branch information
pranalidhanavade authored and KulkarniShashank committed Sep 11, 2024
1 parent ebd3f4e commit 86b3455
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 42 deletions.
34 changes: 27 additions & 7 deletions apps/api-gateway/src/verification/dto/request-proof.dto.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,43 @@
import { IsArray, IsBoolean, IsEmail, IsEnum, IsNotEmpty, IsNumberString, IsObject, IsOptional, IsString, IsUUID } from 'class-validator';
import { ArrayNotEmpty, IsArray, IsBoolean, IsEmail, IsEnum, IsNotEmpty, IsNumberString, IsObject, IsOptional, IsString, ValidateIf, ValidateNested, IsUUID } from 'class-validator';
import { toLowerCase, trim } from '@credebl/common/cast.helper';
import { ApiProperty, ApiPropertyOptional } from '@nestjs/swagger';
import { Transform } from 'class-transformer';
import { Transform, Type } from 'class-transformer';
import { AutoAccept } from '@credebl/enum/enum';
import { IProofFormats } from '../interfaces/verification.interface';


export class ProofRequestAttribute {
@IsString()
@IsNotEmpty({ message: 'attributeName is required.' })
attributeName: string;

@ValidateIf((obj) => obj.attributeNames === undefined)
@IsNotEmpty()
@IsString({each:true})
attributeName?: string;

@ValidateIf((obj) => obj.attributeName === undefined)
@IsArray({ message: 'attributeNames must be an array.' })
@ArrayNotEmpty({ message: 'array can not be empty' })
@IsString({ each: true})
@IsNotEmpty({ each: true, message: 'each element cannot be empty' })
attributeNames?: string[];

@ApiPropertyOptional()
@IsString()
@IsOptional()
schemaId?: string;

@ApiPropertyOptional()
@IsString()
@IsOptional()
@IsNotEmpty({ message: 'condition is required.' })
condition?: string;

@ApiPropertyOptional()
@IsOptional()
@IsNotEmpty({ message: 'value is required.' })
@IsNumberString({}, { message: 'Value must be a number' })
value?: string;

@ApiPropertyOptional()
@IsString()
@IsOptional()
credDefId?: string;
Expand Down Expand Up @@ -72,11 +86,14 @@ export class RequestProofDto extends ProofPayload {
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[];

@ApiPropertyOptional()
Expand Down Expand Up @@ -106,11 +123,14 @@ export class OutOfBandRequestProof extends ProofPayload {
credDefId: '',
schemaId: ''
}
]
],
type: () => [ProofRequestAttribute]
})
@IsArray({ message: 'attributes must be in array' })
@ValidateNested({each: true})
@IsObject({ each: true })
@IsNotEmpty({ message: 'please provide valid attributes' })
@Type(() => ProofRequestAttribute)
attributes: ProofRequestAttribute[];

@ApiProperty()
Expand Down
26 changes: 1 addition & 25 deletions apps/api-gateway/src/verification/verification.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,7 @@ export class VerificationController {
} else {
throw new BadRequestException('Please provide unique attribute names');
}

await this.validateAttribute(attrData);

}

requestProof.orgId = orgId;
Expand Down Expand Up @@ -315,27 +314,4 @@ export class VerificationController {
return res.status(HttpStatus.CREATED).json(finalResponse);

}

async validateAttribute(
attrData: object
): Promise<void> {

if (!attrData['attributeName']) {
throw new BadRequestException('attributeName must be required');
}

if (undefined !== attrData['condition'] && '' === attrData['condition'].trim()) {
throw new BadRequestException('condition cannot be empty');
}

if (undefined !== attrData['value'] && '' === attrData['value'].trim()) {
throw new BadRequestException('value cannot be empty');
}

if (attrData['condition']) {
if (isNaN(attrData['value'])) {
throw new BadRequestException('value must be an integer');
}
}
}
}
53 changes: 43 additions & 10 deletions apps/verification/src/verification.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -648,7 +648,8 @@ export class VerificationService {
try {
const getAgentDetails = await this.verificationRepository.getAgentEndPoint(orgId);
const verificationMethodLabel = 'get-verified-proof';

let credDefId;
let schemaId;
const orgAgentType = await this.verificationRepository.getOrgAgentType(getAgentDetails?.orgAgentTypeId);
const url = await this.getAgentUrl(verificationMethodLabel, orgAgentType, getAgentDetails?.agentEndPoint, getAgentDetails?.tenantId, '', proofId);
let apiKey: string = await this.cacheService.get(CommonConstants.CACHE_APIKEY_KEY);
Expand All @@ -659,27 +660,39 @@ export class VerificationService {
const payload = { apiKey, url };

const getProofPresentationById = await this._getVerifiedProofDetails(payload);

if (!getProofPresentationById?.response?.presentation) {
throw new NotFoundException(ResponseMessages.verification.error.proofPresentationNotFound, {
cause: new Error(),
description: ResponseMessages.errorMessages.notFound
});
}

const requestedAttributes = getProofPresentationById?.response?.request?.indy?.requested_attributes;
const requestedPredicates = getProofPresentationById?.response?.request?.indy?.requested_predicates;
const revealedAttrs = getProofPresentationById?.response?.presentation?.indy?.requested_proof?.revealed_attrs;


const extractedDataArray: IProofPresentationDetails[] = [];

if (requestedAttributes && requestedPredicates) {
if (0 !== Object.keys(requestedAttributes).length && 0 !== Object.keys(requestedPredicates).length) {


for (const key in requestedAttributes) {

if (requestedAttributes.hasOwnProperty(key)) {
const requestedAttributeKey = requestedAttributes[key];
const attributeName = requestedAttributeKey.name;
const credDefId = requestedAttributeKey?.restrictions[0]?.cred_def_id;
const schemaId = requestedAttributeKey?.restrictions[0]?.schema_id;

if (requestedAttributeKey?.restrictions) {

credDefId = requestedAttributeKey?.restrictions[0]?.cred_def_id;
schemaId = requestedAttributeKey?.restrictions[0]?.schema_id;
} else if (getProofPresentationById?.response?.presentation?.indy?.identifiers) {

credDefId = getProofPresentationById?.response?.presentation?.indy?.identifiers[0].cred_def_id;
schemaId = getProofPresentationById?.response?.presentation?.indy?.identifiers[0].schema_id;
}

if (revealedAttrs.hasOwnProperty(key)) {
const extractedData: IProofPresentationDetails = {
Expand Down Expand Up @@ -708,14 +721,17 @@ export class VerificationService {
}
}

} else if (requestedAttributes) {
} else if (0 !== Object.keys(requestedAttributes).length) {

for (const key in requestedAttributes) {

if (requestedAttributes.hasOwnProperty(key)) {
const attribute = requestedAttributes[key];
const attributeName = attribute.name;
const credDefId = attribute?.restrictions[0]?.cred_def_id;
const schemaId = attribute?.restrictions[0]?.schema_id;


[credDefId, schemaId] = await this._schemaCredDefRestriction(attribute, getProofPresentationById);


if (revealedAttrs.hasOwnProperty(key)) {
const extractedData: IProofPresentationDetails = {
Expand All @@ -727,14 +743,14 @@ export class VerificationService {
}
}
}
} else if (requestedPredicates) {
} else if (0 !== Object.keys(requestedPredicates).length) {
for (const key in requestedPredicates) {

if (requestedPredicates.hasOwnProperty(key)) {
const attribute = requestedPredicates[key];
const attributeName = attribute?.name;
const credDefId = attribute?.restrictions[0]?.cred_def_id;
const schemaId = attribute?.restrictions[0]?.schema_id;

[credDefId, schemaId] = await this._schemaCredDefRestriction(attribute, getProofPresentationById);

const extractedData: IProofPresentationDetails = {
[attributeName]: `${requestedPredicates?.p_type}${requestedPredicates?.p_value}`,
Expand Down Expand Up @@ -767,6 +783,23 @@ export class VerificationService {
}
}

async _schemaCredDefRestriction(attribute, getProofPresentationById): Promise<string[]> {
let credDefId;
let schemaId;

if (attribute?.restrictions) {

credDefId = attribute?.restrictions[0]?.cred_def_id;
schemaId = attribute?.restrictions[0]?.schema_id;
} else if (getProofPresentationById?.response?.presentation?.indy?.identifiers) {

credDefId = getProofPresentationById?.response?.presentation?.indy?.identifiers[0].cred_def_id;
schemaId = getProofPresentationById?.response?.presentation?.indy?.identifiers[0].schema_id;
}

return [credDefId, schemaId];
}

async _getVerifiedProofDetails(payload: IVerifiedProofData): Promise<{
response;
}> {
Expand Down

0 comments on commit 86b3455

Please sign in to comment.