From c00b5c186bfb6f87bb2a01d881d2f8ff1200e6f8 Mon Sep 17 00:00:00 2001 From: Simonas Karuzas Date: Tue, 31 Mar 2020 18:43:42 +0300 Subject: [PATCH] feat: SDR helper and specs --- packages/daf-cli/src/sdr.ts | 6 +- .../daf-selective-disclosure/package.json | 3 +- .../src/action-handler.ts | 29 ++++---- .../daf-selective-disclosure/src/graphql.ts | 74 +++++++------------ .../daf-selective-disclosure/src/helper.ts | 40 ++++++++++ .../daf-selective-disclosure/src/index.ts | 2 +- .../src/message-handler.ts | 6 +- 7 files changed, 89 insertions(+), 71 deletions(-) create mode 100644 packages/daf-selective-disclosure/src/helper.ts diff --git a/packages/daf-cli/src/sdr.ts b/packages/daf-cli/src/sdr.ts index 98a419d6d..f8204ee03 100644 --- a/packages/daf-cli/src/sdr.ts +++ b/packages/daf-cli/src/sdr.ts @@ -119,7 +119,7 @@ program ]) claims.push({ - iss: issuers, + issuers: issuers, essential: answers2.essential, claimType: answers2.claimType, reason: answers2.reason, @@ -129,10 +129,10 @@ program const signAction: SD.ActionSignSdr = { type: SD.ActionTypes.signSdr, - did: answers.iss, data: { + issuer: answers.iss, + subject: answers.sub === '' ? undefined : answers.sub, tag: answers.tag === '' ? undefined : answers.tag, - sub: answers.sub === '' ? undefined : answers.sub, claims, }, } diff --git a/packages/daf-selective-disclosure/package.json b/packages/daf-selective-disclosure/package.json index 23c01beb7..b528f98b6 100644 --- a/packages/daf-selective-disclosure/package.json +++ b/packages/daf-selective-disclosure/package.json @@ -13,7 +13,8 @@ "daf-data-store": "^4.0.0-beta.15+00f0d2f", "daf-did-jwt": "^4.0.0-beta.15+00f0d2f", "debug": "^4.1.1", - "did-jwt": "^4.0.0" + "did-jwt": "^4.0.0", + "typeorm": "^0.2.24" }, "devDependencies": { "@types/debug": "^4.1.5", diff --git a/packages/daf-selective-disclosure/src/action-handler.ts b/packages/daf-selective-disclosure/src/action-handler.ts index fb9f757f0..5f9251503 100644 --- a/packages/daf-selective-disclosure/src/action-handler.ts +++ b/packages/daf-selective-disclosure/src/action-handler.ts @@ -5,43 +5,44 @@ import Debug from 'debug' const debug = Debug('daf:selective-disclosure:action-handler') export const ActionTypes = { - signSdr: 'action.sign.sdr', + signSdr: 'sign.sdr.jwt', } -interface Iss { +interface Issuer { did: string url: string } -export interface SDRInput { +export interface SelectiveDisclosureRequest { + issuer: string + subject?: string + replyUrl?: string tag?: string - sub?: string claims: CredentialRequestInput[] } export interface CredentialRequestInput { reason?: string essential?: boolean + credentialType: string + credentialContext: string claimType: string - iss?: Iss[] + claimValue?: string + issuers?: Issuer[] } export interface ActionSignSdr extends Action { - did: string - data: { - sub?: string - tag?: string - claims: any - } + data: SelectiveDisclosureRequest } export class SdrActionHandler extends AbstractActionHandler { public async handleAction(action: Action, agent: Agent) { if (action.type === ActionTypes.signSdr) { - const { did, data } = action as ActionSignSdr + const { data } = action as ActionSignSdr try { - const identity = await agent.identityManager.getIdentity(did) - debug('Signing SDR with', did) + const identity = await agent.identityManager.getIdentity(data.issuer) + delete data.issuer + debug('Signing SDR with', identity.did) const key = await identity.keyByType('Secp256k1') const jwt = await createJWT( diff --git a/packages/daf-selective-disclosure/src/graphql.ts b/packages/daf-selective-disclosure/src/graphql.ts index fb8e385c3..e5f31289f 100644 --- a/packages/daf-selective-disclosure/src/graphql.ts +++ b/packages/daf-selective-disclosure/src/graphql.ts @@ -1,53 +1,22 @@ -import { Agent } from 'daf-core' +import { Agent, Message, Claim } from 'daf-core' import { DataStore } from 'daf-data-store' -import { ActionTypes, ActionSignSdr, SDRInput } from './action-handler' -import { decodeJWT } from 'did-jwt' +import { ActionTypes, ActionSignSdr, SelectiveDisclosureRequest } from './action-handler' +import { findCredentialsForSdr } from './helper' interface Context { agent: Agent dataStore: DataStore } -const actionSignSDR = async ( - _: any, - args: { - did: string - data: SDRInput - }, - ctx: Context, -) => { - const { data } = args - - return await ctx.agent.handleAction({ +const signSdrJwt = async (_: any, args: { data: SelectiveDisclosureRequest }, ctx: Context) => + ctx.agent.handleAction({ type: ActionTypes.signSdr, - did: args.did, - data: data, + data: args.data, } as ActionSignSdr) -} -const sdr = async (message: any, { sub }: { sub: string }, { dataStore }: Context) => { - const { payload }: { payload: SDRInput } = (await decodeJWT(message.raw)) as any - const result: any = [] - const subject = sub || message.receiver?.did - if (payload.claims) { - for (const credentialRequest of payload.claims) { - const iss: any = - credentialRequest.iss !== undefined ? credentialRequest.iss.map((iss: any) => iss.did) : null - const credentials = await dataStore.findCredentialsByFields({ - iss, - sub: subject ? [subject] : [], - claim_type: credentialRequest.claimType, - }) - result.push({ - ...credentialRequest, - iss: credentialRequest.iss?.map(item => ({ url: item.url, did: { did: item.did } })), - vc: credentials.map((credential: any) => ({ ...credential, __typename: 'Credential' })), - }) - } - } - - return result +const sdr = async (message: Message, { did }: { did: string }) => { + return findCredentialsForSdr(message.data, did) } export const resolvers = { @@ -55,7 +24,7 @@ export const resolvers = { sdr, }, Mutation: { - actionSignSDR, + signSdrJwt, }, } @@ -66,15 +35,20 @@ export const typeDefs = ` } input CredentialRequestInput { - iss: [IssuerInput] + issuers: [IssuerInput] reason: String - claimType: String + credentialType: String + credentialContext: String + claimType: String! + claimValue: String essential: Boolean } input SDRInput { + issuer: String! + subject: String + replyUrl: String tag: String - sub: String claims: [CredentialRequestInput]! } @@ -84,19 +58,21 @@ export const typeDefs = ` } type CredentialRequest { - iss: [Issuer] - reason: String - claimType: String + issuers: [Issuer] + credentialType: String + credentialContext: String + claimType: String! + claimValue: String essential: Boolean - vc: [Credential] + credentials: [Credential] } extend type Message { - sdr(sub: ID!): [CredentialRequest] + sdr(did: ID): [CredentialRequest] } extend type Mutation { - actionSignSDR(did: String!, data: SDRInput!): String + signSdrJwt(data: SDRInput!): String } ` export default { diff --git a/packages/daf-selective-disclosure/src/helper.ts b/packages/daf-selective-disclosure/src/helper.ts new file mode 100644 index 000000000..49aa8fb3d --- /dev/null +++ b/packages/daf-selective-disclosure/src/helper.ts @@ -0,0 +1,40 @@ +import { Agent, Message, Claim } from 'daf-core' +import { SelectiveDisclosureRequest } from './action-handler' +import { In, Like } from 'typeorm' + +export const findCredentialsForSdr = async (sdr: SelectiveDisclosureRequest, did?: string) => { + const result = [] + for (const credentialRequest of sdr.claims) { + const where = {} + if (credentialRequest.claimType) { + where['type'] = credentialRequest.claimType + } + + if (credentialRequest.claimValue) { + where['value'] = credentialRequest.claimValue + } + + if (credentialRequest.issuers) { + where['issuer'] = In(credentialRequest.issuers.map(i => i.did)) + } + + if (credentialRequest.credentialType) { + where['credentialType'] = Like('%' + credentialRequest.credentialType + '%') + } + + if (credentialRequest.credentialContext) { + where['credentialContext'] = Like('%' + credentialRequest.credentialContext + '%') + } + + if (did || sdr.subject) { + where['subject'] = did || sdr.subject + } + + const claims = await Claim.find({ where, relations: ['credential']}) + result.push({ + ...credentialRequest, + credentials: claims.map(c => c.credential) + }) + } + return result +} diff --git a/packages/daf-selective-disclosure/src/index.ts b/packages/daf-selective-disclosure/src/index.ts index a7ce0625b..51f326979 100644 --- a/packages/daf-selective-disclosure/src/index.ts +++ b/packages/daf-selective-disclosure/src/index.ts @@ -1,4 +1,4 @@ export { SdrMessageHandler, MessageTypes } from './message-handler' -export { SdrActionHandler, ActionTypes, ActionSignSdr, SDRInput, CredentialRequestInput } from './action-handler' +export { SdrActionHandler, ActionTypes, ActionSignSdr, SelectiveDisclosureRequest, CredentialRequestInput } from './action-handler' import SdrGql from './graphql' export { SdrGql } diff --git a/packages/daf-selective-disclosure/src/message-handler.ts b/packages/daf-selective-disclosure/src/message-handler.ts index 436b6cb8d..fafdea556 100644 --- a/packages/daf-selective-disclosure/src/message-handler.ts +++ b/packages/daf-selective-disclosure/src/message-handler.ts @@ -9,7 +9,7 @@ export const MessageTypes = { } export class SdrMessageHandler extends AbstractMessageHandler { - async validate(message: Message, agent: Agent): Promise { + async handle(message: Message, agent: Agent): Promise { const meta = message.getLastMetaData() if ( @@ -25,9 +25,9 @@ export class SdrMessageHandler extends AbstractMessageHandler { message.from = new Identity() message.from.did = message.data.iss - if (message.data.sub) { + if (message.data.subject) { const to = new Identity() - to.did = message.data.sub + to.did = message.data.subject message.to = to }