Skip to content

Commit

Permalink
WIP: revocation-list-2020
Browse files Browse the repository at this point in the history
  • Loading branch information
hoa-ngo-gs committed Jul 18, 2023
1 parent 3471e76 commit 3e9f98f
Show file tree
Hide file tree
Showing 21 changed files with 8,949 additions and 5,463 deletions.
1 change: 1 addition & 0 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"@vckit/renderer": "^1.0.0-beta.5",
"@vckit/vc-api": "workspace:1.0.0-beta.5",
"@vckit/encrypted-storage": "workspace:*",
"@vckit/revocationlist": "workspace:*",
"@veramo/credential-eip712": "^5.2.0",
"@veramo/credential-ld": "^5.2.0",
"@veramo/credential-w3c": "^5.2.0",
Expand Down
3 changes: 2 additions & 1 deletion packages/core-types/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@
"ICredentialStatusVerifier": "./src/types/ICredentialStatusVerifier.ts",
"ICredentialStatusManager": "./src/types/ICredentialStatusManager.ts",
"IRenderer": "./src/types/IRender.ts",
"IEncryptedStorage": "./src/types/IEncryptedStorage.ts"
"IEncryptedStorage": "./src/types/IEncryptedStorage.ts",
"IRevocationList2020": "./src/types/IRevocationList2020.ts"
}
},
"dependencies": {
Expand Down
1 change: 1 addition & 0 deletions packages/core-types/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ export * from './types/IQRCodeEndpoint.js';
export * from './types/IRender.js';
export * from './types/IRendererProvider.js';
export * from './types/IEncryptedStorage.js';
export * from './types/IRevocationList2020.js';
21 changes: 21 additions & 0 deletions packages/core-types/src/types/IRevocationList2020.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { IPluginMethodMap, IAgent } from './IAgent';
import { Request } from 'express';

export interface IRevocationListDataArgs {
revocationListPath: string;
bitStringLength: string;
req: RequestWithAgent;
revocationVCIssuer: string;
}

export interface RequestWithAgent extends Request {
agent?: IAgent;
}

export interface IRevocationStore extends IPluginMethodMap {
getRevocationData(
args: IRevocationListDataArgs,
req: RequestWithAgent
): Promise<{ revocationListFullUrlPath: string; indexCounter: number }>;
getRevocationListVC(revocationListFullUrlPath: string): Promise<any>;
}
11 changes: 11 additions & 0 deletions packages/revocation-list-2020/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# `encrypted-storage`

> TODO: description
## Usage

```
const encryptedStorage = require('encrypted-storage');
// TODO: DEMONSTRATE API
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
'use strict';

const encryptedStorage = require('..');
const assert = require('assert').strict;

assert.strictEqual(encryptedStorage(), 'Hello from encryptedStorage');
console.info("encryptedStorage tests passed");
18 changes: 18 additions & 0 deletions packages/revocation-list-2020/api-extractor.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
"apiReport": {
"enabled": true,
"reportFolder": "./api",
"reportTempFolder": "./api"
},

"docModel": {
"enabled": true,
"apiJsonFilePath": "./api/<unscopedPackageName>.api.json"
},

"dtsRollup": {
"enabled": false
},
"mainEntryPointFilePath": "<projectFolder>/build/index.d.ts"
}
47 changes: 47 additions & 0 deletions packages/revocation-list-2020/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
{
"name": "@vckit/revocationlist",
"version": "1.0.0-beta.5",
"description": "To encrypt the data and store to the database.",
"author": "Nam Hoang <hoangxuannam160493@gmail.com>",
"homepage": "https://github.com/uncefact/project-vckit#readme",
"main": "build/index.js",
"types": "build/index.d.ts",
"exports": {
".": "./build/index.js",
"./build/plugin.schema.json": "./build/plugin.schema.json"
},
"scripts": {
"build": "tsc",
"extract-api": "node ../cli/bin/vckit.js dev extract-api"
},
"license": "Apache-2.0",
"keywords": [],
"type": "module",
"moduleDirectories": [
"node_modules",
"src"
],
"files": [
"build/**/*",
"src/**/*",
"README.md",
"LICENSE"
],
"repository": {
"type": "git",
"url": "git+https://github.com/uncefact/project-vckit.git"
},
"bugs": {
"url": "https://github.com/uncefact/project-vckit/issues"
},
"dependencies": {
"@govtechsg/oa-encryption": "^1.3.5",
"@transmute/vc-status-rl-2020": "0.7.0-unstable.81",
"@vckit/core-types": "workspace:*",
"@veramo/data-store": "^5.2.0",
"@veramo/utils": "^5.2.0",
"express-interceptor": "^1.2.0",
"typeorm": "^0.3.10",
"uuid": "^9.0.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {
BaseEntity,
BeforeInsert,
BeforeUpdate,
Column,
Entity,
PrimaryColumn,
} from 'typeorm';

@Entity('revocation-data')
export class RevocationData extends BaseEntity {
@PrimaryColumn()
revocationListUrlPath!: string;

@Column({ default: 0 })
listCounter!: number;

@Column({ default: 0 })
indexCounter!: number;

@Column({ default: 8 })
bitStringLength!: number;
}

@Entity('revocation-list')
export class RevocationList extends BaseEntity {
@PrimaryColumn()
revocationListFullUrlPath!: string;

@Column()
verifiableCredential!: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
import { createCredential, createList } from '@transmute/vc-status-rl-2020';
import { IRevocationListDataArgs } from '@vckit/core-types';
import { OrPromise } from '@veramo/utils';
import { DataSource } from 'typeorm';
import {
RevocationData,
RevocationList,
} from '../entities/revocation-list-2020-data.js';
import { RequestWithAgent } from '../revocation-list-2020-router.js';
import { getConnectedDb } from '../utils.js';

/**
* @public
*/
export class RevocationDataStore {
constructor(private dbConnection: OrPromise<DataSource>) {}

async createRevocationListVC(
revocationListFullUrlPath: string,
bitStringLength: number,
revocationVCIssuer: string,
req: RequestWithAgent
): Promise<any> {
try {
if (!req.agent) {
throw Error('Agent not available');
}

const list = await createList({ length: bitStringLength });
const credentialList = await createCredential({
id: revocationListFullUrlPath,
list,
});

// @ts-ignore
credentialList.issuer = revocationVCIssuer;

const { credential, ...rest } = req.body;

// Issue RevocationList VC
const revocationList = await req.agent.execute(
'createVerifiableCredential',
{
credential: credentialList,
...rest,
}
);

return revocationList;
} catch (err) {
throw err;
}
}

async getRevocationData(
args: IRevocationListDataArgs
): Promise<{ revocationListFullUrlPath: string; indexCounter: number }> {
try {
const {
revocationListPath: revocationListUrlPath,
revocationVCIssuer,
bitStringLength,
req,
} = args;
const db = await getConnectedDb(this.dbConnection);

let revocationData = await db
.getRepository(RevocationData)
.findOne({ where: { revocationListUrlPath } });

if (!revocationData) {
revocationData = await db.getRepository(RevocationData).save({
revocationListUrlPath,
bitStringLength: Number(bitStringLength),
});
}

const revocationListFullUrlPath = `/credentials/status/revocation-list-2020/${revocationData.listCounter}`;

let revocationList = await db.getRepository(RevocationList).findOne({
where: {
revocationListFullUrlPath,
},
});

// Not available - create one
if (!revocationList) {
revocationList = await this.createRevocationListVC(
`${revocationListUrlPath}${revocationListFullUrlPath}`,
Number(bitStringLength),
revocationVCIssuer,
req
);

await db.getRepository(RevocationList).save({
revocationListFullUrlPath,
verifiableCredential: JSON.stringify(revocationList),
});
}

await this.updateRevocationData({
revocationData,
args,
});

return {
revocationListFullUrlPath,
indexCounter: revocationData.indexCounter,
};
} catch (err) {
throw new Error(err);
}
}

async updateRevocationData({
revocationData,
args,
}: {
revocationData: RevocationData;
args: IRevocationListDataArgs;
}): Promise<void> {
try {
const db = await getConnectedDb(this.dbConnection);

let nextIndex = revocationData.indexCounter + 1;
let nextList = revocationData.listCounter;
let nextBitStringLength = revocationData.bitStringLength;

// Check if we need to update the bit string length
if (
Number(args.bitStringLength) != revocationData.bitStringLength ||
nextIndex >= revocationData.bitStringLength
) {
nextList += 1;
nextIndex = 0;

if (Number(args.bitStringLength) != revocationData.bitStringLength) {
nextBitStringLength = Number(args.bitStringLength);
}

const revocationListFullUrlPath = `/credentials/status/revocation-list-2020/${nextList}`;

const revocationList = await this.createRevocationListVC(
`${args.revocationListPath}${revocationListFullUrlPath}`,
Number(args.bitStringLength),
args.revocationVCIssuer,
args.req
);

await db.getRepository(RevocationList).save({
revocationListFullUrlPath,
verifiableCredential: JSON.stringify(revocationList),
});
}

const d = await db.getRepository(RevocationData).save({
revocationListUrlPath: revocationData.revocationListUrlPath,
indexCounter: nextIndex,
listCounter: nextList,
bitStringLength: nextBitStringLength,
});
} catch (err) {
// Handle Errors here
throw new Error(err);
}
}

async getRevocationListVC(revocationListFullUrlPath: string) {
try {
const db = await getConnectedDb(this.dbConnection);

const revocationList = await db.getRepository(RevocationList).findOne({
where: {
revocationListFullUrlPath,
},
});

if (!revocationList) {
throw new Error('Revocation List not found');
}

return JSON.parse(revocationList.verifiableCredential);
} catch (err) {
throw new Error(err);
}
}
}
12 changes: 12 additions & 0 deletions packages/revocation-list-2020/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {
RevocationData,
RevocationList,
} from './entities/revocation-list-2020-data.js';

export { RevocationDataStore } from './identifier/revocation-list-2020-store.js';
export { RevocationStatus2020 } from './revocation-list-2020.js';
export { migrations } from './migrations/index.js';
export { revocationList2020 } from './revocation-list-2020-middleware.js';
export { revocationList2020Router } from './revocation-list-2020-router.js';

export const Entities = [RevocationData, RevocationList];
Loading

0 comments on commit 3e9f98f

Please sign in to comment.