Skip to content

Commit 5f2baf8

Browse files
fix: duplicate attributes in proof request (#1092)
* fix: duplicate attributes issue in proof request Signed-off-by: pranalidhanavade <[email protected]> * added common validator function file for common validations Signed-off-by: pranalidhanavade <[email protected]> * added error messages in common file Signed-off-by: pranalidhanavade <[email protected]> * resolved comments on PR Signed-off-by: pranalidhanavade <[email protected]> * resolved comments on PR Signed-off-by: pranalidhanavade <[email protected]> * fix: resolve comments on PR Signed-off-by: pranalidhanavade <[email protected]> --------- Signed-off-by: pranalidhanavade <[email protected]>
1 parent 12e763d commit 5f2baf8

File tree

7 files changed

+93
-72
lines changed

7 files changed

+93
-72
lines changed

apps/api-gateway/src/agent-service/agent-service.controller.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ import { CustomExceptionFilter } from 'apps/api-gateway/common/exception-handler
4141
import { Roles } from '../authz/decorators/roles.decorator';
4242
import { OrgRoles } from 'libs/org-roles/enums';
4343
import { OrgRolesGuard } from '../authz/guards/org-roles.guard';
44-
import { validateDid } from '@credebl/common/did.validator';
44+
import { Validator } from '@credebl/common/validator';
4545
import { CreateWalletDto } from './dto/create-wallet.dto';
4646
import { CreateNewDidDto } from './dto/create-new-did.dto';
4747
import { AgentSpinupValidator, TrimStringParamPipe } from '@credebl/common/cast.helper';
@@ -223,7 +223,7 @@ export class AgentController {
223223
@User() user: user,
224224
@Res() res: Response
225225
): Promise<Response> {
226-
await validateDid(createDidDto);
226+
Validator.validateDid(createDidDto);
227227

228228
if (createDidDto.seed && seedLength !== createDidDto.seed.length) {
229229
this.logger.error(`seed must be at most 32 characters.`);

apps/api-gateway/src/cloud-wallet/cloud-wallet.controller.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { AuthGuard } from '@nestjs/passport';
1414
import { User } from '../authz/decorators/user.decorator';
1515
// eslint-disable-next-line @typescript-eslint/no-unused-vars
1616
import { user } from '@prisma/client';
17-
import { validateDid } from '@credebl/common/did.validator';
17+
import { Validator } from '@credebl/common/validator';
1818
import { CommonConstants } from '@credebl/common/common.constant';
1919
import { UserRoleGuard } from '../authz/guards/user-role.guard';
2020
import { AcceptProofRequestDto } from './dtos/accept-proof-request.dto';
@@ -267,7 +267,7 @@ export class CloudWalletController {
267267
@User() user: user,
268268
@Res() res: Response
269269
): Promise<Response> {
270-
await validateDid(createDidDto);
270+
Validator.validateDid(createDidDto);
271271
const {email, id} = user;
272272
createDidDto.email = email;
273273
createDidDto.userId = id;

apps/api-gateway/src/verification/verification.controller.ts

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { API_Version, ProofRequestType, SortFields } from './enum/verification.e
3636
// eslint-disable-next-line @typescript-eslint/no-unused-vars
3737
import { user } from '@prisma/client';
3838
import { TrimStringParamPipe } from '@credebl/common/cast.helper';
39+
import { Validator } from '@credebl/common/validator';
3940

4041
@UseFilters(CustomExceptionFilter)
4142
@Controller()
@@ -193,19 +194,10 @@ export class VerificationController {
193194
if (requestType === ProofRequestType.PRESENTATIONEXCHANGE && !requestProof.presentationDefinition) {
194195
throw new BadRequestException(`type: ${requestType} requires presentationDefinition`);
195196
}
196-
if (requestProof.proofFormats) {
197-
const attributeArray = [];
198-
for (const attrData of requestProof.proofFormats.indy.attributes) {
199-
if (0 === attributeArray.length) {
200-
attributeArray.push(Object.values(attrData)[0]);
201-
} else if (!attributeArray.includes(Object.values(attrData)[0])) {
202-
attributeArray.push(Object.values(attrData)[0]);
203-
} else {
204-
throw new BadRequestException('Please provide unique attribute names');
205-
}
206-
207-
}
208-
}
197+
198+
if (requestType === ProofRequestType.INDY) {
199+
Validator.validateIndyProofAttributes(requestProof.proofFormats.indy.attributes);
200+
}
209201
const version = API_Version.version_neutral;
210202
requestProof.version = version;
211203
requestProof.orgId = orgId;
@@ -255,19 +247,12 @@ export class VerificationController {
255247
if (requestTypeV1 === ProofRequestType.PRESENTATIONEXCHANGE && !requestProof.presentationDefinition) {
256248
throw new BadRequestException(`type: ${requestTypeV1} requires presentationDefinition`);
257249
}
258-
if (requestProof.proofFormats) {
259-
const attributeArrayV1 = [];
260-
for (const attrData of requestProof.proofFormats.indy.attributes) {
261-
if (0 === attributeArrayV1.length) {
262-
attributeArrayV1.push(Object.values(attrData)[0]);
263-
} else if (!attributeArrayV1.includes(Object.values(attrData)[0])) {
264-
attributeArrayV1.push(Object.values(attrData)[0]);
265-
} else {
266-
throw new BadRequestException('Please provide unique attribute names');
267-
}
268250

269-
}
270-
}
251+
252+
if (requestTypeV1 === ProofRequestType.INDY) {
253+
Validator.validateIndyProofAttributes(requestProof.proofFormats.indy.attributes);
254+
}
255+
271256
const version = API_Version.VERSION_1;
272257
requestProof.version = version;
273258
requestProof.orgId = orgId;

apps/verification/src/interfaces/verification.interface.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { AutoAccept } from '@credebl/enum/enum';
22
import { IUserRequest } from '@credebl/user-request/user-request.interface';
33

4-
interface IProofRequestAttribute {
4+
export interface IProofRequestAttribute {
55
attributeName?: string;
66
attributeNames?:string[];
77
condition?: string;

libs/common/src/did.validator.ts

Lines changed: 0 additions & 40 deletions
This file was deleted.

libs/common/src/response-messages/index.ts

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,7 +257,16 @@ export const ResponseMessages = {
257257
failedOrganization: 'Failed to fetch organization agent type details',
258258
promiseReject: 'One or more promises were rejected.',
259259
orgAgentNotFound: 'Org agent type not found',
260-
walletDoesNotExists: 'Organization wallet does not exists'
260+
walletDoesNotExists: 'Organization wallet does not exists',
261+
requiredDomain: 'Domain is required for Web method',
262+
requiredNetwork: 'Network is required',
263+
keyType: 'Only ed25519 key type is supported',
264+
keyTypeWeb : 'Only ed25519 and bls12381g2 key type is supported',
265+
requiredEndorserDid: 'Role or endorser DID is required',
266+
requiredPrivateKey: 'Privatekey is required for polygon method',
267+
privateKeyLength: 'Private key must be exactly 64 characters long',
268+
requiredSeed: 'Seed is required'
269+
261270
}
262271
},
263272
connection: {
@@ -354,7 +363,8 @@ export const ResponseMessages = {
354363
batchEmailSend: 'Unable to send email in batches',
355364
emailSend: 'Unable to send email to the user',
356365
verificationRecordsNotFound: 'Verification records does not exists',
357-
removeVerificationData: 'First you have to remove verification data'
366+
removeVerificationData: 'First you have to remove verification data',
367+
uniqueAttributes:'Please provide unique attribute names'
358368
}
359369
},
360370

libs/common/src/validator.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { DidMethod } from '@credebl/enum/enum';
2+
import { IDidCreate } from './interfaces/did.interface';
3+
import { BadRequestException } from '@nestjs/common';
4+
import { ResponseMessages } from './response-messages';
5+
import { IProofRequestAttribute } from 'apps/verification/src/interfaces/verification.interface';
6+
7+
8+
export class Validator {
9+
10+
static validateDid(createDid: IDidCreate): void {
11+
const errors = [];
12+
13+
switch (true) {
14+
case DidMethod.WEB === createDid.method && !createDid.domain:
15+
errors.push(ResponseMessages.agent.error.requiredDomain);
16+
break;
17+
case (createDid.method === DidMethod.INDY || createDid.method === DidMethod.POLYGON) && !createDid.network:
18+
errors.push(ResponseMessages.agent.error.requiredNetwork);
19+
break;
20+
case (createDid.method === DidMethod.INDY || createDid.method === DidMethod.POLYGON) && 'ed25519' !== createDid.keyType:
21+
errors.push(ResponseMessages.agent.error.keyType);
22+
break;
23+
case (createDid.method === DidMethod.WEB || createDid.method === DidMethod.KEY) && !('ed25519' === createDid.keyType || 'bls12381g2' === createDid.keyType):
24+
errors.push(ResponseMessages.agent.error.keyTypeWeb);
25+
break;
26+
case DidMethod.INDY === createDid.method && !(createDid.role || createDid.endorserDid):
27+
errors.push(ResponseMessages.agent.error.requiredEndorserDid);
28+
break;
29+
case DidMethod.POLYGON === createDid.method && !createDid.privatekey:
30+
errors.push(ResponseMessages.agent.error.requiredPrivateKey);
31+
break;
32+
case DidMethod.POLYGON === createDid.method && createDid.privatekey && 64 !== createDid.privatekey.length:
33+
errors.push(ResponseMessages.agent.error.privateKeyLength);
34+
break;
35+
case (DidMethod.INDY === createDid.method || DidMethod.KEY === createDid.method || DidMethod.WEB === createDid.method) && (!createDid.seed):
36+
errors.push(ResponseMessages.agent.error.requiredSeed);
37+
break;
38+
default:
39+
break;
40+
}
41+
42+
if (0 < errors.length) {
43+
throw new BadRequestException(errors);
44+
}
45+
}
46+
47+
static validateIndyProofAttributes(attributes: IProofRequestAttribute[]): void {
48+
const seenAttributes = new Map();
49+
50+
for (const attribute of attributes) {
51+
const key = attribute.schemaId || attribute.credDefId
52+
? `${attribute.schemaId || ''}:${attribute.credDefId || ''}`
53+
: 'default';
54+
55+
if (!seenAttributes.has(key)) {
56+
seenAttributes.set(key, new Set());
57+
}
58+
59+
const attributeNames = seenAttributes.get(key);
60+
if (attributeNames.has(attribute.attributeName)) {
61+
throw new BadRequestException(ResponseMessages.verification.error.uniqueAttributes);
62+
}
63+
attributeNames.add(attribute.attributeName);
64+
}
65+
}
66+
}

0 commit comments

Comments
 (0)