Skip to content

Commit

Permalink
refactor(did-comm): improve Coordinate Mediation V3 API (#1297)
Browse files Browse the repository at this point in the history
* refactor: ensure v3 mediation protocol is correctly exported
* refactor: cli mediate feedback on no mediation manager plugin configured
* docs: add additional help text to the mediate cli help page
  • Loading branch information
radleylewis authored Dec 8, 2023
1 parent fc94764 commit ea2d99a
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 102 deletions.
73 changes: 42 additions & 31 deletions packages/cli/src/mediate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,25 @@ const promptForDids = async (action: string): Promise<string[]> => {
return dids.split(' ')
}

/**
* handler function instantiates agent and directs user to README if no Mediation Manager plugin is configured
**/

type Action<T extends Options = Options> = (options: T, cmd: Command, agent: ConfiguredAgent) => Promise<void>

function handler(action: Action) {
return async (options: Options, cmd: Command) => {
const agent = await getAgent(cmd.optsWithGlobals().config)
/**
* NOTE: check if the mediation-manager plugin is configured
**/
if ('isMediateDefaultGrantAll' in agent) return await action(options, cmd, agent)
console.log('[warning] it appears that the Mediation Manager plugin is not configured.')
console.log('[tip] refer to the README (packages/mediation-manager/README.md) for guidance. \n')
throw new Error('[error] Mediation Manager not configured!')
}
}

/**
* cli action functions
**/
Expand All @@ -59,13 +78,11 @@ const policy = (policy: PreMediationRequestPolicy) => {
return async function (
{ fileJson, interactive }: Pick<Options, 'fileJson' | 'interactive'>,
cmd: Command,
agent: ConfiguredAgent,
): Promise<void> {
try {
if (fileJson && interactive) throw new Error('Please specify only one input method')

const agent = await getAgent(cmd.optsWithGlobals().config)
console.log('AGENT CREATED')

if (fileJson) {
const jsonData = await import(fileJson, { assert: { type: 'json' } })
const dids = jsonData.default
Expand All @@ -84,9 +101,7 @@ const policy = (policy: PreMediationRequestPolicy) => {
}
}
}

async function readPolicies(options: Pick<Options, 'interactive' | 'fileJson'>, cmd: Command): Promise<void> {
const agent = await getAgent(cmd.optsWithGlobals().config)
const readPolicies: Action<Pick<Options, 'interactive' | 'fileJson'>> = async (options, cmd, agent) => {
let dids: string[]
if (options.interactive) dids = await promptForDids('read')
else if (options.fileJson) dids = (await import(options.fileJson, { assert: { type: 'json' } })).default
Expand All @@ -100,9 +115,8 @@ async function readPolicies(options: Pick<Options, 'interactive' | 'fileJson'>,
console.table(policies)
}

async function listPolicies(options: Pick<Options, 'allowFrom' | 'denyFrom'>, cmd: Command): Promise<void> {
const listPolicies: Action<Pick<Options, 'allowFrom' | 'denyFrom'>> = async (options, _cmd, agent) => {
try {
const agent = await getAgent(cmd.optsWithGlobals().config)
const res = await agent.mediationManagerListMediationPolicies()
console.log('POLICIES')
if (options.allowFrom) return console.table(Object.entries(res).filter(([, policy]) => policy === ALLOW))
Expand All @@ -113,12 +127,9 @@ async function listPolicies(options: Pick<Options, 'allowFrom' | 'denyFrom'>, cm
}
}

async function listResponses(
{ granted, denied }: Pick<Options, 'granted' | 'denied'>,
cmd: Command,
): Promise<void> {
const listResponses: Action<Pick<Options, 'granted' | 'denied'>> = async (options, _cmd, agent) => {
try {
const agent = await getAgent(cmd.optsWithGlobals().config)
const { granted, denied } = options
const res = await agent.mediationManagerGetAllMediations()
console.log('MEDIATIONS')
if (granted) return console.table(Object.entries(res).filter(([, response]) => response === 'GRANTED'))
Expand All @@ -129,73 +140,73 @@ async function listResponses(
}
}

async function removePolicies(
{ fileJson, interactive }: Pick<Options, 'fileJson' | 'interactive'>,
cmd: Command,
): Promise<void> {
const removePolicies: Action<Pick<Options, 'fileJson' | 'interactive'>> = async (options, cmd, agent) => {
try {
const agent = await getAgent(cmd.optsWithGlobals().config)

if (fileJson) {
const jsonData = await import(fileJson, { assert: { type: 'json' } })
if (options.fileJson) {
const jsonData = await import(options.fileJson, { assert: { type: 'json' } })
const dids = jsonData.default
await updatePolicies({ dids, remove: true, agent })
} else if (interactive) {
} else if (options.interactive) {
const dids = await promptForDids('Remove')
await updatePolicies({ dids, remove: true, agent })
} else {
const dids = cmd.args
await updatePolicies({ dids, remove: true, agent })
}

console.log('Mediation policies removed')
} catch (e) {
console.error(e.message)
}
}

const mediate = new Command('mediate').description('Mediate allow or deny policy on dids')
const mediate = new Command('mediate').description('Mediate allow or deny policy on dids').addHelpText(
'before',
`
IMPORTANT! in order to use the commands below, you need to configure the Mediate Manager in your agent.yml',
see the README (packages/mediation-manager/README.md) for guidance.
`,
)

mediate
.command('allow-from')
.description('add dids that should be allowed for mediation')
.option('-f, --file-json <string>', 'read dids from json file')
.option('-i, --interactive', 'interactively input dids')
.action(policy(ALLOW))
.action(handler(policy(ALLOW)))

mediate
.command('deny-from')
.description('deny dids that should be denied for mediation')
.option('-f, --file-json <string>', 'read dids from json file')
.option('-i, --interactive', 'interactively input dids')
.action(policy(DENY))
.action(handler(policy(DENY)))

mediate
.command('read')
.description('read mediation policy for a specific did')
.description('read mediation policy for a specific did (or list of dids)')
.option('-i, --interactive', 'interactively input dids')
.option('-f, --file-json <string>', 'read dids from json file')
.action(readPolicies)
.action(handler(readPolicies))

mediate
.command('list-policies')
.description('list mediation policies')
.option('-a, --allow-from', 'list allow policies')
.option('-d, --deny-from', 'list deny policies')
.action(listPolicies)
.action(handler(listPolicies))

mediate
.command('list-responses')
.description('list mediation responses')
.option('-a, --granted', 'list granted policies')
.option('-d, --denied', 'list denied policies')
.action(listResponses)
.action(handler(listResponses))

mediate
.command('remove')
.description('remove mediation policies')
.option('-f, --file-json <string>', 'read dids from json file')
.option('-i, --interactive', 'interactively input dids')
.action(removePolicies)
.action(handler(removePolicies))

export { mediate }
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ import { IDIDComm } from '../types/IDIDComm.js'
import { MessageHandler } from '../../../message-handler/src'
import {
CoordinateMediationV3MediatorMessageHandler,
CoordinateMediationRecipientMessageHandler,
createMediateRequestMessage,
createMediateGrantMessage,
createRecipientUpdateMessage,
CoordinateMediationV3RecipientMessageHandler,
createV3MediateRequestMessage,
createV3MediateGrantMessage,
createV3RecipientUpdateMessage,
UpdateAction,
RecipientUpdateResult,
CoordinateMediation,
createRecipientQueryMessage,
createV3RecipientQueryMessage,
} from '../protocols/coordinate-mediation-v3-message-handler.js'
import type { Update, UpdateResult } from '../protocols/coordinate-mediation-v3-message-handler.js'
import { FakeDidProvider, FakeDidResolver } from '../../../test-utils/src'
Expand Down Expand Up @@ -129,14 +129,13 @@ describe('coordinate-mediation-message-handler', () => {
messageHandlers: [
new DIDCommMessageHandler(),
new CoordinateMediationV3MediatorMessageHandler(),
new CoordinateMediationRecipientMessageHandler(),
new CoordinateMediationV3RecipientMessageHandler(),
],
}),
new DataStore(dbConnection),
new DataStoreORM(dbConnection),
DIDCommEventSniffer,
new DIDComm({ transports: [new DIDCommHttpTransport()] }),
// @ts-ignore
new MediationManagerPlugin(true, policyStore, mediationStore, recipientDidStore),
],
})
Expand Down Expand Up @@ -334,7 +333,7 @@ describe('coordinate-mediation-message-handler', () => {
})

it('should receive a mediate request', async () => {
const message = createMediateRequestMessage(recipient.did, mediator.did)
const message = createV3MediateRequestMessage(recipient.did, mediator.did)
const messageId = message.id
const packedMessageContents = { packing: 'authcrypt', message: message } as const
const packedMessage = await agent.packDIDCommMessage(packedMessageContents)
Expand All @@ -346,7 +345,7 @@ describe('coordinate-mediation-message-handler', () => {
})

it('should save the mediation status to the db where request is GRANTED', async () => {
const message = createMediateRequestMessage(recipient.did, mediator.did)
const message = createV3MediateRequestMessage(recipient.did, mediator.did)
const messageId = message.id
const packedMessageContents = { packing: 'authcrypt', message: message } as const
const packedMessage = await agent.packDIDCommMessage(packedMessageContents)
Expand All @@ -363,7 +362,7 @@ describe('coordinate-mediation-message-handler', () => {
})

it('should record the mediation status to the db where request is DENIED', async () => {
const message = createMediateRequestMessage(denyRecipient.did, mediator.did)
const message = createV3MediateRequestMessage(denyRecipient.did, mediator.did)
const messageId = message.id
const packedMessageContents = { packing: 'authcrypt', message: message } as const
const packedMessage = await agent.packDIDCommMessage(packedMessageContents)
Expand All @@ -375,7 +374,7 @@ describe('coordinate-mediation-message-handler', () => {
})

it('should respond correctly to a mediate request where GRANTED', async () => {
const message = createMediateRequestMessage(recipient.did, mediator.did)
const message = createV3MediateRequestMessage(recipient.did, mediator.did)
const messageId = message.id
const packedMessageContents = { packing: 'authcrypt', message: message } as const
const packedMessage = await agent.packDIDCommMessage(packedMessageContents)
Expand All @@ -390,7 +389,7 @@ describe('coordinate-mediation-message-handler', () => {
})

it('should respond correctly to a mediate request where DENIED', async () => {
const message = createMediateRequestMessage(denyRecipient.did, mediator.did)
const message = createV3MediateRequestMessage(denyRecipient.did, mediator.did)
const messageId = message.id
const packedMessageContents = { packing: 'authcrypt', message: message } as const
const packedMessage = await agent.packDIDCommMessage(packedMessageContents)
Expand Down Expand Up @@ -424,7 +423,7 @@ describe('coordinate-mediation-message-handler', () => {

expect(await agent.isMediateDefaultGrantAll()).toBeFalsy()

const message = createMediateRequestMessage(recipient.did, mediator.did)
const message = createV3MediateRequestMessage(recipient.did, mediator.did)
const messageId = message.id
const packedMessageContents = { packing: 'authcrypt', message: message } as const
const packedMessage = await agent.packDIDCommMessage(packedMessageContents)
Expand All @@ -448,7 +447,7 @@ describe('coordinate-mediation-message-handler', () => {

expect(didIsAllowed).toBeFalsy()

const message = createMediateRequestMessage(denyRecipient.did, mediator.did)
const message = createV3MediateRequestMessage(denyRecipient.did, mediator.did)
const messageId = message.id
const packedMessageContents = { packing: 'authcrypt', message: message } as const
const packedMessage = await agent.packDIDCommMessage(packedMessageContents)
Expand Down Expand Up @@ -518,7 +517,7 @@ describe('coordinate-mediation-message-handler', () => {
it('should receive an update request', async () => {
const { mockRecipientDid_00: recipient_did } = mockRecipientDids
const update = { recipient_did, action: UpdateAction.ADD }
const message = createRecipientUpdateMessage(recipient.did, mediator.did, [update])
const message = createV3RecipientUpdateMessage(recipient.did, mediator.did, [update])
const messageId = message.id
const packedMessageContents = { packing: 'authcrypt', message } as const
const packedMessage = await agent.packDIDCommMessage(packedMessageContents)
Expand All @@ -532,7 +531,7 @@ describe('coordinate-mediation-message-handler', () => {
it('should add a new recipient_did to the data store', async () => {
const { mockRecipientDid_00: recipient_did } = mockRecipientDids
const update = { recipient_did, action: UpdateAction.ADD }
const message = createRecipientUpdateMessage(recipient.did, mediator.did, [update])
const message = createV3RecipientUpdateMessage(recipient.did, mediator.did, [update])
const messageId = message.id
const packedMessageContents = { packing: 'authcrypt', message } as const
const packedMessage = await agent.packDIDCommMessage(packedMessageContents)
Expand All @@ -553,7 +552,7 @@ describe('coordinate-mediation-message-handler', () => {
expect(existingRecipientDid).toBe(recipient.did)

const update = { recipient_did: recipientDid, action: UpdateAction.REMOVE }
const message = createRecipientUpdateMessage(recipient.did, mediator.did, [update])
const message = createV3RecipientUpdateMessage(recipient.did, mediator.did, [update])
const messageId = message.id
const packedMessageContents = { packing: 'authcrypt', message } as const
const packedMessage = await agent.packDIDCommMessage(packedMessageContents)
Expand All @@ -570,7 +569,7 @@ describe('coordinate-mediation-message-handler', () => {
{ recipient_did: mockRecipientDids.mockRecipientDid_01, action: UpdateAction.ADD },
{ recipient_did: mockRecipientDids.mockRecipientDid_02, action: UpdateAction.ADD },
]
const message = createRecipientUpdateMessage(recipient.did, mediator.did, updates)
const message = createV3RecipientUpdateMessage(recipient.did, mediator.did, updates)
const messageId = message.id
const packedMessageContents = { packing: 'authcrypt', message } as const
const packedMessage = await agent.packDIDCommMessage(packedMessageContents)
Expand All @@ -593,7 +592,7 @@ describe('coordinate-mediation-message-handler', () => {
*/
const { mockRecipientDid_03: recipient_did } = mockRecipientDids
const update = { recipient_did, action: UpdateAction.REMOVE }
const message = createRecipientUpdateMessage(recipient.did, mediator.did, [update])
const message = createV3RecipientUpdateMessage(recipient.did, mediator.did, [update])
const messageId = message.id
const packedMessageContents = { packing: 'authcrypt', message } as const
const packedMessage = await agent.packDIDCommMessage(packedMessageContents)
Expand All @@ -615,7 +614,7 @@ describe('coordinate-mediation-message-handler', () => {

const { mockRecipientDid_01: recipient_did } = mockRecipientDids
const update = { recipient_did, action: UpdateAction.REMOVE }
const message = createRecipientUpdateMessage(recipient.did, mediator.did, [update])
const message = createV3RecipientUpdateMessage(recipient.did, mediator.did, [update])
const messageId = message.id
const packedMessageContents = { packing: 'authcrypt', message } as const
const packedMessage = await agent.packDIDCommMessage(packedMessageContents)
Expand Down Expand Up @@ -673,7 +672,7 @@ describe('coordinate-mediation-message-handler', () => {
}

it('should receive a query request', async () => {
const message = createRecipientQueryMessage(recipient.did, mediator.did)
const message = createV3RecipientQueryMessage(recipient.did, mediator.did)
const messageId = message.id
const packedMessageContents = { packing: 'authcrypt', message } as const
const packedMessage = await agent.packDIDCommMessage(packedMessageContents)
Expand All @@ -690,7 +689,7 @@ describe('coordinate-mediation-message-handler', () => {
await agent.mediationManagerRemoveRecipientDid({ recipientDid: mockRecipientDids.mockRecipientDid_02 })
await agent.mediationManagerRemoveRecipientDid({ recipientDid: mockRecipientDids.mockRecipientDid_03 })

const message = createRecipientQueryMessage(recipient.did, mediator.did)
const message = createV3RecipientQueryMessage(recipient.did, mediator.did)
const messageId = message.id
const packedMessageContents = { packing: 'authcrypt', message } as const
const packedMessage = await agent.packDIDCommMessage(packedMessageContents)
Expand Down Expand Up @@ -745,7 +744,7 @@ describe('coordinate-mediation-message-handler', () => {
/**
* NOTE: now we query the recipient dids and expect the response to contain the inserted recipient_dids
*/
const message = createRecipientQueryMessage(recipient.did, mediator.did)
const message = createV3RecipientQueryMessage(recipient.did, mediator.did)
const messageId = message.id
const packedMessageContents = { packing: 'authcrypt', message } as const
const packedMessage = await agent.packDIDCommMessage(packedMessageContents)
Expand All @@ -768,7 +767,7 @@ describe('coordinate-mediation-message-handler', () => {
describe('MEDIATE REQUEST RESPONSE', () => {
it('should save new service on mediate grant', async () => {
const messageId = '858b8fcb-2e8e-44db-a3aa-eac10a63bfa2l'
const mediateRequestMessage = createMediateRequestMessage(recipient.did, mediator.did)
const mediateRequestMessage = createV3MediateRequestMessage(recipient.did, mediator.did)
mediateRequestMessage.id = messageId
const packedMessage = await agent.packDIDCommMessage({
packing: 'authcrypt',
Expand All @@ -787,7 +786,7 @@ describe('coordinate-mediation-message-handler', () => {

it('should remove service on mediate deny', async () => {
const messageId = '858b8fcb-2e8e-44db-a3aa-eac10a63bfa2l'
const mediateRequestMessage = createMediateRequestMessage(recipient.did, mediator.did)
const mediateRequestMessage = createV3MediateRequestMessage(recipient.did, mediator.did)
mediateRequestMessage.id = messageId
const packedMessage = await agent.packDIDCommMessage({
packing: 'authcrypt',
Expand Down Expand Up @@ -823,7 +822,7 @@ describe('coordinate-mediation-message-handler', () => {
})

it('should not save service if mediate request cannot be found', async () => {
const mediateGrantMessage = createMediateGrantMessage(recipient.did, mediator.did, '')
const mediateGrantMessage = createV3MediateGrantMessage(recipient.did, mediator.did, '')
const packedMessage = await agent.packDIDCommMessage({
packing: 'authcrypt',
message: mediateGrantMessage,
Expand Down
Loading

0 comments on commit ea2d99a

Please sign in to comment.