From 39f2e39685a58d647822aea73a8bb3f7fb76fe25 Mon Sep 17 00:00:00 2001 From: Simonas Karuzas Date: Fri, 10 Apr 2020 14:28:18 +0300 Subject: [PATCH 1/7] feat: Default IdentityProvider --- docs/Docs.md | 3 +- examples/expressjs-ethr/src/identity.ts | 3 +- examples/expressjs-ethr/yarn.lock | 50 +++++++++---------- examples/send-vc/index.ts | 3 +- examples/send-vc/yarn.lock | 38 +++++++------- packages/daf-cli/src/identity-manager.ts | 28 ++++++----- .../src/graphql/graphql-identity-manager.ts | 2 +- .../daf-core/src/identity/identity-manager.ts | 22 +++++--- 8 files changed, 78 insertions(+), 71 deletions(-) diff --git a/docs/Docs.md b/docs/Docs.md index 72e65b877..68a25a519 100644 --- a/docs/Docs.md +++ b/docs/Docs.md @@ -117,8 +117,7 @@ console.log(`🚀 Server ready at ${info.url}`) ## Typescript ```typescript -const providers = await core.identityManager.getIdentityProviders() -const identity = await core.identityManager.createIdentity(providers[0].type) +const identity = await agent.identityManager.createIdentity() ``` ## GraphQL diff --git a/examples/expressjs-ethr/src/identity.ts b/examples/expressjs-ethr/src/identity.ts index 732f8291d..a4f531d77 100644 --- a/examples/expressjs-ethr/src/identity.ts +++ b/examples/expressjs-ethr/src/identity.ts @@ -8,8 +8,7 @@ export const getIdentity = async () => { if (identities.length > 0) { identity = identities[0] } else { - const identityProviders = await agent.identityManager.getIdentityProviders() - identity = await agent.identityManager.createIdentity(identityProviders[0].type) + identity = await agent.identityManager.createIdentity() } return identity diff --git a/examples/expressjs-ethr/yarn.lock b/examples/expressjs-ethr/yarn.lock index f60629d0e..3e777dedf 100644 --- a/examples/expressjs-ethr/yarn.lock +++ b/examples/expressjs-ethr/yarn.lock @@ -613,51 +613,51 @@ cross-fetch@^3.0.4: node-fetch "2.6.0" whatwg-fetch "3.0.0" -daf-core@../../packages/daf-core, daf-core@^4.0.0-beta.39+63dd12d: - version "4.0.0-beta.39" +daf-core@../../packages/daf-core, daf-core@^4.0.0-beta.42: + version "4.0.0-beta.42" dependencies: blakejs "^1.1.0" debug "^4.1.1" events "^3.0.0" typeorm "^0.2.24" -daf-data-store@../../packages/daf-data-store, daf-data-store@^4.0.0-beta.39+63dd12d: - version "4.0.0-beta.39" +daf-data-store@../../packages/daf-data-store, daf-data-store@^4.0.0-beta.42: + version "4.0.0-beta.42" dependencies: blakejs "^1.1.0" - daf-core "^4.0.0-beta.39+63dd12d" + daf-core "^4.0.0-beta.42" debug "^4.1.1" sql-bricks-sqlite "^0.1.0" daf-did-comm@../../packages/daf-did-comm: - version "4.0.0-beta.39" + version "4.0.0-beta.42" dependencies: - daf-core "^4.0.0-beta.39+63dd12d" + daf-core "^4.0.0-beta.42" debug "^4.1.1" uuid "^3.3.3" -daf-did-jwt@../../packages/daf-did-jwt, daf-did-jwt@^4.0.0-beta.39+63dd12d: - version "4.0.0-beta.39" +daf-did-jwt@../../packages/daf-did-jwt, daf-did-jwt@^4.0.0-beta.42: + version "4.0.0-beta.42" dependencies: - daf-core "^4.0.0-beta.39+63dd12d" + daf-core "^4.0.0-beta.42" debug "^4.1.1" did-jwt "^4.0.0" did-resolver "^1.1.0" daf-ethr-did@../../packages/daf-ethr-did: - version "4.0.0-beta.39" + version "4.0.0-beta.42" dependencies: - daf-core "^4.0.0-beta.39+63dd12d" + daf-core "^4.0.0-beta.42" debug "^4.1.1" ethjs-provider-signer "^0.1.4" ethr-did "^1.1.0" js-sha3 "^0.8.0" daf-libsodium@../../packages/daf-libsodium: - version "4.0.0-beta.39" + version "4.0.0-beta.42" dependencies: base-58 "^0.0.1" - daf-core "^4.0.0-beta.39+63dd12d" + daf-core "^4.0.0-beta.42" debug "^4.1.1" did-jwt "^4.0.0" elliptic "^6.5.2" @@ -665,13 +665,13 @@ daf-libsodium@../../packages/daf-libsodium: libsodium-wrappers "^0.7.6" daf-resolver-universal@../../packages/daf-resolver-universal: - version "3.0.1" + version "4.0.0-beta.42" dependencies: cross-fetch "^3.0.4" debug "^4.1.1" daf-resolver@../../packages/daf-resolver: - version "3.0.1" + version "4.0.0-beta.42" dependencies: debug "^4.1.1" did-resolver "^1.1.0" @@ -680,29 +680,29 @@ daf-resolver@../../packages/daf-resolver: web-did-resolver "^1.2.0" daf-selective-disclosure@../../packages/daf-selective-disclosure: - version "4.0.0-beta.41" + version "4.0.0-beta.42" dependencies: blakejs "^1.1.0" - daf-core "^4.0.0-beta.39+63dd12d" - daf-data-store "^4.0.0-beta.39+63dd12d" - daf-did-jwt "^4.0.0-beta.39+63dd12d" + daf-core "^4.0.0-beta.42" + daf-data-store "^4.0.0-beta.42" + daf-did-jwt "^4.0.0-beta.42" debug "^4.1.1" did-jwt "^4.0.0" typeorm "^0.2.24" daf-url@../../packages/daf-url: - version "4.0.0-beta.39" + version "4.0.0-beta.42" dependencies: - daf-core "^4.0.0-beta.39+63dd12d" + daf-core "^4.0.0-beta.42" debug "^4.1.1" url-parse "^1.4.7" daf-w3c@../../packages/daf-w3c: - version "4.0.0-beta.39" + version "4.0.0-beta.42" dependencies: blakejs "^1.1.0" - daf-core "^4.0.0-beta.39+63dd12d" - daf-did-jwt "^4.0.0-beta.39+63dd12d" + daf-core "^4.0.0-beta.42" + daf-did-jwt "^4.0.0-beta.42" debug "^4.1.1" did-jwt-vc "^0.1.3" did-resolver "^1.1.0" diff --git a/examples/send-vc/index.ts b/examples/send-vc/index.ts index df9f9c8bd..00affc66f 100644 --- a/examples/send-vc/index.ts +++ b/examples/send-vc/index.ts @@ -10,8 +10,7 @@ async function main() { if (identities.length > 0) { identity = identities[0] } else { - const identityProviders = await agent.identityManager.getIdentityProviders() - identity = await agent.identityManager.createIdentity(identityProviders[0].type) + identity = await agent.identityManager.createIdentity() } // Sign verifiable credential diff --git a/examples/send-vc/yarn.lock b/examples/send-vc/yarn.lock index 9911b9218..190021750 100644 --- a/examples/send-vc/yarn.lock +++ b/examples/send-vc/yarn.lock @@ -479,8 +479,8 @@ cross-fetch@^3.0.4: node-fetch "2.6.0" whatwg-fetch "3.0.0" -daf-core@../../packages/daf-core, daf-core@^4.0.0-beta.39+63dd12d: - version "4.0.0-beta.39" +daf-core@../../packages/daf-core, daf-core@^4.0.0-beta.42: + version "4.0.0-beta.42" dependencies: blakejs "^1.1.0" debug "^4.1.1" @@ -488,40 +488,40 @@ daf-core@../../packages/daf-core, daf-core@^4.0.0-beta.39+63dd12d: typeorm "^0.2.24" daf-did-comm@../../packages/daf-did-comm: - version "4.0.0-beta.39" + version "4.0.0-beta.42" dependencies: - daf-core "^4.0.0-beta.39+63dd12d" + daf-core "^4.0.0-beta.42" debug "^4.1.1" uuid "^3.3.3" -daf-did-jwt@../../packages/daf-did-jwt, daf-did-jwt@^4.0.0-beta.39+63dd12d: - version "4.0.0-beta.39" +daf-did-jwt@../../packages/daf-did-jwt, daf-did-jwt@^4.0.0-beta.42: + version "4.0.0-beta.42" dependencies: - daf-core "^4.0.0-beta.39+63dd12d" + daf-core "^4.0.0-beta.42" debug "^4.1.1" did-jwt "^4.0.0" did-resolver "^1.1.0" daf-ethr-did@../../packages/daf-ethr-did: - version "4.0.0-beta.39" + version "4.0.0-beta.42" dependencies: - daf-core "^4.0.0-beta.39+63dd12d" + daf-core "^4.0.0-beta.42" debug "^4.1.1" ethjs-provider-signer "^0.1.4" ethr-did "^1.1.0" js-sha3 "^0.8.0" daf-fs@../../packages/daf-fs: - version "4.0.0-beta.39" + version "4.0.0-beta.42" dependencies: - daf-core "^4.0.0-beta.39+63dd12d" + daf-core "^4.0.0-beta.42" debug "^4.1.1" daf-libsodium@../../packages/daf-libsodium: - version "4.0.0-beta.39" + version "4.0.0-beta.42" dependencies: base-58 "^0.0.1" - daf-core "^4.0.0-beta.39+63dd12d" + daf-core "^4.0.0-beta.42" debug "^4.1.1" did-jwt "^4.0.0" elliptic "^6.5.2" @@ -529,7 +529,7 @@ daf-libsodium@../../packages/daf-libsodium: libsodium-wrappers "^0.7.6" daf-resolver@../../packages/daf-resolver: - version "3.0.1" + version "4.0.0-beta.42" dependencies: debug "^4.1.1" did-resolver "^1.1.0" @@ -538,7 +538,7 @@ daf-resolver@../../packages/daf-resolver: web-did-resolver "^1.2.0" daf-trust-graph@../../packages/daf-trust-graph: - version "4.0.0-beta.39" + version "4.0.0-beta.42" dependencies: apollo-cache-inmemory "^1.6.3" apollo-client "^2.6.4" @@ -547,7 +547,7 @@ daf-trust-graph@../../packages/daf-trust-graph: apollo-link-ws "^1.0.19" apollo-utilities "^1.3.2" cross-fetch "^3.0.4" - daf-core "^4.0.0-beta.39+63dd12d" + daf-core "^4.0.0-beta.42" debug "^4.1.1" did-jwt "^4.0.0" graphql "^14.0.0" @@ -555,11 +555,11 @@ daf-trust-graph@../../packages/daf-trust-graph: subscriptions-transport-ws "^0.9.0" daf-w3c@../../packages/daf-w3c: - version "4.0.0-beta.39" + version "4.0.0-beta.42" dependencies: blakejs "^1.1.0" - daf-core "^4.0.0-beta.39+63dd12d" - daf-did-jwt "^4.0.0-beta.39+63dd12d" + daf-core "^4.0.0-beta.42" + daf-did-jwt "^4.0.0-beta.42" debug "^4.1.1" did-jwt-vc "^0.1.3" did-resolver "^1.1.0" diff --git a/packages/daf-cli/src/identity-manager.ts b/packages/daf-cli/src/identity-manager.ts index 145e7ab97..27bf48773 100644 --- a/packages/daf-cli/src/identity-manager.ts +++ b/packages/daf-cli/src/identity-manager.ts @@ -45,19 +45,23 @@ program if (cmd.create) { try { const providers = await agent.identityManager.getIdentityProviders() + let type + if (providers.length > 1) { + const answers = await inquirer.prompt([ + { + type: 'list', + name: 'type', + choices: providers.map(provider => ({ + name: `${provider.type} - ${provider.description}`, + value: provider.type, + })), + message: 'Select identity provider', + }, + ]) - const answers = await inquirer.prompt([ - { - type: 'list', - name: 'type', - choices: providers.map(provider => ({ - name: `${provider.type} - ${provider.description}`, - value: provider.type, - })), - message: 'Select identity provider', - }, - ]) - const identity = await agent.identityManager.createIdentity(answers.type) + type = answers.type + } + const identity = await agent.identityManager.createIdentity(type) printTable([{ type: identity.identityProviderType, did: identity.did }]) } catch (e) { console.error(e) diff --git a/packages/daf-core/src/graphql/graphql-identity-manager.ts b/packages/daf-core/src/graphql/graphql-identity-manager.ts index fd5338f34..b31cda77e 100644 --- a/packages/daf-core/src/graphql/graphql-identity-manager.ts +++ b/packages/daf-core/src/graphql/graphql-identity-manager.ts @@ -6,7 +6,7 @@ export interface Context { } const identityProviders = async (_: any, args: any, ctx: Context) => { - return await ctx.agent.identityManager.getIdentityProviders() + return ctx.agent.identityManager.getIdentityProviders() } const managedIdentities = async (_: any, args: any, ctx: Context) => { diff --git a/packages/daf-core/src/identity/identity-manager.ts b/packages/daf-core/src/identity/identity-manager.ts index ba3a30b9a..f62a9ead8 100644 --- a/packages/daf-core/src/identity/identity-manager.ts +++ b/packages/daf-core/src/identity/identity-manager.ts @@ -12,18 +12,18 @@ export class IdentityManager { this.identityProviders = options.identityProviders } - async getIdentityProviders(): Promise { + getIdentityProviders(): AbstractIdentityProvider[] { return this.identityProviders } - async getIdentityProvider(type: string): Promise { + getIdentityProvider(type: string): AbstractIdentityProvider { for (const identityProvider of this.identityProviders) { if (identityProvider.type === type) { return identityProvider } } - return Promise.reject('IdentityProvider not found for type: ' + type) + throw Error('IdentityProvider not found for type: ' + type) } async getIdentities(): Promise { @@ -45,23 +45,29 @@ export class IdentityManager { } } - async createIdentity(identityProviderType: string): Promise { - const identityProvider = await this.getIdentityProvider(identityProviderType) + async createIdentity(identityProviderType?: string): Promise { + const identityProvider = identityProviderType + ? this.getIdentityProvider(identityProviderType) + : this.getDefaultIdentityProvider() return identityProvider.createIdentity() } async importIdentity(identityProviderType: string, secret: string): Promise { - const identityProvider = await this.getIdentityProvider(identityProviderType) + const identityProvider = this.getIdentityProvider(identityProviderType) return identityProvider.importIdentity(secret) } async exportIdentity(identityProviderType: string, did: string): Promise { - const identityProvider = await this.getIdentityProvider(identityProviderType) + const identityProvider = this.getIdentityProvider(identityProviderType) return identityProvider.exportIdentity(did) } async deleteIdentity(identityProviderType: string, did: string): Promise { - const identityProvider = await this.getIdentityProvider(identityProviderType) + const identityProvider = this.getIdentityProvider(identityProviderType) return identityProvider.deleteIdentity(did) } + + private getDefaultIdentityProvider(): AbstractIdentityProvider { + return this.identityProviders[0] + } } From f4913711ce4f9dc546bbf5ae29689b1d0ee95e14 Mon Sep 17 00:00:00 2001 From: Simonas Karuzas Date: Tue, 14 Apr 2020 21:23:34 +0300 Subject: [PATCH 2/7] feat: WIP --- packages/daf-core/src/graphql/graphql-core.ts | 347 +++++++++--------- 1 file changed, 176 insertions(+), 171 deletions(-) diff --git a/packages/daf-core/src/graphql/graphql-core.ts b/packages/daf-core/src/graphql/graphql-core.ts index 5ededa384..2f9f9d5a8 100644 --- a/packages/daf-core/src/graphql/graphql-core.ts +++ b/packages/daf-core/src/graphql/graphql-core.ts @@ -1,4 +1,17 @@ -import { In } from 'typeorm' +import { + Not, + LessThan, + LessThanOrEqual, + MoreThan, + MoreThanOrEqual, + Equal, + Like, + Between, + In, + Any, + IsNull, + FindManyOptions, +} from 'typeorm' import { Agent } from '../agent' import { Message } from '../entities/message' import { Presentation } from '../entities/presentation' @@ -10,125 +23,122 @@ export interface Context { agent: Agent } -export interface FindOptions { +export interface Order { + column: string + direction: 'ASC' | 'DESC' +} + +export interface Where { + column: string + value?: string[] + op?: + | 'LessThan' + | 'LessThanOrEqual' + | 'MoreThan' + | 'MoreThanOrEqual' + | 'Equal' + | 'Like' + | 'Between' + | 'In' + | 'Any' + | 'IsNull' +} +export interface FindInput { + where?: Where[] + order?: Order[] take?: number skip?: number } -const messages = async ( - _: any, - { - input, - }: { - input?: { - options?: FindOptions - from?: string[] - to?: string[] - type?: string[] - threadId?: string[] - } - }, - ctx: Context, -) => { - const options = { - where: {}, - } - - if (input?.from) options.where['from'] = In(input.from) - if (input?.to) options.where['to'] = In(input.to) - if (input?.type) options.where['type'] = In(input.type) - if (input?.threadId) options.where['threadId'] = In(input.threadId) - if (input?.options?.skip) options['skip'] = input.options.skip - if (input?.options?.take) options['take'] = input.options.take - - return (await ctx.agent.dbConnection).getRepository(Message).find(options) +interface TypeOrmOrder { + [x: string]: 'ASC' | 'DESC' } -const presentations = async ( - _: any, - { - input, - }: { - input?: { - options?: FindOptions - issuer?: string[] - audience?: string[] - type?: string[] - context?: string[] - } - }, - ctx: Context, -) => { - const options = { +function transformFindInput(input: FindInput): FindManyOptions { + const result: FindManyOptions = { where: {}, } - - if (input?.issuer) options.where['issuer'] = In(input.issuer) - if (input?.audience) options.where['audience'] = In(input.audience) - if (input?.type) options.where['type'] = In(input.type) - if (input?.context) options.where['context'] = In(input.context) - if (input?.options?.skip) options['skip'] = input.options.skip - if (input?.options?.take) options['take'] = input.options.take - - return (await ctx.agent.dbConnection).getRepository(Presentation).find(options) -} - -const credentials = async ( - _: any, - { - input, - }: { - input?: { - options?: FindOptions - issuer?: string[] - subject?: string[] - type?: string[] - context?: string[] + if (input?.skip) result['skip'] = input.skip + if (input?.take) result['take'] = input.take + if (input?.order) { + const order: TypeOrmOrder = {} + for (const item of input.order) { + order[item.column] = item.direction } - }, - ctx: Context, -) => { - const options = { - where: {}, + result['order'] = order } + if (input?.where) { + const where = {} + for (const item of input.where) { + switch (item.op) { + case 'Any': + where[item.column] = Any(item.value) + break + case 'Between': + if (item.value?.length != 2) throw Error('Operation Between requires two values') + where[item.column] = Between(item.value[0], item.value[1]) + break + case 'Equal': + if (item.value?.length != 1) throw Error('Operation Equal requires one value') + where[item.column] = Equal(item.value[0]) + break + case 'IsNull': + where[item.column] = IsNull() + break + case 'LessThan': + if (item.value?.length != 1) throw Error('Operation LessThan requires one value') + where[item.column] = LessThan(item.value[0]) + break + case 'LessThanOrEqual': + if (item.value?.length != 1) throw Error('Operation LessThanOrEqual requires one value') + where[item.column] = LessThanOrEqual(item.value[0]) + break + case 'Like': + if (item.value?.length != 1) throw Error('Operation Like requires one value') + where[item.column] = Like(item.value[0]) + break + case 'MoreThan': + if (item.value?.length != 1) throw Error('Operation MoreThan requires one value') + where[item.column] = MoreThan(item.value[0]) + break + case 'MoreThanOrEqual': + if (item.value?.length != 1) throw Error('Operation MoreThanOrEqual requires one value') + where[item.column] = MoreThanOrEqual(item.value[0]) + break + case 'In': + default: + where[item.column] = In(item.value) + } + } + result['where'] = where + } + return result +} - if (input?.issuer) options.where['issuer'] = In(input.issuer) - if (input?.subject) options.where['audience'] = In(input.subject) - if (input?.type) options.where['type'] = In(input.type) - if (input?.context) options.where['context'] = In(input.context) - if (input?.options?.skip) options['skip'] = input.options.skip - if (input?.options?.take) options['take'] = input.options.take +export interface FindArgs { + input?: FindInput +} - return (await ctx.agent.dbConnection).getRepository(Credential).find(options) +const messages = async (_: any, args: FindArgs, ctx: Context) => { + return (await ctx.agent.dbConnection).getRepository(Message).find(transformFindInput(args.input)) +} +const messagesCount = async (_: any, args: FindArgs, ctx: Context) => { + return (await ctx.agent.dbConnection).getRepository(Message).count(transformFindInput(args.input)) } -const claims = async ( - _: any, - { - input, - }: { - input?: { - options?: FindOptions - issuer?: string[] - subject?: string[] - type?: string[] - value?: string[] - } - }, - ctx: Context, -) => { - const options = { - relations: ['credential'], - where: {}, - } +const presentations = async (_: any, args: FindArgs, ctx: Context) => { + const options = transformFindInput(args.input) + return (await ctx.agent.dbConnection).getRepository(Presentation).find(options) +} - if (input?.issuer) options.where['issuer'] = In(input.issuer) - if (input?.subject) options.where['subject'] = In(input.subject) - if (input?.type) options.where['type'] = In(input.type) - if (input?.value) options.where['value'] = In(input.value) - if (input?.options?.skip) options['skip'] = input.options.skip - if (input?.options?.take) options['take'] = input.options.take +const credentials = async (_: any, args: FindArgs, ctx: Context) => { + const options = transformFindInput(args.input) + return (await ctx.agent.dbConnection).getRepository(Credential).find(options) +} +const claims = async (_: any, args: FindArgs, ctx: Context) => { + const options = transformFindInput(args.input) + options['relations'] = ['credential'] return (await ctx.agent.dbConnection).getRepository(Claim).find(options) } @@ -149,6 +159,7 @@ export const resolvers = { message: async (_: any, { id }, ctx: Context) => (await ctx.agent.dbConnection).getRepository(Message).findOne(id), messages, + messagesCount, presentation: async (_: any, { hash }, ctx: Context) => (await ctx.agent.dbConnection).getRepository(Presentation).findOne(hash), presentations, @@ -167,54 +178,6 @@ export const resolvers = { ( await (await ctx.agent.dbConnection).getRepository(Identity).findOne(identity.did) ).getLatestClaimValue(ctx.agent.dbConnection, { type: args.type }), - sentMessages: async (identity: Identity, args, ctx: Context) => - ( - await (await ctx.agent.dbConnection) - .getRepository(Identity) - .findOne(identity.did, { relations: ['sentMessages'] }) - ).sentMessages, - receivedMessages: async (identity: Identity, args, ctx: Context) => - ( - await (await ctx.agent.dbConnection) - .getRepository(Identity) - .findOne(identity.did, { relations: ['receivedMessages'] }) - ).receivedMessages, - issuedPresentations: async (identity: Identity, args, ctx: Context) => - ( - await (await ctx.agent.dbConnection) - .getRepository(Identity) - .findOne(identity.did, { relations: ['issuedPresentations'] }) - ).issuedPresentations, - receivedPresentations: async (identity: Identity, args, ctx: Context) => - ( - await (await ctx.agent.dbConnection) - .getRepository(Identity) - .findOne(identity.did, { relations: ['receivedPresentations'] }) - ).receivedPresentations, - issuedCredentials: async (identity: Identity, args, ctx: Context) => - ( - await (await ctx.agent.dbConnection) - .getRepository(Identity) - .findOne(identity.did, { relations: ['issuedCredentials'] }) - ).issuedCredentials, - receivedCredentials: async (identity: Identity, args, ctx: Context) => - ( - await (await ctx.agent.dbConnection) - .getRepository(Identity) - .findOne(identity.did, { relations: ['receivedCredentials'] }) - ).receivedCredentials, - issuedClaims: async (identity: Identity, args, ctx: Context) => - ( - await (await ctx.agent.dbConnection) - .getRepository(Identity) - .findOne(identity.did, { relations: ['issuedClaims'] }) - ).issuedClaims, - receivedClaims: async (identity: Identity, args, ctx: Context) => - ( - await (await ctx.agent.dbConnection) - .getRepository(Identity) - .findOne(identity.did, { relations: ['receivedClaims'] }) - ).receivedClaims, }, Credential: { @@ -274,35 +237,84 @@ export const resolvers = { } export const typeDefs = ` + enum WhereOperation { + Not + LessThan + LessThanOrEqual + MoreThan + MoreThanOrEqual + Equal + Like + Between + In + Any + IsNull + } + + enum OrderDirection { + ASC + DESC + } + + enum MessagesColumns { + saveDate + updateDate + createdAt + expiresAt + threadId + type + replyTo + replyUrl + from + to + } + + input MessagesWhere { + column: MessagesColumns! + value: [String] + op: WhereOperation + } + + input MessagesOrder { + column: MessagesColumns! + direction: OrderDirection! + } + + input MessagesInput { + where: [MessagesWhere] + order: [MessagesOrder] + take: Int + skip: Int + } + + input OrderOptions { + field: String! + direction: OrderDirection! + } input FindOptions { take: Int skip: Int + order: [OrderOptions] } input IdentitiesInput { options: FindOptions } - input MessagesInput { - from: [String] - to: [String] - type: [String] - threadId: [String] - options: FindOptions - } + input PresentationsInput { - issuer: [String] - audience: [String] + issuer: [ID] + audience: [ID] type: [String] context: [String] options: FindOptions } input CredentialsInput { - issuer: [String] - subject: [String] + issuer: [ID] + subject: [ID] type: [String] context: [String] options: FindOptions @@ -321,6 +333,7 @@ export const typeDefs = ` identities(input: IdentitiesInput): [Identity] message(id: ID!): Message messages(input: MessagesInput): [Message] + messagesCount(input: MessagesInput): Int presentation(hash: ID!): Presentation presentations(input: PresentationsInput): [Presentation] credential(hash: ID!): Credential @@ -341,14 +354,6 @@ export const typeDefs = ` extend type Identity { shortDid: String! latestClaimValue(type: String): String - sentMessages: [Message] - receivedMessages: [Message] - issuedPresentations: [Presentation] - receivedPresentations: [Presentation] - issuedCredentials: [Credential] - receivedCredentials: [Credential] - issuedClaims: [Claim] - receivedClaims: [Claim] } scalar Object From 0b62eaa30ceb2f79192a476ff9f6809cbe5b1ccf Mon Sep 17 00:00:00 2001 From: Simonas Karuzas Date: Wed, 15 Apr 2020 15:44:11 +0300 Subject: [PATCH 3/7] feat: Added id and tag fields --- packages/daf-core/src/entities/credential.ts | 3 +++ packages/daf-core/src/entities/message.ts | 13 ++++++++-- .../daf-core/src/entities/presentation.ts | 7 ++++-- packages/daf-w3c/src/action-handler.ts | 24 +++++++++++++++++-- packages/daf-w3c/src/graphql.ts | 3 +++ packages/daf-w3c/src/message-handler.ts | 8 +++++++ 6 files changed, 52 insertions(+), 6 deletions(-) diff --git a/packages/daf-core/src/entities/credential.ts b/packages/daf-core/src/entities/credential.ts index c77d3b5bc..a52ed2119 100644 --- a/packages/daf-core/src/entities/credential.ts +++ b/packages/daf-core/src/entities/credential.ts @@ -74,6 +74,9 @@ export class Credential extends BaseEntity { ) subject?: Identity + @Column({ nullable: true }) + id?: String + @Column() issuanceDate: Date diff --git a/packages/daf-core/src/entities/message.ts b/packages/daf-core/src/entities/message.ts index 1dff7df65..2b3879594 100644 --- a/packages/daf-core/src/entities/message.ts +++ b/packages/daf-core/src/entities/message.ts @@ -4,11 +4,13 @@ import { BaseEntity, ManyToOne, ManyToMany, - PrimaryGeneratedColumn, + PrimaryColumn, JoinTable, CreateDateColumn, UpdateDateColumn, + BeforeInsert, } from 'typeorm' +import { blake2bHex } from 'blakejs' import { Identity } from './identity' import { Presentation } from './presentation' import { Credential } from './credential' @@ -30,7 +32,14 @@ export class Message extends BaseEntity { } } - @PrimaryGeneratedColumn('uuid') + @BeforeInsert() + setId() { + if (!this.id) { + this.id = blake2bHex(this.raw) + } + } + + @PrimaryColumn() id: string @CreateDateColumn() diff --git a/packages/daf-core/src/entities/presentation.ts b/packages/daf-core/src/entities/presentation.ts index ad1984625..3f375819e 100644 --- a/packages/daf-core/src/entities/presentation.ts +++ b/packages/daf-core/src/entities/presentation.ts @@ -35,7 +35,7 @@ export class Presentation extends BaseEntity { identity => identity.issuedPresentations, { cascade: ['insert'], - eager: true + eager: true, }, ) issuer: Identity @@ -45,11 +45,14 @@ export class Presentation extends BaseEntity { identity => identity.receivedPresentations, { cascade: ['insert'], - eager: true + eager: true, }, ) audience: Identity + @Column({ nullable: true }) + id?: String + @Column() issuanceDate: Date diff --git a/packages/daf-w3c/src/action-handler.ts b/packages/daf-w3c/src/action-handler.ts index d7906db2c..bb657b182 100644 --- a/packages/daf-w3c/src/action-handler.ts +++ b/packages/daf-w3c/src/action-handler.ts @@ -93,6 +93,7 @@ export interface CredentialInput { '@context'?: string[] context?: string[] type: string[] + id?: string issuer: string expirationDate?: string credentialSubject: CredentialSubjectInput @@ -102,6 +103,7 @@ export interface PresentationInput { '@context'?: string[] context?: string[] type: string[] + id?: string issuer: string audience: string tag?: string @@ -115,7 +117,6 @@ const transformCredentialInput = (input: CredentialInput): VerifiableCredentialP delete credentialSubject.id const result: VerifiableCredentialPayload = { sub: input.credentialSubject.id, - // exp: input.expirationDate, vc: { '@context': input['@context'] || input['context'], type: input.type, @@ -123,6 +124,14 @@ const transformCredentialInput = (input: CredentialInput): VerifiableCredentialP }, } + if (input.expirationDate) { + result['exp'] = new Date(input.expirationDate).getUTCSeconds() + } + + if (input.id) { + result['jti'] = input.id + } + return result } @@ -130,7 +139,6 @@ const transformPresentationInput = (input: PresentationInput): PresentationPaylo // TODO validate input const result: PresentationPayload = { aud: input.audience, - // exp: input.expirationDate, vp: { '@context': input['@context'] || input['context'], type: input.type, @@ -138,5 +146,17 @@ const transformPresentationInput = (input: PresentationInput): PresentationPaylo }, } + if (input.expirationDate) { + result['exp'] = new Date(input.expirationDate).getUTCSeconds() + } + + if (input.id) { + result['jti'] = input.id + } + + if (input.tag) { + result['tag'] = input.tag + } + return result } diff --git a/packages/daf-w3c/src/graphql.ts b/packages/daf-w3c/src/graphql.ts index 691027c67..2731a3feb 100644 --- a/packages/daf-w3c/src/graphql.ts +++ b/packages/daf-w3c/src/graphql.ts @@ -50,6 +50,7 @@ export const typeDefs = ` scalar CredentialSubject input SignCredentialInput { + id: String issuer: String! context: [String]! type: [String]! @@ -57,6 +58,8 @@ export const typeDefs = ` } input SignPresentationInput { + id: String + tag: String issuer: String! audience: String! context: [String]! diff --git a/packages/daf-w3c/src/message-handler.ts b/packages/daf-w3c/src/message-handler.ts index 738c06d5f..bb4204dc9 100644 --- a/packages/daf-w3c/src/message-handler.ts +++ b/packages/daf-w3c/src/message-handler.ts @@ -94,6 +94,10 @@ export function createCredential(payload: VerifiableCredentialPayload, jwt: stri vc.raw = jwt + if (payload.jti) { + vc.id = payload.jti + } + if (payload.nbf || payload.iat) { vc.issuanceDate = timestampToDate(payload.nbf || payload.iat) } @@ -125,6 +129,10 @@ export function createPresentation( vp.raw = jwt + if (payload.jti) { + vp.id = payload.jti + } + if (payload.nbf || payload.iat) { vp.issuanceDate = timestampToDate(payload.nbf || payload.iat) } From e845a841684fa092152bccc91cc1e582bae456c9 Mon Sep 17 00:00:00 2001 From: Simonas Karuzas Date: Wed, 15 Apr 2020 15:45:51 +0300 Subject: [PATCH 4/7] feat: Identity saveDate updateDate --- packages/daf-core/src/entities/identity.ts | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/packages/daf-core/src/entities/identity.ts b/packages/daf-core/src/entities/identity.ts index b75a1e756..826dd6d2c 100644 --- a/packages/daf-core/src/entities/identity.ts +++ b/packages/daf-core/src/entities/identity.ts @@ -1,4 +1,12 @@ -import { Entity, Column, PrimaryColumn, BaseEntity, OneToMany, ManyToMany } from 'typeorm' +import { + Entity, + Column, + PrimaryColumn, + BaseEntity, + OneToMany, + CreateDateColumn, + UpdateDateColumn, +} from 'typeorm' import { Key } from './key' import { Message } from './message' import { Presentation } from './presentation' @@ -14,6 +22,12 @@ export class Identity extends BaseEntity { @Column({ nullable: true }) provider: string + @CreateDateColumn() + saveDate: Date + + @UpdateDateColumn() + updateDate: Date + @Column({ nullable: true }) controllerKeyId: string From dd624c29a103b6f2e279d1b853a26a040ba7d6a9 Mon Sep 17 00:00:00 2001 From: Simonas Karuzas Date: Wed, 15 Apr 2020 15:46:06 +0300 Subject: [PATCH 5/7] feat: Gql Not operator --- packages/daf-core/src/graphql/graphql-core.ts | 131 +++++++++++++++--- 1 file changed, 110 insertions(+), 21 deletions(-) diff --git a/packages/daf-core/src/graphql/graphql-core.ts b/packages/daf-core/src/graphql/graphql-core.ts index 2f9f9d5a8..c68b3fe7a 100644 --- a/packages/daf-core/src/graphql/graphql-core.ts +++ b/packages/daf-core/src/graphql/graphql-core.ts @@ -31,6 +31,7 @@ export interface Order { export interface Where { column: string value?: string[] + not?: boolean op?: | 'LessThan' | 'LessThanOrEqual' @@ -109,6 +110,9 @@ function transformFindInput(input: FindInput): FindManyOptions { default: where[item.column] = In(item.value) } + if (item.not === true) { + where[item.column] = Not(where[item.column]) + } } result['where'] = where } @@ -272,6 +276,7 @@ export const typeDefs = ` input MessagesWhere { column: MessagesColumns! value: [String] + not: Boolean op: WhereOperation } @@ -287,47 +292,127 @@ export const typeDefs = ` skip: Int } - input OrderOptions { - field: String! + + + enum IdentitiesColumns { + saveDate + updateDate + did + provider + } + + input IdentitiesWhere { + column: IdentitiesColumns! + value: [String] + not: Boolean + op: WhereOperation + } + + input IdentitiesOrder { + column: IdentitiesColumns! direction: OrderDirection! } - input FindOptions { + input IdentitiesInput { + where: [IdentitiesWhere] + order: [IdentitiesOrder] take: Int skip: Int - order: [OrderOptions] } - input IdentitiesInput { - options: FindOptions + + enum PresentationsColumns { + id + issuanceDate + expirationDate + context + type + issuer + audience } + input PresentationsWhere { + column: PresentationsColumns! + value: [String] + not: Boolean + op: WhereOperation + } + input PresentationsOrder { + column: PresentationsColumns! + direction: OrderDirection! + } input PresentationsInput { - issuer: [ID] - audience: [ID] - type: [String] - context: [String] - options: FindOptions + where: [PresentationsWhere] + order: [PresentationsOrder] + take: Int + skip: Int + } + + + enum CredentialsColumns { + id + issuanceDate + expirationDate + context + type + issuer + subject + } + + input CredentialsWhere { + column: CredentialsColumns! + value: [String] + not: Boolean + op: WhereOperation + } + + input CredentialsOrder { + column: CredentialsColumns! + direction: OrderDirection! } input CredentialsInput { - issuer: [ID] - subject: [ID] - type: [String] - context: [String] - options: FindOptions + where: [CredentialsWhere] + order: [CredentialsOrder] + take: Int + skip: Int } - input ClaimsInput { - issuer: [ID] - subject: [ID] - type: [String] + + enum ClaimsColumns { + issuanceDate + expirationDate + context + credentialType + type + value + issuer + subject + } + + input ClaimsWhere { + column: ClaimsColumns! value: [String] - options: FindOptions + not: Boolean + op: WhereOperation + } + + input ClaimsOrder { + column: ClaimsColumns! + direction: OrderDirection! + } + + input ClaimsInput { + where: [ClaimsWhere] + order: [ClaimsOrder] + take: Int + skip: Int } + + extend type Query { identity(did: ID!): Identity identities(input: IdentitiesInput): [Identity] @@ -354,6 +439,8 @@ export const typeDefs = ` extend type Identity { shortDid: String! latestClaimValue(type: String): String + saveDate: Date! + updateDate: Date! } scalar Object @@ -385,6 +472,7 @@ export const typeDefs = ` type Presentation { hash: ID! + id: String raw: String! issuer: Identity! audience: Identity! @@ -398,6 +486,7 @@ export const typeDefs = ` type Credential { hash: ID! + id: String raw: String! issuer: Identity! subject: Identity From 55ccdd42f104bc93df4621a854719cb4723b3d89 Mon Sep 17 00:00:00 2001 From: Simonas Karuzas Date: Wed, 15 Apr 2020 16:13:01 +0300 Subject: [PATCH 6/7] feat: Changed DID type from ID to String --- packages/daf-core/src/graphql/graphql-base-type-defs.ts | 2 +- packages/daf-core/src/graphql/graphql-core.ts | 2 +- packages/daf-selective-disclosure/src/graphql.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/daf-core/src/graphql/graphql-base-type-defs.ts b/packages/daf-core/src/graphql/graphql-base-type-defs.ts index 536f16746..028967c6b 100644 --- a/packages/daf-core/src/graphql/graphql-base-type-defs.ts +++ b/packages/daf-core/src/graphql/graphql-base-type-defs.ts @@ -4,7 +4,7 @@ export const baseTypeDefs = ` type Mutation type Identity { - did: ID! + did: String! provider: String } diff --git a/packages/daf-core/src/graphql/graphql-core.ts b/packages/daf-core/src/graphql/graphql-core.ts index c68b3fe7a..de83548a4 100644 --- a/packages/daf-core/src/graphql/graphql-core.ts +++ b/packages/daf-core/src/graphql/graphql-core.ts @@ -414,7 +414,7 @@ export const typeDefs = ` extend type Query { - identity(did: ID!): Identity + identity(did: String!): Identity identities(input: IdentitiesInput): [Identity] message(id: ID!): Message messages(input: MessagesInput): [Message] diff --git a/packages/daf-selective-disclosure/src/graphql.ts b/packages/daf-selective-disclosure/src/graphql.ts index 0e50d1110..f12fa330d 100644 --- a/packages/daf-selective-disclosure/src/graphql.ts +++ b/packages/daf-selective-disclosure/src/graphql.ts @@ -95,7 +95,7 @@ export const typeDefs = ` } extend type Message { - sdr(did: ID): [CredentialRequest] + sdr(did: String): [CredentialRequest] } extend type Mutation { From 564ba7d38cf47d21fd030397866a0bab757e1abd Mon Sep 17 00:00:00 2001 From: Simonas Karuzas Date: Wed, 15 Apr 2020 16:13:13 +0300 Subject: [PATCH 7/7] docs: New GQL API --- docs/Docs.md | 51 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/docs/Docs.md b/docs/Docs.md index 68a25a519..a2fa76620 100644 --- a/docs/Docs.md +++ b/docs/Docs.md @@ -345,10 +345,12 @@ const memberVc = memberClaims[0]?.credential ```typescript const input = { - issuer: ['did:ethr:567', 'did:ethr:659'], - subject: 'did:example:1234', - type: 'member', - value: 'status', + where: [ + { column: 'issuer', value: ['did:ethr:567', 'did:ethr:659'] }, + { column: 'subject', value: ['did:example:1234'] }, + { column: 'type', value: ['member'] }, + { column: 'value', value: ['status'] }, + ], } ``` @@ -642,7 +644,7 @@ Fields import { Identity } from 'daf-core' const dbConnection = await agent.dbConnection const identity = await dbConnection.getRepository(Identity).findOne('did:example:123', { - relations: ['receivedClaims'], + relations: ['issuedClaims'], }) console.log(identity.receivedClaims) // [Claim(type: 'name', value: 'Alice'), ...] @@ -651,14 +653,19 @@ console.log(identity.receivedClaims) // [Claim(type: 'name', value: 'Alice'), .. ### GraphQL ```graphql -query { - identity(did: "did:example:123") { +query identity($did: String!) { + identity(did: $did) { + did + shortDid name: latestClaimValue(type: "name") - profileImage: latestClaimValue(type: "profileImage") - receivedClaims { - type - value + profilePicture: latestClaimValue(type: "profilePicture") + } + issuedClaims: claims(input: { where: [{ column: issuer, value: [$did] }] }) { + subject { + did } + type + value } } ``` @@ -701,7 +708,7 @@ const messages = await dbConnection.getRepository(Message).find({ ```graphql query { - messages(input: { type: "sdr", options: { take: 5 } }) { + messages(input: { where: [{ column: type, value: "sdr" }], take: 5 }) { id from { did @@ -746,7 +753,14 @@ const presentations = await dbConnection.getRepository(Presentation).find({ ```graphql query { - presentations(input: { type: "VerifiablePresentation,KYC", issuer: "did:web:example.com" }) { + presentations( + input: { + where: [ + { column: issuer, value: "did:web:example.com" } + { column: type, value: "VerifiablePresentation,KYC" } + ] + } + ) { audience { did } @@ -800,7 +814,14 @@ const credentials = await dbConnection.getRepository(Credential).find({ ```graphql query { - credentials(input: { subject: "did:web:example.com", expirationDateLessThan: "2020-12-12T10:00:00Z" }) { + credentials( + input: { + where: [ + { column: subject, value: "did:web:example.com" } + { column: expirationDate, value: "2020-12-12T10:00:00Z", op: LessThan } + ] + } + ) { issuer { did } @@ -869,7 +890,7 @@ console.log(claims) ```graphql query { - claims(input: { type: "address" }) { + claims(input: { where: [{ column: type, value: "address" }] }) { type value isObj