diff --git a/__test__/claim/Claim.test.js b/__test__/claim/Claim.test.js index d6e4d0f0..d929cace 100644 --- a/__test__/claim/Claim.test.js +++ b/__test__/claim/Claim.test.js @@ -277,7 +277,7 @@ describe('Claim Constructions tests', () => { expect(uca.value).toBeDefined(); }); - test.skip('Transforming UCA to Claim', async () => { + test('Transforming UCA to Claim', async () => { const identifier = 'cvc:Identity:dateOfBirth'; const value = { day: 20, @@ -298,9 +298,10 @@ describe('Claim Constructions tests', () => { expect(dateOfBirthClaim.value).toBeDefined(); expect(dateOfBirthClaim.value.day).toBeDefined(); expect(dateOfBirthClaim.value.day.value).toBe(20); + expect(dateOfBirthClaim.identifier).toBe('claim-cvc:Identity.dateOfBirth-v1'); }); - test.skip('Transforming alias UCA to Claim', async () => { + test('Transforming alias UCA to Claim', async () => { const identifier = 'cvc:Document:evidences'; const aliasIdentifier = 'cvc:Validation:evidences'; const value = { diff --git a/__test__/creds/VerifiableCredential.test.js b/__test__/creds/VerifiableCredential.test.js index 5f64177d..29741f95 100644 --- a/__test__/creds/VerifiableCredential.test.js +++ b/__test__/creds/VerifiableCredential.test.js @@ -431,7 +431,7 @@ describe('Unit tests for Verifiable Credentials', () => { const presentation = await VC.fromJSON(filteredCredentialJson, true); expect(presentation).toBeDefined(); - expect(VC.fromJSON(filteredCredentialJson)).rejects.toThrow(); + return expect(VC.fromJSON(filteredCredentialJson)).rejects.toThrow(); }); it('Should create alt:Identity-v1 credential', async () => { @@ -708,12 +708,6 @@ describe('Unit tests for Verifiable Credentials', () => { expect(await cred.verify()).toBeGreaterThanOrEqual(VC.VERIFY_LEVELS.PROOFS); }); - it('Should verify an VC with no cryptographic security', async () => { - const credential = require('./fixtures/PhoneNumber.json'); // eslint-disable-line - const isValid = await VC.nonCryptographicallySecureVerify(credential); - expect(isValid).toBeTruthy(); - }); - it('Should verify an credential json with no cryptographic security', async () => { const credential = require('./fixtures/PhoneNumber.json'); // eslint-disable-line const isValid = await VC.nonCryptographicallySecureVerify(credential); diff --git a/package-lock.json b/package-lock.json index 64537587..f662338a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@identity.com/credential-commons", - "version": "2.0.0-beta.4", + "version": "2.0.0-beta.8", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 4684d953..aff901eb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@identity.com/credential-commons", - "version": "2.0.0-beta.5", + "version": "2.0.0-beta.8", "author": "Identity.com Community", "license": "MIT", "description": "Verifiable Credential and Attestation Library", diff --git a/src/schemas/jsonSchema/index.js b/src/schemas/jsonSchema/index.js index ed813a06..c64dadc8 100644 --- a/src/schemas/jsonSchema/index.js +++ b/src/schemas/jsonSchema/index.js @@ -100,7 +100,10 @@ class SummaryMapper { identifierComponents = _.split(identifier, ':'); isNewIdentifier = false; } - return { identifierComponents, isNewIdentifier }; + return { + identifierComponents, + isNewIdentifier, + }; } static getPath(identifier) { @@ -119,6 +122,16 @@ const getSchemaVersion = (identifier) => { return '1'; }; +function transformUcaIdToClaimId(identifier) { + const identifierComponents = identifier.split(':'); + return `claim-cvc:${identifierComponents[1]}.${identifierComponents[2]}-v1`; +} + +function isDefinitionEqual(definition, ucaDefinition) { + return definition.identifier === transformUcaIdToClaimId(ucaDefinition) + || definition.identifier === ucaDefinition; +} + /** * This class loads the schema definitions as needed by using loaders provided by the @@ -131,6 +144,7 @@ class SchemaLoader { this.summaryMap = summaryMap; this.validIdentifiers = []; this.validCredentialIdentifiers = []; + this.ucaCompared = []; this.ajv = new Ajv({ logger: console, allErrors: true, @@ -232,7 +246,37 @@ class SchemaLoader { SummaryMapper.addCredentialDefinition(definition); } + async shouldAddClaimDefinition(schema) { + if (/^[^:]+:[^:]+:[^:]+$/.test(schema.title)) { + const transformed = transformUcaIdToClaimId(schema.title); + + if (!this.ucaCompared.includes(schema.title)) { + await this.loadSchemaFromTitle(transformed); + } + + this.ucaCompared.push(schema.title); + + let found = false; + this.definitions.some((definition) => { + if (isDefinitionEqual(definition, schema.title)) { + found = true; + } + return found; + }); + + if (found) { + return false; + } + } + + return true; + } + async addClaimDefinition(schema) { + if (!(await this.shouldAddClaimDefinition(schema))) { + return; + } + const definition = { identifier: schema.title, version: getSchemaVersion(schema.title), @@ -362,20 +406,12 @@ class SchemaLoader { return null; } - try { - this.ajv.addSchema(schema); - } catch (e) { - // TODO: This could only happen if we have a cyclic dependency, or the same ref multiple times in the schema... - return schema; - } - - await this.addDefinition(schema); - + // Loads all referenced schemas const references = []; traverse(schema, { cb: (currentNode) => { if (currentNode.$ref !== undefined) { - // TODO: Prevent the same schema loaded multiple times + // Prevent the same schema loaded multiple times references.push(this.loadSchemaFromUri(currentNode.$ref)); } }, @@ -383,6 +419,15 @@ class SchemaLoader { await Promise.all(references); + try { + this.ajv.addSchema(schema); + } catch (e) { + // This could only happen if we have a cyclic dependency, or the same ref multiple times in the schema... + return schema; + } + + await this.addDefinition(schema); + return schema; } diff --git a/src/schemas/jsonSchema/loaders/cvc.js b/src/schemas/jsonSchema/loaders/cvc.js index cb4995ff..7324f032 100644 --- a/src/schemas/jsonSchema/loaders/cvc.js +++ b/src/schemas/jsonSchema/loaders/cvc.js @@ -73,20 +73,20 @@ class CVCLoader { */ async loadSchema(identifier) { let schema = null; - if (this.cache !== null) { + if (this.cache) { schema = this.cache.get(identifier); } // Only load the schema remotely if a base url was provided and none was found locally - if (schema === null) { + if (!schema) { schema = await this.remote(identifier); - if (this.cache !== null && schema !== null) { + if (this.cache && schema) { this.cache.set(identifier, schema); } } - return schema == null ? null : JSON.parse(schema); + return !schema ? null : JSON.parse(schema); } /**