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

Refactoring credentials api interface #255

Merged
merged 10 commits into from
Nov 6, 2023
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
5,652 changes: 1,670 additions & 3,982 deletions package-lock.json

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions packages/credentials/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './types.js';
export * as utils from './utils.js';
export * from './ssi.js';
export * from './verifiable-credential.js';
export * from './presentation-exchange.js';
export * as utils from './utils.js';
161 changes: 161 additions & 0 deletions packages/credentials/src/presentation-exchange.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import type { EvaluationResults, PresentationResult, SelectResults, Validated as PexValidated } from '@sphereon/pex';
import { PEX } from '@sphereon/pex';

import type { PresentationDefinitionV2 as PexPresDefV2 } from '@sphereon/pex-models';

import type {
IPresentation,
PresentationSubmission,
} from '@sphereon/ssi-types';

export type Validated = PexValidated;
export type PresentationDefinitionV2 = PexPresDefV2

export class PresentationExchange {
/**
* The Presentation Exchange (PEX) Library implements the functionality described in the DIF Presentation Exchange specification
*/
private static pex: PEX = new PEX();

/**
* Selects credentials that satisfy a given presentation definition.
*
* @param vcJwts The list of Verifiable Credentials to select from.
* @param presentationDefinition The Presentation Definition to match against.
* @return A list of Verifiable Credentials that satisfy the Presentation Definition.
*/
public static selectCredentials(
vcJwts: string[],
presentationDefinition: PresentationDefinitionV2
): string[] {
this.resetPex();
const selectResults: SelectResults = this.pex.selectFrom(presentationDefinition, vcJwts);
return selectResults.verifiableCredential as string[] ?? [];
}

public static satisfiesPresentationDefinition(
vcJwts: string[],
presentationDefinition: PresentationDefinitionV2
): void {
this.resetPex();
const evaluationResults: EvaluationResults = this.pex.evaluateCredentials(presentationDefinition, vcJwts);
if (evaluationResults.warnings?.length) {
console.warn('Warnings were generated during the evaluation process: ' + JSON.stringify(evaluationResults.warnings));
}

Check warning on line 44 in packages/credentials/src/presentation-exchange.ts

View check run for this annotation

Codecov / codecov/patch

packages/credentials/src/presentation-exchange.ts#L43-L44

Added lines #L43 - L44 were not covered by tests

if (evaluationResults.areRequiredCredentialsPresent.toString() !== 'info' || evaluationResults.errors?.length) {
let errorMessage = 'Failed to create Verifiable Presentation JWT due to: ';
if(evaluationResults.areRequiredCredentialsPresent) {
errorMessage += 'Required Credentials Not Present: ' + JSON.stringify(evaluationResults.areRequiredCredentialsPresent);
}

if (evaluationResults.errors?.length) {
errorMessage += 'Errors: ' + JSON.stringify(evaluationResults.errors);
}

throw new Error(errorMessage);
}
}

/**
* Creates a presentation from a list of Verifiable Credentials that satisfy a given presentation definition.
* This function initializes the Presentation Exchange (PEX) process, validates the presentation definition,
* evaluates the credentials against the definition, and finally constructs the presentation result if the
* evaluation is successful.
*
* @param {string[]} vcJwts The list of Verifiable Credentials (VCs) in JWT format to be evaluated.
* @param {PresentationDefinitionV2} presentationDefinition The Presentation Definition V2 to match the VCs against.
* @returns {PresentationResult} The result of the presentation creation process, containing a presentation submission
* that satisfies the presentation definition criteria.
* @throws {Error} If the evaluation results in warnings or errors, or if the required credentials are not present,
* an error is thrown with a descriptive message.
*/
public static createPresentationFromCredentials(
vcJwts: string[],
presentationDefinition: PresentationDefinitionV2
): PresentationResult {
this.resetPex();

const pdValidated: Validated = PEX.validateDefinition(presentationDefinition);
isValid(pdValidated);

const evaluationResults: EvaluationResults = this.pex.evaluateCredentials(presentationDefinition, vcJwts);

if (evaluationResults.warnings?.length) {
console.warn('Warnings were generated during the evaluation process: ' + JSON.stringify(evaluationResults.warnings));
}

Check warning on line 86 in packages/credentials/src/presentation-exchange.ts

View check run for this annotation

Codecov / codecov/patch

packages/credentials/src/presentation-exchange.ts#L85-L86

Added lines #L85 - L86 were not covered by tests

if (evaluationResults.areRequiredCredentialsPresent.toString() !== 'info' || evaluationResults.errors?.length) {
let errorMessage = 'Failed to create Verifiable Presentation JWT due to: ';
if(evaluationResults.areRequiredCredentialsPresent) {
errorMessage += 'Required Credentials Not Present: ' + JSON.stringify(evaluationResults.areRequiredCredentialsPresent);
}

if (evaluationResults.errors?.length) {
errorMessage += 'Errors: ' + JSON.stringify(evaluationResults.errors);
}

throw new Error(errorMessage);
}

const presentationResult: PresentationResult = this.pex.presentationFrom(presentationDefinition, vcJwts);

const submissionValidated: Validated = PEX.validateSubmission(presentationResult.presentationSubmission);
isValid(submissionValidated);

return presentationResult;
}

/**
* This method validates whether an object is usable as a presentation definition or not.
*
* @param presentationDefinition: presentationDefinition to be validated.
*
* @return the validation results to reveal what is acceptable/unacceptable about the passed object to be considered a valid presentation definition
*/
public static validateDefinition(presentationDefinition: PresentationDefinitionV2): Validated {
return PEX.validateDefinition(presentationDefinition);
}

/**
* This method validates whether an object is usable as a presentation submission or not.
*
* @param presentationSubmission the object to be validated.
*
* @return the validation results to reveal what is acceptable/unacceptable about the passed object to be considered a valid presentation submission
*/
public static validateSubmission(presentationSubmission: PresentationSubmission): Validated {
return PEX.validateSubmission(presentationSubmission);
}

/**
* Evaluates a presentation against a presentation definition.
* @returns {EvaluationResults} The result of the evaluation process.
*/
public static evaluatePresentation(
presentationDefinition: PresentationDefinitionV2,
presentation: IPresentation
): EvaluationResults {
this.resetPex();
return this.pex.evaluatePresentation(presentationDefinition, presentation);
}

private static resetPex() {
this.pex = new PEX();
}
}

function isValid(validated: Validated) {
let errorMessage = 'Failed to pass validation check due to: ';
if (Array.isArray(validated)) {
if (!validated.every(item => item.status === 'info')) {
errorMessage += 'Validation Errors: ' + JSON.stringify(validated);
throw new Error(errorMessage);
}
} else {
if (validated.status !== 'info') {
errorMessage += 'Validation Errors: ' + JSON.stringify(validated);
throw new Error(errorMessage);
}
}

Check warning on line 160 in packages/credentials/src/presentation-exchange.ts

View check run for this annotation

Codecov / codecov/patch

packages/credentials/src/presentation-exchange.ts#L156-L160

Added lines #L156 - L160 were not covered by tests
}
Loading
Loading