Skip to content

Commit

Permalink
adjusting vc.create (#311)
Browse files Browse the repository at this point in the history
* adjusting vc.create

* fix spec
  • Loading branch information
nitro-neal authored Nov 22, 2023
1 parent 9af892a commit da7786d
Show file tree
Hide file tree
Showing 4 changed files with 106 additions and 82 deletions.
8 changes: 7 additions & 1 deletion .web5-spec/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,13 @@ export async function credentialIssue(req: Request, res: Response) {
signer : signer
};

const vc: VerifiableCredential = VerifiableCredential.create(body.credential.type[body.credential.type.length - 1], body.credential.issuer, subjectIssuerDid, body.credential.credentialSubject);
const vc: VerifiableCredential = VerifiableCredential.create({
type: body.credential.type[body.credential.type.length - 1],
issuer: body.credential.issuer,
subject: subjectIssuerDid,
data: body.credential.credentialSubject
});

const vcJwt: string = await vc.sign(signOptions);

const resp: paths["/credentials/issue"]["post"]["responses"]["200"]["content"]["application/json"] =
Expand Down
48 changes: 33 additions & 15 deletions packages/credentials/src/verifiable-credential.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,24 @@ export const DEFAULT_VC_TYPE = 'VerifiableCredential';
*/
export type VcDataModel = ICredential;

/**
* @param type Optional. The type of the credential, can be a string or an array of strings.
* @param issuer The issuer URI of the credential, as a string.
* @param subject The subject URI of the credential, as a string.
* @param data The credential data, as a generic type any.
* @param issuanceDate Optional. The issuance date of the credential, as a string.
* Defaults to the current date if not specified.
* @param expirationDate Optional. The expiration date of the credential, as a string.
*/
export type VerifiableCredentialCreateOptions = {
type?: string | string[];
issuer: string;
subject: string;
data: any;
issuanceDate?: string;
expirationDate?: string;
};

export type SignOptions = {
kid: string;
issuerDid: string;
Expand Down Expand Up @@ -113,24 +131,22 @@ export class VerifiableCredential {
/**
* Create a [VerifiableCredential] based on the provided parameters.
*
* @param type The type of the credential, as a [String].
* @param issuer The issuer URI of the credential, as a [String].
* @param subject The subject URI of the credential, as a [String].
* @param data The credential data, as a generic type [T].
* @param vcCreateOptions The options to use when creating the Verifiable Credential.
* @return A [VerifiableCredential] instance.
*
* Example:
* ```
* const vc = VerifiableCredential.create("ExampleCredential", "http://example.com/issuers/1", "http://example.com/subjects/1", myData)
* const vc = VerifiableCredential.create({
* type: 'StreetCredibility',
* issuer: 'did:ex:issuer',
* subject: 'did:ex:subject',
* data: { 'arbitrary': 'data' }
* })
* ```
*/
public static create<T>(
type: string,
issuer: string,
subject: string,
data: T,
expirationDate?: string
): VerifiableCredential {
public static create(vcCreateOptions: VerifiableCredentialCreateOptions): VerifiableCredential {
const { type, issuer, subject, data, issuanceDate, expirationDate } = vcCreateOptions;

const jsonData = JSON.parse(JSON.stringify(data));

if (typeof jsonData !== 'object') {
Expand All @@ -147,11 +163,13 @@ export class VerifiableCredential {
};

const vcDataModel: VcDataModel = {
'@context' : [DEFAULT_CONTEXT],
type : [DEFAULT_VC_TYPE, type],
'@context' : [DEFAULT_CONTEXT],
type : Array.isArray(type)
? [DEFAULT_VC_TYPE, ...type]
: (type ? [DEFAULT_VC_TYPE, type] : [DEFAULT_VC_TYPE]),
id : `urn:uuid:${uuidv4()}`,
issuer : issuer,
issuanceDate : getCurrentXmlSchema112Timestamp(),
issuanceDate : issuanceDate || getCurrentXmlSchema112Timestamp(), // use default if undefined
credentialSubject : credentialSubject,
...(expirationDate && { expirationDate }), // optional property
};
Expand Down
36 changes: 18 additions & 18 deletions packages/credentials/tests/presentation-exchange.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ describe('PresentationExchange', () => {
signer : signer
};

const vc = VerifiableCredential.create(
'StreetCred',
alice.did,
alice.did,
new BitcoinCredential('btcAddress123'),
);
const vc = VerifiableCredential.create({
type : 'StreetCred',
issuer : alice.did,
subject : alice.did,
data : new BitcoinCredential('btcAddress123'),
});

btcCredentialJwt = await vc.sign(signOptions);
presentationDefinition = createPresentationDefinition();
Expand All @@ -57,12 +57,12 @@ describe('PresentationExchange', () => {
});

it('should return the only one verifiable credential', async () => {
const vc = VerifiableCredential.create(
'StreetCred',
signOptions.issuerDid,
signOptions.subjectDid,
new OtherCredential('otherstuff'),
);
const vc = VerifiableCredential.create({
type : 'StreetCred',
issuer : signOptions.issuerDid,
subject : signOptions.subjectDid,
data : new OtherCredential('otherstuff'),
});

const otherCredJwt = await vc.sign(signOptions);

Expand Down Expand Up @@ -127,12 +127,12 @@ describe('PresentationExchange', () => {
});

it('should fail to create a presentation with vc that does not match presentation definition', async() => {
const vc = VerifiableCredential.create(
'StreetCred',
signOptions.issuerDid,
signOptions.subjectDid,
new OtherCredential('otherstuff'),
);
const vc = VerifiableCredential.create({
type : 'StreetCred',
issuer : signOptions.issuerDid,
subject : signOptions.subjectDid,
data : new OtherCredential('otherstuff'),
});

const otherCredJwt = await vc.sign(signOptions);
await expectThrowsAsync(() => PresentationExchange.createPresentationFromCredentials([otherCredJwt], presentationDefinition), 'Failed to create Verifiable Presentation JWT due to: Required Credentials Not Present');
Expand Down
96 changes: 48 additions & 48 deletions packages/credentials/tests/verifiable-credential.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,12 @@ describe('Verifiable Credential Tests', () => {
const issuerDid = signOptions.issuerDid;
const subjectDid = signOptions.subjectDid;

const vc = VerifiableCredential.create(
'StreetCred',
issuerDid,
subjectDid,
new StreetCredibility('high', true),
);
const vc = VerifiableCredential.create({
type : 'StreetCred',
issuer : issuerDid,
subject : subjectDid,
data : new StreetCredibility('high', true),
});

expect(vc.issuer).to.equal(issuerDid);
expect(vc.subject).to.equal(subjectDid);
Expand All @@ -57,12 +57,12 @@ describe('Verifiable Credential Tests', () => {
const invalidData = 'NotAJSONObject';

expect(() => {
VerifiableCredential.create(
'InvalidDataTest',
issuerDid,
subjectDid,
invalidData
);
VerifiableCredential.create({
type : 'InvalidDataTest',
issuer : issuerDid,
subject : subjectDid,
data : invalidData
});
}).to.throw('Expected data to be parseable into a JSON object');
});

Expand All @@ -72,21 +72,21 @@ describe('Verifiable Credential Tests', () => {
const validData = new StreetCredibility('high', true);

expect(() => {
VerifiableCredential.create(
'IssuerUndefinedTest',
'',
subjectDid,
validData
);
VerifiableCredential.create({
type : 'IssuerUndefinedTest',
issuer : '',
subject : subjectDid,
data : validData
});
}).to.throw('Issuer and subject must be defined');

expect(() => {
VerifiableCredential.create(
'SubjectUndefinedTest',
issuerDid,
'',
validData
);
VerifiableCredential.create({
type : 'SubjectUndefinedTest',
issuer : issuerDid,
subject : '',
data : validData
});
}).to.throw('Issuer and subject must be defined');

});
Expand All @@ -95,12 +95,12 @@ describe('Verifiable Credential Tests', () => {
const issuerDid = signOptions.issuerDid;
const subjectDid = signOptions.subjectDid;

const vc = VerifiableCredential.create(
'StreetCred',
issuerDid,
subjectDid,
new StreetCredibility('high', true),
);
const vc = VerifiableCredential.create({
type : 'StreetCred',
issuer : issuerDid,
subject : subjectDid,
data : new StreetCredibility('high', true),
});

const vcJwt = await vc.sign(signOptions);
expect(vcJwt).to.not.be.null;
Expand All @@ -117,12 +117,12 @@ describe('Verifiable Credential Tests', () => {
});

it('verify fails with bad issuer did', async () => {
const vc = VerifiableCredential.create(
'StreetCred',
'bad:did: invalidDid',
signOptions.subjectDid,
new StreetCredibility('high', true)
);
const vc = VerifiableCredential.create({
type : 'StreetCred',
issuer : 'bad:did: invalidDid',
subject : signOptions.subjectDid,
data : new StreetCredibility('high', true)
});

const badSignOptions = {
issuerDid : 'bad:did: invalidDid',
Expand All @@ -141,12 +141,12 @@ describe('Verifiable Credential Tests', () => {
});

it('parseJwt returns an instance of VerifiableCredential on success', async () => {
const vc = VerifiableCredential.create(
'StreetCred',
signOptions.issuerDid,
signOptions.subjectDid,
new StreetCredibility('high', true)
);
const vc = VerifiableCredential.create({
type : 'StreetCred',
issuer : signOptions.issuerDid,
subject : signOptions.subjectDid,
data : new StreetCredibility('high', true),
});

const vcJwt = await vc.sign(signOptions);
const parsedVc = VerifiableCredential.parseJwt(vcJwt);
Expand All @@ -170,12 +170,12 @@ describe('Verifiable Credential Tests', () => {
});

it('verify does not throw an exception with vaild vc', async () => {
const vc = VerifiableCredential.create(
'StreetCred',
signOptions.issuerDid,
signOptions.subjectDid,
new StreetCredibility('high', true)
);
const vc = VerifiableCredential.create({
type : 'StreetCred',
issuer : signOptions.issuerDid,
subject : signOptions.subjectDid,
data : new StreetCredibility('high', true),
});

const vcJwt = await vc.sign(signOptions);

Expand Down

0 comments on commit da7786d

Please sign in to comment.