Skip to content

Commit

Permalink
Expose DWN PermissionsGrant Message
Browse files Browse the repository at this point in the history
  • Loading branch information
diehuxx committed Nov 1, 2023
1 parent 01c56ce commit e2e6760
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 12 deletions.
2 changes: 1 addition & 1 deletion packages/agent/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@web5/agent",
"version": "0.2.2",
"version": "0.2.3",
"type": "module",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
Expand Down
13 changes: 10 additions & 3 deletions packages/agent/src/dwn-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
RecordsWriteMessage,
RecordsWriteOptions,
Signer,
PermissionsGrant,
} from '@tbd54566975/dwn-sdk-js';

import { Jose } from '@web5/crypto';
Expand Down Expand Up @@ -69,6 +70,9 @@ const dwnMessageCreators = {
[DwnInterfaceName.Records + DwnMethodName.Query] : RecordsQuery,
[DwnInterfaceName.Records + DwnMethodName.Write] : RecordsWrite,
[DwnInterfaceName.Records + DwnMethodName.Delete] : RecordsDelete,
[DwnInterfaceName.Permissions + DwnMethodName.Grant] : PermissionsGrant,
[DwnInterfaceName.Permissions + DwnMethodName.Request] : PermissionsGrant,
[DwnInterfaceName.Permissions + DwnMethodName.Revoke] : PermissionsGrant,
[DwnInterfaceName.Protocols + DwnMethodName.Query] : ProtocolsQuery,
[DwnInterfaceName.Protocols + DwnMethodName.Configure] : ProtocolsConfigure,
};
Expand Down Expand Up @@ -184,8 +188,11 @@ export class DwnManager {
});
dwnRpcRequest.message = message;
messageData = data;

} else if ('message' in request) {
dwnRpcRequest.message = request.message;
messageData = request.dataStream;
} else {
// construct message from messageOptions
const { message } = await this.constructDwnMessage({ request });
dwnRpcRequest.message = message;
messageData = request.dataStream;
Expand Down Expand Up @@ -224,7 +231,7 @@ export class DwnManager {
dwnReply = await this.agent.rpcClient.sendDwnRequest(dwnRpcRequest as DwnRpcRequest);
break;
} catch(error: unknown) {
const message = (error instanceof Error) ? error.message : 'Uknown error';
const message = (error instanceof Error) ? error.message : 'Unknown error';
errorMessages.push({ url: dwnUrl, message });
}
}
Expand Down Expand Up @@ -405,7 +412,7 @@ export class DwnManager {
author: string,
messageOptions: unknown,
messageType: string
}): Promise<EventsGet | MessagesGet | RecordsRead | RecordsQuery | RecordsWrite | RecordsDelete | ProtocolsQuery | ProtocolsConfigure> {
}): Promise<Message<GenericMessage>> {
const { author, messageOptions, messageType } = options;

const dwnAuthorizationSigner = await this.constructDwnAuthorizationSigner(author);
Expand Down
5 changes: 4 additions & 1 deletion packages/agent/src/types/agent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import type {
RecordsDeleteMessage,
ProtocolsQueryMessage,
ProtocolsConfigureMessage,
GenericMessage,
} from '@tbd54566975/dwn-sdk-js';

import { DidResolver } from '@web5/dids';
Expand Down Expand Up @@ -57,7 +58,9 @@ export type ProcessDwnRequest = DwnRequest & {
store?: boolean;
};

export type SendDwnRequest = DwnRequest & (ProcessDwnRequest | { messageCid: string })
export type SendDwnRequest = DwnRequest & (
ProcessDwnRequest | { messageCid: string } | { message: GenericMessage, dataStream?: Blob | ReadableStream | Readable }
);

/**
* TODO: add JSDoc
Expand Down
4 changes: 2 additions & 2 deletions packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,10 @@
},
"dependencies": {
"@tbd54566975/dwn-sdk-js": "0.2.4",
"@web5/agent": "0.2.2",
"@web5/agent": "0.2.3",
"@web5/crypto": "0.2.1",
"@web5/dids": "0.2.1",
"@web5/user-agent": "0.2.1",
"@web5/user-agent": "0.2.3",
"level": "8.0.0",
"ms": "2.1.3",
"readable-stream": "4.4.2",
Expand Down
59 changes: 58 additions & 1 deletion packages/api/src/dwn-api.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { DwnResponse, Web5Agent } from '@web5/agent';
import type {
import {
UnionMessageReply,
RecordsReadOptions,
RecordsQueryOptions,
Expand All @@ -11,6 +11,7 @@ import type {
ProtocolsConfigureMessage,
ProtocolsConfigureOptions,
ProtocolsConfigureDescriptor,
Message,

Check failure on line 14 in packages/api/src/dwn-api.ts

View workflow job for this annotation

GitHub Actions / test-with-node

'Message' is defined but never used. Allowed unused vars must match /^_/u
} from '@tbd54566975/dwn-sdk-js';

import { isEmptyObject } from '@web5/common';
Expand All @@ -19,6 +20,14 @@ import { DwnInterfaceName, DwnMethodName } from '@tbd54566975/dwn-sdk-js';
import { Record } from './record.js';
import { Protocol } from './protocol.js';
import { dataToBlob } from './utils.js';
import { PermissionsGrant } from '@tbd54566975/dwn-sdk-js';
import { PermissionsGrantMessage } from '@tbd54566975/dwn-sdk-js';
import { PermissionsGrantOptions } from '@tbd54566975/dwn-sdk-js';

export type PermissionsGrantRequest = {
target?: string;
message: Omit<PermissionsGrantOptions, 'authorizationSigner'>;
}

export type ProtocolsConfigureRequest = {
message: Omit<ProtocolsConfigureOptions, 'authorizationSigner'>;
Expand Down Expand Up @@ -91,6 +100,10 @@ export type RecordsWriteRequest = {
store?: boolean;
}

export type PermissionGrantRequest = {
message?: Omit<Partial<PermissionsGrantOptions>, 'authorizationSigner'>;
}

export type RecordsWriteResponse = {
status: UnionMessageReply['status'];
record?: Record
Expand Down Expand Up @@ -377,4 +390,48 @@ export class DwnApi {
},
};
}

get permissions() {
return {
grant: async (request: PermissionsGrantRequest): Promise<{ permissionsGrant: PermissionsGrant, status: UnionMessageReply['status'] }> => {
const agentRequest = {
author : this.connectedDid,
messageOptions : request.message,
messageType : DwnInterfaceName.Permissions + DwnMethodName.Grant,
target : request.target || this.connectedDid
};

let agentResponse: DwnResponse;

if (request.target) {
agentResponse = await this.agent.sendDwnRequest(agentRequest);
} else {
agentResponse = await this.agent.processDwnRequest(agentRequest);
}

const { message, reply: { status } } = agentResponse;

let permissionsGrant: PermissionsGrant | undefined;
if (200 <= status.code && status.code <= 299) {
permissionsGrant = await PermissionsGrant.parse(message as PermissionsGrantMessage);
}

return {
permissionsGrant,
status,
};
},

send: async (target: string, message: PermissionsGrant): Promise<{ status: UnionMessageReply['status'] }> => {
const { reply: { status } } = await this.agent.sendDwnRequest({
messageType : message.message.descriptor.interface + message.message.descriptor.method,
author : message.author,
target : target,
message : message.message,
});

return { status };
},
};
}
}
35 changes: 35 additions & 0 deletions packages/api/tests/dwn-api.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { PortableDid } from '@web5/dids';
import type { ManagedIdentity } from '@web5/agent';
import { Temporal } from '@js-temporal/polyfill';

import { expect } from 'chai';
import { TestManagedAgent } from '@web5/agent';
Expand All @@ -8,6 +9,7 @@ import { DwnApi } from '../src/dwn-api.js';
import { testDwnUrl } from './test-config.js';
import { TestUserAgent } from './utils/test-user-agent.js';
import emailProtocolDefinition from './fixtures/protocol-definitions/email.json' assert { type: 'json' };
import { DwnInterfaceName, DwnMethodName } from '@tbd54566975/dwn-sdk-js';

let testDwnUrls: string[] = [testDwnUrl];

Expand Down Expand Up @@ -569,4 +571,37 @@ describe('DwnApi', () => {
});
});
});

describe('permissions.grant()', () => {
describe('agent', () => {
it('returns a PermissionsGrant that can be invoked', async () => {
const { did: bobDid } = await testAgent.createIdentity({ testDwnUrls });

const { status, permissionsGrant } = await dwn.permissions.grant({
message: {
dateExpires : Temporal.Now.instant().toString({ smallestUnit: 'microseconds' }),
grantedBy : aliceDid.did,
grantedFor : aliceDid.did,
grantedTo : bobDid.did,
scope : {
interface : DwnInterfaceName.Records,
method : DwnMethodName.Read,
}
},
});

expect(status.code).to.eq(202);
expect(permissionsGrant).not.to.be.undefined;

// send to Alice's remote DWN
const { status: statusSend } = await dwn.permissions.send(aliceDid.did, permissionsGrant);

expect(statusSend.code).to.eq(202);
});
});

describe('target: did', () => {

});
});
});
2 changes: 1 addition & 1 deletion packages/identity-agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"node": ">=18.0.0"
},
"dependencies": {
"@web5/agent": "0.2.2",
"@web5/agent": "0.2.3",
"@web5/api": "0.8.2"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/proxy-agent/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"node": ">=18.0.0"
},
"dependencies": {
"@web5/agent": "0.2.2",
"@web5/agent": "0.2.3",
"@web5/common": "0.2.1",
"@web5/crypto": "0.2.1",
"@web5/dids": "0.2.1"
Expand Down
4 changes: 2 additions & 2 deletions packages/user-agent/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@web5/user-agent",
"version": "0.2.2",
"version": "0.2.3",
"type": "module",
"main": "./dist/cjs/index.js",
"module": "./dist/esm/index.js",
Expand Down Expand Up @@ -67,7 +67,7 @@
"node": ">=18.0.0"
},
"dependencies": {
"@web5/agent": "0.2.2",
"@web5/agent": "0.2.3",
"@web5/common": "0.2.1",
"@web5/crypto": "0.2.1",
"@web5/dids": "0.2.1"
Expand Down

0 comments on commit e2e6760

Please sign in to comment.