diff --git a/packages/api/src/dwn-api.ts b/packages/api/src/dwn-api.ts index e0d6c9db9..5b0205056 100644 --- a/packages/api/src/dwn-api.ts +++ b/packages/api/src/dwn-api.ts @@ -7,6 +7,7 @@ import type { CreateGrantParams, CreateRequestParams, + DwnRecordsInterfaces, FetchPermissionRequestParams, FetchPermissionsParams } from '@web5/agent'; @@ -486,6 +487,31 @@ export class DwnApi { * API to interact with DWN records (e.g., `dwn.records.create()`). */ get records() { + + /** + * Adds the appropriate delegate grant to the messageParams for the given messageType. + * + * @param messageType the type of message to add the delegate grant to + * @param messageParams the message parameters to add the delegate grant to + * @param protocol the protocol to scope the delegate grant to + * + * @returns a copy of the messageParams with the delegate grant added + */ + const addDelegateGrantToMessageParams = ({ messageParams, protocol, messageType }:{ + messageType: T, + messageParams: DwnMessageParams[T], + protocol: string + }) => { + return Record.addDelegateGrantToMessageParams({ + connectedDid : this.connectedDid, + delegateDid : this.delegateDid, + messageParams : messageParams, + cachedPermissions : this.cachedPermissionsApi, + messageType, + protocol, + }); + }; + return { /** * Alias for the `write` method @@ -549,18 +575,11 @@ 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 { message: delegatedGrant } = await this.cachedPermissionsApi.getPermission({ - connectedDid : this.connectedDid, - delegateDid : this.delegateDid, - messageType : DwnInterface.RecordsDelete, - protocol : request.protocol, - cached : true, - delegate : true + agentRequest.messageParams = await addDelegateGrantToMessageParams({ + messageType : DwnInterface.RecordsDelete, + messageParams : agentRequest.messageParams, + protocol : request.protocol }); - - // set the required delegated grant and grantee DID for the read operation - agentRequest.messageParams.delegatedGrant = delegatedGrant; agentRequest.granteeDid = this.delegateDid; } @@ -597,18 +616,11 @@ 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 { message: delegatedGrant } = await this.cachedPermissionsApi.getPermission({ - connectedDid : this.connectedDid, - delegateDid : this.delegateDid, - messageType : DwnInterface.RecordsQuery, - protocol : request.protocol, - cached : true, - delegate : true + agentRequest.messageParams = await addDelegateGrantToMessageParams({ + messageType : DwnInterface.RecordsQuery, + messageParams : agentRequest.messageParams, + protocol : request.protocol }); - - // set the required delegated grant and grantee DID for the read operation - agentRequest.messageParams.delegatedGrant = delegatedGrant; agentRequest.granteeDid = this.delegateDid; } @@ -675,20 +687,13 @@ export class DwnApi { */ target : request.from || 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 { message: delegatedGrant } = await this.cachedPermissionsApi.getPermission({ - connectedDid : this.connectedDid, - delegateDid : this.delegateDid, - messageType : DwnInterface.RecordsRead, - protocol : request.protocol, - cached : true, - delegate : true + agentRequest.messageParams = await addDelegateGrantToMessageParams({ + messageType : DwnInterface.RecordsRead, + messageParams : agentRequest.messageParams, + protocol : request.protocol }); - // set the required delegated grant and grantee DID for the read operation - agentRequest.messageParams.delegatedGrant = delegatedGrant; agentRequest.granteeDid = this.delegateDid; } @@ -769,20 +774,14 @@ 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 { message: delegatedGrant } = await this.cachedPermissionsApi.getPermission({ - connectedDid : this.connectedDid, - delegateDid : this.delegateDid, - messageType : DwnInterface.RecordsSubscribe, - protocol : request.protocol, - cached : true, - delegate : true + agentRequest.messageParams = await addDelegateGrantToMessageParams({ + messageType : DwnInterface.RecordsSubscribe, + messageParams : agentRequest.messageParams, + protocol : request.protocol }); - // set the required delegated grant and grantee DID for the read operation - agentRequest.messageParams.delegatedGrant = delegatedGrant; agentRequest.granteeDid = this.delegateDid; - } + }; let agentResponse: DwnResponse; @@ -824,18 +823,11 @@ export class DwnApi { // if impersonation is enabled, fetch the delegated grant to use with the write operation if (this.delegateDid) { - - const { message: delegatedGrant } = await this.cachedPermissionsApi.getPermission({ - connectedDid : this.connectedDid, - delegateDid : this.delegateDid, - messageType : DwnInterface.RecordsWrite, - protocol : request.message.protocol, - cached : true, - delegate : true + dwnRequestParams.messageParams = await addDelegateGrantToMessageParams({ + messageType : DwnInterface.RecordsWrite, + messageParams : dwnRequestParams.messageParams, + protocol : request.message?.protocol }); - - // set the required delegated grant and grantee DID for the write operation - dwnRequestParams.messageParams.delegatedGrant = delegatedGrant; dwnRequestParams.granteeDid = this.delegateDid; }; diff --git a/packages/api/src/record.ts b/packages/api/src/record.ts index e6f04d154..26721d7b7 100644 --- a/packages/api/src/record.ts +++ b/packages/api/src/record.ts @@ -751,7 +751,7 @@ export class Record implements RecordModel { }; if (this._delegateDid) { - requestOptions.messageParams = await this.addDelegateGrantToMessage(DwnInterface.RecordsWrite, requestOptions); + requestOptions.messageParams = await this.addDelegateGrantToMessageParams(DwnInterface.RecordsWrite, requestOptions); requestOptions.granteeDid = this._delegateDid; } @@ -834,7 +834,7 @@ export class Record implements RecordModel { } if (this._delegateDid) { - deleteOptions.messageParams = await this.addDelegateGrantToMessage(DwnInterface.RecordsDelete, deleteOptions); + deleteOptions.messageParams = await this.addDelegateGrantToMessageParams(DwnInterface.RecordsDelete, deleteOptions); deleteOptions.granteeDid = this._delegateDid; } @@ -874,7 +874,7 @@ export class Record implements RecordModel { }; if (this._delegateDid) { - initialWriteRequest.messageParams = await this.addDelegateGrantToMessage(DwnInterface.RecordsWrite, initialWriteRequest); + initialWriteRequest.messageParams = await this.addDelegateGrantToMessageParams(DwnInterface.RecordsWrite, initialWriteRequest); initialWriteRequest.granteeDid = this._delegateDid; } @@ -933,7 +933,7 @@ export class Record implements RecordModel { } if (this._delegateDid) { - requestOptions.messageParams = await this.addDelegateGrantToMessage(requestOptions.messageType, requestOptions); + requestOptions.messageParams = await this.addDelegateGrantToMessageParams(requestOptions.messageType, requestOptions); requestOptions.granteeDid = this._delegateDid; } @@ -974,7 +974,7 @@ export class Record implements RecordModel { }; if (this._delegateDid) { - readRequest.messageParams = await this.addDelegateGrantToMessage(DwnInterface.RecordsRead, readRequest); + readRequest.messageParams = await this.addDelegateGrantToMessageParams(DwnInterface.RecordsRead, readRequest); readRequest.granteeDid = this._delegateDid; } @@ -1032,13 +1032,58 @@ export class Record implements RecordModel { return descriptor.interface + descriptor.method === DwnInterface.RecordsDelete; } - private async addDelegateGrantToMessage(messageType: T, request: ProcessDwnRequest): Promise { - const messageParams: DwnMessageParams[T] = request.messageParams || {} as DwnMessageParams[T]; + /** + * Adds the appropriate delegate grant to the messageParams for the given messageType. + * + * @param messageType The type of message to add the delegate grant to. + * @param request The request object containing the message parameters. + * + * @returns a copy of the message parameters with the delegate grant added. + */ + private addDelegateGrantToMessageParams(messageType: T, request: ProcessDwnRequest): Promise { + return Record.addDelegateGrantToMessageParams({ + messageType, + delegateDid : this._delegateDid, + connectedDid : this._connectedDid, + protocol : this.protocol, + cachedPermissions : this._cachedPermissions, + messageParams : request.messageParams + }); + } + + /** + * Adds the appropriate delegate grant to the messageParams for the given messageType. + * + * @param messageType The type of message to add the delegate grant to. + * @param messageParams The message parameters to add the delegate grant to. + * @param delegateDid The DID the grant is granted to (grantee). + * @param connectedDid The DID the grant is granted by (grantor). + * @param protocol The protocol the grant is for. + * @param cachedPermissions The cached permissions object. + * + * @returns a copy of the message parameters with the delegate grant added. + */ + static async addDelegateGrantToMessageParams({ + messageType, + delegateDid, + connectedDid, + protocol, + cachedPermissions, + messageParams = {} as DwnMessageParams[T] + }:{ + messageType: T, + delegateDid: string, + connectedDid: string, + protocol: string, + cachedPermissions: CachedPermissions; + messageParams?: DwnMessageParams[T]; + }): Promise { + // 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, - protocol : this.protocol, + const { message: delegatedGrant } = await cachedPermissions.getPermission({ + connectedDid : connectedDid, + delegateDid : delegateDid, + protocol : protocol, delegate : true, cached : true, messageType