Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

fix: upgrade dependencies #16

Merged
merged 2 commits into from
May 5, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46,571 changes: 36,983 additions & 9,588 deletions package-lock.json

Large diffs are not rendered by default.

73 changes: 37 additions & 36 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,44 +33,45 @@
},
"types": "dist/ts/src",
"dependencies": {
"@govtechsg/oa-verify": "^7.0.0",
"@govtechsg/open-attestation": "^4.1.1",
"debug": "4.3.1",
"node-fetch": "2.6.1"
"@govtechsg/oa-verify": "^7.4.3",
"@govtechsg/open-attestation": "^5.2.3",
"debug": "^4.3.1",
"node-fetch": "^2.6.1",
"runtypes": "^6.3.0"
},
"devDependencies": {
"@babel/cli": "7.12.8",
"@babel/core": "7.12.9",
"@babel/plugin-proposal-class-properties": "7.12.1",
"@babel/plugin-proposal-nullish-coalescing-operator": "7.12.1",
"@babel/plugin-proposal-optional-chaining": "7.12.7",
"@babel/preset-env": "7.12.7",
"@babel/preset-typescript": "7.12.7",
"@commitlint/cli": "11.0.0",
"@commitlint/config-conventional": "11.0.0",
"@commitlint/prompt": "11.0.0",
"@ls-age/commitlint-circle": "1.0.0",
"@types/debug": "4.1.5",
"@types/jest": "26.0.15",
"@types/node-fetch": "2.5.7",
"@typescript-eslint/eslint-plugin": "4.9.0",
"@typescript-eslint/parser": "4.9.0",
"babel-eslint": "10.1.0",
"babel-jest": "26.6.3",
"commitizen": "4.2.2",
"documentation": "13.1.0",
"eslint": "7.14.0",
"eslint-config-prettier": "6.15.0",
"eslint-plugin-import": "2.22.1",
"eslint-plugin-prettier": "3.1.4",
"git-cz": "4.7.5",
"jest": "26.6.3",
"lint-staged": "10.5.2",
"open-cli": "6.0.1",
"prettier": "2.2.1",
"rimraf": "3.0.2",
"semantic-release": "^17.3.0",
"typescript": "4.1.2"
"@babel/cli": "^7.13.16",
"@babel/core": "7.14.0",
"@babel/plugin-proposal-class-properties": "^7.13.0",
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8",
"@babel/plugin-proposal-optional-chaining": "^7.13.12",
"@babel/preset-env": "^7.14.1",
"@babel/preset-typescript": "^7.13.0",
"@commitlint/cli": "^12.1.1",
"@commitlint/config-conventional": "^12.1.1",
"@commitlint/prompt": "^12.1.1",
"@ls-age/commitlint-circle": "^1.0.0",
"@types/debug": "^4.1.5",
"@types/jest": "^26.0.23",
"@types/node-fetch": "^2.5.10",
"@typescript-eslint/eslint-plugin": "^4.22.0",
"@typescript-eslint/parser": "^4.22.0",
"babel-eslint": "^10.1.0",
"babel-jest": "^26.6.3",
"commitizen": "^4.2.3",
"documentation": "^13.2.5",
"eslint": "^7.25.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-prettier": "^3.4.0",
"git-cz": "^4.7.6",
"jest": "^26.6.3",
"lint-staged": "^10.5.4",
"open-cli": "^6.0.1",
"prettier": "^2.2.1",
"rimraf": "^3.0.2",
"semantic-release": "^17.4.2",
"typescript": "^4.2.4"
},
"publishConfig": {
"access": "public"
Expand Down
181 changes: 115 additions & 66 deletions src/verify.ts
Original file line number Diff line number Diff line change
@@ -1,34 +1,73 @@
import {
CodedError,
InvalidVerificationFragment,
isValid as oaIsValid,
openAttestationVerifiers,
Reason,
ValidVerificationFragment,
verificationBuilder,
VerificationBuilderOptions,
VerificationFragment,
VerificationFragmentType,
Verifier,
VerifierOptions,
isValid as oaIsValid,
} from "@govtechsg/oa-verify";
import fetch from "node-fetch";
import { getData, utils, v2, v3, WrappedDocument } from "@govtechsg/open-attestation";
import { VerificationBuilderOptions } from "@govtechsg/oa-verify/src/types/core";

export interface RegistryEntry {
name: string;
displayCard: boolean;
website?: string;
email?: string;
phone?: string;
logo?: string;
id?: string;
}
import { getData, utils, v3 } from "@govtechsg/open-attestation";
import { Array as RunTypesArray, Boolean, Literal, Optional, Record, Static, String, Union } from "runtypes";

export const RegistryEntry = Record({
name: String,
displayCard: Boolean,
website: Optional(String),
email: Optional(String),
phone: Optional(String),
logo: Optional(String),
id: Optional(String),
});
export type RegistryEntry = Static<typeof RegistryEntry>;

export interface Registry {
issuers: {
[key: string]: RegistryEntry;
};
}
export type OpencertsRegistryVerificationFragmentData = Partial<RegistryEntry> & {
value: string;
status: "VALID" | "INVALID";
};

export const OpencertsRegistryVerificationValidData = RegistryEntry.And(
Record({
value: String,
status: Literal("VALID"),
})
);
export type OpencertsRegistryVerificationValidData = Static<typeof OpencertsRegistryVerificationValidData>;

export const OpencertsRegistryVerificationInvalidData = Record({
value: String,
status: Literal("INVALID"),
reason: Reason,
});
export type OpencertsRegistryVerificationInvalidData = Static<typeof OpencertsRegistryVerificationInvalidData>;

// if one issuer is valid => fragment status is valid otherwise if all issuers are invalid => invalid
export const OpencertsRegistryVerificationValidDataArray = RunTypesArray(
Union(OpencertsRegistryVerificationValidData, OpencertsRegistryVerificationInvalidData)
);
export type OpencertsRegistryVerificationValidDataArray = Static<typeof OpencertsRegistryVerificationValidDataArray>;
export const OpencertsRegistryVerificationInvalidDataArray = RunTypesArray(OpencertsRegistryVerificationInvalidData);
export type OpencertsRegistryVerificationInvalidDataArray = Static<
typeof OpencertsRegistryVerificationInvalidDataArray
>;

export type OpencertsRegistryVerifierValidFragmentV2 = ValidVerificationFragment<OpencertsRegistryVerificationValidDataArray>;
export type OpencertsRegistryVerifierInvalidFragmentV2 = InvalidVerificationFragment<OpencertsRegistryVerificationInvalidDataArray>;
export type OpencertsRegistryVerifierValidFragmentV3 = ValidVerificationFragment<OpencertsRegistryVerificationValidData>;
export type OpencertsRegistryVerifierInvalidFragmentV3 = InvalidVerificationFragment<OpencertsRegistryVerificationInvalidData>;
export type OpencertsRegistryVerifierVerificationFragment =
| OpencertsRegistryVerifierValidFragmentV2
| OpencertsRegistryVerifierInvalidFragmentV2
| OpencertsRegistryVerifierValidFragmentV3
| OpencertsRegistryVerifierInvalidFragmentV3;

type VerifierType = Verifier<OpencertsRegistryVerifierVerificationFragment>;

export const type = "ISSUER_IDENTITY";
export const name = "OpencertsRegistryVerifier";
Expand All @@ -38,35 +77,24 @@ export const name = "OpencertsRegistryVerifier";
export enum OpencertsRegistryCode {
INVALID_IDENTITY = 0,
SKIPPED = 1,
UNEXPECTED_ERROR = 2,
}

const storeToFragment = (registry: Registry, store: string): VerificationFragment => {
const storeToData = (
registry: Registry,
store: string
): OpencertsRegistryVerificationValidData | OpencertsRegistryVerificationInvalidData => {
const key = Object.keys(registry.issuers).find((k) => k.toLowerCase() === store.toLowerCase());
if (key) {
return {
status: "VALID",
type,
name,
data: {
status: "VALID" as const,
value: store,
...registry.issuers[key],
},
status: "VALID" as const,
value: store,
...registry.issuers[key],
};
}
return {
status: "INVALID",
type,
name,
data: {
value: store,
status: "INVALID" as const,
reason: {
code: OpencertsRegistryCode.INVALID_IDENTITY,
codeString: OpencertsRegistryCode[OpencertsRegistryCode.INVALID_IDENTITY],
message: `Document store ${store} not found in the registry`,
},
},
value: store,
status: "INVALID" as const,
reason: {
code: OpencertsRegistryCode.INVALID_IDENTITY,
codeString: OpencertsRegistryCode[OpencertsRegistryCode.INVALID_IDENTITY],
Expand All @@ -75,24 +103,11 @@ const storeToFragment = (registry: Registry, store: string): VerificationFragmen
};
};

// local function to check data + data.issuers fields
// don't use utils.isWrappedV2Document, as it only checks OpenAttestationDocument version
const isWrappedV2Document = (document: any): document is WrappedDocument<v2.OpenAttestationDocument> => {
return document.data && document.data.issuers;
};

export const registryVerifier: Verifier<
WrappedDocument<v2.OpenAttestationDocument> | WrappedDocument<v3.OpenAttestationDocument>,
VerifierOptions,
OpencertsRegistryVerificationFragmentData | OpencertsRegistryVerificationFragmentData[]
> = {
export const registryVerifier: VerifierType = {
test: (document) => {
if (utils.isWrappedV3Document(document)) {
const documentData = getData(document);
return documentData.proof.method === v3.Method.DocumentStore;
}

if (isWrappedV2Document(document)) {
return document.openAttestationMetadata.proof.method === v3.Method.DocumentStore;
} else if (utils.isWrappedV2Document(document)) {
const documentData = getData(document);
return documentData.issuers.some((issuer) => "documentStore" in issuer || "certificateStore" in issuer);
}
Expand All @@ -115,22 +130,56 @@ export const registryVerifier: Verifier<
const registry: Registry = await fetch("https://opencerts.io/static/registry.json").then((res) => res.json());

if (utils.isWrappedV3Document(document)) {
const documentData = getData(document);
return storeToFragment(registry, documentData.proof.value);
const data = storeToData(registry, document.openAttestationMetadata.proof.value);
if (OpencertsRegistryVerificationValidData.guard(data)) {
return {
type,
name,
status: "VALID",
data,
};
} else {
return {
type,
name,
status: "INVALID",
data,
reason: data.reason,
};
}
}

const documentData = getData(document);
const issuerFragments = documentData.issuers.map((issuer) =>
storeToFragment(registry, issuer.documentStore || issuer.certificateStore || "")
storeToData(registry, issuer.documentStore || issuer.certificateStore || "")
);
// if one issuer is valid => fragment status is valid otherwise if all issuers are invalid => invalid
const status = issuerFragments.some((fragment) => fragment.status === "VALID") ? "VALID" : "INVALID";
return {
type,
name,
status,
data: issuerFragments.map((fragment) => fragment.data),
reason: issuerFragments.find((fragment) => fragment.reason)?.reason,
};
const invalidIssuer = issuerFragments.find(OpencertsRegistryVerificationInvalidData.guard);
if (
OpencertsRegistryVerificationInvalidDataArray.guard(issuerFragments) &&
OpencertsRegistryVerificationInvalidData.guard(invalidIssuer)
) {
return {
type,
name,
status: "INVALID",
data: issuerFragments,
reason: invalidIssuer.reason,
};
} else if (OpencertsRegistryVerificationValidDataArray.guard(issuerFragments)) {
return {
type,
name,
status: "VALID",
data: issuerFragments,
};
}

throw new CodedError(
"Unable to retrieve the reason of the failure",
OpencertsRegistryCode.UNEXPECTED_ERROR,
"UNEXPECTED_ERROR"
);
},
};

Expand Down
1 change: 1 addition & 0 deletions test/fixtures/v2/document.ts
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,7 @@ export const documentDnsDidSigned: any = {
{
type: "OpenAttestationSignature2018",
proofPurpose: "assertionMethod",
created: "2021-03-25T07:52:31.291Z",
verificationMethod: "did:ethr:0xE712878f6E8d5d4F9e87E10DA604F9cB564C9a89#controller",
signature:
"0xd05bb71bdb6f78451e2d12851825421666c6c5e355f516325ce5002a0586f89f6ebbd465227bec59c745dd26918dd8dab9122dcd398256d8e487e0ecf82a53421b",
Expand Down
Loading