Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TECH-334 feat: support for aggregate $and, $or constraints #8

Open
wants to merge 11 commits into
base: identity.com_release_v3.0.2
Choose a base branch
from
69 changes: 35 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

*Warning:* this still is a working in progress and is not ready for usage yet. Please feel free to explore the code but don't integrate yet. We expect API changes before the 1st release.

[![CircleCI](https://circleci.com/gh/identity-com/credential-commons.svg?style=svg)](https://circleci.com/gh/identity-com/credential-commons)
[![NPM](https://img.shields.io/npm/v/%40identity.com/credential-commons.svg)](https://www.npmjs.com/package/@identity.com/credential-commons)
[![CircleCI](https://circleci.com/gh/civic/credential-commons.svg?style=svg)](https://circleci.com/gh/civic/credential-commons)
[![NPM](https://img.shields.io/npm/v/%40identity.com/credential-commons.svg)](https://www.npmjs.com/package/@civic/credential-commons)


## Summary
Expand All @@ -12,37 +12,38 @@ This Javascript Library provides functionality around Verifiable Credentials (VC

## Contents

- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Commands](#commands)
- [Configuration](#configuration)
* [Etc Config File /etc/civic/config](#etc-config-file--etc-civic-config)
* [User Config File ~/.civic/config](#user-config-file---civic-config)
- [Features](#features)
* [User Collectable Attributes](#user-collectable-attributes)
+ [Defining new Claim](#defining-new-claim)
+ [Exporting Claim to the Claim Registry Services](#exporting-claim-to-the-claim-registry-services)
+ [Using a Claim in javascript (with this library)](#using-a-claim-in-javascript--with-this-library-)
- [creating Claim instances with the constructor](#creating-claim-instances-with-the-constructor)
* [Credentials](#credentials)
+ [Defining new Claim](#defining-new-claim-1)
+ [Exporting Claim to the Claim Registry Services](#exporting-claim-to-the-claim-registry-services-1)
+ [Using a VerifiableCredential in javascript (with this library)](#using-a-verifiablecredential-in-javascript--with-this-library-)
- [creating VerifiableCredential instances with the constructor](#creating-verifiablecredential-instances-with-the-constructor)
- [anchoring VerifiableCredential instances with the constructor](#anchoring-verifiablecredential-instances-with-the-constructor)
- [refreshing an anchor (temp => permanent) VerifiableCredential instances with the constructor](#refreshing-an-anchor--temp----permanent--verifiablecredential-instances-with-the-constructor)
- [Verifiable Credential Sample](#verifiable-credential-sample)
- [Construting a VerifiableCredential from a JSON](#construting-a-verifiablecredential-from-a-json)
- [Verifying a Verifiable Credential](#verifying-a-verifiable-credential)
- [Schema Generator](#schema-generator)

- [Conventions:](#conventions-)
* [Publishing schemas](#publishing-schemas)
- [Commands](#commands)
- [Integration with CCS Libraries](#integration-with-ccs-libraries)
- [ES5 and ES6 definitions](#es5-and-es6-definitions)
- [Node vs React usage of this library](#node-vs-react-usage-of-this-library)
- [Releases](#releases)
- [Identity.com Verifiable Credential Library](#identitycom-verifiable-credential-library)
- [Summary](#summary)
- [Contents](#contents)
- [Prerequisites](#prerequisites)
- [Installation ](#installation)
- [Commands](#commands)
- [Configuration](#configuration)
- [Etc Config File /etc/civic/config](#etc-config-file-etccivicconfig)
- [User Config File ~/.civic/config](#user-config-file-civicconfig)
- [incode](#incode)
- [Features](#features)
- [User Collectable Attributes](#user-collectable-attributes)
- [Using a Claim in javascript (with this library)](#using-a-claim-in-javascript-with-this-library)
- [creating Claim instances with the async `create` function](#creating-claim-instances-with-the-async-create-function)
- [Credentials](#credentials)
- [Defining new Claim](#defining-new-claim)
- [Using a VerifiableCredential in javascript (with this library)](#using-a-verifiablecredential-in-javascript-with-this-library)
- [creating VerifiableCredential instances with the constructor](#creating-verifiablecredential-instances-with-the-constructor)
- [creating VerifiableCredential with evidence](#creating-verifiablecredential-with-evidence)
- [anchoring VerifiableCredential instances with the constructor](#anchoring-verifiablecredential-instances-with-the-constructor)
- [refreshing an anchor (temp =\> permanent) VerifiableCredential instances with the constructor](#refreshing-an-anchor-temp--permanent-verifiablecredential-instances-with-the-constructor)
- [Granting the Credential Usage(for single user) from the owner](#granting-the-credential-usagefor-single-user-from-the-owner)
- [Granting](#granting)
- [Verify if is Granted](#verify-if-is-granted)
- [Verifiable Credential Sample](#verifiable-credential-sample)
- [Construting a VerifiableCredential from a JSON](#construting-a-verifiablecredential-from-a-json)
- [Verifying a Verifiable Credential](#verifying-a-verifiable-credential)
- [Loading schemas](#loading-schemas)
- [Conventions:](#conventions)
- [ES5 and ES6 definitions](#es5-and-es6-definitions)
- [Node vs React usage of this library](#node-vs-react-usage-of-this-library)
- [Releases](#releases)

## Prerequisites

Expand All @@ -62,7 +63,7 @@ node src/index.js decrypt
## Installation 
Credential commons is an open-source library that has its binary package published on NPM.
Projects that depend on credential-commons must install the dependency following this way:
`npm install --save @identity.com/credential-commons`
`npm install --save @civic/credential-commons`

All versions follow SemVer (https://semver.org/)

Expand Down
131 changes: 131 additions & 0 deletions __test__/creds/VerifiableCredential.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1232,6 +1232,137 @@ describe('Unit tests for Verifiable Credentials', () => {
})).toBeTruthy();
});

describe('with an aggregate constraint', () => {
describe('$and', () => {
it('Should pass with both matching constraints', async () => {
const name = await Claim.create('claim-cvc:Identity.name-v1', identityName);
const dob = await Claim.create('claim-cvc:Identity.dateOfBirth-v1', identityDateOfBirth);
const cred = await VC.create('credential-cvc:Identity-v3', uuidv4(), null, credentialSubject, [name, dob]);
const timestampBeforeDOB = new Date(identityDateOfBirth.year - 2, 1, 1).getTime() / 1000;
expect(cred.isMatch({
claims: [
{
path: '$and',
is: [
{ 'identity.dateOfBirth': { $lt: '-20y' } },
{ 'identity.dateOfBirth': { $gt: timestampBeforeDOB } },
],
},
],
})).toBeTruthy();
});

it('Should fail if one of the matching $and constraints fails', async () => {
const name = await Claim.create('claim-cvc:Identity.name-v1', identityName);
const dob = await Claim.create('claim-cvc:Identity.dateOfBirth-v1', identityDateOfBirth);
const cred = await VC.create('credential-cvc:Identity-v3', uuidv4(), null, credentialSubject, [name, dob]);
const timestampBeforeDOB = new Date(identityDateOfBirth.year - 2, 1, 1).getTime() / 1000;
expect(cred.isMatch({
claims: [
{
path: '$and',
is: [
{ 'identity.dateOfBirth': { $lt: '-100y' } },
{ 'identity.dateOfBirth': { $gt: timestampBeforeDOB } },
],
},
],
})).toBeFalsy();
});

it('Should fail if both of the constraints fail', async () => {
const name = await Claim.create('claim-cvc:Identity.name-v1', identityName);
const dob = await Claim.create('claim-cvc:Identity.dateOfBirth-v1', identityDateOfBirth);
const cred = await VC.create('credential-cvc:Identity-v3', uuidv4(), null, credentialSubject, [name, dob]);
const timestampAfterDOB = new Date(identityDateOfBirth.year + 2, 1, 1).getTime() / 1000;
expect(cred.isMatch({
claims: [
{
path: '$and',
is: [
{ 'identity.dateOfBirth': { $lt: '-100y' } },
{ 'identity.dateOfBirth': { $gt: timestampAfterDOB } },
],
},
],
})).toBeFalsy();
});
});

describe('$or', () => {
it('Should pass with both matching constraints', async () => {
const name = await Claim.create('claim-cvc:Identity.name-v1', identityName);
const dob = await Claim.create('claim-cvc:Identity.dateOfBirth-v1', identityDateOfBirth);
const cred = await VC.create('credential-cvc:Identity-v3', uuidv4(), null, credentialSubject, [name, dob]);
const timestampBeforeDOB = new Date(identityDateOfBirth.year - 2, 1, 1).getTime() / 1000;
expect(cred.isMatch({
claims: [
{
path: '$or',
is: [
{ 'identity.dateOfBirth': { $lt: '-20y' } },
{ 'identity.dateOfBirth': { $gt: timestampBeforeDOB } },
],
},
],
})).toBeTruthy();
});

it('Should pass if one of the matching constraints fails', async () => {
const name = await Claim.create('claim-cvc:Identity.name-v1', identityName);
const dob = await Claim.create('claim-cvc:Identity.dateOfBirth-v1', identityDateOfBirth);
const cred = await VC.create('credential-cvc:Identity-v3', uuidv4(), null, credentialSubject, [name, dob]);
const timestampBeforeDOB = new Date(identityDateOfBirth.year - 2, 1, 1).getTime() / 1000;
expect(cred.isMatch({
claims: [
{
path: '$or',
is: [
{ 'identity.dateOfBirth': { $lt: '-100y' } },
{ 'identity.dateOfBirth': { $gt: timestampBeforeDOB } },
],
},
],
})).toBeTruthy();
});

it('Should fail if both of the constraints fail', async () => {
const name = await Claim.create('claim-cvc:Identity.name-v1', identityName);
const dob = await Claim.create('claim-cvc:Identity.dateOfBirth-v1', identityDateOfBirth);
const cred = await VC.create('credential-cvc:Identity-v3', uuidv4(), null, credentialSubject, [name, dob]);
const timestampAfterDOB = new Date(identityDateOfBirth.year + 2, 1, 1).getTime() / 1000;
expect(cred.isMatch({
claims: [
{
path: '$or',
is: [
{ 'identity.dateOfBirth': { $lt: '-100y' } },
{ 'identity.dateOfBirth': { $gt: timestampAfterDOB } },
],
},
],
})).toBeFalsy();
});

it('Should allow a null constraint to pass if the path is missing', async () => {
const name = await Claim.create('claim-cvc:Identity.name-v1', identityName);
const cred = await VC.create('credential-cvc:Identity-v3', uuidv4(), null, credentialSubject, [name]);
const timestampAfterDOB = new Date(identityDateOfBirth.year + 2, 1, 1).getTime() / 1000;
expect(cred.isMatch({
claims: [
{
path: '$or',
is: [
{ 'identity.dateOfBirth': { $eq: null } },
{ 'identity.dateOfBirth': { $gt: timestampAfterDOB } },
],
},
],
})).toBeTruthy();
});
});
});

it('Should not match', async () => {
const name = await Claim.create('claim-cvc:Identity.name-v1', identityName);
const dob = await Claim.create('claim-cvc:Identity.dateOfBirth-v1', identityDateOfBirth);
Expand Down
Loading