@enbox/dwn-sdk-js 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.mjs +3 -3
- package/dist/browser.mjs.map +3 -3
- package/dist/esm/generated/precompiled-validators.js +1065 -2160
- package/dist/esm/generated/precompiled-validators.js.map +1 -1
- package/dist/esm/src/core/grant-authorization.js +14 -1
- package/dist/esm/src/core/grant-authorization.js.map +1 -1
- package/dist/esm/src/types/permission-types.js.map +1 -1
- package/dist/esm/tests/core/grant-authorization.spec.js +82 -4
- package/dist/esm/tests/core/grant-authorization.spec.js.map +1 -1
- package/dist/esm/tests/core/records-grant-authorization.spec.js +22 -5
- package/dist/esm/tests/core/records-grant-authorization.spec.js.map +1 -1
- package/dist/esm/tests/features/author-delegated-grant.spec.js +134 -10
- package/dist/esm/tests/features/author-delegated-grant.spec.js.map +1 -1
- package/dist/esm/tests/features/permissions.spec.js +6 -6
- package/dist/esm/tests/features/permissions.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-count.spec.js +2 -2
- package/dist/esm/tests/handlers/records-count.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-query.spec.js +2 -2
- package/dist/esm/tests/handlers/records-query.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-read.spec.js +8 -2
- package/dist/esm/tests/handlers/records-read.spec.js.map +1 -1
- package/dist/esm/tests/handlers/records-subscribe.spec.js +2 -2
- package/dist/esm/tests/handlers/records-subscribe.spec.js.map +1 -1
- package/dist/esm/tests/protocols/permission-request.spec.js +4 -4
- package/dist/esm/tests/protocols/permission-request.spec.js.map +1 -1
- package/dist/esm/tests/protocols/permissions.spec.js +35 -2
- package/dist/esm/tests/protocols/permissions.spec.js.map +1 -1
- package/dist/types/generated/precompiled-validators.d.ts.map +1 -1
- package/dist/types/src/core/grant-authorization.d.ts +2 -1
- package/dist/types/src/core/grant-authorization.d.ts.map +1 -1
- package/dist/types/src/types/permission-types.d.ts +4 -1
- package/dist/types/src/types/permission-types.d.ts.map +1 -1
- package/dist/types/tests/features/author-delegated-grant.spec.d.ts.map +1 -1
- package/dist/types/tests/handlers/records-read.spec.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/core/grant-authorization.ts +18 -1
- package/src/types/permission-types.ts +4 -1
|
@@ -62,7 +62,8 @@ export class GrantAuthorization {
|
|
|
62
62
|
* Verify that the `interface` and `method` grant scopes match the incoming message.
|
|
63
63
|
*
|
|
64
64
|
* For the Messages interface, a `Read` scope is treated as a unified scope that also authorizes
|
|
65
|
-
* `Query
|
|
65
|
+
* `Query` and `Subscribe` operations. For Records, `Read` is likewise the canonical read-like
|
|
66
|
+
* scope and authorizes `Read`, `Query`, `Subscribe`, and `Count` operations.
|
|
66
67
|
*
|
|
67
68
|
* @throws {DwnError} if the `interface` and `method` of the incoming message do not match the scope of the permission grant.
|
|
68
69
|
*/
|
|
@@ -82,6 +83,18 @@ export class GrantAuthorization {
|
|
|
82
83
|
}
|
|
83
84
|
return;
|
|
84
85
|
}
|
|
86
|
+
// Records.Read is the only valid read-like Records scope and covers Read, Query,
|
|
87
|
+
// Subscribe, and Count operations. Reject malformed Records Query/Subscribe/Count
|
|
88
|
+
// grants instead of treating them as compatible with the canonical Read scope.
|
|
89
|
+
if (dwnInterface === DwnInterfaceName.Records) {
|
|
90
|
+
const readLikeMethods = [DwnMethodName.Read, DwnMethodName.Query, DwnMethodName.Subscribe, DwnMethodName.Count];
|
|
91
|
+
if (readLikeMethods.includes(dwnMethod)) {
|
|
92
|
+
if (permissionGrant.scope.method !== DwnMethodName.Read) {
|
|
93
|
+
throw new DwnError(DwnErrorCode.GrantAuthorizationMethodMismatch, `records read-like permission grant must have method 'Read', got '${permissionGrant.scope.method}' for grant ${permissionGrant.id}`);
|
|
94
|
+
}
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
85
98
|
if (dwnMethod !== permissionGrant.scope.method) {
|
|
86
99
|
throw new DwnError(DwnErrorCode.GrantAuthorizationMethodMismatch, `DWN Method of incoming message is outside the scope of permission grant with ID ${permissionGrant.id}`);
|
|
87
100
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grant-authorization.js","sourceRoot":"","sources":["../../../../src/core/grant-authorization.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AAEnF,MAAM,OAAO,kBAAkB;IAE7B;;;;;;;;;;OAUG;IACI,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,KAMvC;QACD,MAAM,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,eAAe,EAAE,qBAAqB,EAAE,GAAG,KAAK,CAAC;QAE5G,MAAM,yBAAyB,GAAG,eAAe,CAAC,UAAU,CAAC;QAE7D,kBAAkB,CAAC,+BAA+B,CAAC,eAAe,EAAE,eAAe,EAAE,eAAe,CAAC,CAAC;QAEtG,iEAAiE;QACjE,MAAM,UAAU,GAAG,eAAe,CAAC,CAAC,8EAA8E;QAClH,MAAM,kBAAkB,CAAC,iBAAiB,CACxC,UAAU,EACV,yBAAyB,CAAC,gBAAgB,EAC1C,eAAe,EACf,qBAAqB,CACtB,CAAC;QAEF,6CAA6C;QAC7C,MAAM,kBAAkB,CAAC,kCAAkC,CACzD,yBAAyB,CAAC,SAAS,EACnC,yBAAyB,CAAC,MAAM,EAChC,eAAe,CAChB,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACK,MAAM,CAAC,+BAA+B,CAC5C,eAAuB,EACvB,eAAuB,EACvB,eAAgC;QAGhC,MAAM,aAAa,GAAG,eAAe,CAAC,OAAO,CAAC;QAC9C,IAAI,eAAe,KAAK,aAAa,EAAE,CAAC;YACtC,MAAM,IAAI,QAAQ,CAChB,YAAY,CAAC,oCAAoC,EACjD,kCAAkC,aAAa,+BAA+B,eAAe,EAAE,CAChG,CAAC;QACJ,CAAC;QAED,MAAM,aAAa,GAAG,eAAe,CAAC,OAAO,CAAC;QAC9C,IAAI,eAAe,KAAK,aAAa,EAAE,CAAC;YACtC,MAAM,IAAI,QAAQ,CAChB,YAAY,CAAC,qCAAqC,EAClD,kCAAkC,aAAa,+BAA+B,eAAe,EAAE,CAChG,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACK,MAAM,CAAC,KAAK,CAAC,iBAAiB,CACpC,UAAkB,EAClB,wBAAgC,EAChC,eAAgC,EAChC,qBAA4C;QAE5C,8DAA8D;QAC9D,IAAI,wBAAwB,GAAG,eAAe,CAAC,WAAW,EAAE,CAAC;YAC3D,0BAA0B;YAC1B,MAAM,IAAI,QAAQ,CAChB,YAAY,CAAC,mCAAmC,EAChD,mFAAmF,CACpF,CAAC;QACJ,CAAC;QAED,IAAI,wBAAwB,IAAI,eAAe,CAAC,WAAW,EAAE,CAAC;YAC5D,oBAAoB;YACpB,MAAM,IAAI,QAAQ,CAChB,YAAY,CAAC,8BAA8B,EAC3C,+EAA+E,CAChF,CAAC;QACJ,CAAC;QAED,MAAM,oBAAoB,GAAG,MAAM,qBAAqB,CAAC,0BAA0B,CAAC,UAAU,EAAE,eAAe,CAAC,EAAE,CAAC,CAAC;QAEpH,IAAI,oBAAoB,KAAK,SAAS,IAAI,oBAAoB,CAAC,UAAU,CAAC,gBAAgB,IAAI,wBAAwB,EAAE,CAAC;YACvH,MAAM,IAAI,QAAQ,CAChB,YAAY,CAAC,8BAA8B,EAC3C,6BAA6B,eAAe,CAAC,EAAE,mBAAmB,CACnE,CAAC;QACJ,CAAC;IACH,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"grant-authorization.js","sourceRoot":"","sources":["../../../../src/core/grant-authorization.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"permission-types.js","sourceRoot":"","sources":["../../../../src/types/permission-types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"permission-types.js","sourceRoot":"","sources":["../../../../src/types/permission-types.ts"],"names":[],"mappings":"AAwHA,MAAM,CAAN,IAAY,8BAGX;AAHD,WAAY,8BAA8B;IACxC,uDAAqB,CAAA;IACrB,2DAAyB,CAAA;AAC3B,CAAC,EAHW,8BAA8B,KAA9B,8BAA8B,QAGzC"}
|
|
@@ -32,7 +32,59 @@ describe('GrantAuthorization', () => {
|
|
|
32
32
|
validationStateReader: validationStateReader,
|
|
33
33
|
})).rejects.toThrow(DwnErrorCode.GrantAuthorizationMethodMismatch);
|
|
34
34
|
});
|
|
35
|
-
it('
|
|
35
|
+
it('allows Records Read grants to authorize read-like record methods', async () => {
|
|
36
|
+
const mockGrant = {
|
|
37
|
+
id: 'grant-records-read',
|
|
38
|
+
grantor: 'did:example:grantor',
|
|
39
|
+
grantee: 'did:example:grantee',
|
|
40
|
+
dateGranted: '2020-01-01T00:00:00.000Z',
|
|
41
|
+
dateExpires: '2040-01-01T00:00:00.000Z',
|
|
42
|
+
scope: { interface: 'Records', method: 'Read', protocol: 'https://proto.example' },
|
|
43
|
+
};
|
|
44
|
+
for (const method of ['Read', 'Query', 'Subscribe', 'Count']) {
|
|
45
|
+
const mockMessage = {
|
|
46
|
+
descriptor: {
|
|
47
|
+
interface: 'Records',
|
|
48
|
+
method,
|
|
49
|
+
messageTimestamp: '2025-01-01T00:00:00.000Z',
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
await expect(GrantAuthorization.performBaseValidation({
|
|
53
|
+
incomingMessage: mockMessage,
|
|
54
|
+
expectedGrantor: 'did:example:grantor',
|
|
55
|
+
expectedGrantee: 'did:example:grantee',
|
|
56
|
+
permissionGrant: mockGrant,
|
|
57
|
+
validationStateReader: validationStateReader,
|
|
58
|
+
})).resolves.toBeUndefined();
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
it('rejects Records Write grants for read-like record methods', async () => {
|
|
62
|
+
const mockGrant = {
|
|
63
|
+
id: 'grant-records-write',
|
|
64
|
+
grantor: 'did:example:grantor',
|
|
65
|
+
grantee: 'did:example:grantee',
|
|
66
|
+
dateGranted: '2020-01-01T00:00:00.000Z',
|
|
67
|
+
dateExpires: '2040-01-01T00:00:00.000Z',
|
|
68
|
+
scope: { interface: 'Records', method: 'Write', protocol: 'https://proto.example' },
|
|
69
|
+
};
|
|
70
|
+
for (const method of ['Read', 'Query', 'Subscribe', 'Count']) {
|
|
71
|
+
const mockMessage = {
|
|
72
|
+
descriptor: {
|
|
73
|
+
interface: 'Records',
|
|
74
|
+
method,
|
|
75
|
+
messageTimestamp: '2025-01-01T00:00:00.000Z',
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
await expect(GrantAuthorization.performBaseValidation({
|
|
79
|
+
incomingMessage: mockMessage,
|
|
80
|
+
expectedGrantor: 'did:example:grantor',
|
|
81
|
+
expectedGrantee: 'did:example:grantee',
|
|
82
|
+
permissionGrant: mockGrant,
|
|
83
|
+
validationStateReader: validationStateReader,
|
|
84
|
+
})).rejects.toThrow(DwnErrorCode.GrantAuthorizationMethodMismatch);
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
it('rejects grants scoped to a different DWN interface', async () => {
|
|
36
88
|
const mockGrant = {
|
|
37
89
|
id: 'grant-records-read',
|
|
38
90
|
grantor: 'did:example:grantor',
|
|
@@ -43,8 +95,8 @@ describe('GrantAuthorization', () => {
|
|
|
43
95
|
};
|
|
44
96
|
const mockMessage = {
|
|
45
97
|
descriptor: {
|
|
46
|
-
interface: '
|
|
47
|
-
method: '
|
|
98
|
+
interface: 'Messages',
|
|
99
|
+
method: 'Read',
|
|
48
100
|
messageTimestamp: '2025-01-01T00:00:00.000Z',
|
|
49
101
|
},
|
|
50
102
|
};
|
|
@@ -54,7 +106,33 @@ describe('GrantAuthorization', () => {
|
|
|
54
106
|
expectedGrantee: 'did:example:grantee',
|
|
55
107
|
permissionGrant: mockGrant,
|
|
56
108
|
validationStateReader: validationStateReader,
|
|
57
|
-
})).rejects.toThrow(DwnErrorCode.
|
|
109
|
+
})).rejects.toThrow(DwnErrorCode.GrantAuthorizationInterfaceMismatch);
|
|
110
|
+
});
|
|
111
|
+
it('rejects read-like Records grants that do not use method Read', async () => {
|
|
112
|
+
for (const method of ['Query', 'Subscribe', 'Count']) {
|
|
113
|
+
const mockGrant = {
|
|
114
|
+
id: `grant-records-${method.toLowerCase()}`,
|
|
115
|
+
grantor: 'did:example:grantor',
|
|
116
|
+
grantee: 'did:example:grantee',
|
|
117
|
+
dateGranted: '2020-01-01T00:00:00.000Z',
|
|
118
|
+
dateExpires: '2040-01-01T00:00:00.000Z',
|
|
119
|
+
scope: { interface: 'Records', method, protocol: 'https://proto.example' },
|
|
120
|
+
};
|
|
121
|
+
const mockMessage = {
|
|
122
|
+
descriptor: {
|
|
123
|
+
interface: 'Records',
|
|
124
|
+
method,
|
|
125
|
+
messageTimestamp: '2025-01-01T00:00:00.000Z',
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
await expect(GrantAuthorization.performBaseValidation({
|
|
129
|
+
incomingMessage: mockMessage,
|
|
130
|
+
expectedGrantor: 'did:example:grantor',
|
|
131
|
+
expectedGrantee: 'did:example:grantee',
|
|
132
|
+
permissionGrant: mockGrant,
|
|
133
|
+
validationStateReader: validationStateReader,
|
|
134
|
+
})).rejects.toThrow(DwnErrorCode.GrantAuthorizationMethodMismatch);
|
|
135
|
+
}
|
|
58
136
|
});
|
|
59
137
|
});
|
|
60
138
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"grant-authorization.spec.js","sourceRoot":"","sources":["../../../../tests/core/grant-authorization.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAE3E,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAClD,MAAM,qBAAqB,GAAG;YAC5B,0BAA0B,EAAE,KAAK,IAAkB,EAAE,CAAC,SAAS;SAChE,CAAC;QAEF,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;YACjE,iEAAiE;YACjE,sCAAsC;YACtC,MAAM,SAAS,GAAG;gBAChB,EAAE,EAAY,iBAAiB;gBAC/B,OAAO,EAAO,qBAAqB;gBACnC,OAAO,EAAO,qBAAqB;gBACnC,WAAW,EAAG,0BAA0B;gBACxC,WAAW,EAAG,0BAA0B;gBACxC,KAAK,EAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,uBAAuB,EAAE;aAC3F,CAAC;YAEF,MAAM,WAAW,GAAG;gBAClB,UAAU,EAAE;oBACV,SAAS,EAAU,UAAU;oBAC7B,MAAM,EAAa,MAAM;oBACzB,gBAAgB,EAAG,0BAA0B;iBAC9C;aACF,CAAC;YAEF,MAAM,MAAM,CACV,kBAAkB,CAAC,qBAAqB,CAAC;gBACvC,eAAe,EAAS,WAAkB;gBAC1C,eAAe,EAAS,qBAAqB;gBAC7C,eAAe,EAAS,qBAAqB;gBAC7C,eAAe,EAAS,SAAgB;gBACxC,qBAAqB,EAAG,qBAA4B;aACrD,CAAC,CACH,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,gCAAgC,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"grant-authorization.spec.js","sourceRoot":"","sources":["../../../../tests/core/grant-authorization.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAE3E,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,QAAQ,CAAC,oCAAoC,EAAE,GAAG,EAAE;QAClD,MAAM,qBAAqB,GAAG;YAC5B,0BAA0B,EAAE,KAAK,IAAkB,EAAE,CAAC,SAAS;SAChE,CAAC;QAEF,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;YACjE,iEAAiE;YACjE,sCAAsC;YACtC,MAAM,SAAS,GAAG;gBAChB,EAAE,EAAY,iBAAiB;gBAC/B,OAAO,EAAO,qBAAqB;gBACnC,OAAO,EAAO,qBAAqB;gBACnC,WAAW,EAAG,0BAA0B;gBACxC,WAAW,EAAG,0BAA0B;gBACxC,KAAK,EAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,uBAAuB,EAAE;aAC3F,CAAC;YAEF,MAAM,WAAW,GAAG;gBAClB,UAAU,EAAE;oBACV,SAAS,EAAU,UAAU;oBAC7B,MAAM,EAAa,MAAM;oBACzB,gBAAgB,EAAG,0BAA0B;iBAC9C;aACF,CAAC;YAEF,MAAM,MAAM,CACV,kBAAkB,CAAC,qBAAqB,CAAC;gBACvC,eAAe,EAAS,WAAkB;gBAC1C,eAAe,EAAS,qBAAqB;gBAC7C,eAAe,EAAS,qBAAqB;gBAC7C,eAAe,EAAS,SAAgB;gBACxC,qBAAqB,EAAG,qBAA4B;aACrD,CAAC,CACH,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,gCAAgC,CAAC,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kEAAkE,EAAE,KAAK,IAAI,EAAE;YAChF,MAAM,SAAS,GAAG;gBAChB,EAAE,EAAY,oBAAoB;gBAClC,OAAO,EAAO,qBAAqB;gBACnC,OAAO,EAAO,qBAAqB;gBACnC,WAAW,EAAG,0BAA0B;gBACxC,WAAW,EAAG,0BAA0B;gBACxC,KAAK,EAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,uBAAuB,EAAE;aAC1F,CAAC;YAEF,KAAK,MAAM,MAAM,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC;gBAC7D,MAAM,WAAW,GAAG;oBAClB,UAAU,EAAE;wBACV,SAAS,EAAU,SAAS;wBAC5B,MAAM;wBACN,gBAAgB,EAAG,0BAA0B;qBAC9C;iBACF,CAAC;gBAEF,MAAM,MAAM,CACV,kBAAkB,CAAC,qBAAqB,CAAC;oBACvC,eAAe,EAAS,WAAkB;oBAC1C,eAAe,EAAS,qBAAqB;oBAC7C,eAAe,EAAS,qBAAqB;oBAC7C,eAAe,EAAS,SAAgB;oBACxC,qBAAqB,EAAG,qBAA4B;iBACrD,CAAC,CACH,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC;YAC7B,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;YACzE,MAAM,SAAS,GAAG;gBAChB,EAAE,EAAY,qBAAqB;gBACnC,OAAO,EAAO,qBAAqB;gBACnC,OAAO,EAAO,qBAAqB;gBACnC,WAAW,EAAG,0BAA0B;gBACxC,WAAW,EAAG,0BAA0B;gBACxC,KAAK,EAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,uBAAuB,EAAE;aAC3F,CAAC;YAEF,KAAK,MAAM,MAAM,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC;gBAC7D,MAAM,WAAW,GAAG;oBAClB,UAAU,EAAE;wBACV,SAAS,EAAU,SAAS;wBAC5B,MAAM;wBACN,gBAAgB,EAAG,0BAA0B;qBAC9C;iBACF,CAAC;gBAEF,MAAM,MAAM,CACV,kBAAkB,CAAC,qBAAqB,CAAC;oBACvC,eAAe,EAAS,WAAkB;oBAC1C,eAAe,EAAS,qBAAqB;oBAC7C,eAAe,EAAS,qBAAqB;oBAC7C,eAAe,EAAS,SAAgB;oBACxC,qBAAqB,EAAG,qBAA4B;iBACrD,CAAC,CACH,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,gCAAgC,CAAC,CAAC;YACnE,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,oDAAoD,EAAE,KAAK,IAAI,EAAE;YAClE,MAAM,SAAS,GAAG;gBAChB,EAAE,EAAY,oBAAoB;gBAClC,OAAO,EAAO,qBAAqB;gBACnC,OAAO,EAAO,qBAAqB;gBACnC,WAAW,EAAG,0BAA0B;gBACxC,WAAW,EAAG,0BAA0B;gBACxC,KAAK,EAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,uBAAuB,EAAE;aAC1F,CAAC;YAEF,MAAM,WAAW,GAAG;gBAClB,UAAU,EAAE;oBACV,SAAS,EAAU,UAAU;oBAC7B,MAAM,EAAa,MAAM;oBACzB,gBAAgB,EAAG,0BAA0B;iBAC9C;aACF,CAAC;YAEF,MAAM,MAAM,CACV,kBAAkB,CAAC,qBAAqB,CAAC;gBACvC,eAAe,EAAS,WAAkB;gBAC1C,eAAe,EAAS,qBAAqB;gBAC7C,eAAe,EAAS,qBAAqB;gBAC7C,eAAe,EAAS,SAAgB;gBACxC,qBAAqB,EAAG,qBAA4B;aACrD,CAAC,CACH,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,mCAAmC,CAAC,CAAC;QACtE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;YAC5E,KAAK,MAAM,MAAM,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC;gBACrD,MAAM,SAAS,GAAG;oBAChB,EAAE,EAAY,iBAAiB,MAAM,CAAC,WAAW,EAAE,EAAE;oBACrD,OAAO,EAAO,qBAAqB;oBACnC,OAAO,EAAO,qBAAqB;oBACnC,WAAW,EAAG,0BAA0B;oBACxC,WAAW,EAAG,0BAA0B;oBACxC,KAAK,EAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,uBAAuB,EAAE;iBAClF,CAAC;gBAEF,MAAM,WAAW,GAAG;oBAClB,UAAU,EAAE;wBACV,SAAS,EAAU,SAAS;wBAC5B,MAAM;wBACN,gBAAgB,EAAG,0BAA0B;qBAC9C;iBACF,CAAC;gBAEF,MAAM,MAAM,CACV,kBAAkB,CAAC,qBAAqB,CAAC;oBACvC,eAAe,EAAS,WAAkB;oBAC1C,eAAe,EAAS,qBAAqB;oBAC7C,eAAe,EAAS,qBAAqB;oBAC7C,eAAe,EAAS,SAAgB;oBACxC,qBAAqB,EAAG,qBAA4B;iBACrD,CAAC,CACH,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,gCAAgC,CAAC,CAAC;YACnE,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -57,7 +57,7 @@ describe('RecordsGrantAuthorization', () => {
|
|
|
57
57
|
incomingMessage: makeIncomingMessage(method, filter),
|
|
58
58
|
expectedGrantor: grantor,
|
|
59
59
|
expectedGrantee: grantee,
|
|
60
|
-
permissionGrant: makePermissionGrant(
|
|
60
|
+
permissionGrant: makePermissionGrant(DwnMethodName.Read, grantScope),
|
|
61
61
|
validationStateReader,
|
|
62
62
|
})).rejects.toThrow(DwnErrorCode.RecordsGrantAuthorizationQueryOrSubscribeProtocolScopeMismatch);
|
|
63
63
|
}
|
|
@@ -90,7 +90,7 @@ describe('RecordsGrantAuthorization', () => {
|
|
|
90
90
|
}),
|
|
91
91
|
expectedGrantor: grantor,
|
|
92
92
|
expectedGrantee: grantee,
|
|
93
|
-
permissionGrant: makePermissionGrant(DwnMethodName.
|
|
93
|
+
permissionGrant: makePermissionGrant(DwnMethodName.Read, {
|
|
94
94
|
protocol,
|
|
95
95
|
protocolPath: 'thread/message',
|
|
96
96
|
}),
|
|
@@ -101,17 +101,34 @@ describe('RecordsGrantAuthorization', () => {
|
|
|
101
101
|
await expectQueryOrSubscribeScopeMismatch(DwnMethodName.Query, { protocol, protocolPath: 'thread/message' }, { protocol, protocolPath: 'thread/reaction' });
|
|
102
102
|
await expectQueryOrSubscribeScopeMismatch(DwnMethodName.Subscribe, { protocol, contextId: 'root' }, { protocol, contextId: 'rootEVIL' });
|
|
103
103
|
});
|
|
104
|
-
it('allows protocol-scoped query and count filters', async () => {
|
|
105
|
-
for (const method of [DwnMethodName.Query, DwnMethodName.Count]) {
|
|
104
|
+
it('allows protocol-scoped query, subscribe, and count filters with a Records.Read grant', async () => {
|
|
105
|
+
for (const method of [DwnMethodName.Query, DwnMethodName.Subscribe, DwnMethodName.Count]) {
|
|
106
106
|
await expect(RecordsGrantAuthorization.authorizeQueryOrSubscribe({
|
|
107
107
|
incomingMessage: makeIncomingMessage(method, { protocol }),
|
|
108
108
|
expectedGrantor: grantor,
|
|
109
109
|
expectedGrantee: grantee,
|
|
110
|
-
permissionGrant: makePermissionGrant(
|
|
110
|
+
permissionGrant: makePermissionGrant(DwnMethodName.Read, { protocol }),
|
|
111
111
|
validationStateReader,
|
|
112
112
|
})).resolves.toBeUndefined();
|
|
113
113
|
}
|
|
114
114
|
});
|
|
115
|
+
it('rejects read-like Records grants that do not use method Read', async () => {
|
|
116
|
+
const cases = [
|
|
117
|
+
[DwnMethodName.Query, DwnMethodName.Query],
|
|
118
|
+
[DwnMethodName.Subscribe, DwnMethodName.Subscribe],
|
|
119
|
+
[DwnMethodName.Count, DwnMethodName.Count],
|
|
120
|
+
[DwnMethodName.Write, DwnMethodName.Query],
|
|
121
|
+
];
|
|
122
|
+
for (const [grantMethod, incomingMethod] of cases) {
|
|
123
|
+
await expect(RecordsGrantAuthorization.authorizeQueryOrSubscribe({
|
|
124
|
+
incomingMessage: makeIncomingMessage(incomingMethod, { protocol }),
|
|
125
|
+
expectedGrantor: grantor,
|
|
126
|
+
expectedGrantee: grantee,
|
|
127
|
+
permissionGrant: makePermissionGrant(grantMethod, { protocol }),
|
|
128
|
+
validationStateReader,
|
|
129
|
+
})).rejects.toThrow(DwnErrorCode.GrantAuthorizationMethodMismatch);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
115
132
|
});
|
|
116
133
|
});
|
|
117
134
|
//# sourceMappingURL=records-grant-authorization.spec.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"records-grant-authorization.spec.js","sourceRoot":"","sources":["../../../../tests/core/records-grant-authorization.spec.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,UAAU,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,yBAAyB,EAAE,MAAM,+CAA+C,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAE1F,QAAQ,CAAC,2BAA2B,EAAE,GAAG,EAAE;IACzC,MAAM,OAAO,GAAG,mBAAmB,CAAC;IACpC,MAAM,OAAO,GAAG,iBAAiB,CAAC;IAClC,MAAM,QAAQ,GAAG,8BAA8B,CAAC;IAChD,MAAM,SAAS,GAAG,6BAA6B,CAAC;IAChD,MAAM,qBAAqB,GAAG;QAC5B,0BAA0B,EAAE,KAAK,IAAI,EAAE,CAAC,SAAS;KACd,CAAC;IAEtC,SAAS,gBAAgB,CAAC,SAAiB;QACzC,MAAM,iBAAiB,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/C,OAAO;YACL,QAAQ,EAAK,iBAAiB,CAAC,iBAAiB,CAAC,MAAM,GAAG,CAAC,CAAC,IAAI,SAAS;YACzE,SAAS;YACT,UAAU,EAAG;gBACX,SAAS,EAAU,gBAAgB,CAAC,OAAO;gBAC3C,MAAM,EAAa,aAAa,CAAC,KAAK;gBACtC,QAAQ,EAAW,8BAA8B;gBACjD,YAAY,EAAO,gBAAgB;gBACnC,UAAU,EAAS,kBAAkB;gBACrC,OAAO,EAAY,mBAAmB;gBACtC,QAAQ,EAAW,CAAC;gBACpB,WAAW,EAAQ,6BAA6B;gBAChD,gBAAgB,EAAG,6BAA6B;aACjD;SACqB,CAAC;IAC3B,CAAC;IAED,SAAS,mBAAmB,CAC1B,
|
|
1
|
+
{"version":3,"file":"records-grant-authorization.spec.js","sourceRoot":"","sources":["../../../../tests/core/records-grant-authorization.spec.ts"],"names":[],"mappings":"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"}
|
|
@@ -356,14 +356,14 @@ export function testAuthorDelegatedGrant() {
|
|
|
356
356
|
});
|
|
357
357
|
const chatRecordReply = await dwn.processMessage(bob.did, chatRecord.message, { dataStream: chatRecord.dataStream });
|
|
358
358
|
expect(chatRecordReply.status.code).toBe(202);
|
|
359
|
-
// Alice creates a delegated
|
|
359
|
+
// Alice creates a delegated read grant for device X to perform read-like operations as Alice.
|
|
360
360
|
const queryGrantForDeviceX = await PermissionsProtocol.createGrant({
|
|
361
361
|
delegated: true, // this is a delegated grant
|
|
362
362
|
dateExpires: Time.createOffsetTimestamp({ seconds: 100 }),
|
|
363
363
|
grantedTo: deviceX.did,
|
|
364
364
|
scope: {
|
|
365
365
|
interface: DwnInterfaceName.Records,
|
|
366
|
-
method: DwnMethodName.
|
|
366
|
+
method: DwnMethodName.Read,
|
|
367
367
|
protocol
|
|
368
368
|
},
|
|
369
369
|
signer: Jws.createSigner(alice)
|
|
@@ -454,6 +454,130 @@ export function testAuthorDelegatedGrant() {
|
|
|
454
454
|
expect(recordsReadByCarolReply.status.code).toBe(400);
|
|
455
455
|
expect(recordsQueryByCarolReply.status.detail).toContain(DwnErrorCode.RecordsAuthorDelegatedGrantGrantedToAndOwnerSignatureMismatch);
|
|
456
456
|
});
|
|
457
|
+
it('should scope author-delegated read-like grants to the matching context subtree', async () => {
|
|
458
|
+
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
459
|
+
const deviceX = await TestDataGenerator.generateDidKeyPersona();
|
|
460
|
+
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
461
|
+
const protocolDefinition = threadRoleProtocolDefinition;
|
|
462
|
+
const protocol = threadRoleProtocolDefinition.protocol;
|
|
463
|
+
const protocolsConfig = await TestDataGenerator.generateProtocolsConfigure({
|
|
464
|
+
author: bob,
|
|
465
|
+
protocolDefinition
|
|
466
|
+
});
|
|
467
|
+
const protocolsConfigureReply = await dwn.processMessage(bob.did, protocolsConfig.message);
|
|
468
|
+
expect(protocolsConfigureReply.status.code).toBe(202);
|
|
469
|
+
const threadRecord = await TestDataGenerator.generateRecordsWrite({
|
|
470
|
+
author: bob,
|
|
471
|
+
protocol: protocolDefinition.protocol,
|
|
472
|
+
protocolPath: 'thread',
|
|
473
|
+
});
|
|
474
|
+
const threadRoleReply = await dwn.processMessage(bob.did, threadRecord.message, { dataStream: threadRecord.dataStream });
|
|
475
|
+
expect(threadRoleReply.status.code).toBe(202);
|
|
476
|
+
const participantRoleRecord = await TestDataGenerator.generateRecordsWrite({
|
|
477
|
+
author: bob,
|
|
478
|
+
recipient: alice.did,
|
|
479
|
+
protocol: protocolDefinition.protocol,
|
|
480
|
+
protocolPath: 'thread/participant',
|
|
481
|
+
parentContextId: threadRecord.message.contextId,
|
|
482
|
+
data: new TextEncoder().encode('Alice is my friend'),
|
|
483
|
+
});
|
|
484
|
+
const participantRoleReply = await dwn.processMessage(bob.did, participantRoleRecord.message, { dataStream: participantRoleRecord.dataStream });
|
|
485
|
+
expect(participantRoleReply.status.code).toBe(202);
|
|
486
|
+
const chatRecord = await TestDataGenerator.generateRecordsWrite({
|
|
487
|
+
author: bob,
|
|
488
|
+
protocol: protocolDefinition.protocol,
|
|
489
|
+
protocolPath: 'thread/chat',
|
|
490
|
+
parentContextId: threadRecord.message.contextId,
|
|
491
|
+
});
|
|
492
|
+
const chatRecordReply = await dwn.processMessage(bob.did, chatRecord.message, { dataStream: chatRecord.dataStream });
|
|
493
|
+
expect(chatRecordReply.status.code).toBe(202);
|
|
494
|
+
const contextScopedReadGrant = await PermissionsProtocol.createGrant({
|
|
495
|
+
delegated: true,
|
|
496
|
+
dateExpires: Time.createOffsetTimestamp({ seconds: 100 }),
|
|
497
|
+
grantedTo: deviceX.did,
|
|
498
|
+
scope: {
|
|
499
|
+
interface: DwnInterfaceName.Records,
|
|
500
|
+
method: DwnMethodName.Read,
|
|
501
|
+
protocol,
|
|
502
|
+
contextId: threadRecord.message.contextId,
|
|
503
|
+
},
|
|
504
|
+
signer: Jws.createSigner(alice)
|
|
505
|
+
});
|
|
506
|
+
const matchingQuery = await RecordsQuery.create({
|
|
507
|
+
signer: Jws.createSigner(deviceX),
|
|
508
|
+
delegatedGrant: contextScopedReadGrant.dataEncodedMessage,
|
|
509
|
+
protocolRole: 'thread/participant',
|
|
510
|
+
filter: {
|
|
511
|
+
protocol,
|
|
512
|
+
contextId: threadRecord.message.contextId,
|
|
513
|
+
protocolPath: 'thread/chat'
|
|
514
|
+
}
|
|
515
|
+
});
|
|
516
|
+
const matchingQueryReply = await dwn.processMessage(bob.did, matchingQuery.message);
|
|
517
|
+
expect(matchingQueryReply.status.code).toBe(200);
|
|
518
|
+
expect(matchingQueryReply.entries?.map(entry => entry.recordId)).toEqual([chatRecord.message.recordId]);
|
|
519
|
+
const mismatchingContextId = `${threadRecord.message.contextId}EVIL`;
|
|
520
|
+
const mismatchingQuery = await RecordsQuery.create({
|
|
521
|
+
signer: Jws.createSigner(deviceX),
|
|
522
|
+
delegatedGrant: contextScopedReadGrant.dataEncodedMessage,
|
|
523
|
+
protocolRole: 'thread/participant',
|
|
524
|
+
filter: {
|
|
525
|
+
protocol,
|
|
526
|
+
contextId: mismatchingContextId,
|
|
527
|
+
protocolPath: 'thread/chat'
|
|
528
|
+
}
|
|
529
|
+
});
|
|
530
|
+
const mismatchingQueryReply = await dwn.processMessage(bob.did, mismatchingQuery.message);
|
|
531
|
+
expect(mismatchingQueryReply.status.code).toBe(401);
|
|
532
|
+
expect(mismatchingQueryReply.status.detail).toContain(DwnErrorCode.RecordsGrantAuthorizationQueryOrSubscribeProtocolScopeMismatch);
|
|
533
|
+
const mismatchingSubscribe = await RecordsSubscribe.create({
|
|
534
|
+
signer: Jws.createSigner(deviceX),
|
|
535
|
+
delegatedGrant: contextScopedReadGrant.dataEncodedMessage,
|
|
536
|
+
protocolRole: 'thread/participant',
|
|
537
|
+
filter: {
|
|
538
|
+
protocol,
|
|
539
|
+
contextId: mismatchingContextId,
|
|
540
|
+
protocolPath: 'thread/chat'
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
const mismatchingSubscribeReply = await dwn.processMessage(bob.did, mismatchingSubscribe.message);
|
|
544
|
+
expect(mismatchingSubscribeReply.status.code).toBe(401);
|
|
545
|
+
expect(mismatchingSubscribeReply.status.detail).toContain(DwnErrorCode.RecordsGrantAuthorizationQueryOrSubscribeProtocolScopeMismatch);
|
|
546
|
+
const subscriptionChatRecords = new Set();
|
|
547
|
+
const captureChatRecords = async (msg) => {
|
|
548
|
+
if (msg.type !== 'event') {
|
|
549
|
+
return;
|
|
550
|
+
}
|
|
551
|
+
const recordId = msg.event.message.recordId;
|
|
552
|
+
subscriptionChatRecords.add(recordId);
|
|
553
|
+
};
|
|
554
|
+
const matchingSubscribe = await RecordsSubscribe.create({
|
|
555
|
+
signer: Jws.createSigner(deviceX),
|
|
556
|
+
delegatedGrant: contextScopedReadGrant.dataEncodedMessage,
|
|
557
|
+
protocolRole: 'thread/participant',
|
|
558
|
+
filter: {
|
|
559
|
+
protocol,
|
|
560
|
+
contextId: threadRecord.message.contextId,
|
|
561
|
+
protocolPath: 'thread/chat'
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
const matchingSubscribeReply = await dwn.processMessage(bob.did, matchingSubscribe.message, {
|
|
565
|
+
subscriptionHandler: captureChatRecords
|
|
566
|
+
});
|
|
567
|
+
expect(matchingSubscribeReply.status.code).toBe(200);
|
|
568
|
+
const subscribedChatRecord = await TestDataGenerator.generateRecordsWrite({
|
|
569
|
+
author: bob,
|
|
570
|
+
protocol: protocolDefinition.protocol,
|
|
571
|
+
protocolPath: 'thread/chat',
|
|
572
|
+
parentContextId: threadRecord.message.contextId,
|
|
573
|
+
});
|
|
574
|
+
const subscribedChatRecordReply = await dwn.processMessage(bob.did, subscribedChatRecord.message, { dataStream: subscribedChatRecord.dataStream });
|
|
575
|
+
expect(subscribedChatRecordReply.status.code).toBe(202);
|
|
576
|
+
await Poller.pollUntilSuccessOrTimeout(async () => {
|
|
577
|
+
expect(subscriptionChatRecords.has(subscribedChatRecord.message.recordId)).toBe(true);
|
|
578
|
+
});
|
|
579
|
+
await matchingSubscribeReply.subscription?.close();
|
|
580
|
+
});
|
|
457
581
|
it('should only allow correct entity invoking an author-delegated grant to subscribe', async () => {
|
|
458
582
|
// scenario:
|
|
459
583
|
// 1. Bob installs a chat protocol and creates a thread, adding Alice as a participant.
|
|
@@ -496,14 +620,14 @@ export function testAuthorDelegatedGrant() {
|
|
|
496
620
|
});
|
|
497
621
|
const participantRoleReply = await dwn.processMessage(bob.did, participantRoleRecord.message, { dataStream: participantRoleRecord.dataStream });
|
|
498
622
|
expect(participantRoleReply.status.code).toBe(202);
|
|
499
|
-
// Alice creates a delegated
|
|
623
|
+
// Alice creates a delegated read grant for device X to subscribe as Alice.
|
|
500
624
|
const subscribeGrantForDeviceX = await PermissionsProtocol.createGrant({
|
|
501
625
|
delegated: true, // this is a delegated grant
|
|
502
626
|
dateExpires: Time.createOffsetTimestamp({ seconds: 100 }),
|
|
503
627
|
grantedTo: deviceX.did,
|
|
504
628
|
scope: {
|
|
505
629
|
interface: DwnInterfaceName.Records,
|
|
506
|
-
method: DwnMethodName.
|
|
630
|
+
method: DwnMethodName.Read,
|
|
507
631
|
protocol
|
|
508
632
|
},
|
|
509
633
|
signer: Jws.createSigner(alice)
|
|
@@ -803,7 +927,7 @@ export function testAuthorDelegatedGrant() {
|
|
|
803
927
|
it('should not allow entity using a non-delegated grant as an author-delegated grant to invoke query', async () => {
|
|
804
928
|
// scenario:
|
|
805
929
|
// 1. Bob has the message protocol installed
|
|
806
|
-
// 2. Alice creates a non-delegated
|
|
930
|
+
// 2. Alice creates a non-delegated read grant for device X
|
|
807
931
|
// 3. Verify that device X cannot query Bob's DWN as Alice using the non-delegated grant
|
|
808
932
|
const alice = await TestDataGenerator.generateDidKeyPersona();
|
|
809
933
|
const bob = await TestDataGenerator.generateDidKeyPersona();
|
|
@@ -824,7 +948,7 @@ export function testAuthorDelegatedGrant() {
|
|
|
824
948
|
grantedTo: deviceX.did,
|
|
825
949
|
scope: {
|
|
826
950
|
interface: DwnInterfaceName.Records,
|
|
827
|
-
method: DwnMethodName.
|
|
951
|
+
method: DwnMethodName.Read,
|
|
828
952
|
protocol
|
|
829
953
|
},
|
|
830
954
|
signer: Jws.createSigner(alice)
|
|
@@ -995,14 +1119,14 @@ export function testAuthorDelegatedGrant() {
|
|
|
995
1119
|
const chatRecordReply = await dwn.processMessage(bob.did, chatRecord.message, { dataStream: chatRecord.dataStream });
|
|
996
1120
|
expect(chatRecordReply.status.code).toBe(202);
|
|
997
1121
|
// 2. Alice creates a delegated grant for device X to act as her for a protocol that is NOT chat protocol
|
|
998
|
-
// Alice creates a delegated
|
|
1122
|
+
// Alice creates a delegated read grant for device X to query as Alice but not for chat protocol
|
|
999
1123
|
const queryGrantForDeviceX = await PermissionsProtocol.createGrant({
|
|
1000
1124
|
delegated: true, // this is a delegated grant
|
|
1001
1125
|
dateExpires: Time.createOffsetTimestamp({ seconds: 100 }),
|
|
1002
1126
|
grantedTo: deviceX.did,
|
|
1003
1127
|
scope: {
|
|
1004
1128
|
interface: DwnInterfaceName.Records,
|
|
1005
|
-
method: DwnMethodName.
|
|
1129
|
+
method: DwnMethodName.Read,
|
|
1006
1130
|
protocol: 'some-other-protocol'
|
|
1007
1131
|
},
|
|
1008
1132
|
signer: Jws.createSigner(alice)
|
|
@@ -1019,14 +1143,14 @@ export function testAuthorDelegatedGrant() {
|
|
|
1019
1143
|
},
|
|
1020
1144
|
signer: Jws.createSigner(alice)
|
|
1021
1145
|
});
|
|
1022
|
-
// Alice creates a delegated
|
|
1146
|
+
// Alice creates a delegated read grant for device X to subscribe as Alice but not for chat protocol
|
|
1023
1147
|
const subscribeGrantForDeviceX = await PermissionsProtocol.createGrant({
|
|
1024
1148
|
delegated: true, // this is a delegated grant
|
|
1025
1149
|
dateExpires: Time.createOffsetTimestamp({ seconds: 100 }),
|
|
1026
1150
|
grantedTo: deviceX.did,
|
|
1027
1151
|
scope: {
|
|
1028
1152
|
interface: DwnInterfaceName.Records,
|
|
1029
|
-
method: DwnMethodName.
|
|
1153
|
+
method: DwnMethodName.Read,
|
|
1030
1154
|
protocol: 'some-other-protocol'
|
|
1031
1155
|
},
|
|
1032
1156
|
signer: Jws.createSigner(alice)
|