Skip to content

Commit

Permalink
Allowed protocol-authorized RecordsWrite to be schema-less (#612)
Browse files Browse the repository at this point in the history
  • Loading branch information
thehenrytsai authored Nov 18, 2023
1 parent b6c0605 commit 6c01ea2
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,7 @@
"type": "object",
"required": [
"protocol",
"protocolPath",
"schema"
"protocolPath"
]
}
},
Expand Down
64 changes: 61 additions & 3 deletions tests/handlers/records-write.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import { TestStores } from '../test-stores.js';
import { TestStubGenerator } from '../utils/test-stub-generator.js';
import { Time } from '../../src/utils/time.js';

import { DwnConstant, DwnInterfaceName, DwnMethodName, KeyDerivationScheme, RecordsDelete } from '../../src/index.js';
import { DwnConstant, DwnInterfaceName, DwnMethodName, KeyDerivationScheme, RecordsDelete, RecordsQuery } from '../../src/index.js';
import { Encryption, EncryptionAlgorithm } from '../../src/utils/encryption.js';

chai.use(chaiAsPromised);
Expand Down Expand Up @@ -1029,7 +1029,7 @@ export function testRecordsWriteHandler(): void {

describe('protocol based writes', () => {
it('should allow write with allow-anyone rule', async () => {
// scenario, Bob writes into Alice's DWN given Alice's "email" protocol allow-anyone rule
// scenario: Bob writes into Alice's DWN given Alice's "email" protocol allow-anyone rule

// write a protocol definition with an allow-anyone rule
const protocolDefinition = emailProtocolDefinition as ProtocolDefinition;
Expand Down Expand Up @@ -2454,7 +2454,7 @@ export function testRecordsWriteHandler(): void {
expect(reply.status.detail).to.contain('unable to find protocol definition');
});

it('should fail authorization if record schema is not an allowed type for protocol-based RecordsWrite', async () => {
it('should fail authorization if record schema is incorrect for a protocol-based RecordsWrite', async () => {
const alice = await DidKeyResolver.generate();

const protocolDefinition = credentialIssuanceProtocolDefinition;
Expand Down Expand Up @@ -3000,6 +3000,64 @@ export function testRecordsWriteHandler(): void {
const bobRecordsReadReply = await dwn.processMessage(alice.did, bobRecordsReadData.message);
expect(bobRecordsReadReply.status.code).to.equal(404);
});

it('should allow record with or without schema if protocol does not require schema for a record type', async () => {
// scenario: Alice's DWN has a protocol that allows anyone to write a record without schema

// write a protocol definition that has a record type without schema
const protocolDefinition = anyoneCollaborateProtocolDefinition as ProtocolDefinition;
const alice = await DidKeyResolver.generate();

const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
author: alice,
protocolDefinition
});

const protocolsConfigureReply = await dwn.processMessage(alice.did, protocolsConfig.message);
expect(protocolsConfigureReply.status.code).to.equal(202);

// write a `RecordsWrite` message without schema
const data = TestDataGenerator.randomBytes(100);
const dataStream = DataStream.fromBytes(data);
const docWrite = await RecordsWrite.create(
{
protocol : protocolDefinition.protocol,
protocolPath : 'doc',
dataFormat : 'application/octet-stream',
data,
signer : Jws.createSigner(alice)
}
);

const writeReply = await dwn.processMessage(alice.did, docWrite.message, dataStream);
expect(writeReply.status.code).to.equal(202);

// write a `RecordsWrite` message with schema
const data2 = TestDataGenerator.randomBytes(100);
const data2Stream = DataStream.fromBytes(data2);
const doc2Write = await RecordsWrite.create(
{
protocol : protocolDefinition.protocol,
protocolPath : 'doc',
schema : TestDataGenerator.randomString(10),
dataFormat : 'application/octet-stream',
data : data2,
signer : Jws.createSigner(alice)
}
);

const write2Reply = await dwn.processMessage(alice.did, doc2Write.message, data2Stream);
expect(write2Reply.status.code).to.equal(202);

// verify messages got written to the DB
const recordsQuery = await RecordsQuery.create({
filter : { protocolPath: 'doc' },
signer : Jws.createSigner(alice)
});
const recordsReadReply = await dwn.processMessage(alice.did, recordsQuery.message);
expect(recordsReadReply.status.code).to.equal(200);
expect(recordsReadReply.entries?.length).to.equal(2);
});
});

describe('grant based writes', () => {
Expand Down
24 changes: 0 additions & 24 deletions tests/validation/json-schemas/records/records-write.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,30 +276,6 @@ describe('RecordsWrite schema definition', () => {
}).throws('descriptor: must have required property \'protocol\'');
});

it('should throw if `protocol` is defined but `schema` is missing', () => {
const invalidMessage = {
recordId : 'anyRecordId',
contextId : 'anyContextId', // required by protocol-based message
descriptor : {
interface : 'Records',
method : 'Write',
protocol : 'http://foo.bar',
protocolPath : 'foo/bar',
// schema : 'http://foo.bar/schema', // intentionally missing
dataCid : 'anyCid',
dataFormat : 'application/json',
dataSize : 123,
dateCreated : '2022-12-19T10:20:30.123456Z',
messageTimestamp : '2022-12-19T10:20:30.123456Z'
},
authorization: TestDataGenerator.generateAuthorization()
};

expect(() => {
Message.validateJsonSchema(invalidMessage);
}).throws('descriptor: must have required property \'schema\'');
});

it('should throw if `protocol` is undefined but `recipient` is defined', () => {
const invalidMessage = {
recordId : 'anyRecordId',
Expand Down

0 comments on commit 6c01ea2

Please sign in to comment.