Skip to content

Commit

Permalink
fix: obfuscate typing and guard exports (#292)
Browse files Browse the repository at this point in the history
* fix: obfuscate typing refused to accept document that could be multiple version

* fix: improve consistency of utils guard

* fix: simplify obfuscateVerifiableCredential typing
  • Loading branch information
phanshiyu committed May 13, 2024
1 parent f416085 commit facd046
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 71 deletions.
6 changes: 3 additions & 3 deletions src/4.0/obfuscate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,9 +66,9 @@ const obfuscate = (_data: V4WrappedDocument, fields: string[] | string) => {
};
};

export type ObfuscateVerifiableCredentialResult<T extends V4WrappedDocument | V4SignedWrappedDocument> = Override<
T extends V4SignedWrappedDocument ? V4SignedWrappedDocument : V4WrappedDocument,
Required<PartialDeep<Pick<T, "credentialSubject">>>
export type ObfuscateVerifiableCredentialResult<T extends V4WrappedDocument> = Override<
T,
{ credentialSubject: PartialDeep<T["credentialSubject"]> }
>;
export const obfuscateVerifiableCredential = <T extends V4WrappedDocument | V4SignedWrappedDocument>(
document: T,
Expand Down
33 changes: 11 additions & 22 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { ethers, Signer } from "ethers";

import { getSchema } from "./shared/ajv";
import * as utils from "./shared/utils";
import { SchemaValidationError } from "./shared/utils";
import { validateSchema as validate } from "./shared/validate";
import { SchemaId, WrappedDocument, OpenAttestationDocument, SignedWrappedDocument } from "./shared/@types/document";
import { WrapDocumentOptionV2, WrapDocumentOptionV3 } from "./shared/@types/wrap";
Expand Down Expand Up @@ -31,7 +30,7 @@ import {
obfuscateVerifiableCredential as obfuscateVerifiableCredentialV4,
} from "./4.0/obfuscate";
import { v4Diagnose } from "./4.0/diagnose";
import { V4WrappedDocument } from "./4.0/types";
import { V4WrappedDocument, isV4WrappedDocument } from "./4.0/types";

export function wrapDocument<T extends OpenAttestationDocumentV2>(
data: T,
Expand Down Expand Up @@ -66,7 +65,7 @@ export const validateSchema = (document: WrappedDocument<any>): boolean => {
return validate(document, getSchema(SchemaId.v2)).length === 0;
else if (utils.isWrappedV3Document(document) || document?.version === SchemaId.v3)
return validate(document, getSchema(SchemaId.v3)).length === 0;
else if (utils.isWrappedV4OpenAttestationDocument(document)) {
else if (isV4WrappedDocument(document)) {
return v4Diagnose({ document, kind: "wrapped", debug: false, mode: "strict" }).length === 0;
}

Expand All @@ -76,7 +75,7 @@ export const validateSchema = (document: WrappedDocument<any>): boolean => {
export function verifySignature<T extends WrappedDocument<OpenAttestationDocument>>(document: T) {
if (utils.isWrappedV2Document(document)) return verify(document);
else if (utils.isWrappedV3Document(document)) return verifyV3(document);
else if (utils.isWrappedV4OpenAttestationDocument(document)) return verifyV4(document);
else if (isV4WrappedDocument(document)) return verifyV4(document);

throw new Error("Unsupported document type: Only OpenAttestation v2, v3 or v4 documents can be signature verified");
}
Expand All @@ -88,30 +87,20 @@ export function digest(document: OpenAttestationDocumentV3, salts: v3.Salt[], ob
);
}

export function obfuscate<T extends OpenAttestationDocumentV2>(
document: WrappedDocument<T>,
fields: string[] | string
): WrappedDocument<T>;
export function obfuscate<T extends OpenAttestationDocumentV3>(
document: WrappedDocument<T>,
fields: string[] | string
): WrappedDocument<T>;
export function obfuscate<T extends V4WrappedDocument>(
type ObfuscateReturn<T> = T extends V4WrappedDocument ? ObfuscateVerifiableCredentialResult<T> : T;
export function obfuscate<T extends WrappedDocument<OpenAttestationDocument>>(
document: T,
fields: string[] | string
): ObfuscateVerifiableCredentialResult<T>;
export function obfuscate<T extends OpenAttestationDocument>(document: WrappedDocument<T>, fields: string[] | string) {
if (utils.isWrappedV2Document(document)) return obfuscateDocumentV2(document, fields);
else if (utils.isWrappedV3Document(document)) return obfuscateVerifiableCredentialV3(document, fields);
else if (utils.isWrappedV4OpenAttestationDocument(document)) return obfuscateVerifiableCredentialV4(document, fields);
): ObfuscateReturn<T> {
if (utils.isWrappedV2Document(document)) return obfuscateDocumentV2(document, fields) as ObfuscateReturn<T>;
else if (utils.isWrappedV3Document(document))
return obfuscateVerifiableCredentialV3(document, fields) as ObfuscateReturn<T>;
else if (isV4WrappedDocument(document))
return obfuscateVerifiableCredentialV4(document, fields) as ObfuscateReturn<T>;

throw new Error("Unsupported document type: Only OpenAttestation v2, v3 or v4 documents can be obfuscated");
}

export const isSchemaValidationError = (error: any): error is SchemaValidationError => {
return !!error.validationErrors;
};

export async function signDocument<T extends v2.OpenAttestationDocument | v3.OpenAttestationDocument>(
document: WrappedDocument<T> | SignedWrappedDocument<T>,
algorithm: SUPPORTED_SIGNING_ALGORITHM,
Expand Down
41 changes: 5 additions & 36 deletions src/shared/utils/guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
OpenAttestationDocument as OpenAttestationDocumentV3,
WrappedDocument as WrappedDocumentV3,
} from "../../3.0/types";
import { V4WrappedDocument, V4SignedWrappedDocument, V4OpenAttestationDocument } from "../../4.0/types";
import { diagnose } from "./diagnose";
import { Mode } from "./@types/diagnose";

Expand Down Expand Up @@ -35,18 +34,6 @@ export const isRawV3Document = (
return diagnose({ version: "3.0", kind: "raw", document, debug: false, mode }).length === 0;
};

/**
*
* @param document
* @param mode strict or non-strict. Strict will perform additional check on the data. For instance strict validation will ensure that a target hash is a 32 bytes hex string while non strict validation will just check that target hash is a string.
*/
export const isRawV4OpenAttestationDocument = (
document: any,
{ mode }: { mode: Mode } = { mode: "non-strict" }
): document is V4OpenAttestationDocument => {
return diagnose({ version: "4.0", kind: "raw", document, debug: false, mode }).length === 0;
};

/**
*
* @param document
Expand All @@ -71,18 +58,6 @@ export const isWrappedV3Document = <T extends OpenAttestationDocumentV3 = OpenAt
return diagnose({ version: "3.0", kind: "wrapped", document, debug: false, mode }).length === 0;
};

/**
*
* @param document
* @param mode strict or non-strict. Strict will perform additional check on the data. For instance strict validation will ensure that a target hash is a 32 bytes hex string while non strict validation will just check that target hash is a string.
*/
export const isWrappedV4OpenAttestationDocument = <T extends V4OpenAttestationDocument = V4OpenAttestationDocument>(
document: unknown,
{ mode }: { mode: Mode } = { mode: "non-strict" }
): document is V4WrappedDocument<T> => {
return diagnose({ version: "4.0", kind: "wrapped", document, debug: false, mode }).length === 0;
};

/**
*
* @param document
Expand All @@ -107,14 +82,8 @@ export const isSignedWrappedV3Document = (
return diagnose({ version: "3.0", kind: "signed", document, debug: false, mode }).length === 0;
};

/**
*
* @param document
* @param mode strict or non-strict. Strict will perform additional check on the data. For instance strict validation will ensure that a target hash is a 32 bytes hex string while non strict validation will just check that target hash is a string.
*/
export const isSignedWrappedV4OpenAttestationDocument = <T extends V4SignedWrappedDocument = V4SignedWrappedDocument>(
document: unknown,
{ mode }: { mode: Mode } = { mode: "non-strict" }
): document is T => {
return diagnose({ version: "4.0", kind: "signed", document, debug: false, mode }).length === 0;
};
export {
isV4OpenAttestationDocument as isRawV4Document,
isV4WrappedDocument as isWrappedV4Document,
isV4SignedWrappedDocument as isSignedWrappedV4Document,
} from "../../4.0/types";
20 changes: 10 additions & 10 deletions src/shared/utils/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ import {
isWrappedV2Document,
isRawV3Document,
isWrappedV3Document,
isRawV4OpenAttestationDocument,
isWrappedV4OpenAttestationDocument,
isWrappedV4Document,
isRawV4Document,
} from "./guard";
import { Version } from "./diagnose";

Expand All @@ -31,7 +31,7 @@ export function getIssuerAddress(document: any): any {
return document.openAttestationMetadata.proof.value;
}
// TODO: OA v4 proof schema not updated to support document store issuance yet
// else if (isWrappedV4OpenAttestationDocument(document)) {
// else if (isWrappedV4Document(document)) {
// return document.proof.?
// }
throw new Error(
Expand All @@ -42,7 +42,7 @@ export function getIssuerAddress(document: any): any {
export const getMerkleRoot = (document: any): string => {
if (isWrappedV2Document(document)) return document.signature.merkleRoot;
else if (isWrappedV3Document(document)) return document.proof.merkleRoot;
else if (isWrappedV4OpenAttestationDocument(document)) return document.proof.merkleRoot;
else if (isWrappedV4Document(document)) return document.proof.merkleRoot;

throw new Error(
"Unsupported document type: Only can retrieve merkle root from wrapped OpenAttestation v2, v3 & v4 documents."
Expand All @@ -52,7 +52,7 @@ export const getMerkleRoot = (document: any): string => {
export const getTargetHash = (document: any): string => {
if (isWrappedV2Document(document)) return document.signature.targetHash;
else if (isWrappedV3Document(document)) return document.proof.targetHash;
else if (isWrappedV4OpenAttestationDocument(document)) return document.proof.targetHash;
else if (isWrappedV4Document(document)) return document.proof.targetHash;

throw new Error(
"Unsupported document type: Only can retrieve target hash from wrapped OpenAttestation v2, v3 & v4 documents."
Expand All @@ -70,7 +70,7 @@ export const getTemplateURL = (document: any): string | undefined => {
else return document.$template?.url;
} else if (isRawV3Document(document) || isWrappedV3Document(document)) {
return document.openAttestationMetadata.template?.url;
} else if (isRawV4OpenAttestationDocument(document) || isWrappedV4OpenAttestationDocument(document)) {
} else if (isRawV4Document(document) || isWrappedV4Document(document)) {
return document.renderMethod && document.renderMethod[0].id;
}

Expand All @@ -80,7 +80,7 @@ export const getTemplateURL = (document: any): string | undefined => {
};

export const getDocumentData = (document: WrappedDocument<OpenAttestationDocument>): OpenAttestationDocument => {
if (isWrappedV3Document(document) || isWrappedV4OpenAttestationDocument(document)) {
if (isWrappedV3Document(document) || isWrappedV4Document(document)) {
const omit = (keys: any, obj: any): any =>
Object.fromEntries(Object.entries(obj).filter(([k]) => !keys.includes(k)));
return omit(["proof"], document);
Expand Down Expand Up @@ -123,7 +123,7 @@ export const isDocumentRevokable = (document: any): boolean => {
!!document.openAttestationMetadata.proof.value;

return isDocumentStoreRevokableV3 || isDidRevokableV3;
} else if (isWrappedV4OpenAttestationDocument(document)) {
} else if (isWrappedV4Document(document)) {
if (typeof document.issuer === "string" || !document.credentialStatus) return false;
const isDidRevokableV4 =
document.issuer.identityProof?.identityProofType === "DNS-DID"
Expand Down Expand Up @@ -170,7 +170,7 @@ export const isObfuscated = (
return !!document.privacy?.obfuscatedData?.length;
} else if (isWrappedV3Document(document)) {
return !!document.proof.privacy.obfuscated.length;
} else if (isWrappedV4OpenAttestationDocument(document)) {
} else if (isWrappedV4Document(document)) {
return !!document.proof.privacy.obfuscated.length;
}

Expand All @@ -189,7 +189,7 @@ export const getObfuscatedData = (
return document.privacy?.obfuscatedData || [];
} else if (isWrappedV3Document(document)) {
return document.proof.privacy.obfuscated || [];
} else if (isWrappedV4OpenAttestationDocument(document)) {
} else if (isWrappedV4Document(document)) {
return document.proof.privacy.obfuscated || [];
}

Expand Down

0 comments on commit facd046

Please sign in to comment.