From cf2c41ff119f11d75bef1a23b4a18f1171830ef7 Mon Sep 17 00:00:00 2001 From: David McFadzean Date: Thu, 25 Jul 2024 16:54:08 -0400 Subject: [PATCH] refactor: Fixed sonarjs lint warnings (#254) * Fixed sonarjs/prefer-immediate-return warnings * Fixed eqeqeq warnings * Fixed sonarjs/no-collapsible-if warnings * Standardized expected exceptions in unit tests * Removed warnings report * Added standard exceptions.js * Added file links to keymaster-app * Refactored wallet exceptions * Refactored createDID exceptions * Consolidated gatekeeper exceptions * Consolidated keymaster exceptions * Added @babel dependency to remove warning * Consolidated poll exceptions * Consolidated more keymaster exceptions * Removed wallet exception * Fixed gk build * Fixed CLI error messages * Consolidated CLI status messages * Refactored isEmpty * Rephrased test descriptions * Refactored jest config * Removed last lint warning * Removed 'only-warn' from lint reporting --- .eslintignore | 3 +- .eslintrc.json | 5 +- Dockerfile.gatekeeper | 2 + jest.config.js | 4 +- package-lock.json | 26 +- package.json | 1 + rebuildGatekeeper | 2 + src/cipher-lib.js | 14 +- src/db-json.js | 8 +- src/db-mongodb.js | 10 +- src/db-sqlite.js | 16 +- src/db-wallet-json.js | 5 +- src/exceptions.js | 11 + src/gatekeeper-lib.js | 85 +++---- src/gatekeeper.test.js | 196 +++++++++++---- src/hyperswarm-mediator.js | 4 +- src/kc-app/package-lock.json | 28 ++- src/kc-app/package.json | 3 + src/kc-app/src/KeymasterUI.js | 3 +- src/keychain-cli.js | 155 ++++++------ src/keymaster-app/package-lock.json | 28 ++- src/keymaster-app/package.json | 3 + src/keymaster-app/src/KeymasterUI.js | 3 +- src/keymaster-app/src/db-wallet-web.js | 5 +- src/keymaster-app/src/exceptions.js | 11 + src/keymaster-app/src/keymaster-lib.js | 271 +++++++++----------- src/keymaster-lib.js | 271 +++++++++----------- src/keymaster.test.js | 335 +++++++++++++------------ 28 files changed, 826 insertions(+), 682 deletions(-) create mode 100644 src/exceptions.js create mode 100644 src/keymaster-app/src/exceptions.js diff --git a/.eslintignore b/.eslintignore index 6e2d1d06..0133f3b3 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,3 @@ data/ -keymaster-app/ +src/kc-app/build/ +src/keymaster-app/build/ diff --git a/.eslintrc.json b/.eslintrc.json index a0e96e79..6d6694a8 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,7 +5,7 @@ "node": true, "jest": true }, - "plugins": ["sonarjs", "only-warn"], + "plugins": ["sonarjs"], "extends": ["plugin:sonarjs/recommended-legacy","react-app"], "parserOptions": { "ecmaVersion": "latest", @@ -16,6 +16,5 @@ "error", 4 ] - } -} \ No newline at end of file +} diff --git a/Dockerfile.gatekeeper b/Dockerfile.gatekeeper index 11d78d93..14b042ee 100644 --- a/Dockerfile.gatekeeper +++ b/Dockerfile.gatekeeper @@ -16,6 +16,8 @@ RUN cd keymaster-app && npm ci COPY src/keymaster-app/public ./keymaster-app/public/ COPY src/keymaster-app/src ./keymaster-app/src/ +COPY src/keymaster-lib.js ./keymaster-app/src/ +COPY src/exceptions.js ./keymaster-app/src/ RUN cd keymaster-app && npm run build # Copy app diff --git a/jest.config.js b/jest.config.js index bfcebcb2..ccf78c17 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,4 +1,4 @@ -export default { +const config = { transform: {}, testEnvironment: 'node', moduleFileExtensions: ['js', 'mjs'], @@ -8,3 +8,5 @@ export default { "/keymaster-app/" ], }; + +export default config; diff --git a/package-lock.json b/package-lock.json index d2824906..89853c8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,6 +35,7 @@ "uuid": "^9.0.1" }, "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "eslint": "^8.57.0", "eslint-config-react-app": "^7.0.1", "eslint-plugin-only-warn": "^1.1.0", @@ -764,9 +765,17 @@ } }, "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "version": "7.21.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", + "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead.", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, "engines": { "node": ">=6.9.0" }, @@ -2044,6 +2053,17 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-env/node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/preset-env/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", diff --git a/package.json b/package.json index 52b1c27b..d414285d 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "uuid": "^9.0.1" }, "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", "eslint": "^8.57.0", "eslint-config-react-app": "^7.0.1", "eslint-plugin-only-warn": "^1.1.0", diff --git a/rebuildGatekeeper b/rebuildGatekeeper index f39c551e..725555e9 100755 --- a/rebuildGatekeeper +++ b/rebuildGatekeeper @@ -1,5 +1,7 @@ #!/usr/bin/env bash set -e +cp src/exceptions.js src/keymaster-app/src +cp src/keymaster-lib.js src/keymaster-app/src npm --prefix src/keymaster-app run build node src/gatekeeper-api.js diff --git a/src/cipher-lib.js b/src/cipher-lib.js index 552d9760..999c76d0 100644 --- a/src/cipher-lib.js +++ b/src/cipher-lib.js @@ -23,8 +23,7 @@ export function generateMnemonic() { export function generateHDKey(mnemonic) { const seed = bip39.mnemonicToSeedSync(mnemonic); - const hdkey = HDKey.fromMasterSeed(seed); - return hdkey; + return HDKey.fromMasterSeed(seed); } export function generateHDKeyJSON(json) { @@ -76,8 +75,7 @@ export function convertJwkToCompressedBytes(jwk) { export function hashMessage(msg) { const hash = sha256(msg); - const msgHash = Buffer.from(hash).toString('hex'); - return msgHash; + return Buffer.from(hash).toString('hex'); } export function hashJSON(json) { @@ -87,15 +85,15 @@ export function hashJSON(json) { export function signHash(msgHash, privateJwk) { const privKey = base64url.baseDecode(privateJwk.d); const signature = secp.sign(msgHash, privKey); - const sigHex = signature.toCompactHex(); - return sigHex; + + return signature.toCompactHex(); } export function verifySig(msgHash, sigHex, publicJwk) { const compressedPublicKeyBytes = convertJwkToCompressedBytes(publicJwk); const signature = secp.Signature.fromCompact(sigHex); - const isValid = secp.verify(signature, msgHash, compressedPublicKeyBytes); - return isValid; + + return secp.verify(signature, msgHash, compressedPublicKeyBytes); } export function encryptMessage(pubKey, privKey, message) { diff --git a/src/db-json.js b/src/db-json.js index efc5d703..878f519f 100644 --- a/src/db-json.js +++ b/src/db-json.js @@ -1,4 +1,5 @@ import fs from 'fs'; +import * as exceptions from './exceptions.js'; const dataFolder = 'data'; let dbName; @@ -39,7 +40,7 @@ export async function addEvent(did, event) { const db = loadDb(); if (!did) { - throw "Invalid DID"; + throw exceptions.INVALID_DID; } const suffix = did.split(':').pop(); @@ -74,7 +75,7 @@ export async function getEvents(did) { export async function setEvents(did, events) { if (!did) { - throw "Invalid DID"; + throw exceptions.INVALID_DID; } const db = loadDb(); @@ -156,6 +157,5 @@ export async function clearQueue(registry, batch) { export async function getAllKeys() { const db = loadDb(); - const ids = Object.keys(db.dids); - return ids; + return Object.keys(db.dids); } diff --git a/src/db-mongodb.js b/src/db-mongodb.js index 75275dd5..315b352e 100644 --- a/src/db-mongodb.js +++ b/src/db-mongodb.js @@ -1,5 +1,6 @@ import { MongoClient } from 'mongodb'; import config from './config.js'; +import * as exceptions from './exceptions.js'; let client; let db; @@ -21,7 +22,7 @@ export async function resetDb() { export async function addEvent(did, event) { if (!did) { - throw "Invalid DID"; + throw exceptions.INVALID_DID; } const id = did.split(':').pop(); @@ -37,7 +38,7 @@ export async function addEvent(did, event) { export async function getEvents(did) { if (!did) { - throw "Invalid DID"; + throw exceptions.INVALID_DID; } try { @@ -54,7 +55,7 @@ export async function getEvents(did) { export async function deleteEvents(did) { if (!did) { - throw "Invalid DID"; + throw exceptions.INVALID_DID; } const id = did.split(':').pop(); @@ -63,8 +64,7 @@ export async function deleteEvents(did) { export async function getAllKeys() { const rows = await db.collection('dids').find().toArray(); - const ids = rows.map(row => row.id); - return ids; + return rows.map(row => row.id); } export async function queueOperation(registry, op) { diff --git a/src/db-sqlite.js b/src/db-sqlite.js index de0c7fff..8c7d5db4 100644 --- a/src/db-sqlite.js +++ b/src/db-sqlite.js @@ -1,5 +1,6 @@ import * as sqlite from 'sqlite'; import sqlite3 from 'sqlite3'; +import * as exceptions from './exceptions.js'; const dataFolder = 'data'; @@ -34,7 +35,7 @@ export async function resetDb() { export async function addEvent(did, event) { if (!did) { - throw "Invalid DID"; + throw exceptions.INVALID_DID; } const events = await getEvents(did); @@ -49,7 +50,7 @@ export async function addEvent(did, event) { export async function getEvents(did) { if (!did) { - throw "Invalid DID"; + throw exceptions.INVALID_DID; } try { @@ -57,8 +58,7 @@ export async function getEvents(did) { console.time("SELECT"); const row = await db.get('SELECT * FROM dids WHERE id = ?', id); console.timeEnd("SELECT"); - const events = JSON.parse(row.events); - return events; + return JSON.parse(row.events); } catch { return []; @@ -67,7 +67,7 @@ export async function getEvents(did) { export async function deleteEvents(did) { if (!did) { - throw "Invalid DID"; + throw exceptions.INVALID_DID; } const id = did.split(':').pop(); @@ -90,8 +90,7 @@ export async function getQueue(registry) { return []; } - const ops = JSON.parse(row.ops); - return ops; + return JSON.parse(row.ops); } catch { return []; @@ -114,6 +113,5 @@ export async function clearQueue(registry, batch) { export async function getAllKeys() { const rows = await db.all('SELECT id FROM dids'); - const ids = rows.map(row => row.id); - return ids; + return rows.map(row => row.id); } diff --git a/src/db-wallet-json.js b/src/db-wallet-json.js index 3747a742..5a0641a8 100644 --- a/src/db-wallet-json.js +++ b/src/db-wallet-json.js @@ -1,5 +1,6 @@ import fs from 'fs'; import * as cipher from './cipher-lib.js'; +import * as exceptions from './exceptions.js'; const dataFolder = 'data'; const walletName = `${dataFolder}/wallet.json`; @@ -25,7 +26,7 @@ export function loadWallet() { export function newWallet(mnemonic, overwrite) { if (fs.existsSync(walletName) && !overwrite) { - throw "Wallet already exists"; + throw exceptions.UPDATE_FAILED; } try { @@ -49,6 +50,6 @@ export function newWallet(mnemonic, overwrite) { return wallet; } catch (error) { - throw "Invalid mnemonic"; + throw exceptions.INVALID_PARAMETER; } } diff --git a/src/exceptions.js b/src/exceptions.js new file mode 100644 index 00000000..5a0bc1dd --- /dev/null +++ b/src/exceptions.js @@ -0,0 +1,11 @@ +export const INVALID_DID = new Error('Invalid DID'); +export const UNKNOWN_DID = new Error('Unknown DID'); +export const UNKNOWN_ID = new Error('Unknown ID'); +export const INVALID_UPDATE = new Error('Invalid update'); +export const INVALID_OPERATION = new Error('Invalid operation'); +export const INVALID_VERSION = new Error('Invalid version'); +export const INVALID_TYPE = new Error('Invalid type'); +export const INVALID_REGISTRY = new Error('Invalid registry'); +export const INVALID_PARAMETER = new Error('Invalid parameter'); +export const UPDATE_FAILED = new Error('Update failed'); +export const EXPECTED_EXCEPTION = new Error('Expected to throw an exception'); diff --git a/src/gatekeeper-lib.js b/src/gatekeeper-lib.js index 28a35e95..80091257 100644 --- a/src/gatekeeper-lib.js +++ b/src/gatekeeper-lib.js @@ -4,6 +4,7 @@ import canonicalize from 'canonicalize'; import { createHelia } from 'helia'; import * as cipher from './cipher-lib.js'; import config from './config.js'; +import * as exceptions from './exceptions.js'; const validVersions = [1]; const validTypes = ['agent', 'asset']; @@ -80,37 +81,34 @@ export async function resetDb() { export async function anchorSeed(seed) { const cid = await ipfs.add(JSON.parse(canonicalize(seed))); - const did = `${config.didPrefix}:${cid.toString(base58btc)}`; - return did; + return `${config.didPrefix}:${cid.toString(base58btc)}`; } async function verifyCreateAgent(operation) { if (!operation.signature) { - throw "Invalid operation"; + throw exceptions.INVALID_OPERATION; } if (!operation.publicJwk) { - throw "Invalid operation"; + throw exceptions.INVALID_OPERATION; } const operationCopy = JSON.parse(JSON.stringify(operation)); delete operationCopy.signature; const msgHash = cipher.hashJSON(operationCopy); - const isValid = cipher.verifySig(msgHash, operation.signature.value, operation.publicJwk); - - return isValid; + return cipher.verifySig(msgHash, operation.signature.value, operation.publicJwk); } async function verifyCreateAsset(operation) { - if (operation.controller !== operation.signature.signer) { - throw "Invalid operation"; + if (operation.controller !== operation.signature?.signer) { + throw exceptions.INVALID_OPERATION; } const doc = await resolveDID(operation.signature.signer, { atTime: operation.signature.signed }); if (doc.mdip.registry === 'local' && operation.mdip.registry !== 'local') { - throw "Invalid operation"; + throw exceptions.INVALID_OPERATION; } const operationCopy = JSON.parse(JSON.stringify(operation)); @@ -118,35 +116,33 @@ async function verifyCreateAsset(operation) { const msgHash = cipher.hashJSON(operationCopy); // TBD select the right key here, not just the first one const publicJwk = doc.didDocument.verificationMethod[0].publicKeyJwk; - const isValid = cipher.verifySig(msgHash, operation.signature.value, publicJwk); - - return isValid; + return cipher.verifySig(msgHash, operation.signature.value, publicJwk); } async function verifyCreate(operation) { if (operation?.type !== "create") { - throw "Invalid operation"; + throw exceptions.INVALID_OPERATION; } if (!operation.created) { // TBD ensure valid timestamp format - throw "Invalid operation"; + throw exceptions.INVALID_OPERATION; } if (!operation.mdip) { - throw "Invalid operation"; + throw exceptions.INVALID_OPERATION; } if (!validVersions.includes(operation.mdip.version)) { - throw `Valid versions include: ${validVersions}`; + throw exceptions.INVALID_VERSION; } if (!validTypes.includes(operation.mdip.type)) { - throw `Valid types include: ${validTypes}`; + throw exceptions.INVALID_TYPE; } if (!validRegistries.includes(operation.mdip.registry)) { - throw `Valid registries include: ${validRegistries}`; + throw exceptions.INVALID_REGISTRY; } if (operation.mdip.type === 'agent') { @@ -157,7 +153,7 @@ async function verifyCreate(operation) { return verifyCreateAsset(operation); } - throw "Invalid operation"; + throw exceptions.INVALID_OPERATION; } export async function createDID(operation) { @@ -187,11 +183,12 @@ export async function createDID(operation) { return did; } else { - throw "Invalid operation"; + throw exceptions.INVALID_OPERATION; } } async function generateDoc(anchor) { + let doc = {}; try { if (!anchor?.mdip) { return {}; @@ -213,7 +210,7 @@ async function generateDoc(anchor) { if (anchor.mdip.type === 'agent') { // TBD support different key types? - const doc = { + doc = { "@context": "https://w3id.org/did-resolution/v1", "didDocument": { "@context": ["https://www.w3.org/ns/did/v1"], @@ -236,12 +233,10 @@ async function generateDoc(anchor) { "didDocumentData": {}, "mdip": anchor.mdip, }; - - return doc; } if (anchor.mdip.type === 'asset') { - const doc = { + doc = { "@context": "https://w3id.org/did-resolution/v1", "didDocument": { "@context": ["https://www.w3.org/ns/did/v1"], @@ -254,15 +249,13 @@ async function generateDoc(anchor) { "didDocumentData": anchor.data, "mdip": anchor.mdip, }; - - return doc; } } catch (error) { // console.error(error); } - return {}; // TBD unknown type error + return doc; } async function verifyUpdate(operation, doc) { @@ -292,9 +285,7 @@ async function verifyUpdate(operation, doc) { // TBD get the right signature, not just the first one const publicJwk = doc.didDocument.verificationMethod[0].publicKeyJwk; - const isValid = cipher.verifySig(msgHash, signature.value, publicJwk); - - return isValid; + return cipher.verifySig(msgHash, signature.value, publicJwk); } export async function resolveDID(did, { atTime, atVersion, confirm, verify } = {}) { @@ -312,7 +303,7 @@ export async function resolveDID(did, { atTime, atVersion, confirm, verify } = { const events = await db.getEvents(did); if (events.length === 0) { - throw "Invalid DID"; + throw exceptions.INVALID_DID; } const anchor = events[0]; @@ -320,7 +311,7 @@ export async function resolveDID(did, { atTime, atVersion, confirm, verify } = { let mdip = doc?.mdip; if (!mdip) { - throw "Invalid DID"; + throw exceptions.INVALID_DID; } if (atTime && new Date(mdip.created) > new Date(atTime)) { @@ -352,7 +343,7 @@ export async function resolveDID(did, { atTime, atVersion, confirm, verify } = { const valid = await verifyUpdate(operation, doc); if (!valid) { - throw "Invalid update"; + throw exceptions.INVALID_UPDATE; } } @@ -380,7 +371,7 @@ export async function resolveDID(did, { atTime, atVersion, confirm, verify } = { } else { if (verify) { - throw "Invalid operation"; + throw exceptions.INVALID_OPERATION; } console.error(`unknown type ${operation.type}`); @@ -493,7 +484,7 @@ export async function exportDIDs(dids) { export async function removeDIDs(dids) { if (!Array.isArray(dids)) { - throw "Invalid array"; + throw exceptions.INVALID_PARAMETER; } for (const did of dids) { @@ -542,7 +533,7 @@ async function importUpdateEvent(event) { export async function importEvent(event) { if (!event.registry || !event.time || !event.operation) { - throw "Invalid import"; + throw exceptions.INVALID_PARAMETER; } let did; @@ -556,11 +547,11 @@ export async function importEvent(event) { } if (!did) { - throw "Invalid operation"; + throw exceptions.INVALID_OPERATION; } } catch { - throw "Invalid operation"; + throw exceptions.INVALID_OPERATION; } const current = await exportDID(did); @@ -569,7 +560,7 @@ export async function importEvent(event) { const ok = await importCreateEvent(event); if (!ok) { - throw "Invalid operation"; + throw exceptions.INVALID_OPERATION; } return true; @@ -602,7 +593,7 @@ export async function importEvent(event) { const ok = await importUpdateEvent(event); if (!ok) { - throw "Invalid operation"; + throw exceptions.INVALID_OPERATION; } delete confirmedCache[did]; @@ -612,7 +603,7 @@ export async function importEvent(event) { export async function importBatch(batch) { if (!batch || !Array.isArray(batch) || batch.length < 1) { - throw "Invalid import"; + throw exceptions.INVALID_PARAMETER; } let verified = 0; @@ -647,18 +638,16 @@ export async function importBatch(batch) { export async function getQueue(registry) { if (!validRegistries.includes(registry)) { - throw `Invalid registry`; + throw exceptions.INVALID_REGISTRY; } - const queue = db.getQueue(registry); - return queue; + return db.getQueue(registry); } export async function clearQueue(registry, events) { if (!validRegistries.includes(registry)) { - throw `Invalid registry`; + throw exceptions.INVALID_REGISTRY; } - const ok = db.clearQueue(registry, events); - return ok; + return db.clearQueue(registry, events); } diff --git a/src/gatekeeper.test.js b/src/gatekeeper.test.js index e26a16fb..1ad4ff47 100644 --- a/src/gatekeeper.test.js +++ b/src/gatekeeper.test.js @@ -2,6 +2,7 @@ import mockFs from 'mock-fs'; import * as cipher from './cipher-lib.js'; import * as gatekeeper from './gatekeeper-lib.js'; import * as db_json from './db-json.js'; +import * as exceptions from './exceptions.js'; beforeEach(async () => { db_json.start(); @@ -89,7 +90,7 @@ async function createUpdateOp(keypair, did, doc) { const msgHash = cipher.hashJSON(operation); const signature = cipher.signHash(msgHash, keypair.privateJwk); - const signed = { + return { ...operation, signature: { signer: did, @@ -98,8 +99,6 @@ async function createUpdateOp(keypair, did, doc) { value: signature, } }; - - return signed; } async function createAssetOp(agent, keypair, registry = 'local') { @@ -117,7 +116,8 @@ async function createAssetOp(agent, keypair, registry = 'local') { const msgHash = cipher.hashJSON(dataAnchor); const signature = cipher.signHash(msgHash, keypair.privateJwk); - const assetOp = { + + return { ...dataAnchor, signature: { signer: agent, @@ -126,8 +126,6 @@ async function createAssetOp(agent, keypair, registry = 'local') { value: signature, } }; - - return assetOp; } describe('createDID', () => { @@ -165,9 +163,9 @@ describe('createDID', () => { try { await gatekeeper.createDID(agentOp); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error.startsWith('Valid versions include')).toBe(true); + expect(error).toBe(exceptions.INVALID_VERSION); } }); @@ -179,9 +177,82 @@ describe('createDID', () => { try { await gatekeeper.createDID(agentOp); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; + } catch (error) { + expect(error).toBe(exceptions.INVALID_REGISTRY); + } + }); + + it('should throw exception on invalid type', async () => { + mockFs({}); + + const keypair = cipher.generateRandomJwk(); + const agentOp = await createAgentOp(keypair, 1, 'mockRegistry'); + agentOp.mdip.type = 'mock'; + + try { + await gatekeeper.createDID(agentOp); + throw exceptions.EXPECTED_EXCEPTION; + } catch (error) { + expect(error).toBe(exceptions.INVALID_TYPE); + } + }); + + it('should throw exception on invalid agent operation', async () => { + mockFs({}); + + try { + await gatekeeper.createDID(); + throw exceptions.EXPECTED_EXCEPTION; + } catch (error) { + expect(error).toBe(exceptions.INVALID_OPERATION); + } + + const keypair = cipher.generateRandomJwk(); + + try { + const agentOp = await createAgentOp(keypair); + agentOp.type = 'mock'; + await gatekeeper.createDID(agentOp); + throw exceptions.EXPECTED_EXCEPTION; + } catch (error) { + expect(error).toBe(exceptions.INVALID_OPERATION); + } + + try { + const agentOp = await createAgentOp(keypair); + agentOp.mdip = null; + await gatekeeper.createDID(agentOp); + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error.startsWith('Valid registries include')).toBe(true); + expect(error).toBe(exceptions.INVALID_OPERATION); + } + + try { + const agentOp = await createAgentOp(keypair); + agentOp.created = null; + await gatekeeper.createDID(agentOp); + throw exceptions.EXPECTED_EXCEPTION; + } catch (error) { + expect(error).toBe(exceptions.INVALID_OPERATION); + } + + try { + const agentOp = await createAgentOp(keypair); + agentOp.signature = null; + await gatekeeper.createDID(agentOp); + throw exceptions.EXPECTED_EXCEPTION; + } catch (error) { + expect(error).toBe(exceptions.INVALID_OPERATION); + } + + try { + const agentOp = await createAgentOp(keypair); + agentOp.publicJwk = null; + await gatekeeper.createDID(agentOp); + throw exceptions.EXPECTED_EXCEPTION; + } catch (error) { + expect(error).toBe(exceptions.INVALID_OPERATION); } }); @@ -197,8 +268,41 @@ describe('createDID', () => { expect(did.startsWith('did:test:')).toBe(true); }); -}); + it('should throw exception on invalid asset operation', async () => { + mockFs({}); + + const keypair = cipher.generateRandomJwk(); + const agentOp = await createAgentOp(keypair); + const agent = await gatekeeper.createDID(agentOp); + + try { + const assetOp = await createAssetOp(agent, keypair, 'hyperswarm'); + await gatekeeper.createDID(assetOp); + throw exceptions.EXPECTED_EXCEPTION; + } catch (error) { + expect(error).toBe(exceptions.INVALID_OPERATION); + } + + try { + const assetOp = await createAssetOp(agent, keypair, 'hyperswarm'); + assetOp.controller = 'mock'; + await gatekeeper.createDID(assetOp); + throw exceptions.EXPECTED_EXCEPTION; + } catch (error) { + expect(error).toBe(exceptions.INVALID_OPERATION); + } + + try { + const assetOp = await createAssetOp(agent, keypair, 'hyperswarm'); + assetOp.signature = null; + await gatekeeper.createDID(assetOp); + throw exceptions.EXPECTED_EXCEPTION; + } catch (error) { + expect(error).toBe(exceptions.INVALID_OPERATION); + } + }); +}); describe('resolveDID', () => { @@ -214,9 +318,11 @@ describe('resolveDID', () => { const did = await gatekeeper.createDID(agentOp); const doc = await gatekeeper.resolveDID(did); const expected = { + // eslint-disable-next-line "@context": "https://w3id.org/did-resolution/v1", didDocument: { "@context": [ + // eslint-disable-next-line "https://www.w3.org/ns/did/v1", ], authentication: [ @@ -506,7 +612,7 @@ describe('resolveDID', () => { for (let i = 0; i < 10; i++) { const update = await gatekeeper.resolveDID(did); - if (i == 5) { + if (i === 5) { expected = update; } @@ -533,7 +639,7 @@ describe('resolveDID', () => { for (let i = 0; i < 10; i++) { const update = await gatekeeper.resolveDID(did); - if (i == 5) { + if (i === 5) { expected = update; } @@ -581,65 +687,65 @@ describe('resolveDID', () => { try { await gatekeeper.resolveDID(); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await gatekeeper.resolveDID(''); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await gatekeeper.resolveDID('mock'); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await gatekeeper.resolveDID([]); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await gatekeeper.resolveDID([1, 2, 3]); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await gatekeeper.resolveDID({}); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await gatekeeper.resolveDID({ mock: 1 }); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await gatekeeper.resolveDID('did:test:xxx'); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await gatekeeper.resolveDID('did:test:z3v8Auah2NPDigFc3qKx183QKL6vY8fJYQk6NeLz7KF2RFtC9c8'); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } }); }); @@ -830,9 +936,9 @@ describe('removeDIDs', () => { try { await gatekeeper.resolveDID(did); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } }); @@ -841,9 +947,9 @@ describe('removeDIDs', () => { try { await gatekeeper.removeDIDs(); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error).toBe('Invalid array'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); @@ -1044,9 +1150,9 @@ describe('importBatch', () => { try { await gatekeeper.importBatch(); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error).toBe('Invalid import'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); @@ -1055,9 +1161,9 @@ describe('importBatch', () => { try { await gatekeeper.importBatch('mock'); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error).toBe('Invalid import'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); @@ -1066,9 +1172,9 @@ describe('importBatch', () => { try { await gatekeeper.importBatch([]); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error).toBe('Invalid import'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); @@ -1110,9 +1216,9 @@ describe('getQueue', () => { try { await gatekeeper.getQueue('mock'); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error).toBe('Invalid registry'); + expect(error).toBe(exceptions.INVALID_REGISTRY); } }); }); @@ -1207,9 +1313,9 @@ describe('clearQueue', () => { try { await gatekeeper.clearQueue('mock', []); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION; } catch (error) { - expect(error).toBe('Invalid registry'); + expect(error).toBe(exceptions.INVALID_REGISTRY); } }); }); diff --git a/src/hyperswarm-mediator.js b/src/hyperswarm-mediator.js index a9b3c055..d75166aa 100644 --- a/src/hyperswarm-mediator.js +++ b/src/hyperswarm-mediator.js @@ -101,11 +101,9 @@ async function createBatch() { return registry && registry !== 'local' }); - const operations = nonlocalDIDs.flat() + return nonlocalDIDs.flat() .map(event => event.operation) .sort((a, b) => new Date(a.signature.signed) - new Date(b.signature.signed)); - - return operations; } function cacheBatch(batch) { diff --git a/src/kc-app/package-lock.json b/src/kc-app/package-lock.json index a68226dc..2eb7449a 100644 --- a/src/kc-app/package-lock.json +++ b/src/kc-app/package-lock.json @@ -20,6 +20,9 @@ "react-router-dom": "^6.11.2", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" + }, + "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11" } }, "node_modules/@adobe/css-tools": { @@ -656,9 +659,17 @@ } }, "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "version": "7.21.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", + "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead.", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, "engines": { "node": ">=6.9.0" }, @@ -1901,6 +1912,17 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-env/node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/preset-env/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", diff --git a/src/kc-app/package.json b/src/kc-app/package.json index d6c40806..541a2548 100644 --- a/src/kc-app/package.json +++ b/src/kc-app/package.json @@ -39,5 +39,8 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11" } } diff --git a/src/kc-app/src/KeymasterUI.js b/src/kc-app/src/KeymasterUI.js index 07adac3d..68cfc4cd 100644 --- a/src/kc-app/src/KeymasterUI.js +++ b/src/kc-app/src/KeymasterUI.js @@ -55,6 +55,7 @@ function KeymasterUI({ keymaster, title }) { useEffect(() => { refreshAll(); + // eslint-disable-next-line }, []); async function refreshAll() { @@ -678,7 +679,7 @@ function KeymasterUI({ keymaster, title }) { try { const { checked, invalid, deleted } = await keymaster.checkWallet(); - if (invalid == 0 && deleted == 0) { + if (invalid === 0 && deleted === 0) { window.alert(`${checked} DIDs checked, no problems found`); } else if (window.confirm(`${checked} DIDs checked\n${invalid} invalid DIDs found\n${deleted} deleted DIDs found\n\nFix wallet?`)) { diff --git a/src/keychain-cli.js b/src/keychain-cli.js index 2e905c0f..da224d93 100644 --- a/src/keychain-cli.js +++ b/src/keychain-cli.js @@ -5,6 +5,9 @@ import * as keymaster from './keymaster-lib.js'; import * as db_wallet from './db-wallet-json.js'; import config from './config.js'; +const UPDATE_OK = "OK"; +const UPDATE_FAILED = "Update failed"; + program .version('1.0.0') .description('Keychain CLI tool') @@ -19,7 +22,7 @@ program console.log(JSON.stringify(wallet, null, 4)); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -30,7 +33,7 @@ program try { const { checked, invalid, deleted } = await keymaster.checkWallet(); - if (invalid == 0 && deleted == 0) { + if (invalid === 0 && deleted === 0) { console.log(`${checked} DIDs checked, no problems found`); } else { @@ -38,7 +41,7 @@ program } } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -52,7 +55,7 @@ program console.log(`${idsRemoved} IDs and ${ownedRemoved} owned DIDs and ${heldRemoved} held DIDs and ${namesRemoved} names were removed`); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -65,7 +68,7 @@ program console.log(JSON.stringify(wallet, null, 4)); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -78,7 +81,7 @@ program console.log(JSON.stringify(wallet, null, 4)); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -91,7 +94,7 @@ program console.log(mnenomic); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -104,7 +107,7 @@ program console.log(did); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -117,7 +120,7 @@ program console.log(JSON.stringify(wallet, null, 4)); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -130,7 +133,7 @@ program console.log(did); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -143,7 +146,7 @@ program console.log(JSON.stringify(doc, null, 4)); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -153,10 +156,15 @@ program .action(async () => { try { const ok = await keymaster.backupId(); - console.log(ok ? 'OK' : 'backup failed'); + if (ok) { + console.log(UPDATE_OK); + } + else { + console.log(UPDATE_FAILED); + } } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -165,11 +173,11 @@ program .description('Recovers the ID from the DID') .action(async (did) => { try { - const ok = await keymaster.recoverId(did); - console.log(ok); + const response = await keymaster.recoverId(did); + console.log(response); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -182,7 +190,7 @@ program console.log(`ID ${name} removed`); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -204,7 +212,7 @@ program } } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -214,10 +222,10 @@ program .action(async (name) => { try { keymaster.setCurrentId(name); - console.log('OK'); + console.log(UPDATE_OK); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -230,7 +238,7 @@ program console.log(JSON.stringify(doc, null, 4)); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -269,7 +277,7 @@ program console.log(cipherDid); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -283,7 +291,7 @@ program console.log(cipherDid); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -324,7 +332,7 @@ program console.log(JSON.stringify(json, null, 4)); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -338,7 +346,7 @@ program console.log(`signature in ${file}`, isValid ? 'is valid' : 'is NOT valid'); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -357,7 +365,7 @@ program console.log(did); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -376,7 +384,7 @@ program console.log(did); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -396,7 +404,7 @@ program console.log(did); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -409,7 +417,7 @@ program console.log(JSON.stringify(vc, null, 4)); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -428,7 +436,7 @@ program console.log(did); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -442,7 +450,7 @@ program console.log(JSON.stringify(response, null, 4)); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -452,10 +460,15 @@ program .action(async (did) => { try { const ok = await keymaster.revokeCredential(did); - console.log(ok ? 'OK revoked' : 'Not revoked'); + if (ok) { + console.log(UPDATE_OK); + } + else { + console.log(UPDATE_FAILED); + } } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -467,18 +480,18 @@ program const ok = await keymaster.acceptCredential(did); if (ok) { - console.log('OK saved'); + console.log(UPDATE_OK); if (name) { keymaster.addName(name, did); } } else { - console.log('Not saved'); + console.log(UPDATE_FAILED); } } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -491,7 +504,7 @@ program console.log(JSON.stringify(response, null, 4)); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -504,7 +517,7 @@ program console.log(JSON.stringify(response, null, 4)); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -517,7 +530,7 @@ program console.log(response); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -530,7 +543,7 @@ program console.log(did); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -543,7 +556,7 @@ program console.log(JSON.stringify(vp, null, 4)); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -553,10 +566,10 @@ program .action(async (name, did) => { try { keymaster.addName(name, did); - console.log('OK'); + console.log(UPDATE_OK); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -566,10 +579,10 @@ program .action(async (name) => { try { keymaster.removeName(name); - console.log('OK'); + console.log(UPDATE_OK); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -588,7 +601,7 @@ program } } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -601,7 +614,7 @@ program console.log(JSON.stringify(ops, null, 4)); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -616,7 +629,7 @@ program console.log(did); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -630,7 +643,7 @@ program keymaster.addName(name, did); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -643,7 +656,7 @@ program console.log(response); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -656,7 +669,7 @@ program console.log(response); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -669,7 +682,7 @@ program console.log(response); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -688,7 +701,7 @@ program console.log(did); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -701,7 +714,7 @@ program console.log(JSON.stringify(template, null, 4)); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -715,7 +728,7 @@ program console.log(did); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -728,7 +741,7 @@ program console.log(JSON.stringify(template, null, 4)); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -747,7 +760,7 @@ program console.log(did); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -760,7 +773,7 @@ program console.log(JSON.stringify(response, null, 4)); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -773,7 +786,7 @@ program console.log(did); } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -784,14 +797,14 @@ program try { const ok = await keymaster.updatePoll(ballot); if (ok) { - console.log("OK"); + console.log(UPDATE_OK); } else { - console.log("Update failed"); + console.log(UPDATE_FAILED); } } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -802,14 +815,14 @@ program try { const ok = await keymaster.publishPoll(poll); if (ok) { - console.log("OK"); + console.log(UPDATE_OK); } else { - console.log("Update failed"); + console.log(UPDATE_FAILED); } } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -820,14 +833,14 @@ program try { const ok = await keymaster.publishPoll(poll, true); if (ok) { - console.log("OK"); + console.log(UPDATE_OK); } else { - console.log("Update failed"); + console.log(UPDATE_FAILED); } } catch (error) { - console.error(error); + console.error(error.message); } }); @@ -838,14 +851,14 @@ program try { const ok = await keymaster.unpublishPoll(poll); if (ok) { - console.log("OK"); + console.log(UPDATE_OK); } else { - console.log("Update failed"); + console.log(UPDATE_FAILED); } } catch (error) { - console.error(error); + console.error(error.message); } }); diff --git a/src/keymaster-app/package-lock.json b/src/keymaster-app/package-lock.json index be6006bb..9a7a0844 100644 --- a/src/keymaster-app/package-lock.json +++ b/src/keymaster-app/package-lock.json @@ -29,6 +29,9 @@ "react-router-dom": "^6.11.2", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" + }, + "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11" } }, "node_modules/@adobe/css-tools": { @@ -665,9 +668,17 @@ } }, "node_modules/@babel/plugin-proposal-private-property-in-object": { - "version": "7.21.0-placeholder-for-preset-env.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", - "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "version": "7.21.11", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.11.tgz", + "integrity": "sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead.", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.18.6", + "@babel/helper-create-class-features-plugin": "^7.21.0", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, "engines": { "node": ">=6.9.0" }, @@ -1910,6 +1921,17 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/preset-env/node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/preset-env/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", diff --git a/src/keymaster-app/package.json b/src/keymaster-app/package.json index 6846eb89..4ce2da15 100644 --- a/src/keymaster-app/package.json +++ b/src/keymaster-app/package.json @@ -48,5 +48,8 @@ "last 1 firefox version", "last 1 safari version" ] + }, + "devDependencies": { + "@babel/plugin-proposal-private-property-in-object": "^7.21.11" } } diff --git a/src/keymaster-app/src/KeymasterUI.js b/src/keymaster-app/src/KeymasterUI.js index 07adac3d..68cfc4cd 100644 --- a/src/keymaster-app/src/KeymasterUI.js +++ b/src/keymaster-app/src/KeymasterUI.js @@ -55,6 +55,7 @@ function KeymasterUI({ keymaster, title }) { useEffect(() => { refreshAll(); + // eslint-disable-next-line }, []); async function refreshAll() { @@ -678,7 +679,7 @@ function KeymasterUI({ keymaster, title }) { try { const { checked, invalid, deleted } = await keymaster.checkWallet(); - if (invalid == 0 && deleted == 0) { + if (invalid === 0 && deleted === 0) { window.alert(`${checked} DIDs checked, no problems found`); } else if (window.confirm(`${checked} DIDs checked\n${invalid} invalid DIDs found\n${deleted} deleted DIDs found\n\nFix wallet?`)) { diff --git a/src/keymaster-app/src/db-wallet-web.js b/src/keymaster-app/src/db-wallet-web.js index 149dc79a..f868baf8 100644 --- a/src/keymaster-app/src/db-wallet-web.js +++ b/src/keymaster-app/src/db-wallet-web.js @@ -1,4 +1,5 @@ import * as cipher from './cipher-lib.js'; +import * as exceptions from './exceptions.js'; const walletName = 'mdip-keymaster'; @@ -19,7 +20,7 @@ export function loadWallet() { export function newWallet(mnemonic, overwrite = false) { if (!overwrite && window.localStorage.getItem(walletName)) { - throw "Wallet already exists"; + throw exceptions.UPDATE_FAILED; } try { @@ -43,6 +44,6 @@ export function newWallet(mnemonic, overwrite = false) { return wallet; } catch (error) { - throw "Invalid mnemonic"; + throw exceptions.INVALID_PARAMETER; } } diff --git a/src/keymaster-app/src/exceptions.js b/src/keymaster-app/src/exceptions.js new file mode 100644 index 00000000..5a0bc1dd --- /dev/null +++ b/src/keymaster-app/src/exceptions.js @@ -0,0 +1,11 @@ +export const INVALID_DID = new Error('Invalid DID'); +export const UNKNOWN_DID = new Error('Unknown DID'); +export const UNKNOWN_ID = new Error('Unknown ID'); +export const INVALID_UPDATE = new Error('Invalid update'); +export const INVALID_OPERATION = new Error('Invalid operation'); +export const INVALID_VERSION = new Error('Invalid version'); +export const INVALID_TYPE = new Error('Invalid type'); +export const INVALID_REGISTRY = new Error('Invalid registry'); +export const INVALID_PARAMETER = new Error('Invalid parameter'); +export const UPDATE_FAILED = new Error('Update failed'); +export const EXPECTED_EXCEPTION = new Error('Expected to throw an exception'); diff --git a/src/keymaster-app/src/keymaster-lib.js b/src/keymaster-app/src/keymaster-lib.js index dec152c5..cc312c91 100644 --- a/src/keymaster-app/src/keymaster-lib.js +++ b/src/keymaster-app/src/keymaster-lib.js @@ -1,5 +1,6 @@ import { JSONSchemaFaker } from "json-schema-faker"; import * as cipher from './cipher-lib.js'; +import * as exceptions from './exceptions.js'; let gatekeeper = null; let db = null; @@ -35,9 +36,8 @@ export function newWallet(mnemonic, overwrite = false) { export function decryptMnemonic() { const wallet = loadWallet(); const keypair = hdKeyPair(); - const mnenomic = cipher.decryptMessage(keypair.publicJwk, keypair.privateJwk, wallet.seed.mnemonic); - return mnenomic; + return cipher.decryptMessage(keypair.publicJwk, keypair.privateJwk, wallet.seed.mnemonic); } export async function checkWallet() { @@ -248,9 +248,7 @@ export async function resolveSeedBank() { } } const did = await gatekeeper.createDID(signed); - const doc = await gatekeeper.resolveDID(did); - - return doc; + return await gatekeeper.resolveDID(did); } async function updateSeedBank(doc) { @@ -278,8 +276,7 @@ async function updateSeedBank(doc) { } }; - const ok = await gatekeeper.updateDID(signed); - return ok; + return await gatekeeper.updateDID(signed); } export async function backupWallet(registry = defaultRegistry) { @@ -352,7 +349,7 @@ export function setCurrentId(name) { saveWallet(wallet); } else { - throw `Unknown ID`; + throw exceptions.UNKNOWN_ID; } } @@ -379,12 +376,12 @@ function fetchId(id) { idInfo = wallet.ids[wallet.current]; if (!idInfo) { - throw "No current ID"; + throw exceptions.UNKNOWN_ID; } } if (!idInfo) { - throw "Unknown ID"; + throw exceptions.UNKNOWN_ID; } return idInfo; @@ -393,9 +390,8 @@ function fetchId(id) { function hdKeyPair() { const wallet = loadWallet(); const hdkey = cipher.generateHDKeyJSON(wallet.seed.hdkey); - const keypair = cipher.generateJwk(hdkey.privateKey); - return keypair; + return cipher.generateJwk(hdkey.privateKey); } function fetchKeyPair(name = null) { @@ -404,9 +400,8 @@ function fetchKeyPair(name = null) { const hdkey = cipher.generateHDKeyJSON(wallet.seed.hdkey); const path = `m/44'/0'/${id.account}'/0/${id.index}`; const didkey = hdkey.derive(path); - const keypair = cipher.generateJwk(didkey.privateKey); - return keypair; + return cipher.generateJwk(didkey.privateKey); } export async function encrypt(msg, did, encryptForSender = true, registry = defaultRegistry) { @@ -417,15 +412,14 @@ export async function encrypt(msg, did, encryptForSender = true, registry = defa const cipher_sender = encryptForSender ? cipher.encryptMessage(keypair.publicJwk, keypair.privateJwk, msg) : null; const cipher_receiver = cipher.encryptMessage(publicJwk, keypair.privateJwk, msg); const msgHash = cipher.hashMessage(msg); - const cipherDid = await createAsset({ + + return await createAsset({ sender: id.did, created: new Date().toISOString(), cipher_hash: msgHash, cipher_sender: cipher_sender, cipher_receiver: cipher_receiver, }, registry); - - return cipherDid; } export async function decrypt(did) { @@ -434,7 +428,7 @@ export async function decrypt(did) { const crypt = await resolveAsset(did); if (!crypt || !crypt.cipher_hash) { - throw "DID is not encrypted"; + throw exceptions.INVALID_PARAMETER; } const doc = await resolveDID(crypt.sender, { atTime: crypt.created }); @@ -455,7 +449,7 @@ export async function decrypt(did) { } } - throw 'Cannot decrypt'; + throw new Error('Cannot decrypt'); } export async function encryptJSON(json, did, encryptForSender = true, registry = defaultRegistry) { @@ -488,7 +482,7 @@ export async function addSignature(obj, controller = null) { }; } catch (error) { - throw 'Invalid input'; + throw exceptions.INVALID_PARAMETER; } } @@ -605,17 +599,14 @@ function removeFromHeld(did) { } export async function resolveDID(did, options = {}) { - const doc = await gatekeeper.resolveDID(lookupDID(did), options); - return doc; + return await gatekeeper.resolveDID(lookupDID(did), options); } export async function resolveAsset(did) { const doc = await resolveDID(did); - if (doc?.didDocumentMetadata) { - if (!doc.didDocumentMetadata.deactivated) { - return doc.didDocumentData; - } + if (doc?.didDocumentMetadata && !doc.didDocumentMetadata.deactivated) { + return doc.didDocumentData; } return null; @@ -624,7 +615,7 @@ export async function resolveAsset(did) { export async function createId(name, registry = defaultRegistry) { const wallet = loadWallet(); if (wallet.ids && Object.keys(wallet.ids).includes(name)) { - throw `Already have an ID named ${name}`; + throw exceptions.INVALID_PARAMETER; } const account = wallet.counter; @@ -687,7 +678,7 @@ export function removeId(name) { return true; } else { - throw `No ID named ${name}`; + throw exceptions.UNKNOWN_ID; } } @@ -712,9 +703,7 @@ export async function backupId(name = null) { const vaultDid = await createAsset({ backup: backup }, registry, name); doc.didDocumentData.vault = vaultDid; - const ok = await updateDID(id.did, doc); - - return ok; + return await updateDID(id.did, doc); } export async function recoverId(did) { @@ -736,7 +725,7 @@ export async function recoverId(did) { return `Recovered ${data.name}!`; } catch { - throw "Cannot recover ID"; + throw exceptions.INVALID_PARAMETER; } } @@ -763,7 +752,7 @@ export async function rotateKeys() { return doc; } else { - throw 'cannot rotate keys'; + throw new Error('Cannot rotate keys'); } } @@ -781,11 +770,11 @@ export function addName(name, did) { } if (Object.keys(wallet.names).includes(name)) { - throw `Name already in use`; + throw exceptions.INVALID_PARAMETER; } if (Object.keys(wallet.ids).includes(name)) { - throw `Name already in use`; + throw exceptions.INVALID_PARAMETER; } wallet.names[name] = did; @@ -797,11 +786,9 @@ export function addName(name, did) { export function removeName(name) { const wallet = loadWallet(); - if (wallet.names) { - if (Object.keys(wallet.names).includes(name)) { - delete wallet.names[name]; - saveWallet(wallet); - } + if (wallet.names && Object.keys(wallet.names).includes(name)) { + delete wallet.names[name]; + saveWallet(wallet); } return true; @@ -814,37 +801,34 @@ export function lookupDID(name) { } } catch { - throw "Invalid DID"; + throw exceptions.INVALID_DID; } const wallet = loadWallet(); - if (wallet.names) { - if (Object.keys(wallet.names).includes(name)) { - return wallet.names[name]; - } + if (wallet.names && Object.keys(wallet.names).includes(name)) { + return wallet.names[name]; } - if (wallet.ids) { - if (Object.keys(wallet.ids).includes(name)) { - return wallet.ids[name].did; - } + if (wallet.ids && Object.keys(wallet.ids).includes(name)) { + return wallet.ids[name].did; } - throw "Unknown DID"; + throw exceptions.UNKNOWN_DID; } export async function createAsset(data, registry = defaultRegistry, owner = null) { function isEmpty(data) { - if (!data) return true; - if (Array.isArray(data) && data.length === 0) return true; - if (typeof data === 'object' && Object.keys(data).length === 0) return true; - return false; + return ( + !data || + (Array.isArray(data) && data.length === 0) || + (typeof data === 'object' && Object.keys(data).length === 0) + ); } if (isEmpty(data)) { - throw 'Invalid input'; + throw exceptions.INVALID_PARAMETER; } const id = fetchId(owner); @@ -888,7 +872,7 @@ export async function bindCredential(schemaId, subjectId, validUntil = null) { const schema = await resolveAsset(type); const credential = JSONSchemaFaker.generate(schema); - const vc = { + return { "@context": [ "https://www.w3.org/ns/credentials/v2", "https://www.w3.org/ns/credentials/examples/v2" @@ -902,15 +886,13 @@ export async function bindCredential(schemaId, subjectId, validUntil = null) { }, credential: credential, }; - - return vc; } export async function issueCredential(vc, registry = defaultRegistry) { const id = fetchId(); if (vc.issuer !== id.did) { - throw 'Invalid VC'; + throw exceptions.INVALID_PARAMETER; } // Don't allow credentials that will be garbage-collected @@ -958,7 +940,7 @@ export async function acceptCredential(did) { const vc = await decryptJSON(credential); if (vc.credentialSubject.id !== id.did) { - throw 'VC not valid or not assigned to this ID'; + throw exceptions.INVALID_PARAMETER; } return addToHeld(credential); @@ -981,39 +963,34 @@ export async function listCredentials(id) { } export async function publishCredential(did, reveal = false) { - try { - const id = fetchId(); - const credential = lookupDID(did); - const vc = await decryptJSON(credential); + const id = fetchId(); + const credential = lookupDID(did); + const vc = await decryptJSON(credential); - if (vc.credentialSubject.id !== id.did) { - throw 'VC not valid or not assigned to this ID'; - } + if (vc.credentialSubject.id !== id.did) { + throw exceptions.INVALID_PARAMETER; + } - const doc = await resolveDID(id.did); + const doc = await resolveDID(id.did); - if (!doc.didDocumentData.manifest) { - doc.didDocumentData.manifest = {}; - } + if (!doc.didDocumentData.manifest) { + doc.didDocumentData.manifest = {}; + } - if (!reveal) { - // Remove the credential values - vc.credential = null; - } + if (!reveal) { + // Remove the credential values + vc.credential = null; + } - doc.didDocumentData.manifest[credential] = vc; + doc.didDocumentData.manifest[credential] = vc; - const ok = await updateDID(id.did, doc); + const ok = await updateDID(id.did, doc); - if (ok) { - return vc; - } - else { - return "Update failed"; - } + if (ok) { + return vc; } - catch (error) { - return error; + else { + throw exceptions.UPDATE_FAILED; } } @@ -1030,7 +1007,7 @@ export async function unpublishCredential(did) { return `OK credential ${did} removed from manifest`; } - throw `Error: credential ${did} not found in manifest`; + throw exceptions.INVALID_PARAMETER; } export async function createChallenge(challenge) { @@ -1046,11 +1023,11 @@ export async function createChallenge(challenge) { } if (!challenge.credentials) { - throw "Invalid input"; + throw exceptions.INVALID_PARAMETER; } if (!Array.isArray(challenge.credentials)) { - throw "Invalid input"; + throw exceptions.INVALID_PARAMETER; } return createAsset(challenge, ephemeralRegistry); @@ -1079,18 +1056,14 @@ async function findMatchingCredential(credential) { continue; } - if (credential.issuers) { - if (!credential.issuers.includes(doc.issuer)) { - // Attestor not trusted by Verifier - continue; - } + if (credential.issuers && !credential.issuers.includes(doc.issuer)) { + // Attestor not trusted by Verifier + continue; } - if (doc.type) { - if (!doc.type.includes(credential.schema)) { - // Wrong type - continue; - } + if (doc.type && !doc.type.includes(credential.schema)) { + // Wrong type + continue; } // TBD test for VC expiry too @@ -1106,7 +1079,7 @@ export async function createResponse(did) { const challenge = lookupDID(did); if (!challenge) { - throw "Invalid challenge"; + throw exceptions.INVALID_PARAMETER; } const doc = await resolveDID(challenge); @@ -1114,7 +1087,7 @@ export async function createResponse(did) { const { credentials } = await resolveAsset(challenge); if (!credentials) { - throw "Invalid challenge"; + throw exceptions.INVALID_PARAMETER; } const matches = []; @@ -1128,7 +1101,7 @@ export async function createResponse(did) { } if (!matches) { - throw "VCs don't match challenge"; + throw exceptions.INVALID_PARAMETER; } const pairs = []; @@ -1154,8 +1127,7 @@ export async function createResponse(did) { ephemeral: { validUntil: expires.toISOString() } }; - const responseDid = await encryptJSON(response, requestor, true, ephemeralRegistry); - return responseDid; + return await encryptJSON(response, requestor, true, ephemeralRegistry); } export async function verifyResponse(responseDID, challengeDID) { @@ -1163,7 +1135,7 @@ export async function verifyResponse(responseDID, challengeDID) { challengeDID = lookupDID(challengeDID); if (!responseDID) { - throw "Invalid response"; + throw exceptions.INVALID_PARAMETER; } const response = await decryptJSON(responseDID); @@ -1206,10 +1178,8 @@ export async function verifyResponse(responseDID, challengeDID) { } // Check if issuer of VP is in the trusted issuer list - if (credential.issuers && credential.issuers.length > 0) { - if (!credential.issuers.includes(vp.issuer)) { - continue; - } + if (credential.issuers && credential.issuers.length > 0 && !credential.issuers.includes(vp.issuer)) { + continue; } } @@ -1243,7 +1213,7 @@ export async function getGroup(id) { const isGroup = await groupTest(id); if (!isGroup) { - throw "Invalid group"; + throw exceptions.INVALID_PARAMETER; } return resolveAsset(id); @@ -1255,7 +1225,7 @@ export async function groupAdd(groupId, memberId) { const data = doc.didDocumentData; if (!data.members || !Array.isArray(data.members)) { - throw "Invalid group"; + throw exceptions.INVALID_PARAMETER; } const memberDID = lookupDID(memberId); @@ -1265,7 +1235,7 @@ export async function groupAdd(groupId, memberId) { await resolveDID(memberDID); } catch { - throw "Invalid DID"; + throw exceptions.INVALID_DID; } // If already a member, return immediately @@ -1275,14 +1245,14 @@ export async function groupAdd(groupId, memberId) { // Can't add a group to itself if (memberDID === groupDID) { - throw "Invalid member"; + throw exceptions.INVALID_PARAMETER; } // Can't add a mutual membership relation const isMember = await groupTest(memberId, groupId); if (isMember) { - throw "Invalid member"; + throw exceptions.INVALID_PARAMETER; } const members = new Set(data.members); @@ -1292,7 +1262,7 @@ export async function groupAdd(groupId, memberId) { const ok = await updateDID(groupDID, doc); if (!ok) { - throw `Error: can't update ${groupId}` + throw exceptions.UPDATE_FAILED; } return data; @@ -1304,7 +1274,7 @@ export async function groupRemove(groupId, memberId) { const data = doc.didDocumentData; if (!data.members) { - throw "Invalid group"; + throw exceptions.INVALID_PARAMETER; } const memberDID = lookupDID(memberId); @@ -1314,7 +1284,7 @@ export async function groupRemove(groupId, memberId) { await resolveDID(memberDID); } catch { - throw "Invalid DID"; + throw exceptions.INVALID_DID; } // If not already a member, return immediately @@ -1329,7 +1299,7 @@ export async function groupRemove(groupId, memberId) { const ok = await updateDID(groupDID, doc); if (!ok) { - throw `Error: can't update ${groupId}` + throw exceptions.UPDATE_FAILED; } return data; @@ -1394,14 +1364,14 @@ export const defaultSchema = { function validateSchema(schema) { try { if (!Object.keys(schema).includes('$schema')) { - throw "Invalid schema"; + throw exceptions.INVALID_PARAMETER; } // Attempt to instantiate the schema JSONSchemaFaker.generate(schema); } catch { - throw "Invalid schema"; + throw exceptions.INVALID_PARAMETER; } return true; @@ -1449,7 +1419,7 @@ export async function createTemplate(id) { const isSchema = await testSchema(id); if (!isSchema) { - throw "Invalid schema"; + throw exceptions.INVALID_PARAMETER; } const schemaDID = lookupDID(id); @@ -1478,48 +1448,48 @@ export async function pollTemplate() { export async function createPoll(poll) { if (poll.type !== 'poll') { - throw "Invalid poll type"; + throw exceptions.INVALID_PARAMETER; } if (poll.version !== 1) { - throw "Invalid poll version"; + throw exceptions.INVALID_PARAMETER; } if (!poll.description) { - throw "Invalid poll description"; + throw exceptions.INVALID_PARAMETER; } if (!poll.options || !Array.isArray(poll.options) || poll.options.length < 2 || poll.options.length > 10) { - throw "Invalid poll options"; + throw exceptions.INVALID_PARAMETER; } if (!poll.roster) { - throw "Invalid poll roster"; + throw exceptions.INVALID_PARAMETER; } try { const isValidGroup = await groupTest(poll.roster); if (!isValidGroup) { - throw "Invalid poll roster"; + throw exceptions.INVALID_PARAMETER; } } catch { - throw "Invalid poll roster"; + throw exceptions.INVALID_PARAMETER; } if (!poll.deadline) { - throw "Invalid poll deadline"; + throw exceptions.INVALID_PARAMETER; } const deadline = new Date(poll.deadline); if (isNaN(deadline.getTime())) { - throw "Invalid poll deadline"; + throw exceptions.INVALID_PARAMETER; } if (deadline < new Date()) { - throw "Invalid poll deadline"; + throw exceptions.INVALID_PARAMETER; } return createAsset(poll); @@ -1532,7 +1502,7 @@ export async function viewPoll(poll) { const data = doc.didDocumentData; if (!data || !data.options || !data.deadline) { - throw "Invalid poll"; + throw exceptions.INVALID_PARAMETER; } let hasVoted = false; @@ -1616,11 +1586,11 @@ export async function votePoll(poll, vote, spoil = false) { const owner = doc.didDocument.controller; if (!eligible) { - throw "Not eligible to vote on this poll"; + throw exceptions.INVALID_PARAMETER; } if (expired) { - throw "The deadline to vote has passed for this poll"; + throw exceptions.INVALID_PARAMETER; } let ballot; @@ -1636,7 +1606,7 @@ export async function votePoll(poll, vote, spoil = false) { vote = parseInt(vote); if (!Number.isInteger(vote) || vote < 1 || vote > max) { - throw `Vote must be a number between 1 and ${max}`; + throw exceptions.INVALID_PARAMETER; } ballot = { @@ -1647,8 +1617,7 @@ export async function votePoll(poll, vote, spoil = false) { // Encrypt for receiver only // TBD which registry? - const didBallot = await encryptJSON(ballot, owner, false); - return didBallot; + return await encryptJSON(ballot, owner, false); } export async function updatePoll(ballot) { @@ -1663,11 +1632,11 @@ export async function updatePoll(ballot) { dataBallot = await decryptJSON(didBallot); if (!dataBallot.poll || !dataBallot.vote) { - throw "Invalid ballot"; + throw exceptions.INVALID_PARAMETER; } } catch { - throw "Invalid ballot"; + throw exceptions.INVALID_PARAMETER; } const didPoll = lookupDID(dataBallot.poll); @@ -1676,26 +1645,26 @@ export async function updatePoll(ballot) { const didOwner = docPoll.didDocument.controller; if (id.did !== didOwner) { - throw "Only poll owners can add a ballot"; + throw exceptions.INVALID_PARAMETER; } const eligible = await groupTest(dataPoll.roster, didVoter); if (!eligible) { - throw "Voter not eligible to vote on this poll"; + throw exceptions.INVALID_PARAMETER; } const expired = (Date(dataPoll.deadline) > new Date()); if (expired) { - throw "The deadline to vote has passed for this poll"; + throw exceptions.INVALID_PARAMETER; } const max = dataPoll.options.length; const vote = parseInt(dataBallot.vote); if (!vote || vote < 0 || vote > max) { - throw "Invalid ballot vote"; + throw exceptions.INVALID_PARAMETER; } if (!dataPoll.ballots) { @@ -1707,9 +1676,7 @@ export async function updatePoll(ballot) { received: new Date().toISOString(), }; - const ok = await updateDID(didPoll, docPoll); - - return ok; + return await updateDID(didPoll, docPoll); } export async function publishPoll(poll, reveal = false) { @@ -1719,13 +1686,13 @@ export async function publishPoll(poll, reveal = false) { const owner = doc.didDocument.controller; if (id.did !== owner) { - throw "Only poll owners can publish"; + throw exceptions.INVALID_PARAMETER; } const view = await viewPoll(poll); if (!view.results.final) { - throw "Poll can be published only when results are final"; + throw exceptions.INVALID_PARAMETER; } if (!reveal) { @@ -1734,9 +1701,7 @@ export async function publishPoll(poll, reveal = false) { doc.didDocumentData.results = view.results; - const ok = await updateDID(didPoll, doc); - - return ok; + return await updateDID(didPoll, doc); } export async function unpublishPoll(poll) { @@ -1746,12 +1711,10 @@ export async function unpublishPoll(poll) { const owner = doc.didDocument.controller; if (id.did !== owner) { - throw "Only poll owners can unpublish"; + throw exceptions.INVALID_PARAMETER; } delete doc.didDocumentData.results; - const ok = await updateDID(didPoll, doc); - - return ok; + return await updateDID(didPoll, doc); } diff --git a/src/keymaster-lib.js b/src/keymaster-lib.js index dec152c5..cc312c91 100644 --- a/src/keymaster-lib.js +++ b/src/keymaster-lib.js @@ -1,5 +1,6 @@ import { JSONSchemaFaker } from "json-schema-faker"; import * as cipher from './cipher-lib.js'; +import * as exceptions from './exceptions.js'; let gatekeeper = null; let db = null; @@ -35,9 +36,8 @@ export function newWallet(mnemonic, overwrite = false) { export function decryptMnemonic() { const wallet = loadWallet(); const keypair = hdKeyPair(); - const mnenomic = cipher.decryptMessage(keypair.publicJwk, keypair.privateJwk, wallet.seed.mnemonic); - return mnenomic; + return cipher.decryptMessage(keypair.publicJwk, keypair.privateJwk, wallet.seed.mnemonic); } export async function checkWallet() { @@ -248,9 +248,7 @@ export async function resolveSeedBank() { } } const did = await gatekeeper.createDID(signed); - const doc = await gatekeeper.resolveDID(did); - - return doc; + return await gatekeeper.resolveDID(did); } async function updateSeedBank(doc) { @@ -278,8 +276,7 @@ async function updateSeedBank(doc) { } }; - const ok = await gatekeeper.updateDID(signed); - return ok; + return await gatekeeper.updateDID(signed); } export async function backupWallet(registry = defaultRegistry) { @@ -352,7 +349,7 @@ export function setCurrentId(name) { saveWallet(wallet); } else { - throw `Unknown ID`; + throw exceptions.UNKNOWN_ID; } } @@ -379,12 +376,12 @@ function fetchId(id) { idInfo = wallet.ids[wallet.current]; if (!idInfo) { - throw "No current ID"; + throw exceptions.UNKNOWN_ID; } } if (!idInfo) { - throw "Unknown ID"; + throw exceptions.UNKNOWN_ID; } return idInfo; @@ -393,9 +390,8 @@ function fetchId(id) { function hdKeyPair() { const wallet = loadWallet(); const hdkey = cipher.generateHDKeyJSON(wallet.seed.hdkey); - const keypair = cipher.generateJwk(hdkey.privateKey); - return keypair; + return cipher.generateJwk(hdkey.privateKey); } function fetchKeyPair(name = null) { @@ -404,9 +400,8 @@ function fetchKeyPair(name = null) { const hdkey = cipher.generateHDKeyJSON(wallet.seed.hdkey); const path = `m/44'/0'/${id.account}'/0/${id.index}`; const didkey = hdkey.derive(path); - const keypair = cipher.generateJwk(didkey.privateKey); - return keypair; + return cipher.generateJwk(didkey.privateKey); } export async function encrypt(msg, did, encryptForSender = true, registry = defaultRegistry) { @@ -417,15 +412,14 @@ export async function encrypt(msg, did, encryptForSender = true, registry = defa const cipher_sender = encryptForSender ? cipher.encryptMessage(keypair.publicJwk, keypair.privateJwk, msg) : null; const cipher_receiver = cipher.encryptMessage(publicJwk, keypair.privateJwk, msg); const msgHash = cipher.hashMessage(msg); - const cipherDid = await createAsset({ + + return await createAsset({ sender: id.did, created: new Date().toISOString(), cipher_hash: msgHash, cipher_sender: cipher_sender, cipher_receiver: cipher_receiver, }, registry); - - return cipherDid; } export async function decrypt(did) { @@ -434,7 +428,7 @@ export async function decrypt(did) { const crypt = await resolveAsset(did); if (!crypt || !crypt.cipher_hash) { - throw "DID is not encrypted"; + throw exceptions.INVALID_PARAMETER; } const doc = await resolveDID(crypt.sender, { atTime: crypt.created }); @@ -455,7 +449,7 @@ export async function decrypt(did) { } } - throw 'Cannot decrypt'; + throw new Error('Cannot decrypt'); } export async function encryptJSON(json, did, encryptForSender = true, registry = defaultRegistry) { @@ -488,7 +482,7 @@ export async function addSignature(obj, controller = null) { }; } catch (error) { - throw 'Invalid input'; + throw exceptions.INVALID_PARAMETER; } } @@ -605,17 +599,14 @@ function removeFromHeld(did) { } export async function resolveDID(did, options = {}) { - const doc = await gatekeeper.resolveDID(lookupDID(did), options); - return doc; + return await gatekeeper.resolveDID(lookupDID(did), options); } export async function resolveAsset(did) { const doc = await resolveDID(did); - if (doc?.didDocumentMetadata) { - if (!doc.didDocumentMetadata.deactivated) { - return doc.didDocumentData; - } + if (doc?.didDocumentMetadata && !doc.didDocumentMetadata.deactivated) { + return doc.didDocumentData; } return null; @@ -624,7 +615,7 @@ export async function resolveAsset(did) { export async function createId(name, registry = defaultRegistry) { const wallet = loadWallet(); if (wallet.ids && Object.keys(wallet.ids).includes(name)) { - throw `Already have an ID named ${name}`; + throw exceptions.INVALID_PARAMETER; } const account = wallet.counter; @@ -687,7 +678,7 @@ export function removeId(name) { return true; } else { - throw `No ID named ${name}`; + throw exceptions.UNKNOWN_ID; } } @@ -712,9 +703,7 @@ export async function backupId(name = null) { const vaultDid = await createAsset({ backup: backup }, registry, name); doc.didDocumentData.vault = vaultDid; - const ok = await updateDID(id.did, doc); - - return ok; + return await updateDID(id.did, doc); } export async function recoverId(did) { @@ -736,7 +725,7 @@ export async function recoverId(did) { return `Recovered ${data.name}!`; } catch { - throw "Cannot recover ID"; + throw exceptions.INVALID_PARAMETER; } } @@ -763,7 +752,7 @@ export async function rotateKeys() { return doc; } else { - throw 'cannot rotate keys'; + throw new Error('Cannot rotate keys'); } } @@ -781,11 +770,11 @@ export function addName(name, did) { } if (Object.keys(wallet.names).includes(name)) { - throw `Name already in use`; + throw exceptions.INVALID_PARAMETER; } if (Object.keys(wallet.ids).includes(name)) { - throw `Name already in use`; + throw exceptions.INVALID_PARAMETER; } wallet.names[name] = did; @@ -797,11 +786,9 @@ export function addName(name, did) { export function removeName(name) { const wallet = loadWallet(); - if (wallet.names) { - if (Object.keys(wallet.names).includes(name)) { - delete wallet.names[name]; - saveWallet(wallet); - } + if (wallet.names && Object.keys(wallet.names).includes(name)) { + delete wallet.names[name]; + saveWallet(wallet); } return true; @@ -814,37 +801,34 @@ export function lookupDID(name) { } } catch { - throw "Invalid DID"; + throw exceptions.INVALID_DID; } const wallet = loadWallet(); - if (wallet.names) { - if (Object.keys(wallet.names).includes(name)) { - return wallet.names[name]; - } + if (wallet.names && Object.keys(wallet.names).includes(name)) { + return wallet.names[name]; } - if (wallet.ids) { - if (Object.keys(wallet.ids).includes(name)) { - return wallet.ids[name].did; - } + if (wallet.ids && Object.keys(wallet.ids).includes(name)) { + return wallet.ids[name].did; } - throw "Unknown DID"; + throw exceptions.UNKNOWN_DID; } export async function createAsset(data, registry = defaultRegistry, owner = null) { function isEmpty(data) { - if (!data) return true; - if (Array.isArray(data) && data.length === 0) return true; - if (typeof data === 'object' && Object.keys(data).length === 0) return true; - return false; + return ( + !data || + (Array.isArray(data) && data.length === 0) || + (typeof data === 'object' && Object.keys(data).length === 0) + ); } if (isEmpty(data)) { - throw 'Invalid input'; + throw exceptions.INVALID_PARAMETER; } const id = fetchId(owner); @@ -888,7 +872,7 @@ export async function bindCredential(schemaId, subjectId, validUntil = null) { const schema = await resolveAsset(type); const credential = JSONSchemaFaker.generate(schema); - const vc = { + return { "@context": [ "https://www.w3.org/ns/credentials/v2", "https://www.w3.org/ns/credentials/examples/v2" @@ -902,15 +886,13 @@ export async function bindCredential(schemaId, subjectId, validUntil = null) { }, credential: credential, }; - - return vc; } export async function issueCredential(vc, registry = defaultRegistry) { const id = fetchId(); if (vc.issuer !== id.did) { - throw 'Invalid VC'; + throw exceptions.INVALID_PARAMETER; } // Don't allow credentials that will be garbage-collected @@ -958,7 +940,7 @@ export async function acceptCredential(did) { const vc = await decryptJSON(credential); if (vc.credentialSubject.id !== id.did) { - throw 'VC not valid or not assigned to this ID'; + throw exceptions.INVALID_PARAMETER; } return addToHeld(credential); @@ -981,39 +963,34 @@ export async function listCredentials(id) { } export async function publishCredential(did, reveal = false) { - try { - const id = fetchId(); - const credential = lookupDID(did); - const vc = await decryptJSON(credential); + const id = fetchId(); + const credential = lookupDID(did); + const vc = await decryptJSON(credential); - if (vc.credentialSubject.id !== id.did) { - throw 'VC not valid or not assigned to this ID'; - } + if (vc.credentialSubject.id !== id.did) { + throw exceptions.INVALID_PARAMETER; + } - const doc = await resolveDID(id.did); + const doc = await resolveDID(id.did); - if (!doc.didDocumentData.manifest) { - doc.didDocumentData.manifest = {}; - } + if (!doc.didDocumentData.manifest) { + doc.didDocumentData.manifest = {}; + } - if (!reveal) { - // Remove the credential values - vc.credential = null; - } + if (!reveal) { + // Remove the credential values + vc.credential = null; + } - doc.didDocumentData.manifest[credential] = vc; + doc.didDocumentData.manifest[credential] = vc; - const ok = await updateDID(id.did, doc); + const ok = await updateDID(id.did, doc); - if (ok) { - return vc; - } - else { - return "Update failed"; - } + if (ok) { + return vc; } - catch (error) { - return error; + else { + throw exceptions.UPDATE_FAILED; } } @@ -1030,7 +1007,7 @@ export async function unpublishCredential(did) { return `OK credential ${did} removed from manifest`; } - throw `Error: credential ${did} not found in manifest`; + throw exceptions.INVALID_PARAMETER; } export async function createChallenge(challenge) { @@ -1046,11 +1023,11 @@ export async function createChallenge(challenge) { } if (!challenge.credentials) { - throw "Invalid input"; + throw exceptions.INVALID_PARAMETER; } if (!Array.isArray(challenge.credentials)) { - throw "Invalid input"; + throw exceptions.INVALID_PARAMETER; } return createAsset(challenge, ephemeralRegistry); @@ -1079,18 +1056,14 @@ async function findMatchingCredential(credential) { continue; } - if (credential.issuers) { - if (!credential.issuers.includes(doc.issuer)) { - // Attestor not trusted by Verifier - continue; - } + if (credential.issuers && !credential.issuers.includes(doc.issuer)) { + // Attestor not trusted by Verifier + continue; } - if (doc.type) { - if (!doc.type.includes(credential.schema)) { - // Wrong type - continue; - } + if (doc.type && !doc.type.includes(credential.schema)) { + // Wrong type + continue; } // TBD test for VC expiry too @@ -1106,7 +1079,7 @@ export async function createResponse(did) { const challenge = lookupDID(did); if (!challenge) { - throw "Invalid challenge"; + throw exceptions.INVALID_PARAMETER; } const doc = await resolveDID(challenge); @@ -1114,7 +1087,7 @@ export async function createResponse(did) { const { credentials } = await resolveAsset(challenge); if (!credentials) { - throw "Invalid challenge"; + throw exceptions.INVALID_PARAMETER; } const matches = []; @@ -1128,7 +1101,7 @@ export async function createResponse(did) { } if (!matches) { - throw "VCs don't match challenge"; + throw exceptions.INVALID_PARAMETER; } const pairs = []; @@ -1154,8 +1127,7 @@ export async function createResponse(did) { ephemeral: { validUntil: expires.toISOString() } }; - const responseDid = await encryptJSON(response, requestor, true, ephemeralRegistry); - return responseDid; + return await encryptJSON(response, requestor, true, ephemeralRegistry); } export async function verifyResponse(responseDID, challengeDID) { @@ -1163,7 +1135,7 @@ export async function verifyResponse(responseDID, challengeDID) { challengeDID = lookupDID(challengeDID); if (!responseDID) { - throw "Invalid response"; + throw exceptions.INVALID_PARAMETER; } const response = await decryptJSON(responseDID); @@ -1206,10 +1178,8 @@ export async function verifyResponse(responseDID, challengeDID) { } // Check if issuer of VP is in the trusted issuer list - if (credential.issuers && credential.issuers.length > 0) { - if (!credential.issuers.includes(vp.issuer)) { - continue; - } + if (credential.issuers && credential.issuers.length > 0 && !credential.issuers.includes(vp.issuer)) { + continue; } } @@ -1243,7 +1213,7 @@ export async function getGroup(id) { const isGroup = await groupTest(id); if (!isGroup) { - throw "Invalid group"; + throw exceptions.INVALID_PARAMETER; } return resolveAsset(id); @@ -1255,7 +1225,7 @@ export async function groupAdd(groupId, memberId) { const data = doc.didDocumentData; if (!data.members || !Array.isArray(data.members)) { - throw "Invalid group"; + throw exceptions.INVALID_PARAMETER; } const memberDID = lookupDID(memberId); @@ -1265,7 +1235,7 @@ export async function groupAdd(groupId, memberId) { await resolveDID(memberDID); } catch { - throw "Invalid DID"; + throw exceptions.INVALID_DID; } // If already a member, return immediately @@ -1275,14 +1245,14 @@ export async function groupAdd(groupId, memberId) { // Can't add a group to itself if (memberDID === groupDID) { - throw "Invalid member"; + throw exceptions.INVALID_PARAMETER; } // Can't add a mutual membership relation const isMember = await groupTest(memberId, groupId); if (isMember) { - throw "Invalid member"; + throw exceptions.INVALID_PARAMETER; } const members = new Set(data.members); @@ -1292,7 +1262,7 @@ export async function groupAdd(groupId, memberId) { const ok = await updateDID(groupDID, doc); if (!ok) { - throw `Error: can't update ${groupId}` + throw exceptions.UPDATE_FAILED; } return data; @@ -1304,7 +1274,7 @@ export async function groupRemove(groupId, memberId) { const data = doc.didDocumentData; if (!data.members) { - throw "Invalid group"; + throw exceptions.INVALID_PARAMETER; } const memberDID = lookupDID(memberId); @@ -1314,7 +1284,7 @@ export async function groupRemove(groupId, memberId) { await resolveDID(memberDID); } catch { - throw "Invalid DID"; + throw exceptions.INVALID_DID; } // If not already a member, return immediately @@ -1329,7 +1299,7 @@ export async function groupRemove(groupId, memberId) { const ok = await updateDID(groupDID, doc); if (!ok) { - throw `Error: can't update ${groupId}` + throw exceptions.UPDATE_FAILED; } return data; @@ -1394,14 +1364,14 @@ export const defaultSchema = { function validateSchema(schema) { try { if (!Object.keys(schema).includes('$schema')) { - throw "Invalid schema"; + throw exceptions.INVALID_PARAMETER; } // Attempt to instantiate the schema JSONSchemaFaker.generate(schema); } catch { - throw "Invalid schema"; + throw exceptions.INVALID_PARAMETER; } return true; @@ -1449,7 +1419,7 @@ export async function createTemplate(id) { const isSchema = await testSchema(id); if (!isSchema) { - throw "Invalid schema"; + throw exceptions.INVALID_PARAMETER; } const schemaDID = lookupDID(id); @@ -1478,48 +1448,48 @@ export async function pollTemplate() { export async function createPoll(poll) { if (poll.type !== 'poll') { - throw "Invalid poll type"; + throw exceptions.INVALID_PARAMETER; } if (poll.version !== 1) { - throw "Invalid poll version"; + throw exceptions.INVALID_PARAMETER; } if (!poll.description) { - throw "Invalid poll description"; + throw exceptions.INVALID_PARAMETER; } if (!poll.options || !Array.isArray(poll.options) || poll.options.length < 2 || poll.options.length > 10) { - throw "Invalid poll options"; + throw exceptions.INVALID_PARAMETER; } if (!poll.roster) { - throw "Invalid poll roster"; + throw exceptions.INVALID_PARAMETER; } try { const isValidGroup = await groupTest(poll.roster); if (!isValidGroup) { - throw "Invalid poll roster"; + throw exceptions.INVALID_PARAMETER; } } catch { - throw "Invalid poll roster"; + throw exceptions.INVALID_PARAMETER; } if (!poll.deadline) { - throw "Invalid poll deadline"; + throw exceptions.INVALID_PARAMETER; } const deadline = new Date(poll.deadline); if (isNaN(deadline.getTime())) { - throw "Invalid poll deadline"; + throw exceptions.INVALID_PARAMETER; } if (deadline < new Date()) { - throw "Invalid poll deadline"; + throw exceptions.INVALID_PARAMETER; } return createAsset(poll); @@ -1532,7 +1502,7 @@ export async function viewPoll(poll) { const data = doc.didDocumentData; if (!data || !data.options || !data.deadline) { - throw "Invalid poll"; + throw exceptions.INVALID_PARAMETER; } let hasVoted = false; @@ -1616,11 +1586,11 @@ export async function votePoll(poll, vote, spoil = false) { const owner = doc.didDocument.controller; if (!eligible) { - throw "Not eligible to vote on this poll"; + throw exceptions.INVALID_PARAMETER; } if (expired) { - throw "The deadline to vote has passed for this poll"; + throw exceptions.INVALID_PARAMETER; } let ballot; @@ -1636,7 +1606,7 @@ export async function votePoll(poll, vote, spoil = false) { vote = parseInt(vote); if (!Number.isInteger(vote) || vote < 1 || vote > max) { - throw `Vote must be a number between 1 and ${max}`; + throw exceptions.INVALID_PARAMETER; } ballot = { @@ -1647,8 +1617,7 @@ export async function votePoll(poll, vote, spoil = false) { // Encrypt for receiver only // TBD which registry? - const didBallot = await encryptJSON(ballot, owner, false); - return didBallot; + return await encryptJSON(ballot, owner, false); } export async function updatePoll(ballot) { @@ -1663,11 +1632,11 @@ export async function updatePoll(ballot) { dataBallot = await decryptJSON(didBallot); if (!dataBallot.poll || !dataBallot.vote) { - throw "Invalid ballot"; + throw exceptions.INVALID_PARAMETER; } } catch { - throw "Invalid ballot"; + throw exceptions.INVALID_PARAMETER; } const didPoll = lookupDID(dataBallot.poll); @@ -1676,26 +1645,26 @@ export async function updatePoll(ballot) { const didOwner = docPoll.didDocument.controller; if (id.did !== didOwner) { - throw "Only poll owners can add a ballot"; + throw exceptions.INVALID_PARAMETER; } const eligible = await groupTest(dataPoll.roster, didVoter); if (!eligible) { - throw "Voter not eligible to vote on this poll"; + throw exceptions.INVALID_PARAMETER; } const expired = (Date(dataPoll.deadline) > new Date()); if (expired) { - throw "The deadline to vote has passed for this poll"; + throw exceptions.INVALID_PARAMETER; } const max = dataPoll.options.length; const vote = parseInt(dataBallot.vote); if (!vote || vote < 0 || vote > max) { - throw "Invalid ballot vote"; + throw exceptions.INVALID_PARAMETER; } if (!dataPoll.ballots) { @@ -1707,9 +1676,7 @@ export async function updatePoll(ballot) { received: new Date().toISOString(), }; - const ok = await updateDID(didPoll, docPoll); - - return ok; + return await updateDID(didPoll, docPoll); } export async function publishPoll(poll, reveal = false) { @@ -1719,13 +1686,13 @@ export async function publishPoll(poll, reveal = false) { const owner = doc.didDocument.controller; if (id.did !== owner) { - throw "Only poll owners can publish"; + throw exceptions.INVALID_PARAMETER; } const view = await viewPoll(poll); if (!view.results.final) { - throw "Poll can be published only when results are final"; + throw exceptions.INVALID_PARAMETER; } if (!reveal) { @@ -1734,9 +1701,7 @@ export async function publishPoll(poll, reveal = false) { doc.didDocumentData.results = view.results; - const ok = await updateDID(didPoll, doc); - - return ok; + return await updateDID(didPoll, doc); } export async function unpublishPoll(poll) { @@ -1746,12 +1711,10 @@ export async function unpublishPoll(poll) { const owner = doc.didDocument.controller; if (id.did !== owner) { - throw "Only poll owners can unpublish"; + throw exceptions.INVALID_PARAMETER; } delete doc.didDocumentData.results; - const ok = await updateDID(didPoll, doc); - - return ok; + return await updateDID(didPoll, doc); } diff --git a/src/keymaster.test.js b/src/keymaster.test.js index 21bc4767..14019039 100644 --- a/src/keymaster.test.js +++ b/src/keymaster.test.js @@ -5,6 +5,7 @@ import * as gatekeeper from './gatekeeper-lib.js'; import * as cipher from './cipher-lib.js'; import * as db_json from './db-json.js'; import * as db_wallet from './db-wallet-json.js'; +import * as exceptions from './exceptions.js'; beforeEach(async () => { db_json.start('mdip'); @@ -87,10 +88,10 @@ describe('newWallet', () => { try { keymaster.newWallet(); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Wallet already exists'); + expect(error).toBe(exceptions.UPDATE_FAILED); } }); @@ -103,6 +104,18 @@ describe('newWallet', () => { expect(mnemonic1 === mnemonic2).toBe(true); }); + + it('should throw exception on invalid mnemonic', async () => { + mockFs({}); + + try { + keymaster.newWallet([]); + throw exceptions.EXPECTED_EXCEPTION;; + } + catch (error) { + expect(error).toBe(exceptions.INVALID_PARAMETER); + } + }); }); describe('resolveSeedBank', () => { @@ -206,9 +219,9 @@ describe('createId', () => { try { await keymaster.createId(name); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe(`Already have an ID named ${name}`); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); @@ -259,9 +272,9 @@ describe('removeId', () => { try { keymaster.removeId(name2); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe(`No ID named ${name2}`); + expect(error).toBe(exceptions.UNKNOWN_ID); } }); }); @@ -294,10 +307,10 @@ describe('setCurrentId', () => { try { keymaster.setCurrentId('Alice'); - throw "Expected to throw an exception"; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe(`Unknown ID`); + expect(error).toBe(exceptions.UNKNOWN_ID); } }); }); @@ -395,10 +408,10 @@ describe('recoverId', () => { try { await keymaster.recoverId(did); - throw "Expected to throw an exception"; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Cannot recover ID'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); }); @@ -433,10 +446,10 @@ describe('testAgent', () => { try { await keymaster.testAgent(); - throw "Expected to throw an exception"; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } }); @@ -445,10 +458,10 @@ describe('testAgent', () => { try { await keymaster.testAgent('mock'); - throw "Expected to throw an exception"; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Unknown DID'); + expect(error).toBe(exceptions.UNKNOWN_DID); } }); }); @@ -576,10 +589,10 @@ describe('addName', () => { try { keymaster.addName('Jack', alice); keymaster.addName('Jack', bob); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Name already in use'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); @@ -590,10 +603,10 @@ describe('addName', () => { try { keymaster.addName('Alice', alice); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Name already in use'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); }); @@ -696,9 +709,9 @@ describe('resolveDID', () => { try { await keymaster.resolveDID('mock'); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Unknown DID'); + expect(error).toBe(exceptions.UNKNOWN_DID); } }); }); @@ -770,9 +783,9 @@ describe('createAsset', () => { try { const mockAnchor = { name: 'mockAnchor' }; await keymaster.createAsset(mockAnchor); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('No current ID'); + expect(error).toBe(exceptions.UNKNOWN_ID); } }); @@ -782,9 +795,9 @@ describe('createAsset', () => { try { await keymaster.createId('Bob'); await keymaster.createAsset(); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid input'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); @@ -794,9 +807,9 @@ describe('createAsset', () => { try { await keymaster.createId('Bob'); await keymaster.createAsset(""); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid input'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); @@ -806,9 +819,9 @@ describe('createAsset', () => { try { await keymaster.createId('Bob'); await keymaster.createAsset([]); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid input'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); @@ -818,9 +831,9 @@ describe('createAsset', () => { try { await keymaster.createId('Bob'); await keymaster.createAsset({}); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid input'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); }); @@ -1095,9 +1108,9 @@ describe('addSignature', () => { try { await keymaster.addSignature(mockJson); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('No current ID'); + expect(error).toBe(exceptions.UNKNOWN_ID); } }); @@ -1108,9 +1121,9 @@ describe('addSignature', () => { try { await keymaster.addSignature(); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid input'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); }); @@ -1281,10 +1294,10 @@ describe('issueCredential', () => { try { await keymaster.issueCredential(boundCredential); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid VC'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); }); @@ -1376,10 +1389,10 @@ describe('revokeCredential', () => { try { await keymaster.revokeCredential(did); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Unknown ID'); + expect(error).toBe(exceptions.UNKNOWN_ID); } }); @@ -1526,26 +1539,26 @@ describe('createChallenge', () => { try { await keymaster.createChallenge([]); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid input'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } try { await keymaster.createChallenge({ credentials: 123 }); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid input'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } try { await keymaster.createChallenge({ mock: [] }); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid input'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); }); @@ -1956,10 +1969,10 @@ describe('unpublishCredential', () => { try { await keymaster.unpublishCredential('mock'); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('No current ID'); + expect(error).toBe(exceptions.UNKNOWN_ID); } }); @@ -1970,10 +1983,10 @@ describe('unpublishCredential', () => { try { await keymaster.unpublishCredential('did:test:mock'); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Error: credential did:test:mock not found in manifest'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); @@ -1987,10 +2000,10 @@ describe('unpublishCredential', () => { try { await keymaster.unpublishCredential(did); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe(`Error: credential ${did} not found in manifest`); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); }); @@ -2075,10 +2088,10 @@ describe('groupAdd', () => { try { await keymaster.groupAdd(groupDid, 'mockAlias'); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Unknown DID'); + expect(error).toBe(exceptions.UNKNOWN_DID); } }); @@ -2112,10 +2125,10 @@ describe('groupAdd', () => { try { await keymaster.groupAdd('mockAlias', dataDid); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Unknown DID'); + expect(error).toBe(exceptions.UNKNOWN_DID); } }); @@ -2190,42 +2203,42 @@ describe('groupAdd', () => { try { await keymaster.groupAdd(groupDid); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupAdd(groupDid, 100); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupAdd(groupDid, [1, 2, 3]); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupAdd(groupDid, { name: 'mock' }); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupAdd(groupDid, 'did:mock'); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } }); @@ -2238,50 +2251,50 @@ describe('groupAdd', () => { try { await keymaster.groupAdd(null, dataDid); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupAdd(100, dataDid); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupAdd([1, 2, 3], dataDid); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupAdd({ name: 'mock' }, dataDid); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupAdd(agentDid, dataDid); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid group'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } try { await keymaster.groupAdd(dataDid, agentDid); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid group'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); @@ -2293,10 +2306,10 @@ describe('groupAdd', () => { try { await keymaster.groupAdd(groupDid, groupDid); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid member'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); @@ -2313,10 +2326,10 @@ describe('groupAdd', () => { try { await keymaster.groupAdd(group3Did, group1Did); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid member'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); }); @@ -2416,42 +2429,42 @@ describe('groupRemove', () => { try { await keymaster.groupRemove(groupDid); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupRemove(groupDid, 100); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupRemove(groupDid, [1, 2, 3]); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupRemove(groupDid, { name: 'mock' }); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupRemove(groupDid, 'did:mock'); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } }); @@ -2464,58 +2477,58 @@ describe('groupRemove', () => { try { await keymaster.groupRemove(); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupRemove(null, dataDid); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupRemove(100, dataDid); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupRemove([1, 2, 3], dataDid); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupRemove({ name: 'mock' }, dataDid); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } try { await keymaster.groupRemove(agentDid, dataDid); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid group'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } try { await keymaster.groupRemove(dataDid, agentDid); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid group'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); }); @@ -2632,10 +2645,10 @@ describe('getGroup', () => { try { await keymaster.getGroup(); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid DID'); + expect(error).toBe(exceptions.INVALID_DID); } }); @@ -2645,10 +2658,10 @@ describe('getGroup', () => { try { const agentDID = await keymaster.createId('Bob'); await keymaster.getGroup(agentDID); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid group'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); }); @@ -2711,100 +2724,100 @@ describe('createPoll', () => { const poll = JSON.parse(JSON.stringify(template)); poll.type = "wrong type"; await keymaster.createPoll(poll); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid poll type'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } try { const poll = JSON.parse(JSON.stringify(template)); poll.version = 0; await keymaster.createPoll(poll); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid poll version'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } try { const poll = JSON.parse(JSON.stringify(template)); delete poll.description; await keymaster.createPoll(poll); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid poll description'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } try { const poll = JSON.parse(JSON.stringify(template)); delete poll.roster; await keymaster.createPoll(poll); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid poll roster'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } try { const poll = JSON.parse(JSON.stringify(template)); delete poll.options; await keymaster.createPoll(poll); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid poll options'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } try { const poll = JSON.parse(JSON.stringify(template)); poll.options = ['one option']; await keymaster.createPoll(poll); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid poll options'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } try { const poll = JSON.parse(JSON.stringify(template)); poll.options = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; await keymaster.createPoll(poll); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid poll options'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } try { const poll = JSON.parse(JSON.stringify(template)); poll.options = "not a list"; await keymaster.createPoll(poll); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid poll options'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } try { const poll = JSON.parse(JSON.stringify(template)); delete poll.deadline; await keymaster.createPoll(poll); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid poll deadline'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } try { const poll = JSON.parse(JSON.stringify(template)); poll.deadline = "not a date"; await keymaster.createPoll(poll); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid poll deadline'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } try { @@ -2816,10 +2829,10 @@ describe('createPoll', () => { poll.deadline = lastWeek.toISOString(); await keymaster.createPoll(poll); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid poll deadline'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); }); @@ -2901,10 +2914,10 @@ describe('votePoll', () => { try { await keymaster.votePoll(pollDid, 5); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Vote must be a number between 1 and 3'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); @@ -2921,10 +2934,10 @@ describe('votePoll', () => { try { await keymaster.votePoll(pollDid, 5); - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Not eligible to vote on this poll'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); }); @@ -2965,10 +2978,10 @@ describe('updatePoll', () => { try { await keymaster.updatePoll(pollDid) - throw 'Expected to throw an exception'; + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe('Invalid ballot'); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); }); @@ -3102,16 +3115,16 @@ describe('createSchema', () => { }); - it('should throw an exception on invalid schema', async () => { + it('should throw an exception on create invalid schema', async () => { mockFs({}); await keymaster.createId('Bob'); try { await keymaster.createSchema({ mock: 'not a schema' }); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe(`Invalid schema`); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); }); @@ -3132,16 +3145,16 @@ describe('getSchema', () => { expect(schema).toStrictEqual(mockSchema); }); - it('should throw an exception on invalid schema', async () => { + it('should throw an exception on get invalid schema', async () => { mockFs({}); await keymaster.createId('Bob'); try { await keymaster.getSchema('bogus'); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe(`Unknown DID`); + expect(error).toBe(exceptions.UNKNOWN_DID); } }); }); @@ -3164,7 +3177,7 @@ describe('setSchema', () => { expect(newSchema).toStrictEqual(mockSchema); }); - it('should throw an exception on invalid schema', async () => { + it('should throw an exception on set invalid schema', async () => { mockFs({}); await keymaster.createId('Bob'); @@ -3172,9 +3185,9 @@ describe('setSchema', () => { try { await keymaster.setSchema(did, { mock: 'not a schema' }); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe(`Invalid schema`); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); }); @@ -3211,9 +3224,9 @@ describe('testSchema', () => { try { await keymaster.testSchema(); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe(`Invalid DID`); + expect(error).toBe(exceptions.INVALID_DID); } }); }); @@ -3245,9 +3258,9 @@ describe('createTemplate', () => { try { await keymaster.createTemplate(); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe(`Invalid DID`); + expect(error).toBe(exceptions.INVALID_DID); } }); }); @@ -3482,9 +3495,9 @@ describe('listCredentials', () => { try { await keymaster.listCredentials('mock'); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe(`Unknown ID`); + expect(error).toBe(exceptions.UNKNOWN_ID); } }); }); @@ -3510,9 +3523,9 @@ describe('getCredential', () => { try { await keymaster.getCredential('mock'); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe(`Unknown DID`); + expect(error).toBe(exceptions.UNKNOWN_DID); } }); @@ -3522,9 +3535,9 @@ describe('getCredential', () => { try { const agentDID = await keymaster.createId('Rando'); await keymaster.getCredential(agentDID); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe(`DID is not encrypted`); + expect(error).toBe(exceptions.INVALID_PARAMETER); } }); }); @@ -3564,9 +3577,9 @@ describe('removeCredential', () => { try { await keymaster.removeCredential(); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe(`Invalid DID`); + expect(error).toBe(exceptions.INVALID_DID); } }); @@ -3575,9 +3588,9 @@ describe('removeCredential', () => { try { await keymaster.removeCredential('mock'); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe(`Unknown DID`); + expect(error).toBe(exceptions.UNKNOWN_DID); } }); }); @@ -3653,9 +3666,9 @@ describe('setCurrentId', () => { try { keymaster.setCurrentId('mock'); - throw ('Expected to throw an exception'); + throw exceptions.EXPECTED_EXCEPTION;; } catch (error) { - expect(error).toBe(`Unknown ID`); + expect(error).toBe(exceptions.UNKNOWN_ID); } }); });