Skip to content

Commit

Permalink
add grant to Record class methods
Browse files Browse the repository at this point in the history
  • Loading branch information
LiranCohen committed Aug 29, 2024
1 parent 9f08161 commit eb8508c
Showing 1 changed file with 103 additions and 1 deletion.
104 changes: 103 additions & 1 deletion packages/api/src/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,13 @@ import {
DwnPaginationCursor,
isDwnMessage,
SendDwnRequest,
isRecordsWrite
CachedPermissions,
} from '@web5/agent';

import { Convert, isEmptyObject, NodeStream, removeUndefinedProperties, Stream } from '@web5/common';

import { dataToBlob, SendCache } from './utils.js';
import { PermissionGrant } from './permission-grant.js';

/**
* Represents Immutable Record properties that cannot be changed after the record is created.
Expand Down Expand Up @@ -92,6 +93,9 @@ export type RecordOptions = DwnMessage[DwnInterface.RecordsWrite | DwnInterface.
/** The DID of the DWN tenant under which record operations are being performed. */
connectedDid: string;

/** The optional DID that will sign the records on behalf of the connectedDid */
delegateDid?: string;

/** The data of the record, either as a Base64 URL encoded string or a Blob. */
encodedData?: string | Blob;

Expand Down Expand Up @@ -205,6 +209,10 @@ export class Record implements RecordModel {
private _agent: Web5Agent;
/** The DID of the DWN tenant under which operations are being performed. */
private _connectedDid: string;
/** The optional DID that is delegated to act on behalf of the connectedDid */
private _delegateDid?: string;
/** cache for fetching a permission {@link PermissionGrant}, keyed by a specific MessageType and protocol */
private _cachedPermissions?: CachedPermissions;
/** Encoded data of the record, if available. */
private _encodedData?: Blob;
/** Stream of the record's data. */
Expand Down Expand Up @@ -359,6 +367,7 @@ export class Record implements RecordModel {
// Store the currently `connectedDid` so that subsequent message signing is done with the
// connected DID's keys and DWN requests target the connected DID's DWN.
this._connectedDid = options.connectedDid;
this._delegateDid = options.delegateDid;

// If the record was queried or read from a remote DWN, the `remoteOrigin` DID will be
// defined. This value is used to send subsequent read requests to the same remote DWN in the
Expand Down Expand Up @@ -798,6 +807,20 @@ 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,
}
});

// set the required delegated grant and grantee DID for the read operation
deleteOptions.messageParams.delegatedGrant = delegatedGrant;
deleteOptions.granteeDid = this._delegateDid;
}

Check warning on line 822 in packages/api/src/record.ts

View check run for this annotation

Codecov / codecov/patch

packages/api/src/record.ts#L811-L822

Added lines #L811 - L822 were not covered by tests

const agentResponse = await this._agent.processDwnRequest(deleteOptions);
const { message, reply: { status } } = agentResponse;

Expand Down Expand Up @@ -842,6 +865,21 @@ export class Record implements RecordModel {
store,
};


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,
}
});

// set the required delegated grant and grantee DID for the read operation
initialWriteRequest.messageParams.delegatedGrant = delegatedGrant;
initialWriteRequest.granteeDid = this._delegateDid;
}

Check warning on line 881 in packages/api/src/record.ts

View check run for this annotation

Codecov / codecov/patch

packages/api/src/record.ts#L870-L881

Added lines #L870 - L881 were not covered by tests

// Process the prepared initial write, with the options set for storing and/or signing as the owner.
const agentResponse = await this._agent.processDwnRequest(initialWriteRequest);

Expand Down Expand Up @@ -871,6 +909,19 @@ export class Record implements RecordModel {
signAsOwner,
store,
};
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,
}
});

// set the required delegated grant and grantee DID for the read operation
requestOptions.messageParams.delegatedGrant = delegatedGrant;
requestOptions.granteeDid = this._delegateDid;
}

Check warning on line 924 in packages/api/src/record.ts

View check run for this annotation

Codecov / codecov/patch

packages/api/src/record.ts#L913-L924

Added lines #L913 - L924 were not covered by tests
} else {
requestOptions = {
messageType : DwnInterface.RecordsWrite,
Expand All @@ -881,6 +932,19 @@ export class Record implements RecordModel {
signAsOwner,
store,
};
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,
}
});

// set the required delegated grant and grantee DID for the read operation
requestOptions.messageParams.delegatedGrant = delegatedGrant;
requestOptions.granteeDid = this._delegateDid;
}

Check warning on line 947 in packages/api/src/record.ts

View check run for this annotation

Codecov / codecov/patch

packages/api/src/record.ts#L936-L947

Added lines #L936 - L947 were not covered by tests
}

const agentResponse = await this._agent.processDwnRequest(requestOptions);
Expand Down Expand Up @@ -919,6 +983,20 @@ export class Record implements RecordModel {
target,
};

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,
}
});

// set the required delegated grant and grantee DID for the read operation
readRequest.messageParams.delegatedGrant = delegatedGrant;
readRequest.granteeDid = this._delegateDid;
}

Check warning on line 998 in packages/api/src/record.ts

View check run for this annotation

Codecov / codecov/patch

packages/api/src/record.ts#L987-L998

Added lines #L987 - L998 were not covered by tests

const agentResponsePromise = isRemote ?
this._agent.sendDwnRequest(readRequest) :
this._agent.processDwnRequest(readRequest);
Expand Down Expand Up @@ -972,4 +1050,28 @@ 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<T extends DwnInterface>({ messageParams, cached = true }:{
cached?: boolean;
messageParams: {
messageType: T;
protocol: string;
}
}) : Promise<PermissionGrant> {
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;
}

Check warning on line 1076 in packages/api/src/record.ts

View check run for this annotation

Codecov / codecov/patch

packages/api/src/record.ts#L1055-L1076

Added lines #L1055 - L1076 were not covered by tests
}

0 comments on commit eb8508c

Please sign in to comment.