Skip to content

Commit 0d8d89d

Browse files
authored
#209 - added support for attestation property in records
1 parent 15a253b commit 0d8d89d

34 files changed

+514
-335
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# Decentralized Web Node (DWN) SDK
44

55
Code Coverage
6-
![Statements](https://img.shields.io/badge/statements-94%25-brightgreen.svg?style=flat) ![Branches](https://img.shields.io/badge/branches-92.19%25-brightgreen.svg?style=flat) ![Functions](https://img.shields.io/badge/functions-90.85%25-brightgreen.svg?style=flat) ![Lines](https://img.shields.io/badge/lines-94%25-brightgreen.svg?style=flat)
6+
![Statements](https://img.shields.io/badge/statements-94.56%25-brightgreen.svg?style=flat) ![Branches](https://img.shields.io/badge/branches-93.93%25-brightgreen.svg?style=flat) ![Functions](https://img.shields.io/badge/functions-91.51%25-brightgreen.svg?style=flat) ![Lines](https://img.shields.io/badge/lines-94.56%25-brightgreen.svg?style=flat)
77

88
## Introduction
99

json-schemas/records/records-write.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
"contextId": {
1616
"type": "string"
1717
},
18+
"attestation": {
19+
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
20+
},
1821
"authorization": {
1922
"$ref": "https://identity.foundation/dwn/json-schemas/general-jws.json"
2023
},

package-lock.json

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/core/auth.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { DidResolver } from '../did/did-resolver.js';
55
import { GeneralJws } from '../jose/jws/general/types.js';
66
import { GeneralJwsVerifier } from '../jose/jws/general/verifier.js';
77
import { Message } from './message.js';
8-
import { generateCid, parseCid } from '../utils/cid.js';
8+
import { computeCid, parseCid } from '../utils/cid.js';
99

1010
type AuthorizationPayloadConstraints = {
1111
/** permissible properties within payload. Note that `descriptorCid` is implied and does not need to be added */
@@ -45,7 +45,7 @@ export async function validateAuthorizationIntegrity(
4545

4646
// `descriptorCid` validation - ensure that the provided descriptorCid matches the CID of the actual message
4747
const providedDescriptorCid = parseCid(descriptorCid); // parseCid throws an exception if parsing fails
48-
const expectedDescriptorCid = await generateCid(message.descriptor);
48+
const expectedDescriptorCid = await computeCid(message.descriptor);
4949
if (!providedDescriptorCid.equals(expectedDescriptorCid)) {
5050
throw new Error(`provided descriptorCid ${providedDescriptorCid} does not match expected CID ${expectedDescriptorCid}`);
5151
}

src/core/message.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import type { SignatureInput } from '../jose/jws/general/types.js';
22
import type { BaseDecodedAuthorizationPayload, BaseMessage, Descriptor, TimestampedMessage } from './types.js';
33

44
import { CID } from 'multiformats/cid';
5+
import { computeCid } from '../utils/cid.js';
56
import { GeneralJws } from '../jose/jws/general/types.js';
67
import { GeneralJwsSigner } from '../jose/jws/general/signer.js';
78
import { GeneralJwsVerifier } from '../jose/jws/general/verifier.js';
8-
import { generateCid } from '../utils/cid.js';
99
import { lexicographicalCompare } from '../utils/string.js';
1010
import { RecordsWriteMessage } from '../interfaces/records/types.js';
1111
import { validateJsonSchema } from '../validator.js';
@@ -79,7 +79,7 @@ export abstract class Message {
7979
delete (messageCopy as RecordsWriteMessage).encodedData;
8080
}
8181

82-
const cid = await generateCid(messageCopy);
82+
const cid = await computeCid(messageCopy);
8383
return cid;
8484
}
8585

@@ -128,7 +128,7 @@ export abstract class Message {
128128
descriptor: Descriptor,
129129
signatureInput: SignatureInput
130130
): Promise<GeneralJws> {
131-
const descriptorCid = await generateCid(descriptor);
131+
const descriptorCid = await computeCid(descriptor);
132132

133133
const authPayload: BaseDecodedAuthorizationPayload = { descriptorCid: descriptorCid.toString() };
134134
const authPayloadStr = JSON.stringify(authPayload);

src/core/types.ts

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { GeneralJws, SignatureInput } from '../jose/jws/general/types.js';
1+
import type { GeneralJws } from '../jose/jws/general/types.js';
22

33
/**
44
* Intersection type for all concrete message types.
@@ -42,7 +42,3 @@ export type DataReferencingMessage = {
4242

4343
encodedData: string;
4444
};
45-
46-
export type AuthCreateOptions = {
47-
signatureInput: SignatureInput
48-
};

src/dwn.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ export class Dwn {
6868
message = JSON.parse(requestString);
6969
} catch (error) {
7070
return new MessageReply({
71-
status: { code: 400, detail: error.message }
71+
status: { code: 400, detail: 'unable to JSON parse request' }
7272
});
7373
}
7474

@@ -85,7 +85,7 @@ export class Dwn {
8585
const dwnMethod = rawMessage?.descriptor?.method;
8686
if (dwnInterface === undefined || dwnMethod === undefined) {
8787
return new MessageReply({
88-
status: { code: 400, detail: `DWN interface or method is undefined` }
88+
status: { code: 400, detail: `Both interface and method must be present, interface: ${dwnInterface}, method: ${dwnMethod}` }
8989
});
9090
}
9191

src/interfaces/hooks/messages/hooks-write.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { AuthCreateOptions } from '../../../core/types.js';
1+
import type { SignatureInput } from '../../../jose/jws/general/types.js';
22
import type { HooksWriteDescriptor, HooksWriteMessage } from '../../hooks/types.js';
33

44
import { getCurrentTimeInHighPrecision } from '../../../utils/time.js';
@@ -9,7 +9,7 @@ import { DwnInterfaceName, DwnMethodName, Message } from '../../../core/message.
99
/**
1010
* Input to `HookssWrite.create()`.
1111
*/
12-
export type HooksWriteOptions = AuthCreateOptions & {
12+
export type HooksWriteOptions = {
1313
dateCreated?: string,
1414
/**
1515
* leave as `undefined` for customer handler.
@@ -18,7 +18,8 @@ export type HooksWriteOptions = AuthCreateOptions & {
1818
uri?: string,
1919
filter: {
2020
method: string,
21-
}
21+
},
22+
authorizationSignatureInput: SignatureInput;
2223
};
2324

2425
/**
@@ -47,7 +48,7 @@ export class HooksWrite extends Message {
4748
// Error: `undefined` is not supported by the IPLD Data Model and cannot be encoded
4849
removeUndefinedProperties(descriptor);
4950

50-
const authorization = await Message.signAsAuthorization(descriptor, options.signatureInput);
51+
const authorization = await Message.signAsAuthorization(descriptor, options.authorizationSignatureInput);
5152
const message = { descriptor, authorization };
5253

5354
Message.validateJsonSchema(message);

src/interfaces/permissions/messages/permissions-grant.ts

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1-
import type { AuthCreateOptions } from '../../../core/types';
21
import type { SignatureInput } from '../../../jose/jws/general/types';
32
import type { PermissionConditions, PermissionScope } from '../types';
43
import type { PermissionsGrantDescriptor, PermissionsGrantMessage } from '../types';
54

65
import { CID } from 'multiformats/cid';
7-
import { generateCid } from '../../../utils/cid';
6+
import { computeCid } from '../../../utils/cid';
87
import { getCurrentTimeInHighPrecision } from '../../../utils/time';
98
import { v4 as uuidv4 } from 'uuid';
109

1110
import { DEFAULT_CONDITIONS, PermissionsRequest } from './permissions-request';
1211
import { DwnInterfaceName, DwnMethodName, Message } from '../../../core/message';
1312

14-
type PermissionsGrantOptions = AuthCreateOptions & {
13+
type PermissionsGrantOptions = {
1514
dateCreated?: string;
1615
conditions?: PermissionConditions;
1716
description: string;
@@ -20,6 +19,7 @@ type PermissionsGrantOptions = AuthCreateOptions & {
2019
objectId?: string;
2120
permissionsRequestId?: string;
2221
scope: PermissionScope;
22+
authorizationSignatureInput: SignatureInput;
2323
};
2424

2525
export class PermissionsGrant extends Message {
@@ -46,7 +46,7 @@ export class PermissionsGrant extends Message {
4646
scope : options.scope,
4747
};
4848

49-
const authorization = await Message.signAsAuthorization(descriptor, options.signatureInput);
49+
const authorization = await Message.signAsAuthorization(descriptor, options.authorizationSignatureInput);
5050
const message: PermissionsGrantMessage = { descriptor, authorization };
5151

5252
Message.validateJsonSchema(message);
@@ -58,12 +58,12 @@ export class PermissionsGrant extends Message {
5858
/**
5959
* generates a PermissionsGrant using the provided PermissionsRequest
6060
* @param permissionsRequest
61-
* @param signatureInput - the private key and additional signature material of the grantor
61+
* @param authorizationSignatureInput - the private key and additional signature material of the grantor
6262
* @param conditionOverrides - any conditions that the grantor may want to override
6363
*/
6464
static async fromPermissionsRequest(
6565
permissionsRequest: PermissionsRequest,
66-
signatureInput: SignatureInput,
66+
authorizationSignatureInput: SignatureInput,
6767
conditionOverrides: Partial<PermissionConditions> = {}
6868
): Promise<PermissionsGrant> {
6969
const conditions = { ...permissionsRequest.conditions, ...conditionOverrides };
@@ -75,33 +75,33 @@ export class PermissionsGrant extends Message {
7575
grantedTo : permissionsRequest.grantedTo,
7676
permissionsRequestId : permissionsRequest.id,
7777
scope : permissionsRequest.scope,
78-
signatureInput : signatureInput
78+
authorizationSignatureInput
7979
});
8080
}
8181

8282
/**
8383
* delegates the permission to the DID provided
8484
* @param to - the DID of the grantee
85-
* @param signatureInput - the private key and additional signature material of this permission's `grantedTo`
85+
* @param authorizationSignatureInput - the private key and additional signature material of this permission's `grantedTo`
8686
* @throws {Error} - if the permission cannot be delegated
8787
*/
88-
async delegate(to: string, signatureInput: SignatureInput): Promise<PermissionsGrant> {
88+
async delegate(to: string, authorizationSignatureInput: SignatureInput): Promise<PermissionsGrant> {
8989
// throw an exception if the permission cannot be delegated
9090
if (!this.conditions.delegation) {
9191
throw new Error('this permission cannot be delegated');
9292
}
9393

9494
// `grantedBy` of the delegated permission will be `grantedTo` of the permission being delegated because the grantee is the delegator
9595
const delegatedGrant = await PermissionsGrant.create({
96-
conditions : this.conditions,
97-
description : this.description,
98-
grantedBy : this.grantedTo,
99-
grantedTo : to,
100-
scope : this.scope,
101-
signatureInput : signatureInput
96+
conditions : this.conditions,
97+
description : this.description,
98+
grantedBy : this.grantedTo,
99+
grantedTo : to,
100+
scope : this.scope,
101+
authorizationSignatureInput
102102
});
103103

104-
delegatedGrant.delegatedFrom = await generateCid(this.message);
104+
delegatedGrant.delegatedFrom = await computeCid(this.message);
105105
delegatedGrant.delegationChain = this.message;
106106

107107
return delegatedGrant;

src/interfaces/permissions/messages/permissions-request.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { AuthCreateOptions } from '../../../core/types.js';
1+
import type { SignatureInput } from '../../../jose/jws/general/types.js';
22
import type { PermissionConditions, PermissionScope } from '../types.js';
33
import type { PermissionsRequestDescriptor, PermissionsRequestMessage } from '../types.js';
44

@@ -7,14 +7,15 @@ import { v4 as uuidv4 } from 'uuid';
77
import { validateAuthorizationIntegrity } from '../../../core/auth.js';
88
import { DwnInterfaceName, DwnMethodName, Message } from '../../../core/message.js';
99

10-
type PermissionsRequestOptions = AuthCreateOptions & {
10+
type PermissionsRequestOptions = {
1111
dateCreated?: string;
1212
conditions?: PermissionConditions;
1313
description: string;
1414
grantedTo: string;
1515
grantedBy: string;
1616
objectId?: string;
1717
scope: PermissionScope;
18+
authorizationSignatureInput: SignatureInput;
1819
};
1920

2021
export class PermissionsRequest extends Message {
@@ -49,7 +50,7 @@ export class PermissionsRequest extends Message {
4950

5051
Message.validateJsonSchema({ descriptor, authorization: { } });
5152

52-
const auth = await Message.signAsAuthorization(descriptor, options.signatureInput);
53+
const auth = await Message.signAsAuthorization(descriptor, options.authorizationSignatureInput);
5354
const message: PermissionsRequestMessage = { descriptor, authorization: auth };
5455

5556
return new PermissionsRequest(message);

0 commit comments

Comments
 (0)