Skip to content

Commit

Permalink
add tests for EventsSubscribe by protocol including permission messages
Browse files Browse the repository at this point in the history
  • Loading branch information
LiranCohen committed Jun 24, 2024
1 parent 35f2684 commit 862d2b9
Showing 1 changed file with 125 additions and 24 deletions.
149 changes: 125 additions & 24 deletions tests/scenarios/subscriptions.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ import { Poller } from '../utils/poller.js';
import { TestDataGenerator } from '../utils/test-data-generator.js';
import { TestEventStream } from '../test-event-stream.js';
import { TestStores } from '../test-stores.js';
import { DataStream, Dwn, DwnInterfaceName, DwnMethodName, Jws, Message, PermissionGrant, PermissionsProtocol, Time } from '../../src/index.js';
import { DidKey, UniversalResolver } from '@web5/dids';
import { Dwn, DwnInterfaceName, DwnMethodName, Message } from '../../src/index.js';

import { expect } from 'chai';

Expand Down Expand Up @@ -310,12 +310,23 @@ export function testSubscriptionScenarios(): void {
});

it('filters by a protocol across different message types', async () => {
// NOTE: This test validates the ability to filter by a specific protocol across different message types.
// This will return any of the `RecordsWrite`, `RecordsDelete` and `ProtocolConfigure` messages that are associated with the protocol
// Additionally this will return permission-protocol `RecordsWrite` messages that are associated with the protocol.

// scenario:
// alice creates (3) different message types all related to "proto1" (Configure, RecordsWrite, RecordsDelete)
// alice creates (3) different message types all related to "proto2" (Configure, RecordsWrite, RecordsDelete)
// when subscribing for a specific protocol, only Messages related to it should be received by the handler.
// alice creates two different subscriptions, one for each protocol (proto1, proto2)
// alice configures the two different protocols (proto1, proto2)
// alice creates records for each protocol
// bob requests permissions for both protocols
// alice grants bob permissions for both protocols
// when checking the handler arrays for the specific protocol, only Events related to it should be present.
// alice then deletes the records for each protocol
// alice revokes bob's permissions for both protocols
// now when checking the handler arrays, the delete and revocation messages should be present

const alice = await TestDataGenerator.generateDidKeyPersona();
const bob = await TestDataGenerator.generateDidKeyPersona();

const proto1Messages:string[] = [];
const proto1Handler = async (event: MessageEvent):Promise<void> => {
Expand Down Expand Up @@ -355,16 +366,9 @@ export function testSubscriptionScenarios(): void {
protocolDefinition : { ...freeForAll, protocol: 'http://proto1' }
});

const postProperties = {
protocolPath : 'post',
schema : freeForAll.types.post.schema,
dataFormat : freeForAll.types.post.dataFormats[0],
};

const proto1 = protoConf1.message.descriptor.definition.protocol;
const protoConf1Response = await dwn.processMessage(alice.did, protoConf1.message);
expect(protoConf1Response.status.code).equals(202);
const proto1ConfMessageCid = await Message.getCid(protoConf1.message);

// configure proto2
const protoConf2 = await TestDataGenerator.generateProtocolsConfigure({
Expand All @@ -374,29 +378,96 @@ export function testSubscriptionScenarios(): void {
const proto2 = protoConf2.message.descriptor.definition.protocol;
const protoConf2Response = await dwn.processMessage(alice.did, protoConf2.message);
expect(protoConf2Response.status.code).equals(202);
const proto2ConfMessageCid = await Message.getCid(protoConf2.message);

const postProperties = {
protocolPath : 'post',
schema : freeForAll.types.post.schema,
dataFormat : freeForAll.types.post.dataFormats[0],
};

// create a record for proto1
const write1proto1 = await TestDataGenerator.generateRecordsWrite({ author: alice, protocol: proto1, ...postProperties });
const write1Response = await dwn.processMessage(alice.did, write1proto1.message, { dataStream: write1proto1.dataStream });
expect(write1Response.status.code).equals(202);
const write1Proto1MessageCid = await Message.getCid(write1proto1.message);

// create a record for proto2
const write1proto2 = await TestDataGenerator.generateRecordsWrite({ author: alice, protocol: proto2, ...postProperties });
const write1Proto2Response = await dwn.processMessage(alice.did, write1proto2.message, { dataStream: write1proto2.dataStream });
expect(write1Proto2Response.status.code).equals(202);
const write1Proto2MessageCid = await Message.getCid(write1proto2.message);

// bob requests permissions for proto1
const requestProto1 = await PermissionsProtocol.createRequest({
signer : Jws.createSigner(bob),
scope : { interface: DwnInterfaceName.Records, method: DwnMethodName.Write, protocol: proto1 },
delegated : false,
});
const requestProto1Response = await dwn.processMessage(
alice.did,
requestProto1.recordsWrite.message,
{ dataStream: DataStream.fromBytes(requestProto1.permissionRequestBytes) }
);
expect(requestProto1Response.status.code).equals(202);

// bob requests permissions for proto2
const requestProto2 = await PermissionsProtocol.createRequest({
signer : Jws.createSigner(bob),
scope : { interface: DwnInterfaceName.Records, method: DwnMethodName.Write, protocol: proto2 },
delegated : false,
});
const requestProto2Response = await dwn.processMessage(
alice.did,
requestProto2.recordsWrite.message,
{ dataStream: DataStream.fromBytes(requestProto2.permissionRequestBytes) }
);
expect(requestProto2Response.status.code).equals(202);

// alice grants permissions for proto1
const grantProto1 = await PermissionsProtocol.createGrant({
signer : Jws.createSigner(alice),
scope : requestProto1.permissionRequestData.scope,
dateExpires : Time.createOffsetTimestamp({ seconds: 5 }),
grantedTo : bob.did,
});
const grantProto1Response = await dwn.processMessage(
alice.did,
grantProto1.recordsWrite.message,
{ dataStream: DataStream.fromBytes(grantProto1.permissionGrantBytes) }
);
expect(grantProto1Response.status.code).equals(202);

// alice grants permissions for proto2
const grantProto2 = await PermissionsProtocol.createGrant({
signer : Jws.createSigner(alice),
scope : requestProto2.permissionRequestData.scope,
dateExpires : Time.createOffsetTimestamp({ seconds: 5 }),
grantedTo : bob.did,
});
const grantProto2Response = await dwn.processMessage(
alice.did,
grantProto2.recordsWrite.message,
{ dataStream: DataStream.fromBytes(grantProto2.permissionGrantBytes) }
);
expect(grantProto2Response.status.code).equals(202);

// poll until the messages are received by the handlers
await Poller.pollUntilSuccessOrTimeout(async () => {
// check for proto1 messages
expect(proto1Messages.length).to.equal(2);
expect(proto1Messages).to.have.members([ proto1ConfMessageCid, write1Proto1MessageCid ]);
expect(proto1Messages.length).to.equal(4);
expect(proto1Messages).to.have.members([
await Message.getCid(protoConf1.message),
await Message.getCid(write1proto1.message),
await Message.getCid(requestProto1.recordsWrite.message),
await Message.getCid(grantProto1.recordsWrite.message),
]);

// check for proto2 messages
expect(proto2Messages.length).to.equal(2);
expect(proto2Messages).to.have.members([ proto2ConfMessageCid, write1Proto2MessageCid ]);
expect(proto2Messages.length).to.equal(4);
expect(proto2Messages).to.have.members([
await Message.getCid(protoConf2.message),
await Message.getCid(write1proto2.message),
await Message.getCid(requestProto2.recordsWrite.message),
await Message.getCid(grantProto2.recordsWrite.message),
]);
});

// delete proto1 message
Expand All @@ -409,15 +480,45 @@ export function testSubscriptionScenarios(): void {
const deleteProto2MessageReply = await dwn.processMessage(alice.did, deleteProto2Message.message);
expect(deleteProto2MessageReply.status.code).to.equal(202);

// revoke permissions for proto1
const revokeProto1 = await PermissionsProtocol.createRevocation({
signer : Jws.createSigner(alice),
grant : await PermissionGrant.parse(grantProto1.dataEncodedMessage),
});
const revokeProto1Response = await dwn.processMessage(
alice.did,
revokeProto1.recordsWrite.message,
{ dataStream: DataStream.fromBytes(revokeProto1.permissionRevocationBytes) }
);
expect(revokeProto1Response.status.code).equals(202);

// revoke permissions for proto2
const revokeProto2 = await PermissionsProtocol.createRevocation({
signer : Jws.createSigner(alice),
grant : await PermissionGrant.parse(grantProto2.dataEncodedMessage),
});
const revokeProto2Response = await dwn.processMessage(
alice.did,
revokeProto2.recordsWrite.message,
{ dataStream: DataStream.fromBytes(revokeProto2.permissionRevocationBytes) }
);
expect(revokeProto2Response.status.code).equals(202);

// poll until the messages are received by the handlers
await Poller.pollUntilSuccessOrTimeout(async () => {
// check for the delete in proto1 messages
expect(proto1Messages.length).to.equal(3);
expect(proto1Messages).to.include.members([ await Message.getCid(deleteProto1Message.message) ]);
// check for the delete and revocation in proto1 messages
expect(proto1Messages.length).to.equal(6); // 2 additional messages
expect(proto1Messages).to.include.members([
await Message.getCid(deleteProto1Message.message),
await Message.getCid(revokeProto1.recordsWrite.message),
]);

// check for the delete in proto2 messages
expect(proto2Messages.length).to.equal(3);
expect(proto2Messages).to.include.members([ await Message.getCid(deleteProto2Message.message) ]);
// check for the delete and revocation in proto2 messages
expect(proto2Messages.length).to.equal(6); // 2 additional messages
expect(proto2Messages).to.include.members([
await Message.getCid(deleteProto2Message.message),
await Message.getCid(revokeProto2.recordsWrite.message),
]);
});
});

Expand Down

0 comments on commit 862d2b9

Please sign in to comment.