Skip to content

Commit

Permalink
flesh out protocolRole and add helper method to extract role
Browse files Browse the repository at this point in the history
  • Loading branch information
LiranCohen committed Oct 18, 2024
1 parent 158c3b2 commit e5d02af
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 8 deletions.
10 changes: 9 additions & 1 deletion packages/agent/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { DidUrlDereferencer } from '@web5/dids';
import { PaginationCursor, RecordsDeleteMessage, RecordsWriteMessage } from '@tbd54566975/dwn-sdk-js';
import { Jws, PaginationCursor, RecordsDeleteMessage, RecordsWriteMessage } from '@tbd54566975/dwn-sdk-js';

import { Readable } from '@web5/common';
import { utils as didUtils } from '@web5/dids';
Expand Down Expand Up @@ -42,6 +42,14 @@ export function getRecordAuthor(record: RecordsWriteMessage | RecordsDeleteMessa
return Message.getAuthor(record);
}

/**
* Get the `protocolRole` string from the signature payload of the given RecordsWriteMessage or RecordsDeleteMessage.
*/
export function getRecordProtocolRole(message: RecordsWriteMessage | RecordsDeleteMessage): string | undefined {
const signaturePayload = Jws.decodePlainObjectPayload(message.authorization.signature);
return signaturePayload?.protocolRole;
}

export function isRecordsWrite(obj: unknown): obj is RecordsWrite {
// Validate that the given value is an object.
if (!obj || typeof obj !== 'object' || obj === null) return false;
Expand Down
26 changes: 25 additions & 1 deletion packages/agent/tests/utils.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { expect } from 'chai';

import { DateSort, Message, TestDataGenerator } from '@tbd54566975/dwn-sdk-js';
import { getPaginationCursor, getRecordAuthor, getRecordMessageCid } from '../src/utils.js';
import { getPaginationCursor, getRecordAuthor, getRecordMessageCid, getRecordProtocolRole } from '../src/utils.js';

describe('Utils', () => {
describe('getPaginationCursor', () => {
Expand Down Expand Up @@ -84,4 +84,28 @@ describe('Utils', () => {
expect(deleteAuthorFromFunction!).to.equal(recordsDeleteAuthor.did);
});
});

describe('getRecordProtocolRole', () => {
it('gets a protocol role from a RecordsWrite', async () => {
const recordsWrite = await TestDataGenerator.generateRecordsWrite({ protocolRole: 'some-role' });
const role = getRecordProtocolRole(recordsWrite.message);
expect(role).to.equal('some-role');
});

it('gets a protocol role from a RecordsDelete', async () => {
const recordsDelete = await TestDataGenerator.generateRecordsDelete({ protocolRole: 'some-role' });
const role = getRecordProtocolRole(recordsDelete.message);
expect(role).to.equal('some-role');
});

it('returns undefined if no role is defined', async () => {
const recordsWrite = await TestDataGenerator.generateRecordsWrite();
const writeRole = getRecordProtocolRole(recordsWrite.message);
expect(writeRole).to.be.undefined;

const recordsDelete = await TestDataGenerator.generateRecordsDelete();
const deleteRole = getRecordProtocolRole(recordsDelete.message);
expect(deleteRole).to.be.undefined;
});
});
});
2 changes: 1 addition & 1 deletion packages/api/src/dwn-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -699,7 +699,7 @@ export class DwnApi {
*/
remoteOrigin : request.from,
delegateDid : this.delegateDid,
protocolRole : request.message.protocolRole,
protocolRole : agentRequest.messageParams.protocolRole,
...entry as DwnMessage[DwnInterface.RecordsWrite]
};
const record = new Record(this.agent, recordOptions, this.permissionsApi);
Expand Down
14 changes: 9 additions & 5 deletions packages/api/src/record.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
SendDwnRequest,
PermissionsApi,
AgentPermissionsApi,
getRecordProtocolRole
} from '@web5/agent';

import { Convert, isEmptyObject, NodeStream, removeUndefinedProperties, Stream } from '@web5/common';
Expand Down Expand Up @@ -150,7 +151,7 @@ export type RecordUpdateParams = {
datePublished?: DwnMessageDescriptor[DwnInterface.RecordsWrite]['datePublished'];

/** The protocol role under which this record is written. */
protocolRole?: string;
protocolRole?: RecordOptions['protocolRole'];

/** The published status of the record. */
published?: DwnMessageDescriptor[DwnInterface.RecordsWrite]['published'];
Expand Down Expand Up @@ -224,8 +225,6 @@ export class Record implements RecordModel {
private _readableStream?: Readable;
/** The origin DID if the record was fetched from a remote DWN. */
private _remoteOrigin?: string;
/** The protocolRole to use when reading the record */
private _protocolRole?: string;

// Private variables for DWN `RecordsWrite` message properties.

Expand All @@ -251,6 +250,8 @@ export class Record implements RecordModel {
private _initialWriteSigned: boolean;
/** Unique identifier of the record. */
private _recordId: string;
/** Role under which the record is written. */
private _protocolRole?: RecordOptions['protocolRole'];

/** The `RecordsWriteMessage` descriptor unless the record is in a deleted state */
private get _recordsWriteDescriptor() {
Expand Down Expand Up @@ -330,6 +331,9 @@ export class Record implements RecordModel {
/** Record's signatures attestation */
get attestation(): DwnMessage[DwnInterface.RecordsWrite]['attestation'] | undefined { return this._attestation; }

/** Role under which the author is writing the record */
get protocolRole() { return this._protocolRole; }

/** Record's deleted state (true/false) */
get deleted() { return isDwnMessage(DwnInterface.RecordsDelete, this.rawMessage); }

Expand Down Expand Up @@ -782,6 +786,7 @@ export class Record implements RecordModel {

// Only update the local Record instance mutable properties if the record was successfully (over)written.
this._authorization = responseMessage.authorization;
this._protocolRole = updateMessage.protocolRole;
mutableDescriptorProperties.forEach(property => {
this._descriptor[property] = responseMessage.descriptor[property];
});
Expand Down Expand Up @@ -831,8 +836,7 @@ export class Record implements RecordModel {

// Check to see if the provided protocolRole is different from the current protocolRole
// If so we need to construct a delete message with the new protocolRole, otherwise we can use the existing
// NOTE: currently this is testing the instance _protocolRole, not the actual signature payload.
const differentRole = deleteParams?.protocolRole ? this._protocolRole !== deleteParams.protocolRole : false;
const differentRole = deleteParams?.protocolRole ? getRecordProtocolRole(this.rawMessage) !== deleteParams.protocolRole : false;
if (this.deleted && !differentRole) {
// if we have a delete message we can just use it
deleteOptions.rawMessage = this.rawMessage as DwnMessage[DwnInterface.RecordsDelete];
Expand Down

0 comments on commit e5d02af

Please sign in to comment.