Skip to content

Commit

Permalink
feat(vc): delete w3c credential record (#886)
Browse files Browse the repository at this point in the history
Signed-off-by: Karim <karim@animo.id>
  • Loading branch information
karimStekelenburg authored and TimoGlastra committed Aug 26, 2022
1 parent 7cbccb1 commit be37011
Show file tree
Hide file tree
Showing 3 changed files with 109 additions and 38 deletions.
27 changes: 16 additions & 11 deletions packages/core/src/modules/vc/W3cCredentialService.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { AgentContext } from '../../agent/context'
import type { Key } from '../../crypto/Key'
import type { Query } from '../../storage/StorageService'
import type { DocumentLoader } from './jsonldUtil'
import type { W3cVerifyCredentialResult } from './models'
import type {
Expand Down Expand Up @@ -340,15 +341,15 @@ export class W3cCredentialService {
): Promise<W3cCredentialRecord> {
// Get the expanded types
const expandedTypes = (
await jsonld.expand(JsonTransformer.toJSON(options.record), {
await jsonld.expand(JsonTransformer.toJSON(options.credential), {
documentLoader: this.documentLoaderWithContext(agentContext),
})
)[0]['@type']

// Create an instance of the w3cCredentialRecord
const w3cCredentialRecord = new W3cCredentialRecord({
tags: { expandedTypes: orArrayToArray<string>(expandedTypes) },
credential: options.record,
credential: options.credential,
})

// Store the w3c credential record
Expand All @@ -357,26 +358,30 @@ export class W3cCredentialService {
return w3cCredentialRecord
}

public async getAllCredentials(agentContext: AgentContext): Promise<W3cVerifiableCredential[]> {
const allRecords = await this.w3cCredentialRepository.getAll(agentContext)
return allRecords.map((record) => record.credential)
public async removeCredentialRecord(agentContext: AgentContext, id: string) {
const credential = await this.w3cCredentialRepository.getById(agentContext, id)
await this.w3cCredentialRepository.delete(agentContext, credential)
}

public async getCredentialById(agentContext: AgentContext, id: string): Promise<W3cVerifiableCredential> {
return (await this.w3cCredentialRepository.getById(agentContext, id)).credential
public async getAllCredentialRecords(agentContext: AgentContext): Promise<W3cCredentialRecord[]> {
return await this.w3cCredentialRepository.getAll(agentContext)
}

public async findCredentialsByQuery(
public async getCredentialRecordById(agentContext: AgentContext, id: string): Promise<W3cCredentialRecord> {
return await this.w3cCredentialRepository.getById(agentContext, id)
}

public async findCredentialRecordsByQuery(
agentContext: AgentContext,
query: Parameters<typeof W3cCredentialRepository.prototype.findByQuery>[1]
query: Query<W3cCredentialRecord>
): Promise<W3cVerifiableCredential[]> {
const result = await this.w3cCredentialRepository.findByQuery(agentContext, query)
return result.map((record) => record.credential)
}

public async findSingleCredentialByQuery(
public async findCredentialRecordByQuery(
agentContext: AgentContext,
query: Parameters<typeof W3cCredentialRepository.prototype.findSingleByQuery>[1]
query: Query<W3cCredentialRecord>
): Promise<W3cVerifiableCredential | undefined> {
const result = await this.w3cCredentialRepository.findSingleByQuery(agentContext, query)
return result?.credential
Expand Down
118 changes: 92 additions & 26 deletions packages/core/src/modules/vc/__tests__/W3cCredentialService.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { AgentContext } from '../../../agent'

import { getAgentConfig, getAgentContext } from '../../../../tests/helpers'
import { getAgentConfig, getAgentContext, mockFunction } from '../../../../tests/helpers'
import { KeyType } from '../../../crypto'
import { Key } from '../../../crypto/Key'
import { Bls12381g2SigningProvider, SigningProviderRegistry } from '../../../crypto/signing-provider'
Expand All @@ -13,13 +13,14 @@ import { IndyLedgerService } from '../../ledger/services/IndyLedgerService'
import { SignatureSuiteRegistry } from '../SignatureSuiteRegistry'
import { W3cCredentialService } from '../W3cCredentialService'
import { orArrayToArray } from '../jsonldUtil'
import jsonld from '../libraries/jsonld'
import { purposes } from '../libraries/jsonld-signatures'
import { W3cCredential, W3cVerifiableCredential } from '../models'
import { LinkedDataProof } from '../models/LinkedDataProof'
import { W3cPresentation } from '../models/presentation/W3Presentation'
import { W3cVerifiablePresentation } from '../models/presentation/W3cVerifiablePresentation'
import { CredentialIssuancePurpose } from '../proof-purposes/CredentialIssuancePurpose'
import { W3cCredentialRepository } from '../repository/W3cCredentialRepository'
import { W3cCredentialRecord, W3cCredentialRepository } from '../repository'
import { Ed25519Signature2018 } from '../signature-suites'
import { BbsBlsSignature2020, BbsBlsSignatureProof2020 } from '../signature-suites/bbs'

Expand Down Expand Up @@ -59,6 +60,19 @@ const W3cCredentialRepositoryMock = W3cCredentialRepository as jest.Mock<W3cCred

const agentConfig = getAgentConfig('W3cCredentialServiceTest')

// Helper func
const credentialRecordFactory = async (credential: W3cVerifiableCredential) => {
const expandedTypes = (
await jsonld.expand(JsonTransformer.toJSON(credential), { documentLoader: customDocumentLoader })
)[0]['@type']

// Create an instance of the w3cCredentialRecord
return new W3cCredentialRecord({
tags: { expandedTypes: orArrayToArray<string>(expandedTypes) },
credential: credential,
})
}

describe('W3cCredentialService', () => {
let wallet: IndyWallet
let agentContext: AgentContext
Expand Down Expand Up @@ -285,30 +299,6 @@ describe('W3cCredentialService', () => {
expect(result.verified).toBe(true)
})
})
describe('storeCredential', () => {
it('should store a credential', async () => {
const credential = JsonTransformer.fromJSON(
Ed25519Signature2018Fixtures.TEST_LD_DOCUMENT_SIGNED,
W3cVerifiableCredential
)

const w3cCredentialRecord = await w3cCredentialService.storeCredential(agentContext, { record: credential })

expect(w3cCredentialRecord).toMatchObject({
type: 'W3cCredentialRecord',
id: expect.any(String),
createdAt: expect.any(Date),
credential: expect.any(W3cVerifiableCredential),
})

expect(w3cCredentialRecord.getTags()).toMatchObject({
expandedTypes: [
'https://www.w3.org/2018/credentials#VerifiableCredential',
'https://example.org/examples#UniversityDegreeCredential',
],
})
})
})
})

describe('BbsBlsSignature2020', () => {
Expand Down Expand Up @@ -454,4 +444,80 @@ describe('W3cCredentialService', () => {
})
})
})
describe('Credential Storage', () => {
let w3cCredentialRecord: W3cCredentialRecord
let w3cCredentialRepositoryDeleteMock: jest.MockedFunction<typeof w3cCredentialRepository['delete']>

beforeEach(async () => {
const credential = JsonTransformer.fromJSON(
Ed25519Signature2018Fixtures.TEST_LD_DOCUMENT_SIGNED,
W3cVerifiableCredential
)

w3cCredentialRecord = await credentialRecordFactory(credential)

mockFunction(w3cCredentialRepository.getById).mockResolvedValue(w3cCredentialRecord)
mockFunction(w3cCredentialRepository.getAll).mockResolvedValue([w3cCredentialRecord])
w3cCredentialRepositoryDeleteMock = mockFunction(w3cCredentialRepository.delete).mockResolvedValue()
})
describe('storeCredential', () => {
it('should store a credential and expand the tags correctly', async () => {
const credential = JsonTransformer.fromJSON(
Ed25519Signature2018Fixtures.TEST_LD_DOCUMENT_SIGNED,
W3cVerifiableCredential
)

w3cCredentialRecord = await w3cCredentialService.storeCredential(agentContext, { credential: credential })

expect(w3cCredentialRecord).toMatchObject({
type: 'W3cCredentialRecord',
id: expect.any(String),
createdAt: expect.any(Date),
credential: expect.any(W3cVerifiableCredential),
})

expect(w3cCredentialRecord.getTags()).toMatchObject({
expandedTypes: [
'https://www.w3.org/2018/credentials#VerifiableCredential',
'https://example.org/examples#UniversityDegreeCredential',
],
})
})
})

describe('removeCredentialRecord', () => {
it('should remove a credential', async () => {
const credential = JsonTransformer.fromJSON(
Ed25519Signature2018Fixtures.TEST_LD_DOCUMENT_SIGNED,
W3cVerifiableCredential
)

// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
await w3cCredentialService.removeCredentialRecord(agentContext, credential.id!)

expect(w3cCredentialRepositoryDeleteMock).toBeCalledWith(agentContext, w3cCredentialRecord)
})
})

describe('getAllCredentialRecords', () => {
it('should retrieve all W3cCredentialRecords', async () => {
const credential = JsonTransformer.fromJSON(
Ed25519Signature2018Fixtures.TEST_LD_DOCUMENT_SIGNED,
W3cVerifiableCredential
)
await w3cCredentialService.storeCredential(agentContext, { credential: credential })

const records = await w3cCredentialService.getAllCredentialRecords(agentContext)

expect(records.length).toEqual(1)
})
})
describe('getCredentialRecordById', () => {
it('should retrieve a W3cCredentialRecord by id', async () => {
const credential = await w3cCredentialService.getCredentialRecordById(agentContext, w3cCredentialRecord.id)

expect(credential.id).toEqual(w3cCredentialRecord.id)
})
})
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export interface VerifyCredentialOptions {
}

export interface StoreCredentialOptions {
record: W3cVerifiableCredential
credential: W3cVerifiableCredential
}

export interface CreatePresentationOptions {
Expand Down

0 comments on commit be37011

Please sign in to comment.