Skip to content

Commit

Permalink
Improved typing of PermissionGrant.parse() to avoid misuse (#760)
Browse files Browse the repository at this point in the history
1. Improved typing of PermissionGrant.parse() to avoid misuse
2. Detected and fixed a couple of unimportant misuses in the tests after
the above change (case in point).
  • Loading branch information
thehenrytsai authored Jun 15, 2024
1 parent 158470f commit b1ea021
Show file tree
Hide file tree
Showing 11 changed files with 25 additions and 23 deletions.
4 changes: 2 additions & 2 deletions src/core/message.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { DataEncodedRecordsWriteMessage } from '../types/records-types.js';
import type { GeneralJws } from '../types/jws-types.js';
import type { RecordsWriteMessage } from '../types/records-types.js';
import type { Signer } from '../types/signer.js';
import type { AuthorizationModel, Descriptor, GenericMessage, GenericSignaturePayload } from '../types/message-types.js';

Expand Down Expand Up @@ -79,7 +79,7 @@ export class Message {
public static async createAuthorization(input: {
descriptor: Descriptor,
signer: Signer,
delegatedGrant?: RecordsWriteMessage,
delegatedGrant?: DataEncodedRecordsWriteMessage,
permissionGrantId?: string,
protocolRole?: string
}): Promise<AuthorizationModel> {
Expand Down
4 changes: 2 additions & 2 deletions src/interfaces/records-delete.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { KeyValues } from '../types/query-types.js';
import type { MessageStore } from '../types//message-store.js';
import type { Signer } from '../types/signer.js';
import type { RecordsDeleteDescriptor, RecordsDeleteMessage, RecordsWriteMessage } from '../types/records-types.js';
import type { DataEncodedRecordsWriteMessage, RecordsDeleteDescriptor, RecordsDeleteMessage, RecordsWriteMessage } from '../types/records-types.js';

import { AbstractMessage } from '../core/abstract-message.js';
import { Message } from '../core/message.js';
Expand All @@ -26,7 +26,7 @@ export type RecordsDeleteOptions = {
/**
* The delegated grant to sign on behalf of the logical author, which is the grantor (`grantedBy`) of the delegated grant.
*/
delegatedGrant?: RecordsWriteMessage;
delegatedGrant?: DataEncodedRecordsWriteMessage;
};

export class RecordsDelete extends AbstractMessage<RecordsDeleteMessage> {
Expand Down
4 changes: 2 additions & 2 deletions src/interfaces/records-query.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { MessageStore } from '../types//message-store.js';
import type { Pagination } from '../types/message-types.js';
import type { Signer } from '../types/signer.js';
import type { RecordsFilter, RecordsQueryDescriptor, RecordsQueryMessage, RecordsWriteMessage } from '../types/records-types.js';
import type { DataEncodedRecordsWriteMessage, RecordsFilter, RecordsQueryDescriptor, RecordsQueryMessage } from '../types/records-types.js';

import { AbstractMessage } from '../core/abstract-message.js';
import { DateSort } from '../types/records-types.js';
Expand All @@ -26,7 +26,7 @@ export type RecordsQueryOptions = {
/**
* The delegated grant to sign on behalf of the logical author, which is the grantor (`grantedBy`) of the delegated grant.
*/
delegatedGrant?: RecordsWriteMessage;
delegatedGrant?: DataEncodedRecordsWriteMessage;
};

/**
Expand Down
4 changes: 2 additions & 2 deletions src/interfaces/records-read.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { MessageStore } from '../types//message-store.js';
import type { Signer } from '../types/signer.js';
import type { RecordsFilter , RecordsReadDescriptor, RecordsReadMessage, RecordsWriteMessage } from '../types/records-types.js';
import type { DataEncodedRecordsWriteMessage, RecordsFilter , RecordsReadDescriptor, RecordsReadMessage, RecordsWriteMessage } from '../types/records-types.js';

import { AbstractMessage } from '../core/abstract-message.js';
import { Message } from '../core/message.js';
Expand All @@ -25,7 +25,7 @@ export type RecordsReadOptions = {
/**
* The delegated grant to sign on behalf of the logical author, which is the grantor (`grantedBy`) of the delegated grant.
*/
delegatedGrant?: RecordsWriteMessage;
delegatedGrant?: DataEncodedRecordsWriteMessage;
};

export class RecordsRead extends AbstractMessage<RecordsReadMessage> {
Expand Down
4 changes: 2 additions & 2 deletions src/interfaces/records-subscribe.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { MessageStore } from '../types/message-store.js';
import type { Signer } from '../types/signer.js';
import type { RecordsFilter, RecordsSubscribeDescriptor, RecordsSubscribeMessage, RecordsWriteMessage } from '../types/records-types.js';
import type { DataEncodedRecordsWriteMessage, RecordsFilter, RecordsSubscribeDescriptor, RecordsSubscribeMessage } from '../types/records-types.js';

import { AbstractMessage } from '../core/abstract-message.js';
import { Message } from '../core/message.js';
Expand All @@ -22,7 +22,7 @@ export type RecordsSubscribeOptions = {
/**
* The delegated grant to sign on behalf of the logical author, which is the grantor (`grantedBy`) of the delegated grant.
*/
delegatedGrant?: RecordsWriteMessage;
delegatedGrant?: DataEncodedRecordsWriteMessage;
};

/**
Expand Down
9 changes: 5 additions & 4 deletions src/interfaces/records-write.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type { MessageStore } from '../types/message-store.js';
import type { PublicJwk } from '../types/jose-types.js';
import type { Signer } from '../types/signer.js';
import type {
DataEncodedRecordsWriteMessage,
EncryptedKey,
EncryptionProperty,
InternalRecordsWriteMessage,
Expand Down Expand Up @@ -66,7 +67,7 @@ export type RecordsWriteOptions = {
/**
* The delegated grant invoked to sign on behalf of the logical author, which is the grantor of the delegated grant.
*/
delegatedGrant?: RecordsWriteMessage;
delegatedGrant?: DataEncodedRecordsWriteMessage;

attestationSigners?: Signer[];
encryptionInput?: EncryptionInput;
Expand Down Expand Up @@ -148,7 +149,7 @@ export type CreateFromOptions = {
/**
* The delegated grant to sign on behalf of the logical author, which is the grantor (`grantedBy`) of the delegated grant.
*/
delegatedGrant?: RecordsWriteMessage;
delegatedGrant?: DataEncodedRecordsWriteMessage;

attestationSigners?: Signer[];
encryptionInput?: EncryptionInput;
Expand Down Expand Up @@ -491,7 +492,7 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
*/
public async sign(options: {
signer: Signer,
delegatedGrant?: RecordsWriteMessage,
delegatedGrant?: DataEncodedRecordsWriteMessage,
permissionGrantId?: string,
protocolRole?: string
}): Promise<void> {
Expand Down Expand Up @@ -576,7 +577,7 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
* This is used when a DWN owner-delegate wants to retain a copy of a message that the owner did not author.
* NOTE: requires the `RecordsWrite` to already have the author's signature.
*/
public async signAsOwnerDelegate(signer: Signer, delegatedGrant: RecordsWriteMessage): Promise<void> {
public async signAsOwnerDelegate(signer: Signer, delegatedGrant: DataEncodedRecordsWriteMessage): Promise<void> {
if (this._author === undefined) {
throw new DwnError(
DwnErrorCode.RecordsWriteSignAsOwnerDelegateUnknownAuthor,
Expand Down
8 changes: 4 additions & 4 deletions src/protocols/permission-grant.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { RecordsQueryReplyEntry, RecordsWriteMessage } from '../types/records-types.js';
import type { DataEncodedRecordsWriteMessage } from '../types/records-types.js';

import type { PermissionConditions, PermissionGrantData, PermissionScope } from '../types/permission-types.js';

Expand Down Expand Up @@ -61,23 +61,23 @@ export class PermissionGrant {
*/
public readonly conditions?: PermissionConditions;

public static async parse(message: RecordsWriteMessage): Promise<PermissionGrant> {
public static async parse(message: DataEncodedRecordsWriteMessage): Promise<PermissionGrant> {
const permissionGrant = new PermissionGrant(message);
return permissionGrant;
}

/**
* Creates a Permission Grant abstraction for
*/
private constructor(message: RecordsWriteMessage) {
private constructor(message: DataEncodedRecordsWriteMessage) {
// properties derived from the generic DWN message properties
this.id = message.recordId;
this.grantor = Message.getSigner(message)!;
this.grantee = message.descriptor.recipient!;
this.dateGranted = message.descriptor.dateCreated;

// properties from the data payload itself.
const permissionGrantEncoded = (message as RecordsQueryReplyEntry).encodedData!;
const permissionGrantEncoded = message.encodedData;
const permissionGrant = Encoder.base64UrlToObject(permissionGrantEncoded) as PermissionGrantData;
this.dateExpires = permissionGrant.dateExpires;
this.delegated = permissionGrant.delegated;
Expand Down
2 changes: 1 addition & 1 deletion src/protocols/permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,7 @@ export class PermissionsProtocol {
);
}

const permissionGrantMessage = possibleGrantMessage as RecordsWriteMessage;
const permissionGrantMessage = possibleGrantMessage as DataEncodedRecordsWriteMessage;
const permissionGrant = await PermissionGrant.parse(permissionGrantMessage);

return permissionGrant;
Expand Down
3 changes: 2 additions & 1 deletion src/types/message-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ type DelegatedGrantRecordsWriteMessage = {
},
recordId: string,
contextId?: string;
// NOTE: This is a direct copy of `RecordsWriteDescriptor` to avoid circular references.
// NOTE: This is a direct expansion and copy of `DataEncodedRecordsWriteMessage` to avoid circular references.
descriptor: {
interface: DwnInterfaceName.Records;
method: DwnMethodName.Write;
Expand All @@ -62,6 +62,7 @@ type DelegatedGrantRecordsWriteMessage = {
datePublished?: string;
dataFormat: string;
};
encodedData: string;
};

/**
Expand Down
2 changes: 1 addition & 1 deletion src/types/records-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export type DataEncodedRecordsWriteMessage = RecordsWriteMessage & {
/**
* The encoded data of the record if the data associated with the record is equal or smaller than `DwnConstant.maxDataSizeAllowedToBeEncoded`.
*/
encodedData?: string;
encodedData: string;
};

export type RecordsQueryDescriptor = {
Expand Down
4 changes: 2 additions & 2 deletions tests/interfaces/records-write.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ describe('RecordsWrite', () => {
});

const createPromise = RecordsWrite.create({
delegatedGrant : grantToBob.recordsWrite.message,
delegatedGrant : grantToBob.dataEncodedMessage,
dataFormat : 'application/octet-stream',
data : TestDataGenerator.randomBytes(10),
});
Expand Down Expand Up @@ -452,7 +452,7 @@ describe('RecordsWrite', () => {
scope
});

await expect(recordsWrite.signAsOwnerDelegate(Jws.createSigner(bob), ownerDelegatedGrant.recordsWrite.message))
await expect(recordsWrite.signAsOwnerDelegate(Jws.createSigner(bob), ownerDelegatedGrant.dataEncodedMessage))
.to.be.rejectedWith(DwnErrorCode.RecordsWriteSignAsOwnerDelegateUnknownAuthor);

expect(recordsWrite.owner).to.be.undefined;
Expand Down

0 comments on commit b1ea021

Please sign in to comment.