Skip to content

Commit

Permalink
getAuthor moved to Message util (#734)
Browse files Browse the repository at this point in the history
Move `getAuthor` method to the `records` util so that it can be used on
both `RecordsWriteMessage` and `RecordsDeleteMessage`
  • Loading branch information
LiranCohen committed May 10, 2024
1 parent c1736f5 commit 83a6b41
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 26 deletions.
25 changes: 2 additions & 23 deletions src/interfaces/records-write.ts
Expand Up @@ -250,13 +250,7 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
this._message = message;

if (message.authorization !== undefined) {
// if the message authorization contains author delegated grant, the author would be the grantor of the grant
// else the author would be the signer of the message
if (message.authorization.authorDelegatedGrant !== undefined) {
this._author = Message.getSigner(message.authorization.authorDelegatedGrant);
} else {
this._author = Message.getSigner(message as GenericMessage);
}
this._author = Records.getAuthor(message as RecordsWriteMessage);

this._signaturePayload = Jws.decodePlainObjectPayload(message.authorization.signature);

Expand Down Expand Up @@ -836,26 +830,11 @@ export class RecordsWrite implements MessageInterface<RecordsWriteMessage> {
}

const recordsWriteMessage = message as RecordsWriteMessage;
const author = RecordsWrite.getAuthor(recordsWriteMessage);
const author = Records.getAuthor(recordsWriteMessage);
const entryId = await RecordsWrite.getEntryId(author, recordsWriteMessage.descriptor);
return (entryId === recordsWriteMessage.recordId);
}

/**
* Gets the DID of the author of the given message.
*/
public static getAuthor(message: RecordsWriteMessage): string | undefined {
let author;

if (message.authorization.authorDelegatedGrant !== undefined) {
author = Message.getSigner(message.authorization.authorDelegatedGrant);
} else {
author = Message.getSigner(message);
}

return author;
}

/**
* Creates the `encryption` property if encryption input is given. Else `undefined` is returned.
*/
Expand Down
15 changes: 15 additions & 0 deletions src/utils/records.ts
Expand Up @@ -34,6 +34,21 @@ export class Records {
return isRecordsWrite;
}

/**
* Gets the DID of the author of the given message.
*/
public static getAuthor(message: RecordsWriteMessage | RecordsDeleteMessage): string | undefined {
let author;

if (message.authorization.authorDelegatedGrant !== undefined) {
author = Message.getSigner(message.authorization.authorDelegatedGrant);
} else {
author = Message.getSigner(message);
}

return author;
}

/**
* Decrypts the encrypted data in a message reply using the given ancestor private key.
* @param ancestorPrivateKey Any ancestor private key in the key derivation path.
Expand Down
60 changes: 57 additions & 3 deletions tests/utils/records.spec.ts
@@ -1,9 +1,11 @@
import type { DerivedPrivateJwk, RecordsWriteDescriptor } from '../../src/index.js';
import type { DerivedPrivateJwk, PermissionScope, RecordsWriteDescriptor } from '../../src/index.js';

import { expect } from 'chai';

import { DwnErrorCode } from '../../src/core/dwn-error.js';
import { ed25519 } from '../../src/jose/algorithms/signing/ed25519.js';
import { expect } from 'chai';
import { DwnInterfaceName, DwnMethodName, KeyDerivationScheme, Records } from '../../src/index.js';
import { RecordsWrite } from '../../src/interfaces/records-write.js';
import { DwnInterfaceName, DwnMethodName, Jws, KeyDerivationScheme, PermissionsProtocol, Records, TestDataGenerator, Time } from '../../src/index.js';

describe('Records', () => {
describe('deriveLeafPrivateKey()', () => {
Expand All @@ -17,6 +19,58 @@ describe('Records', () => {
});
});

describe('getAuthor()', () => {
it('should return the author of RecordsWrite, RecordsDelete types', async () => {
const bob = await TestDataGenerator.generatePersona();

// create a record message
const { message: recordsWriteMessage } = await TestDataGenerator.generateRecordsWrite({ author: bob });
const recordsWriteAuthor = Records.getAuthor(recordsWriteMessage);
expect(recordsWriteAuthor).to.equal(bob.did);

// create a delete message
const { message: recordsDeleteMessage } = await TestDataGenerator.generateRecordsDelete({ author: bob });
const recordsDeleteAuthor = Records.getAuthor(recordsDeleteMessage);
expect(recordsDeleteAuthor).to.equal(bob.did);
});

it('should get the author of a delegated message', async () => {
const alice = await TestDataGenerator.generatePersona();
const deviceX = await TestDataGenerator.generatePersona();

// create a delegation scope from alice to deviceX for writing records with schema `foo/bar`
const scope:PermissionScope = {
interface : DwnInterfaceName.Records,
method : DwnMethodName.Write,
schema : 'foo/bar',
};

// create the delegated grant message
const bobGrant = await PermissionsProtocol.createGrant({
delegated : true,
dateExpires : Time.createOffsetTimestamp({ seconds: 100 }),
grantedTo : deviceX.did,
scope : scope,
signer : Jws.createSigner(alice)
});

// create a record message using the grant
const writeData = TestDataGenerator.randomBytes(32);

const { message } = await RecordsWrite.create({
signer : Jws.createSigner(deviceX),
delegatedGrant : bobGrant.dataEncodedMessage,
schema : 'foo/bar',
dataFormat : 'application/json',
data : writeData,
});

// expect message author to be alice
const author = Records.getAuthor(message);
expect(author).to.equal(alice.did);
});
});

describe('constructKeyDerivationPathUsingProtocolPathScheme()', () => {
it('should throw if given a flat-space descriptor', async () => {
const descriptor: RecordsWriteDescriptor = {
Expand Down

0 comments on commit 83a6b41

Please sign in to comment.