Skip to content

Commit

Permalink
feat(did-discovery): implement a DID discovery plugin with simple pro…
Browse files Browse the repository at this point in the history
…viders (#597)

* feat(did-discovery): types and interfaces

* feat: alias and profile discovery providers

* docs: inline API docs

* test: note about a DB breaking test

* fix: license

* fix: constructor takes an array of providers
  • Loading branch information
simonas-notcat authored Jul 5, 2021
1 parent 6c74eed commit 6f01df3
Show file tree
Hide file tree
Showing 22 changed files with 788 additions and 10 deletions.
18 changes: 15 additions & 3 deletions __tests__/localAgent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
} from '../packages/core/src'
import { MessageHandler } from '../packages/message-handler/src'
import { KeyManager } from '../packages/key-manager/src'
import { DIDManager } from '../packages/did-manager/src'
import { DIDManager, AliasDiscoveryProvider } from '../packages/did-manager/src'
import { createConnection, Connection } from 'typeorm'
import { DIDResolverPlugin } from '../packages/did-resolver/src'
import { JwtMessageHandler } from '../packages/did-jwt/src'
Expand All @@ -32,11 +32,13 @@ import {
IDataStoreORM,
DataStore,
DataStoreORM,
ProfileDiscoveryProvider
} from '../packages/data-store/src'
import { Resolver } from 'did-resolver'
import { getResolver as ethrDidResolver } from 'ethr-did-resolver'
import { getResolver as webDidResolver } from 'web-did-resolver'
import { getDidKeyResolver } from '../packages/did-provider-key'
import { IDIDDiscovery, DIDDiscovery } from '../packages/did-discovery'
import fs from 'fs'

jest.setTimeout(30000)
Expand All @@ -52,6 +54,7 @@ import keyManager from './shared/keyManager'
import didManager from './shared/didManager'
import didComm from './shared/didcomm'
import messageHandler from './shared/messageHandler'
import didDiscovery from './shared/didDiscovery'

const databaseFile = 'local-database.sqlite'
const infuraProjectId = '5ffc47f65c4042ce847ef66a3fa70d4c'
Expand All @@ -66,7 +69,8 @@ let agent: TAgent<
IMessageHandler &
IDIDComm &
ICredentialIssuer &
ISelectiveDisclosure
ISelectiveDisclosure &
IDIDDiscovery
>
let dbConnection: Promise<Connection>

Expand All @@ -88,7 +92,8 @@ const setup = async (options?: IAgentOptions): Promise<boolean> => {
IMessageHandler &
IDIDComm &
ICredentialIssuer &
ISelectiveDisclosure
ISelectiveDisclosure &
IDIDDiscovery
>({
...options,
context: {
Expand Down Expand Up @@ -147,6 +152,12 @@ const setup = async (options?: IAgentOptions): Promise<boolean> => {
new DIDComm(),
new CredentialIssuer(),
new SelectiveDisclosure(),
new DIDDiscovery({
providers: [
new AliasDiscoveryProvider(),
new ProfileDiscoveryProvider(),
]
}),
],
})
return true
Expand All @@ -173,4 +184,5 @@ describe('Local integration tests', () => {
didManager(testContext)
messageHandler(testContext)
didComm(testContext)
didDiscovery(testContext)
})
4 changes: 2 additions & 2 deletions __tests__/localMemoryStoreAgent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ let agent: TAgent<
IMessageHandler &
IDIDComm &
ICredentialIssuer &
ISelectiveDisclosure
ISelectiveDisclosure
>
let dbConnection: Promise<Connection>

Expand All @@ -81,7 +81,7 @@ const setup = async (options?: IAgentOptions): Promise<boolean> => {
IMessageHandler &
IDIDComm &
ICredentialIssuer &
ISelectiveDisclosure
ISelectiveDisclosure
>({
...options,
context: {
Expand Down
18 changes: 15 additions & 3 deletions __tests__/restAgent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import {
} from '../packages/core/src'
import { MessageHandler } from '../packages/message-handler/src'
import { KeyManager } from '../packages/key-manager/src'
import { DIDManager } from '../packages/did-manager/src'
import { DIDManager, AliasDiscoveryProvider } from '../packages/did-manager/src'
import { createConnection, Connection } from 'typeorm'
import { DIDResolverPlugin } from '../packages/did-resolver/src'
import { JwtMessageHandler } from '../packages/did-jwt/src'
Expand All @@ -34,6 +34,7 @@ import {
IDataStoreORM,
DataStore,
DataStoreORM,
ProfileDiscoveryProvider
} from '../packages/data-store/src'
import { AgentRestClient } from '../packages/remote-client/src'
import express from 'express'
Expand All @@ -42,6 +43,9 @@ import { AgentRouter, RequestWithAgentRouter } from '../packages/remote-server/s
import { Resolver } from 'did-resolver'
import { getResolver as ethrDidResolver } from 'ethr-did-resolver'
import { getResolver as webDidResolver } from 'web-did-resolver'
import { IDIDDiscovery, DIDDiscovery } from '../packages/did-discovery'
import { getUniversalResolver } from '../packages/did-resolver/src/universal-resolver'

import fs from 'fs'

jest.setTimeout(30000)
Expand All @@ -56,7 +60,7 @@ import keyManager from './shared/keyManager'
import didManager from './shared/didManager'
import didComm from './shared/didcomm'
import messageHandler from './shared/messageHandler'
import { getUniversalResolver } from '../packages/did-resolver/src/universal-resolver'
import didDiscovery from './shared/didDiscovery'

const databaseFile = 'rest-database.sqlite'
const infuraProjectId = '5ffc47f65c4042ce847ef66a3fa70d4c'
Expand All @@ -78,7 +82,8 @@ const getAgent = (options?: IAgentOptions) =>
IMessageHandler &
IDIDComm &
ICredentialIssuer &
ISelectiveDisclosure
ISelectiveDisclosure &
IDIDDiscovery
>({
...options,
plugins: [
Expand Down Expand Up @@ -154,6 +159,12 @@ const setup = async (options?: IAgentOptions): Promise<boolean> => {
new DIDComm(),
new CredentialIssuer(),
new SelectiveDisclosure(),
new DIDDiscovery({
providers: [
new AliasDiscoveryProvider(),
new ProfileDiscoveryProvider(),
]
}),
],
})

Expand Down Expand Up @@ -193,4 +204,5 @@ describe('REST integration tests', () => {
didManager(testContext)
messageHandler(testContext)
didComm(testContext)
didDiscovery(testContext)
})
118 changes: 118 additions & 0 deletions __tests__/shared/didDiscovery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { IDIDDiscovery } from '../../packages/did-discovery'
import { TAgent, IDIDManager, IKeyManager, IIdentifier } from '../../packages/core/src'
import { IDataStoreORM } from '../../packages/data-store/src'
import { ICredentialIssuer } from '../../packages/credential-w3c/src'
import { getConnection } from 'typeorm'

type ConfiguredAgent = TAgent<IDIDManager & IDIDDiscovery & IDataStoreORM & ICredentialIssuer>

export default (testContext: {
getAgent: () => ConfiguredAgent
setup: () => Promise<boolean>
tearDown: () => Promise<boolean>
}) => {
describe('DID discovery', () => {
let agent: ConfiguredAgent

beforeAll(async () => {
await testContext.setup()
agent = testContext.getAgent()
return true
})
afterAll(testContext.tearDown)


it('should discover did by alias', async () => {
const identifier = await agent.didManagerCreate({
alias: 'alice',
})

const result = await agent.discoverDid({ query: 'alice'})

expect(result.results[0].matches[0]).toEqual({
did: identifier.did,
metaData: {
alias: 'alice'
}
})
})


it('should discover did by profile vc', async () => {
const identifier = await agent.didManagerCreate({})

const verifiableCredential = await agent.createVerifiableCredential({
credential: {
issuer: { id: identifier.did },
'@context': ['https://www.w3.org/2018/credentials/v1'],
type: ['VerifiableCredential', 'Profile'],
issuanceDate: new Date().toISOString(),
credentialSubject: {
id: identifier.did,
name: 'bob',
},
},
proofFormat: 'jwt',
save: true
})

const result = await agent.discoverDid({ query: 'bob'})

expect(result.results[0].matches[0]).toEqual({
did: identifier.did,
metaData: { verifiableCredential }
})
})

it('should discover did by alias and profile vc', async () => {
const identifier = await agent.didManagerCreate({
alias: 'bob'
})

const verifiableCredential = await agent.createVerifiableCredential({
credential: {
issuer: { id: identifier.did },
'@context': ['https://www.w3.org/2018/credentials/v1'],
type: ['VerifiableCredential', 'Profile'],
issuanceDate: new Date().toISOString(),
credentialSubject: {
id: identifier.did,
name: 'bobby',
},
},
proofFormat: 'jwt',
save: true
})

const result = await agent.discoverDid({ query: 'bob'})

expect(result.results).toHaveLength(2)
expect(result.results[0].matches).toHaveLength(1)
expect(result.results[1].matches).toHaveLength(2)

expect(result.results[0].matches[0]).toEqual({
did: identifier.did,
metaData: {
alias: 'bob'
}
})

expect(result.results[1].matches[1]).toEqual({
did: identifier.did,
metaData: { verifiableCredential }
})
})

// THIS HAS TO BE THE LAST TEST IN THIS FILE!
it('should return errors', async () => {
const connection = getConnection()
await connection.query('PRAGMA foreign_keys = OFF;')
await connection.query('DROP TABLE claim;')

const result = await agent.discoverDid({ query: 'bob'})
expect(result.errors).toEqual({ profile: 'SQLITE_ERROR: no such table: claim' })

})

})
}
1 change: 1 addition & 0 deletions packages/data-store/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
},
"dependencies": {
"@veramo/core": "^1.2.0",
"@veramo/did-discovery": "^1.2.0",
"@veramo/did-manager": "^1.2.0",
"@veramo/key-manager": "^1.2.0",
"debug": "^4.1.1",
Expand Down
37 changes: 37 additions & 0 deletions packages/data-store/src/did-discovery-provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { IAgentContext } from '@veramo/core'
import { IDataStoreORM } from './data-store-orm'
import { AbstractDidDiscoveryProvider, IDIDDiscoverMatch, IDIDDiscoveryProviderResult, IDIDDiscoveryDiscoverDidArgs } from '@veramo/did-discovery'

export class ProfileDiscoveryProvider implements AbstractDidDiscoveryProvider {

readonly name = 'profile'

async discoverDid(
args: IDIDDiscoveryDiscoverDidArgs,
context: IAgentContext<IDataStoreORM>,
): Promise<IDIDDiscoveryProviderResult> {
const matches: IDIDDiscoverMatch[] = []

const credentials = await context.agent.dataStoreORMGetVerifiableCredentialsByClaims({
where: [
{ column: 'type', value: ['name'] },
{ column: 'value', value: [`${args.query}%`], op: 'Like' },
{ column: 'credentialType', value: ['VerifiableCredential,Profile'] }
]
})

credentials.forEach( vc => {
matches.push({
did: vc.verifiableCredential.credentialSubject.id as string,
metaData: {
verifiableCredential: vc.verifiableCredential
}
})
})

return {
provider: this.name,
matches
}
}
}
1 change: 1 addition & 0 deletions packages/data-store/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export {
UniqueVerifiableCredential,
} from './data-store-orm'
export * from './types'
export { ProfileDiscoveryProvider } from './did-discovery-provider'
import { Key, KeyType } from './entities/key'
import { Identifier } from './entities/identifier'
import { Claim } from './entities/claim'
Expand Down
Loading

0 comments on commit 6f01df3

Please sign in to comment.