Skip to content

Commit

Permalink
feat: Method identityManagerGetOrCreateIdentity
Browse files Browse the repository at this point in the history
  • Loading branch information
simonas-notcat authored and mirceanis committed Sep 7, 2020
1 parent 46fd3a2 commit 0155389
Show file tree
Hide file tree
Showing 22 changed files with 592 additions and 12 deletions.
6 changes: 6 additions & 0 deletions __tests__/graphqlAgent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { DafResolver } from 'daf-resolver'
import { JwtMessageHandler } from 'daf-did-jwt'
import { W3c, IW3c, W3cMessageHandler } from 'daf-w3c'
import { EthrIdentityProvider } from 'daf-ethr-did'
import { WebIdentityProvider } from 'daf-web-did'
import { DIDComm, DIDCommMessageHandler, ISendMessageDIDCommAlpha1 } from 'daf-did-comm'
import { Sdr, ISdr, SdrMessageHandler } from 'daf-selective-disclosure'
import { KeyManagementSystem, SecretBox } from 'daf-libsodium'
Expand All @@ -32,6 +33,7 @@ import fs from 'fs'
import createVerifiableCredential from './shared/createVerifiableCredential'
import handleSdrMessage from './shared/handleSdrMessage'
import resolveDid from './shared/resolveDid'
import webDidFlow from './shared/webDidFlow'

const databaseFile = 'graphql-database.sqlite'
const infuraProjectId = '5ffc47f65c4042ce847ef66a3fa70d4c'
Expand Down Expand Up @@ -90,6 +92,9 @@ const setup = async (): Promise<boolean> => {
gas: 1000001,
ttl: 60 * 60 * 24 * 30 * 12 + 1,
}),
'did:web': new WebIdentityProvider({
defaultKms: 'local',
}),
},
}),
new DafResolver({ infuraProjectId }),
Expand Down Expand Up @@ -144,4 +149,5 @@ describe('GraphQL integration tests', () => {
createVerifiableCredential(testContext)
handleSdrMessage(testContext)
resolveDid(testContext)
webDidFlow(testContext)
})
6 changes: 6 additions & 0 deletions __tests__/localAgent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { DafResolver } from 'daf-resolver'
import { JwtMessageHandler } from 'daf-did-jwt'
import { W3c, IW3c, W3cMessageHandler } from 'daf-w3c'
import { EthrIdentityProvider } from 'daf-ethr-did'
import { WebIdentityProvider } from 'daf-web-did'
import { DIDComm, DIDCommMessageHandler, ISendMessageDIDCommAlpha1 } from 'daf-did-comm'
import { Sdr, ISdr, SdrMessageHandler } from 'daf-selective-disclosure'
import { KeyManagementSystem, SecretBox } from 'daf-libsodium'
Expand All @@ -25,6 +26,7 @@ import fs from 'fs'
import createVerifiableCredential from './shared/createVerifiableCredential'
import handleSdrMessage from './shared/handleSdrMessage'
import resolveDid from './shared/resolveDid'
import webDidFlow from './shared/webDidFlow'

const databaseFile = 'local-database.sqlite'
const infuraProjectId = '5ffc47f65c4042ce847ef66a3fa70d4c'
Expand Down Expand Up @@ -84,6 +86,9 @@ const setup = async (): Promise<boolean> => {
gas: 1000001,
ttl: 60 * 60 * 24 * 30 * 12 + 1,
}),
'did:web': new WebIdentityProvider({
defaultKms: 'local',
}),
},
}),
new DafResolver({ infuraProjectId }),
Expand Down Expand Up @@ -119,4 +124,5 @@ describe('Local integration tests', () => {
createVerifiableCredential(testContext)
handleSdrMessage(testContext)
resolveDid(testContext)
webDidFlow(testContext)
})
6 changes: 6 additions & 0 deletions __tests__/restAgent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { DafResolver } from 'daf-resolver'
import { JwtMessageHandler } from 'daf-did-jwt'
import { W3c, IW3c, W3cMessageHandler } from 'daf-w3c'
import { EthrIdentityProvider } from 'daf-ethr-did'
import { WebIdentityProvider } from 'daf-web-did'
import { DIDComm, DIDCommMessageHandler, ISendMessageDIDCommAlpha1 } from 'daf-did-comm'
import { Sdr, ISdr, SdrMessageHandler } from 'daf-selective-disclosure'
import { KeyManagementSystem, SecretBox } from 'daf-libsodium'
Expand All @@ -32,6 +33,7 @@ import fs from 'fs'
import createVerifiableCredential from './shared/createVerifiableCredential'
import handleSdrMessage from './shared/handleSdrMessage'
import resolveDid from './shared/resolveDid'
import webDidFlow from './shared/webDidFlow'

const databaseFile = 'rest-database.sqlite'
const infuraProjectId = '5ffc47f65c4042ce847ef66a3fa70d4c'
Expand Down Expand Up @@ -90,6 +92,9 @@ const setup = async (): Promise<boolean> => {
gas: 1000001,
ttl: 60 * 60 * 24 * 30 * 12 + 1,
}),
'did:web': new WebIdentityProvider({
defaultKms: 'local',
}),
},
}),
new DafResolver({ infuraProjectId }),
Expand Down Expand Up @@ -138,4 +143,5 @@ describe('REST integration tests', () => {
createVerifiableCredential(testContext)
handleSdrMessage(testContext)
resolveDid(testContext)
webDidFlow(testContext)
})
118 changes: 118 additions & 0 deletions __tests__/shared/webDidFlow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { TAgent, IIdentityManager, IIdentity, IKey } from 'daf-core'
import { IW3c } from 'daf-w3c'

type ConfiguredAgent = TAgent<IIdentityManager & IW3c>

export default (testContext: {
getAgent: () => ConfiguredAgent
setup: () => Promise<boolean>
tearDown: () => Promise<boolean>
}) => {
describe('web did flow', () => {
let agent: ConfiguredAgent
let serviceIdentity: IIdentity
let serviceIdentityKey: IKey
let alice: IIdentity
let bob: IIdentity

beforeAll(() => {
testContext.setup()
agent = testContext.getAgent()
})
afterAll(testContext.tearDown)

it('should create service identity', async () => {
serviceIdentity = await agent.identityManagerGetOrCreateIdentity({
provider: 'did:web',
alias: 'example.com',
})

expect(serviceIdentity.provider).toEqual('did:web')
expect(serviceIdentity.alias).toEqual('example.com')
expect(serviceIdentity.did).toEqual('did:web:example.com')
serviceIdentityKey = serviceIdentity.keys[0]
})

it('should get existing service identity', async () => {
const testIdentity = await agent.identityManagerGetOrCreateIdentity({
provider: 'did:web',
alias: 'example.com',
})

expect(testIdentity.keys[0]).toEqual(serviceIdentityKey)
expect(testIdentity.provider).toEqual('did:web')
expect(testIdentity.alias).toEqual('example.com')
expect(testIdentity.did).toEqual('did:web:example.com')
})

it('should create identity with alias: alice', async () => {
alice = await agent.identityManagerGetOrCreateIdentity({
alias: 'alice',
})

expect(alice.provider).toEqual('did:ethr:rinkeby')
expect(alice.alias).toEqual('alice')
expect(alice.did).toBeDefined()
})

it('should create identity with alias: bob', async () => {
bob = await agent.identityManagerGetOrCreateIdentity({
alias: 'bob',
})

expect(bob.provider).toEqual('did:ethr:rinkeby')
expect(bob.alias).toEqual('bob')
expect(bob.did).toBeDefined()
})

describe('should create verifiable credential', () => {
it('issuer: serviceIdentity', async () => {
const verifiableCredential = await agent.createVerifiableCredential({
credential: {
issuer: { id: serviceIdentity.did },
'@context': ['https://www.w3.org/2018/credentials/v1'],
type: ['VerifiableCredential'],
issuanceDate: new Date().toISOString(),
credentialSubject: {
id: alice.did,
name: 'Alice',
},
},
proofFormat: 'jwt',
})

expect(verifiableCredential.issuer).toEqual({ id: serviceIdentity.did })
expect(verifiableCredential.credentialSubject).toEqual({ id: alice.did, name: 'Alice' })
expect(verifiableCredential).toHaveProperty('proof.jwt')
})

it('issuer - Alice, subject - Bob', async () => {
const a = await agent.identityManagerGetOrCreateIdentity({
alias: 'alice',
})

const b = await agent.identityManagerGetOrCreateIdentity({
alias: 'bob',
})

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

expect(verifiableCredential.issuer).toEqual({ id: alice.did })
expect(verifiableCredential.credentialSubject).toEqual({ id: bob.did, name: 'Bob' })
expect(verifiableCredential).toHaveProperty('proof.jwt')
})
})
})
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { IKeyManager } from '../key-manager'
*/
export abstract class AbstractIdentityProvider {
abstract createIdentity(
args: { kms?: string; options?: any },
args: { kms?: string; alias?: string; options?: any },
context: IAgentContext<IKeyManager>,
): Promise<Omit<IIdentity, 'provider'>>
abstract deleteIdentity(args: IIdentity, context: IAgentContext<IKeyManager>): Promise<boolean>
Expand Down
3 changes: 2 additions & 1 deletion packages/daf-core/src/abstract/abstract-identity-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { IIdentity } from '../types'

export abstract class AbstractIdentityStore {
abstract import(args: IIdentity): Promise<boolean>
abstract get(args: { did?: string; alias?: string }): Promise<IIdentity>
abstract get(args: { did: string }): Promise<IIdentity>
abstract get(args: { alias: string }): Promise<IIdentity>
abstract delete(args: { did: string }): Promise<boolean>
abstract list(): Promise<IIdentity[]>
}
20 changes: 18 additions & 2 deletions packages/daf-core/src/identity-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ export interface IIdentityManager extends IPluginMethodMap {
},
context: IAgentContext<IKeyManager>,
) => Promise<IIdentity>
// identityManagerGetOrCreateIdentity?: (args: { alias: string, provider?: string, kms?: string, options?: any}) => Promise<IIdentity>
identityManagerGetOrCreateIdentity: (
args: { alias: string; provider?: string; kms?: string; options?: any },
context: IAgentContext<IKeyManager>,
) => Promise<IIdentity>
identityManagerImportIdentity: (args: IIdentity) => Promise<IIdentity>
identityManagerDeleteIdentity: (
args: { did: string },
Expand Down Expand Up @@ -59,6 +62,7 @@ export class IdentityManager implements IAgentPlugin {
identityManagerGetIdentities: this.identityManagerGetIdentities.bind(this),
identityManagerGetIdentity: this.identityManagerGetIdentity.bind(this),
identityManagerCreateIdentity: this.identityManagerCreateIdentity.bind(this),
identityManagerGetOrCreateIdentity: this.identityManagerGetOrCreateIdentity.bind(this),
identityManagerImportIdentity: this.identityManagerImportIdentity.bind(this),
identityManagerDeleteIdentity: this.identityManagerDeleteIdentity.bind(this),
identityManagerAddKey: this.identityManagerAddKey.bind(this),
Expand Down Expand Up @@ -92,12 +96,24 @@ export class IdentityManager implements IAgentPlugin {
): Promise<IIdentity> {
const providerName = provider || this.defaultProvider
const identityProvider = this.getProvider(providerName)
const partialIdentity = await identityProvider.createIdentity({ kms, options }, context)
const partialIdentity = await identityProvider.createIdentity({ kms, alias, options }, context)
const identity: IIdentity = { ...partialIdentity, alias, provider: providerName }
await this.store.import(identity)
return identity
}

async identityManagerGetOrCreateIdentity(
{ provider, alias, kms, options }: { alias: string; provider?: string; kms?: string; options?: any },
context: IAgentContext<IKeyManager>,
): Promise<IIdentity> {
try {
const identity = await this.store.get({ alias })
return identity
} catch {
return this.identityManagerCreateIdentity({ provider, alias, kms, options }, context)
}
}

async identityManagerImportIdentity(identity: IIdentity): Promise<IIdentity> {
await this.store.import(identity)
return identity
Expand Down
3 changes: 3 additions & 0 deletions packages/daf-core/src/key-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ export class KeyManager implements IAgentPlugin {
const partialKey = await kms.createKey({ type: args.type, meta: args.meta })
const key: IKey = { ...partialKey, kms: args.kms }
await this.store.import(key)
if (key.privateKeyHex) {
delete key.privateKeyHex
}
return key
}

Expand Down
2 changes: 1 addition & 1 deletion packages/daf-ethr-did/src/identity-provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export class EthrIdentityProvider extends AbstractIdentityProvider {
}

async createIdentity(
{ kms, options }: { kms: string; options?: any },
{ kms, options }: { kms?: string; options?: any },
context: IContext,
): Promise<Omit<IIdentity, 'provider'>> {
const key = await context.agent.keyManagerCreateKey({ kms: kms || this.defaultKms, type: 'Secp256k1' })
Expand Down
17 changes: 17 additions & 0 deletions packages/daf-graphql/src/base-type-def.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,26 @@ export const baseTypeDef = `
type Query
type Mutation
type Key {
kid: String!
kms: String!
type: String!
publicKeyHex: String
}
type Service {
id: String!
type: String!
serviceEndpoint: String!
description: String
}
type Identity {
did: String!
provider: String
alias: String
keys: [Key]
services: [Service]
}
scalar Object
Expand Down
Loading

0 comments on commit 0155389

Please sign in to comment.