From 2efa57012447be1ebed18df10db5e082cbbad5c4 Mon Sep 17 00:00:00 2001 From: Liran Cohen Date: Fri, 30 Aug 2024 15:22:38 -0400 Subject: [PATCH] remove unecessary abstraction --- packages/api/src/dwn-api.ts | 88 +++++++-------------- packages/api/src/record.ts | 101 +++++++++++------------- packages/api/tests/dwn-api.spec.ts | 120 +---------------------------- 3 files changed, 76 insertions(+), 233 deletions(-) diff --git a/packages/api/src/dwn-api.ts b/packages/api/src/dwn-api.ts index 802b0fc04..2761e857d 100644 --- a/packages/api/src/dwn-api.ts +++ b/packages/api/src/dwn-api.ts @@ -312,45 +312,6 @@ export class DwnApi { this.cachedPermissionsApi = new CachedPermissions({ agent: this.agent, cachedDefault: true }); } - /** - * API to interact with the DWN Permissions when the agent is connected to a delegateDid. - * - * NOTE: This is an EXPERIMENTAL API that will change behavior. - * @beta - */ - private get connected() { - return { - /** - * Finds the appropriate permission grants associated with a message request - * - * (optionally) Caches the results for the given parameters to avoid redundant queries. - */ - findPermissionGrantForMessage: async ({ messageParams, cached = true }:{ - cached?: boolean; - messageParams: { - messageType: T; - protocol: string; - } - }) : Promise => { - if(!this.delegateDid) { - throw new Error('AgentDwnApi: Cannot find connected grants without a signer DID'); - } - - const delegateGrant = await this.cachedPermissionsApi.getPermission({ - connectedDid : this.connectedDid, - delegateDid : this.delegateDid, - messageType : messageParams.messageType, - protocol : messageParams.protocol, - delegate : true, - cached, - }); - - const grant = await PermissionGrant.parse({ connectedDid: this.delegateDid, agent: this.agent, message: delegateGrant.message }); - return grant; - } - }; - } - /** * API to interact with Grants * @@ -586,11 +547,13 @@ export class DwnApi { if (this.delegateDid) { // if an app is scoped down to a specific protocolPath or contextId, it must include those filters in the read request - const { rawMessage: delegatedGrant } = await this.connected.findPermissionGrantForMessage({ - messageParams: { - messageType : DwnInterface.RecordsDelete, - protocol : request.protocol, - } + const { message: delegatedGrant } = await this.cachedPermissionsApi.getPermission({ + connectedDid : this.connectedDid, + delegateDid : this.delegateDid, + messageType : DwnInterface.RecordsDelete, + protocol : request.protocol, + cached : true, + delegate : true }); // set the required delegated grant and grantee DID for the read operation @@ -632,11 +595,13 @@ export class DwnApi { if (this.delegateDid) { // if an app is scoped down to a specific protocolPath or contextId, it must include those filters in the read request - const { rawMessage: delegatedGrant } = await this.connected.findPermissionGrantForMessage({ - messageParams: { - messageType : DwnInterface.RecordsQuery, - protocol : agentRequest.messageParams.filter.protocol, - } + const { message: delegatedGrant } = await this.cachedPermissionsApi.getPermission({ + connectedDid : this.connectedDid, + delegateDid : this.delegateDid, + messageType : DwnInterface.RecordsQuery, + protocol : request.protocol, + cached : true, + delegate : true }); // set the required delegated grant and grantee DID for the read operation @@ -710,11 +675,13 @@ export class DwnApi { if (this.delegateDid) { // if an app is scoped down to a specific protocolPath or contextId, it must include those filters in the read request - const { rawMessage: delegatedGrant } = await this.connected.findPermissionGrantForMessage({ - messageParams: { - messageType : DwnInterface.RecordsRead, - protocol : request.protocol - } + const { message: delegatedGrant } = await this.cachedPermissionsApi.getPermission({ + connectedDid : this.connectedDid, + delegateDid : this.delegateDid, + messageType : DwnInterface.RecordsRead, + protocol : request.protocol, + cached : true, + delegate : true }); // set the required delegated grant and grantee DID for the read operation @@ -838,11 +805,14 @@ export class DwnApi { // if impersonation is enabled, fetch the delegated grant to use with the write operation if (this.delegateDid) { - const { rawMessage: delegatedGrant } = await this.connected.findPermissionGrantForMessage({ - messageParams: { - messageType : DwnInterface.RecordsWrite, - protocol : dwnRequestParams.messageParams.protocol, - } + + const { message: delegatedGrant } = await this.cachedPermissionsApi.getPermission({ + connectedDid : this.connectedDid, + delegateDid : this.delegateDid, + messageType : DwnInterface.RecordsWrite, + protocol : request.message?.protocol, + cached : true, + delegate : true }); // set the required delegated grant and grantee DID for the write operation diff --git a/packages/api/src/record.ts b/packages/api/src/record.ts index a374ee8b8..ae44b304e 100644 --- a/packages/api/src/record.ts +++ b/packages/api/src/record.ts @@ -749,12 +749,15 @@ export class Record implements RecordModel { target : this._connectedDid, }; if (this._delegateDid) { + // if an app is scoped down to a specific protocolPath or contextId, it must include those filters in the read request - const { rawMessage: delegatedGrant } = await this.findPermissionGrantForMessage({ - messageParams: { - messageType : DwnInterface.RecordsWrite, - protocol : this.protocol, - } + const { message: delegatedGrant } = await this._cachedPermissions.getPermission({ + connectedDid : this._connectedDid, + delegateDid : this._delegateDid, + messageType : DwnInterface.RecordsWrite, + protocol : this.protocol, + delegate : true, + cached : true, }); // set the required delegated grant and grantee DID for the read operation @@ -827,12 +830,14 @@ export class Record implements RecordModel { } if (this._delegateDid) { - // if an app is scoped down to a specific protocolPath or contextId, it must include those filters in the read request - const { rawMessage: delegatedGrant } = await this.findPermissionGrantForMessage({ - messageParams: { - messageType : DwnInterface.RecordsDelete, - protocol : this.protocol, - } + + const { message: delegatedGrant } = await this._cachedPermissions.getPermission({ + connectedDid : this._connectedDid, + delegateDid : this._delegateDid, + messageType : DwnInterface.RecordsDelete, + protocol : this.protocol, + delegate : true, + cached : true, }); // set the required delegated grant and grantee DID for the read operation @@ -886,12 +891,14 @@ export class Record implements RecordModel { if (this._delegateDid) { - // if an app is scoped down to a specific protocolPath or contextId, it must include those filters in the read request - const { rawMessage: delegatedGrant } = await this.findPermissionGrantForMessage({ - messageParams: { - messageType : DwnInterface.RecordsWrite, - protocol : this.protocol, - } + // if an app is scoped down to a specific protocolPath or contextId, it must include those filters in the read request + const { message: delegatedGrant } = await this._cachedPermissions.getPermission({ + connectedDid : this._connectedDid, + delegateDid : this._delegateDid, + messageType : DwnInterface.RecordsWrite, + protocol : this.protocol, + delegate : true, + cached : true, }); // set the required delegated grant and grantee DID for the read operation @@ -930,11 +937,13 @@ export class Record implements RecordModel { }; if (this._delegateDid) { // if an app is scoped down to a specific protocolPath or contextId, it must include those filters in the read request - const { rawMessage: delegatedGrant } = await this.findPermissionGrantForMessage({ - messageParams: { - messageType : DwnInterface.RecordsDelete, - protocol : this.protocol, - } + const { message: delegatedGrant } = await this._cachedPermissions.getPermission({ + connectedDid : this._connectedDid, + delegateDid : this._delegateDid, + messageType : DwnInterface.RecordsDelete, + protocol : this.protocol, + delegate : true, + cached : true, }); // set the required delegated grant and grantee DID for the read operation @@ -953,11 +962,13 @@ export class Record implements RecordModel { }; if (this._delegateDid) { // if an app is scoped down to a specific protocolPath or contextId, it must include those filters in the read request - const { rawMessage: delegatedGrant } = await this.findPermissionGrantForMessage({ - messageParams: { - messageType : DwnInterface.RecordsWrite, - protocol : this.protocol, - } + const { message: delegatedGrant } = await this._cachedPermissions.getPermission({ + connectedDid : this._connectedDid, + delegateDid : this._delegateDid, + messageType : DwnInterface.RecordsWrite, + protocol : this.protocol, + delegate : true, + cached : true, }); // set the required delegated grant and grantee DID for the read operation @@ -1004,11 +1015,13 @@ export class Record implements RecordModel { if (this._delegateDid) { // if an app is scoped down to a specific protocolPath or contextId, it must include those filters in the read request - const { rawMessage: delegatedGrant } = await this.findPermissionGrantForMessage({ - messageParams: { - messageType : DwnInterface.RecordsRead, - protocol : this.protocol, - } + const { message: delegatedGrant } = await this._cachedPermissions.getPermission({ + connectedDid : this._connectedDid, + delegateDid : this._delegateDid, + messageType : DwnInterface.RecordsRead, + protocol : this.protocol, + delegate : true, + cached : true, }); // set the required delegated grant and grantee DID for the read operation @@ -1069,28 +1082,4 @@ export class Record implements RecordModel { private isRecordsDeleteDescriptor(descriptor: DwnMessageDescriptor[DwnInterface.RecordsWrite | DwnInterface.RecordsDelete]): descriptor is DwnMessageDescriptor[DwnInterface.RecordsDelete] { return descriptor.interface + descriptor.method === DwnInterface.RecordsDelete; } - - private async findPermissionGrantForMessage({ messageParams, cached = true }:{ - cached?: boolean; - messageParams: { - messageType: T; - protocol: string; - } - }) : Promise { - if(!this._delegateDid) { - throw new Error('Record: Cannot find connected grants without a signer DID'); - } - - const delegateGrant = await this._cachedPermissions.getPermission({ - connectedDid : this._connectedDid, - delegateDid : this._delegateDid, - messageType : messageParams.messageType, - protocol : messageParams.protocol, - delegate : true, - cached, - }); - - const grant = await PermissionGrant.parse({ connectedDid: this._delegateDid, agent: this._agent, message: delegateGrant.message }); - return grant; - } } \ No newline at end of file diff --git a/packages/api/tests/dwn-api.spec.ts b/packages/api/tests/dwn-api.spec.ts index d98e399e0..8a87463de 100644 --- a/packages/api/tests/dwn-api.spec.ts +++ b/packages/api/tests/dwn-api.spec.ts @@ -3,15 +3,14 @@ import type { BearerDid } from '@web5/dids'; import sinon from 'sinon'; import { expect } from 'chai'; import { Web5UserAgent } from '@web5/user-agent'; -import { AgentPermissionsApi, DwnDateSort, DwnInterface, getRecordAuthor, PlatformAgentTestHarness } from '@web5/agent'; +import { AgentPermissionsApi, DwnDateSort, getRecordAuthor, PlatformAgentTestHarness } from '@web5/agent'; import { DwnApi } from '../src/dwn-api.js'; import { testDwnUrl } from './utils/test-config.js'; import emailProtocolDefinition from './fixtures/protocol-definitions/email.json' assert { type: 'json' }; import photosProtocolDefinition from './fixtures/protocol-definitions/photos.json' assert { type: 'json' }; -import { DwnInterfaceName, DwnMethodName, PermissionsProtocol, Poller, RecordsWrite, Time } from '@tbd54566975/dwn-sdk-js'; +import { DwnInterfaceName, DwnMethodName, PermissionsProtocol, Poller, Time } from '@tbd54566975/dwn-sdk-js'; import { PermissionGrant } from '../src/permission-grant.js'; -import { Web5 } from '../src/web5.js'; import { Record } from '../src/record.js'; let testDwnUrls: string[] = [testDwnUrl]; @@ -1542,121 +1541,6 @@ describe('DwnApi', () => { }); }); - describe('connected.findPermissionGrantForRequest', () => { - it('caches result', async () => { - // create a grant for bob - const deviceXGrant = await dwnAlice.permissions.grant({ - store : true, - grantedTo : bobDid.uri, - dateExpires : Time.createOffsetTimestamp({ seconds: 60 }), - delegated : true, - scope : { - interface : DwnInterfaceName.Records, - method : DwnMethodName.Write, - protocol : 'http://example.com/protocol' - } - }); - - // simulate a connect where bobDid can impersonate aliceDid - dwnBob['connectedDid'] = aliceDid.uri; - dwnBob['delegateDid'] = bobDid.uri; - await Web5.processConnectedGrants({ - agent : testHarness.agent, - delegateDid : bobDid.uri, - grants : [ deviceXGrant.rawMessage ] - }); - - const fetchGrantsSpy = sinon.spy(AgentPermissionsApi.prototype, 'fetchGrants'); - - // find the grant for a request - let grantForRequest = await dwnBob['connected'].findPermissionGrantForMessage({ - messageParams: { - messageType : DwnInterface.RecordsWrite, - protocol : 'http://example.com/protocol' - } - }); - - // expect to have the grant - expect(grantForRequest).to.exist; - expect(grantForRequest.id).to.equal(deviceXGrant.id); - expect(fetchGrantsSpy.callCount).to.equal(1); - - fetchGrantsSpy.resetHistory(); - - // attempt to find the grant again - grantForRequest = await dwnBob['connected'].findPermissionGrantForMessage({ - messageParams: { - messageType : DwnInterface.RecordsWrite, - protocol : 'http://example.com/protocol' - } - }); - expect(grantForRequest).to.exist; - expect(grantForRequest.id).to.equal(deviceXGrant.id); - expect(fetchGrantsSpy.callCount).to.equal(0); - - // should call again if cached:false is passed - grantForRequest = await dwnBob['connected'].findPermissionGrantForMessage({ - messageParams: { - messageType : DwnInterface.RecordsWrite, - protocol : 'http://example.com/protocol' - }, - cached: false - }); - expect(grantForRequest).to.exist; - expect(grantForRequest.id).to.equal(deviceXGrant.id); - expect(fetchGrantsSpy.callCount).to.equal(1); - - // reset the spy - fetchGrantsSpy.resetHistory(); - expect(fetchGrantsSpy.callCount).to.equal(0); - - // call for a different grant - try { - await dwnBob['connected'].findPermissionGrantForMessage({ - messageParams: { - messageType : DwnInterface.RecordsRead, - protocol : 'http://example.com/protocol' - } - }); - expect.fail('Should have thrown an error'); - } catch(error:any) { - expect(error.message).to.equal('CachedPermissions: No permissions found for RecordsRead: http://example.com/protocol'); - } - expect(fetchGrantsSpy.callCount).to.equal(1); - - // call again to ensure grants which are not found are not cached - try { - await dwnBob['connected'].findPermissionGrantForMessage({ - messageParams: { - messageType : DwnInterface.RecordsRead, - protocol : 'http://example.com/protocol' - } - }); - expect.fail('Should have thrown an error'); - } catch(error:any) { - expect(error.message).to.equal('CachedPermissions: No permissions found for RecordsRead: http://example.com/protocol'); - } - - expect(fetchGrantsSpy.callCount).to.equal(2); // should have been called again - }); - - it('throws if no delegateDid is set', async () => { - // make sure delegateDid is undefined - dwnAlice['delegateDid'] = undefined; - try { - await dwnAlice['connected'].findPermissionGrantForMessage({ - messageParams: { - messageType : DwnInterface.RecordsWrite, - protocol : 'http://example.com/protocol' - } - }); - expect.fail('Error was not thrown'); - } catch (e) { - expect(e.message).to.equal('AgentDwnApi: Cannot find connected grants without a signer DID'); - } - }); - }); - describe('permissions.grant', () => { it('uses the connected DID to create a grant if no delegate DID is set', async () => { // scenario: create a permission grant for bob, confirm that alice is the signer