From a3eefbc243f39f5392f7918b1cdb4e782faf8001 Mon Sep 17 00:00:00 2001 From: Jakub Sydor Date: Mon, 11 Apr 2022 16:40:26 +0200 Subject: [PATCH] feat(claim): issue VC when approving role request --- docs/api/classes/ClaimsService.md | 6 ++-- docs/api/interfaces/IClaimIssuance.md | 7 ++++ e2e/claims.service.e2e.ts | 33 +++++++++++++++++-- src/init.ts | 3 +- src/modules/claims/claims.service.ts | 47 +++++++++++++++++++++++---- src/modules/claims/claims.types.ts | 2 +- 6 files changed, 84 insertions(+), 14 deletions(-) diff --git a/docs/api/classes/ClaimsService.md b/docs/api/classes/ClaimsService.md index 639fc23c..fc45be67 100644 --- a/docs/api/classes/ClaimsService.md +++ b/docs/api/classes/ClaimsService.md @@ -33,7 +33,7 @@ ### constructor -• **new ClaimsService**(`_signerService`, `_domainsService`, `_cacheClient`, `_didRegistry`) +• **new ClaimsService**(`_signerService`, `_domainsService`, `_cacheClient`, `_didRegistry`, `_verifiableCredentialService`) #### Parameters @@ -43,6 +43,7 @@ | `_domainsService` | [`DomainsService`](DomainsService.md) | | `_cacheClient` | [`CacheClient`](CacheClient.md) | | `_didRegistry` | [`DidRegistry`](DidRegistry.md) | +| `_verifiableCredentialService` | [`VerifiableCredentialsServiceBase`](VerifiableCredentialsServiceBase.md) | ## Methods @@ -432,7 +433,7 @@ ___ ### create -▸ `Static` **create**(`signerService`, `domainsService`, `cacheClient`, `didRegistry`): `Promise`<[`ClaimsService`](ClaimsService.md)\> +▸ `Static` **create**(`signerService`, `domainsService`, `cacheClient`, `didRegistry`, `verifiableCredentialService`): `Promise`<[`ClaimsService`](ClaimsService.md)\> #### Parameters @@ -442,6 +443,7 @@ ___ | `domainsService` | [`DomainsService`](DomainsService.md) | | `cacheClient` | [`CacheClient`](CacheClient.md) | | `didRegistry` | [`DidRegistry`](DidRegistry.md) | +| `verifiableCredentialService` | [`VerifiableCredentialsServiceBase`](VerifiableCredentialsServiceBase.md) | #### Returns diff --git a/docs/api/interfaces/IClaimIssuance.md b/docs/api/interfaces/IClaimIssuance.md index 4898c1ac..cf00f1c3 100644 --- a/docs/api/interfaces/IClaimIssuance.md +++ b/docs/api/interfaces/IClaimIssuance.md @@ -18,6 +18,7 @@ - [issuedToken](IClaimIssuance.md#issuedtoken) - [onChainProof](IClaimIssuance.md#onchainproof) - [requester](IClaimIssuance.md#requester) +- [vp](IClaimIssuance.md#vp) ## Properties @@ -78,3 +79,9 @@ ___ #### Inherited from [IMessage](IMessage.md).[requester](IMessage.md#requester) + +___ + +### vp + +• `Optional` **vp**: `string` diff --git a/e2e/claims.service.e2e.ts b/e2e/claims.service.e2e.ts index dde525f1..6d08b9b4 100644 --- a/e2e/claims.service.e2e.ts +++ b/e2e/claims.service.e2e.ts @@ -1,4 +1,7 @@ -import { IRoleDefinition, PreconditionType } from '@energyweb/credential-governance'; +import { + IRoleDefinition, + PreconditionType, +} from '@energyweb/credential-governance'; import { Methods, Chain } from '@ew-did-registry/did'; import { addressOf } from '@ew-did-registry/did-ethr-resolver'; import { KeyTags } from '@ew-did-registry/did-resolver-interface'; @@ -24,6 +27,7 @@ import { ProofVerifier } from '@ew-did-registry/claims'; import { ClaimManager } from '../ethers/ClaimManager'; import { setLogger } from '../src/config/logger.config'; import { ConsoleLogger, LogLevel } from '../src/utils/logger'; +import { VerifiablePresentation } from '@ew-did-registry/credentials-interface'; const { namehash } = utils; @@ -201,11 +205,34 @@ describe('Enrollment claim tests', () => { mockIssueClaim.mock.calls.pop() ); - const { issuedToken, requester, claimIssuer, onChainProof, acceptedBy } = - issuedClaim; + const { + issuedToken, + requester, + claimIssuer, + onChainProof, + acceptedBy, + vp, + } = issuedClaim; if (registrationTypes.includes(RegistrationTypes.OffChain)) { expect(issuedToken).toBeDefined(); + expect(vp).toBeDefined(); + + const vpObject = JSON.parse(vp) as VerifiablePresentation; + + expect(vpObject.verifiableCredential).toHaveLength(1); + expect(vpObject.verifiableCredential[0].credentialSubject).toEqual({ + id: subjectDID, + role: { + namespace: claimType, + version: version.toString(), + }, + issuerFields, + }); + expect(vpObject.verifiableCredential[0].issuer).toEqual( + signerService.didHex + ); + expect(vpObject.holder).toEqual(signerService.didHex); const { claimData, signer, did } = (await didRegistry.decodeJWTToken({ token: issuedToken, diff --git a/src/init.ts b/src/init.ts index a6fde3da..3bdc6724 100644 --- a/src/init.ts +++ b/src/init.ts @@ -104,7 +104,8 @@ export async function init(signerService: SignerService) { signerService, domainsService, cacheClient, - didRegistry + didRegistry, + verifiableCredentialsService ); return { didRegistry, claimsService }; } diff --git a/src/modules/claims/claims.service.ts b/src/modules/claims/claims.service.ts index d196af18..12ac1702 100644 --- a/src/modules/claims/claims.service.ts +++ b/src/modules/claims/claims.service.ts @@ -39,6 +39,7 @@ import { compareDID, isValidDID } from '../../utils/did'; import { JWT } from '@ew-did-registry/jwt'; import { privToPem, KeyType } from '@ew-did-registry/keys'; import { readyToBeRegisteredOnchain } from './claims.types'; +import { VerifiableCredentialsServiceBase } from '../verifiable-credentials'; const { id, @@ -57,7 +58,8 @@ export class ClaimsService { private _signerService: SignerService, private _domainsService: DomainsService, private _cacheClient: CacheClient, - private _didRegistry: DidRegistry + private _didRegistry: DidRegistry, + private _verifiableCredentialService: VerifiableCredentialsServiceBase ) { this._signerService.onInit(this.init.bind(this)); } @@ -66,13 +68,15 @@ export class ClaimsService { signerService: SignerService, domainsService: DomainsService, cacheClient: CacheClient, - didRegistry: DidRegistry + didRegistry: DidRegistry, + verifiableCredentialService: VerifiableCredentialsServiceBase ) { const service = new ClaimsService( signerService, domainsService, cacheClient, - didRegistry + didRegistry, + verifiableCredentialService ); await service.init(); return service; @@ -266,9 +270,9 @@ export class ClaimsService { acceptedBy: this._signerService.did, }; const strippedClaimData = this.stripClaimData(claimData); + const { claimType: role, claimTypeVersion: version } = claimData; if (registrationTypes.includes(RegistrationTypes.OnChain)) { - const { claimType: role, claimTypeVersion: version } = claimData; const expiry = defaultClaimExpiry; const onChainProof = await this.createOnChainProof( role, @@ -296,14 +300,43 @@ export class ClaimsService { ...(issuerFields && { issuerFields }), }, }; - message.issuedToken = await this._didRegistry.issuePublicClaim({ - publicClaim, - }); + const [issuedToken, vp] = await Promise.all([ + this._didRegistry.issuePublicClaim({ + publicClaim, + }), + this.issueVerifiablePresentation({ + subject: sub, + namespace: role, + version: version.toString(), + issuerFields, + }), + ]); + message.issuedToken = issuedToken; + message.vp = vp; } await this._cacheClient.issueClaim(this._signerService.did, message); } + private async issueVerifiablePresentation(options: { + subject: string; + namespace: string; + version: string; + issuerFields?: { key: string; value: string | number }[]; + }) { + const vc = await this._verifiableCredentialService.createRoleVC({ + id: options.subject, + namespace: options.namespace, + version: options.version, + issuerFields: options.issuerFields, + }); + const vp = + await this._verifiableCredentialService.createVerifiablePresentation([ + vc, + ]); + return JSON.stringify(vp); + } + /** * * @param token optional token containing claimType, version and subject diff --git a/src/modules/claims/claims.types.ts b/src/modules/claims/claims.types.ts index 5e53e788..e9085672 100644 --- a/src/modules/claims/claims.types.ts +++ b/src/modules/claims/claims.types.ts @@ -16,8 +16,8 @@ export interface IClaimIssuance extends IMessage { onChainProof?: string; claimType?: string; claimTypeVersion?: string; - acceptedBy: string; + vp?: string; } export interface IClaimRejection extends IMessage {