@bedrock/vc-verifier 9.0.0 → 12.0.0
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/README.md +4 -4
- package/lib/challenges.js +1 -3
- package/lib/documentLoader.js +8 -8
- package/lib/http.js +8 -12
- package/lib/index.js +1 -1
- package/lib/status.js +8 -10
- package/package.json +28 -23
- package/.eslintrc.cjs +0 -12
- package/.github/workflows/main.yml +0 -77
- package/CHANGELOG.md +0 -162
- package/test/mocha/.eslintrc.cjs +0 -9
- package/test/mocha/10-provision.js +0 -868
- package/test/mocha/20-verify.js +0 -390
- package/test/mocha/30-credential-status.js +0 -488
- package/test/mocha/cert.pem +0 -18
- package/test/mocha/helpers.js +0 -230
- package/test/mocha/key.pem +0 -28
- package/test/mocha/mock-credential.json +0 -39
- package/test/mocha/mock.data.js +0 -21
- package/test/package.json +0 -72
- package/test/test.config.js +0 -40
- package/test/test.js +0 -40
|
@@ -1,868 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) 2019-2022 Digital Bazaar, Inc. All rights reserved.
|
|
3
|
-
*/
|
|
4
|
-
import * as bedrock from '@bedrock/core';
|
|
5
|
-
import * as helpers from './helpers.js';
|
|
6
|
-
import {agent} from '@bedrock/https-agent';
|
|
7
|
-
import {createContextDocumentLoader} from '@bedrock/service-context-store';
|
|
8
|
-
import {createRequire} from 'node:module';
|
|
9
|
-
import {documentStores} from '@bedrock/service-agent';
|
|
10
|
-
import {httpClient} from '@digitalbazaar/http-client';
|
|
11
|
-
import {mockData} from './mock.data.js';
|
|
12
|
-
const require = createRequire(import.meta.url);
|
|
13
|
-
const {CapabilityAgent} = require('@digitalbazaar/webkms-client');
|
|
14
|
-
|
|
15
|
-
const {baseUrl} = mockData;
|
|
16
|
-
const serviceType = 'vc-verifier';
|
|
17
|
-
|
|
18
|
-
describe('provision API', () => {
|
|
19
|
-
let capabilityAgent;
|
|
20
|
-
const zcaps = {};
|
|
21
|
-
beforeEach(async () => {
|
|
22
|
-
const secret = '53ad64ce-8e1d-11ec-bb12-10bf48838a41';
|
|
23
|
-
const handle = 'test';
|
|
24
|
-
capabilityAgent = await CapabilityAgent.fromSecret({secret, handle});
|
|
25
|
-
|
|
26
|
-
// create keystore for capability agent
|
|
27
|
-
const keystoreAgent = await helpers.createKeystoreAgent(
|
|
28
|
-
{capabilityAgent});
|
|
29
|
-
|
|
30
|
-
// create EDV for storage (creating hmac and kak in the process)
|
|
31
|
-
const {
|
|
32
|
-
edvConfig,
|
|
33
|
-
hmac,
|
|
34
|
-
keyAgreementKey
|
|
35
|
-
} = await helpers.createEdv({capabilityAgent, keystoreAgent});
|
|
36
|
-
|
|
37
|
-
// get service agent to delegate to
|
|
38
|
-
const serviceAgentUrl =
|
|
39
|
-
`${baseUrl}/service-agents/${encodeURIComponent(serviceType)}`;
|
|
40
|
-
const {data: serviceAgent} = await httpClient.get(serviceAgentUrl, {
|
|
41
|
-
agent
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
// delegate edv, hmac, and key agreement key zcaps to service agent
|
|
45
|
-
const {id: edvId} = edvConfig;
|
|
46
|
-
zcaps.edv = await helpers.delegate({
|
|
47
|
-
controller: serviceAgent.id,
|
|
48
|
-
delegator: capabilityAgent,
|
|
49
|
-
invocationTarget: edvId
|
|
50
|
-
});
|
|
51
|
-
const {keystoreId} = keystoreAgent;
|
|
52
|
-
zcaps.hmac = await helpers.delegate({
|
|
53
|
-
capability: `urn:zcap:root:${encodeURIComponent(keystoreId)}`,
|
|
54
|
-
controller: serviceAgent.id,
|
|
55
|
-
invocationTarget: hmac.id,
|
|
56
|
-
delegator: capabilityAgent
|
|
57
|
-
});
|
|
58
|
-
zcaps.keyAgreementKey = await helpers.delegate({
|
|
59
|
-
capability: `urn:zcap:root:${encodeURIComponent(keystoreId)}`,
|
|
60
|
-
controller: serviceAgent.id,
|
|
61
|
-
invocationTarget: keyAgreementKey.kmsId,
|
|
62
|
-
delegator: capabilityAgent
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
describe('create config', () => {
|
|
66
|
-
it('throws error on missing zcaps', async () => {
|
|
67
|
-
let err;
|
|
68
|
-
let result;
|
|
69
|
-
try {
|
|
70
|
-
result = await helpers.createConfig({capabilityAgent});
|
|
71
|
-
} catch(e) {
|
|
72
|
-
err = e;
|
|
73
|
-
}
|
|
74
|
-
should.exist(err);
|
|
75
|
-
should.not.exist(result);
|
|
76
|
-
err.data.details.errors.should.have.length(1);
|
|
77
|
-
const [error] = err.data.details.errors;
|
|
78
|
-
error.name.should.equal('ValidationError');
|
|
79
|
-
error.message.should.contain(`should have required property 'zcaps'`);
|
|
80
|
-
});
|
|
81
|
-
it('creates a config', async () => {
|
|
82
|
-
let err;
|
|
83
|
-
let result;
|
|
84
|
-
try {
|
|
85
|
-
result = await helpers.createConfig({capabilityAgent, zcaps});
|
|
86
|
-
} catch(e) {
|
|
87
|
-
err = e;
|
|
88
|
-
}
|
|
89
|
-
assertNoError(err);
|
|
90
|
-
should.exist(result);
|
|
91
|
-
result.should.have.keys([
|
|
92
|
-
'controller', 'id', 'sequence', 'meterId', 'zcaps'
|
|
93
|
-
]);
|
|
94
|
-
result.sequence.should.equal(0);
|
|
95
|
-
const {id: capabilityAgentId} = capabilityAgent;
|
|
96
|
-
result.controller.should.equal(capabilityAgentId);
|
|
97
|
-
});
|
|
98
|
-
it('creates a config including proper ipAllowList', async () => {
|
|
99
|
-
const ipAllowList = ['127.0.0.1/32'];
|
|
100
|
-
|
|
101
|
-
let err;
|
|
102
|
-
let result;
|
|
103
|
-
try {
|
|
104
|
-
result = await helpers.createConfig(
|
|
105
|
-
{capabilityAgent, ipAllowList, zcaps});
|
|
106
|
-
} catch(e) {
|
|
107
|
-
err = e;
|
|
108
|
-
}
|
|
109
|
-
assertNoError(err);
|
|
110
|
-
should.exist(result);
|
|
111
|
-
result.should.have.keys([
|
|
112
|
-
'controller', 'id', 'ipAllowList', 'sequence', 'meterId', 'zcaps'
|
|
113
|
-
]);
|
|
114
|
-
result.sequence.should.equal(0);
|
|
115
|
-
const {id: capabilityAgentId} = capabilityAgent;
|
|
116
|
-
result.controller.should.equal(capabilityAgentId);
|
|
117
|
-
result.ipAllowList.should.eql(ipAllowList);
|
|
118
|
-
});
|
|
119
|
-
it('throws error on invalid ipAllowList', async () => {
|
|
120
|
-
// this is not a valid CIDR
|
|
121
|
-
const ipAllowList = ['127.0.0.1/33'];
|
|
122
|
-
|
|
123
|
-
let err;
|
|
124
|
-
let result;
|
|
125
|
-
try {
|
|
126
|
-
result = await helpers.createConfig(
|
|
127
|
-
{capabilityAgent, ipAllowList, zcaps});
|
|
128
|
-
} catch(e) {
|
|
129
|
-
err = e;
|
|
130
|
-
}
|
|
131
|
-
should.exist(err);
|
|
132
|
-
should.not.exist(result);
|
|
133
|
-
err.data.details.errors.should.have.length(1);
|
|
134
|
-
const [error] = err.data.details.errors;
|
|
135
|
-
error.name.should.equal('ValidationError');
|
|
136
|
-
error.message.should.contain('should match pattern');
|
|
137
|
-
error.details.path.should.equal('.ipAllowList[0]');
|
|
138
|
-
});
|
|
139
|
-
it('throws error on invalid ipAllowList', async () => {
|
|
140
|
-
// an empty allow list is invalid
|
|
141
|
-
const ipAllowList = [];
|
|
142
|
-
|
|
143
|
-
let err;
|
|
144
|
-
let result;
|
|
145
|
-
try {
|
|
146
|
-
result = await helpers.createConfig(
|
|
147
|
-
{capabilityAgent, ipAllowList, zcaps});
|
|
148
|
-
} catch(e) {
|
|
149
|
-
err = e;
|
|
150
|
-
}
|
|
151
|
-
should.exist(err);
|
|
152
|
-
should.not.exist(result);
|
|
153
|
-
err.data.details.errors.should.have.length(1);
|
|
154
|
-
const [error] = err.data.details.errors;
|
|
155
|
-
error.name.should.equal('ValidationError');
|
|
156
|
-
error.message.should.contain('should NOT have fewer than 1 items');
|
|
157
|
-
error.details.path.should.equal('.ipAllowList');
|
|
158
|
-
});
|
|
159
|
-
it('throws error on no "sequence"', async () => {
|
|
160
|
-
const url = `${bedrock.config.server.baseUri}/verifiers`;
|
|
161
|
-
const config = {
|
|
162
|
-
controller: capabilityAgent.id
|
|
163
|
-
};
|
|
164
|
-
|
|
165
|
-
let err;
|
|
166
|
-
let result;
|
|
167
|
-
try {
|
|
168
|
-
result = await httpClient.post(url, {agent, json: config});
|
|
169
|
-
} catch(e) {
|
|
170
|
-
err = e;
|
|
171
|
-
}
|
|
172
|
-
should.exist(err);
|
|
173
|
-
should.not.exist(result);
|
|
174
|
-
err.data.type.should.equal('ValidationError');
|
|
175
|
-
err.data.message.should.equal(
|
|
176
|
-
'A validation error occured in the \'createConfigBody\' validator.');
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
describe('get config', () => {
|
|
181
|
-
it('gets a config', async () => {
|
|
182
|
-
const config = await helpers.createConfig(
|
|
183
|
-
{capabilityAgent, zcaps});
|
|
184
|
-
let err;
|
|
185
|
-
let result;
|
|
186
|
-
try {
|
|
187
|
-
result = await helpers.getConfig({id: config.id, capabilityAgent});
|
|
188
|
-
} catch(e) {
|
|
189
|
-
err = e;
|
|
190
|
-
}
|
|
191
|
-
assertNoError(err);
|
|
192
|
-
should.exist(result);
|
|
193
|
-
result.should.have.keys([
|
|
194
|
-
'controller', 'id', 'sequence', 'meterId', 'zcaps'
|
|
195
|
-
]);
|
|
196
|
-
result.id.should.equal(config.id);
|
|
197
|
-
});
|
|
198
|
-
it('gets a config with ipAllowList', async () => {
|
|
199
|
-
const ipAllowList = ['127.0.0.1/32'];
|
|
200
|
-
|
|
201
|
-
const config = await helpers.createConfig(
|
|
202
|
-
{capabilityAgent, ipAllowList, zcaps});
|
|
203
|
-
let err;
|
|
204
|
-
let result;
|
|
205
|
-
try {
|
|
206
|
-
result = await helpers.getConfig({id: config.id, capabilityAgent});
|
|
207
|
-
} catch(e) {
|
|
208
|
-
err = e;
|
|
209
|
-
}
|
|
210
|
-
assertNoError(err);
|
|
211
|
-
should.exist(result);
|
|
212
|
-
result.should.have.keys([
|
|
213
|
-
'controller', 'id', 'ipAllowList', 'sequence', 'meterId', 'zcaps'
|
|
214
|
-
]);
|
|
215
|
-
result.should.have.property('id');
|
|
216
|
-
result.id.should.equal(config.id);
|
|
217
|
-
result.ipAllowList.should.eql(ipAllowList);
|
|
218
|
-
});
|
|
219
|
-
it('returns NotAllowedError for invalid source IP', async () => {
|
|
220
|
-
const ipAllowList = ['8.8.8.8/32'];
|
|
221
|
-
|
|
222
|
-
const config = await helpers.createConfig(
|
|
223
|
-
{capabilityAgent, ipAllowList, zcaps});
|
|
224
|
-
let err;
|
|
225
|
-
let result;
|
|
226
|
-
try {
|
|
227
|
-
result = await helpers.getConfig({id: config.id, capabilityAgent});
|
|
228
|
-
} catch(e) {
|
|
229
|
-
err = e;
|
|
230
|
-
}
|
|
231
|
-
should.not.exist(result);
|
|
232
|
-
should.exist(err);
|
|
233
|
-
err.status.should.equal(403);
|
|
234
|
-
err.data.type.should.equal('NotAllowedError');
|
|
235
|
-
});
|
|
236
|
-
}); // get config
|
|
237
|
-
|
|
238
|
-
describe('update config', () => {
|
|
239
|
-
it('updates a config', async () => {
|
|
240
|
-
// create new capability agent to change config `controller` to
|
|
241
|
-
const capabilityAgent2 = await CapabilityAgent.fromSecret(
|
|
242
|
-
{secret: 's2', handle: 'h2'});
|
|
243
|
-
|
|
244
|
-
let err;
|
|
245
|
-
let result;
|
|
246
|
-
let existingConfig;
|
|
247
|
-
try {
|
|
248
|
-
existingConfig = result = await helpers.createConfig(
|
|
249
|
-
{capabilityAgent, zcaps});
|
|
250
|
-
} catch(e) {
|
|
251
|
-
err = e;
|
|
252
|
-
}
|
|
253
|
-
assertNoError(err);
|
|
254
|
-
should.exist(result);
|
|
255
|
-
result.should.have.property('id');
|
|
256
|
-
result.should.have.property('sequence');
|
|
257
|
-
result.sequence.should.equal(0);
|
|
258
|
-
const {id: capabilityAgentId} = capabilityAgent;
|
|
259
|
-
result.should.have.property('controller');
|
|
260
|
-
result.controller.should.equal(capabilityAgentId);
|
|
261
|
-
|
|
262
|
-
// this update does not change the `meterId`
|
|
263
|
-
const {id: url} = result;
|
|
264
|
-
const newConfig = {
|
|
265
|
-
controller: capabilityAgent2.id,
|
|
266
|
-
id: url,
|
|
267
|
-
meterId: existingConfig.meterId,
|
|
268
|
-
sequence: 1,
|
|
269
|
-
zcaps
|
|
270
|
-
};
|
|
271
|
-
|
|
272
|
-
err = null;
|
|
273
|
-
result = null;
|
|
274
|
-
try {
|
|
275
|
-
const zcapClient = helpers.createZcapClient({capabilityAgent});
|
|
276
|
-
result = await zcapClient.write({url, json: newConfig});
|
|
277
|
-
} catch(e) {
|
|
278
|
-
err = e;
|
|
279
|
-
}
|
|
280
|
-
assertNoError(err);
|
|
281
|
-
should.exist(result.data);
|
|
282
|
-
result.status.should.equal(200);
|
|
283
|
-
result.data.should.have.keys([
|
|
284
|
-
'id', 'controller', 'sequence', 'meterId', 'zcaps'
|
|
285
|
-
]);
|
|
286
|
-
const expectedConfig = {
|
|
287
|
-
...existingConfig,
|
|
288
|
-
...newConfig
|
|
289
|
-
};
|
|
290
|
-
result.data.should.eql(expectedConfig);
|
|
291
|
-
|
|
292
|
-
// should fail to retrieve the config now that controller
|
|
293
|
-
// has changed
|
|
294
|
-
err = null;
|
|
295
|
-
result = null;
|
|
296
|
-
try {
|
|
297
|
-
result = await helpers.getConfig(
|
|
298
|
-
{id: newConfig.id, capabilityAgent});
|
|
299
|
-
} catch(e) {
|
|
300
|
-
err = e;
|
|
301
|
-
}
|
|
302
|
-
should.exist(err);
|
|
303
|
-
should.not.exist(result);
|
|
304
|
-
err.status.should.equal(403);
|
|
305
|
-
err.data.type.should.equal('NotAllowedError');
|
|
306
|
-
|
|
307
|
-
// retrieve the config to confirm update was effective
|
|
308
|
-
err = null;
|
|
309
|
-
result = null;
|
|
310
|
-
try {
|
|
311
|
-
result = await helpers.getConfig(
|
|
312
|
-
{id: newConfig.id, capabilityAgent: capabilityAgent2});
|
|
313
|
-
} catch(e) {
|
|
314
|
-
err = e;
|
|
315
|
-
}
|
|
316
|
-
assertNoError(err);
|
|
317
|
-
should.exist(result);
|
|
318
|
-
result.should.eql(expectedConfig);
|
|
319
|
-
});
|
|
320
|
-
it('rejects config update for an invalid zcap', async () => {
|
|
321
|
-
const capabilityAgent2 = await CapabilityAgent.fromSecret(
|
|
322
|
-
{secret: 's2', handle: 'h2'});
|
|
323
|
-
|
|
324
|
-
let err;
|
|
325
|
-
let result;
|
|
326
|
-
try {
|
|
327
|
-
result = await helpers.createConfig(
|
|
328
|
-
{capabilityAgent, zcaps});
|
|
329
|
-
} catch(e) {
|
|
330
|
-
err = e;
|
|
331
|
-
}
|
|
332
|
-
assertNoError(err);
|
|
333
|
-
should.exist(result);
|
|
334
|
-
result.should.have.property('id');
|
|
335
|
-
result.should.have.property('sequence');
|
|
336
|
-
result.sequence.should.equal(0);
|
|
337
|
-
const {id: capabilityAgentId} = capabilityAgent;
|
|
338
|
-
result.should.have.property('controller');
|
|
339
|
-
result.controller.should.equal(capabilityAgentId);
|
|
340
|
-
|
|
341
|
-
const {id: url} = result;
|
|
342
|
-
const newConfig = {
|
|
343
|
-
controller: capabilityAgent2.id,
|
|
344
|
-
id: url,
|
|
345
|
-
meterId: result.meterId,
|
|
346
|
-
sequence: 1,
|
|
347
|
-
zcaps
|
|
348
|
-
};
|
|
349
|
-
|
|
350
|
-
err = null;
|
|
351
|
-
result = null;
|
|
352
|
-
try {
|
|
353
|
-
// the capability invocation here is signed by `capabilityAgent2`
|
|
354
|
-
// which is not the `controller` of the config
|
|
355
|
-
const zcapClient = helpers.createZcapClient({
|
|
356
|
-
capabilityAgent: capabilityAgent2
|
|
357
|
-
});
|
|
358
|
-
result = await zcapClient.write({url, json: newConfig});
|
|
359
|
-
} catch(e) {
|
|
360
|
-
err = e;
|
|
361
|
-
}
|
|
362
|
-
should.exist(err);
|
|
363
|
-
should.not.exist(result);
|
|
364
|
-
err.status.should.equal(403);
|
|
365
|
-
err.data.type.should.equal('NotAllowedError');
|
|
366
|
-
err.data.cause.message.should.contain(
|
|
367
|
-
'The capability controller does not match the verification method ' +
|
|
368
|
-
'(or its controller) used to invoke.');
|
|
369
|
-
});
|
|
370
|
-
it('rejects config update with an invalid sequence', async () => {
|
|
371
|
-
const capabilityAgent2 = await CapabilityAgent.fromSecret(
|
|
372
|
-
{secret: 's2', handle: 'h2'});
|
|
373
|
-
|
|
374
|
-
let err;
|
|
375
|
-
let result;
|
|
376
|
-
try {
|
|
377
|
-
result = await helpers.createConfig(
|
|
378
|
-
{capabilityAgent, zcaps});
|
|
379
|
-
} catch(e) {
|
|
380
|
-
err = e;
|
|
381
|
-
}
|
|
382
|
-
assertNoError(err);
|
|
383
|
-
should.exist(result);
|
|
384
|
-
result.should.have.property('id');
|
|
385
|
-
result.should.have.property('sequence');
|
|
386
|
-
result.sequence.should.equal(0);
|
|
387
|
-
const {id: capabilityAgentId} = capabilityAgent;
|
|
388
|
-
result.should.have.property('controller');
|
|
389
|
-
result.controller.should.equal(capabilityAgentId);
|
|
390
|
-
|
|
391
|
-
const {id: url} = result;
|
|
392
|
-
const newConfig = {
|
|
393
|
-
controller: capabilityAgent2.id,
|
|
394
|
-
id: url,
|
|
395
|
-
meterId: result.meterId,
|
|
396
|
-
// the proper sequence would be 1
|
|
397
|
-
sequence: 10,
|
|
398
|
-
zcaps
|
|
399
|
-
};
|
|
400
|
-
|
|
401
|
-
err = null;
|
|
402
|
-
result = null;
|
|
403
|
-
try {
|
|
404
|
-
const zcapClient = helpers.createZcapClient({capabilityAgent});
|
|
405
|
-
result = await zcapClient.write({url, json: newConfig});
|
|
406
|
-
} catch(e) {
|
|
407
|
-
err = e;
|
|
408
|
-
}
|
|
409
|
-
should.exist(err);
|
|
410
|
-
should.not.exist(result);
|
|
411
|
-
err.status.should.equal(409);
|
|
412
|
-
err.data.type.should.equal('InvalidStateError');
|
|
413
|
-
});
|
|
414
|
-
describe('updates with ipAllowList', () => {
|
|
415
|
-
it('updates a config with ipAllowList', async () => {
|
|
416
|
-
const capabilityAgent2 = await CapabilityAgent.fromSecret(
|
|
417
|
-
{secret: 's2', handle: 'h2'});
|
|
418
|
-
|
|
419
|
-
const ipAllowList = ['127.0.0.1/32'];
|
|
420
|
-
|
|
421
|
-
let err;
|
|
422
|
-
let result;
|
|
423
|
-
let existingConfig;
|
|
424
|
-
try {
|
|
425
|
-
existingConfig = result = await helpers.createConfig(
|
|
426
|
-
{capabilityAgent, ipAllowList, zcaps});
|
|
427
|
-
} catch(e) {
|
|
428
|
-
err = e;
|
|
429
|
-
}
|
|
430
|
-
assertNoError(err);
|
|
431
|
-
should.exist(result);
|
|
432
|
-
result.should.have.property('id');
|
|
433
|
-
result.should.have.property('sequence');
|
|
434
|
-
result.sequence.should.equal(0);
|
|
435
|
-
const {id: capabilityAgentId} = capabilityAgent;
|
|
436
|
-
result.should.have.property('controller');
|
|
437
|
-
result.controller.should.equal(capabilityAgentId);
|
|
438
|
-
|
|
439
|
-
const {id: url} = result;
|
|
440
|
-
const newConfig = {
|
|
441
|
-
controller: capabilityAgent2.id,
|
|
442
|
-
id: url,
|
|
443
|
-
ipAllowList,
|
|
444
|
-
meterId: existingConfig.meterId,
|
|
445
|
-
sequence: 1,
|
|
446
|
-
zcaps
|
|
447
|
-
};
|
|
448
|
-
|
|
449
|
-
err = null;
|
|
450
|
-
result = null;
|
|
451
|
-
try {
|
|
452
|
-
const zcapClient = helpers.createZcapClient({capabilityAgent});
|
|
453
|
-
result = await zcapClient.write({url, json: newConfig});
|
|
454
|
-
} catch(e) {
|
|
455
|
-
err = e;
|
|
456
|
-
}
|
|
457
|
-
assertNoError(err);
|
|
458
|
-
should.exist(result.data);
|
|
459
|
-
result.status.should.equal(200);
|
|
460
|
-
result.data.should.have.keys([
|
|
461
|
-
'id', 'controller', 'sequence', 'meterId', 'ipAllowList', 'zcaps'
|
|
462
|
-
]);
|
|
463
|
-
const expectedConfig = {
|
|
464
|
-
...existingConfig,
|
|
465
|
-
...newConfig
|
|
466
|
-
};
|
|
467
|
-
result.data.should.eql(expectedConfig);
|
|
468
|
-
|
|
469
|
-
// should fail to retrieve the config now that controller
|
|
470
|
-
// has changed
|
|
471
|
-
err = null;
|
|
472
|
-
result = null;
|
|
473
|
-
try {
|
|
474
|
-
result = await helpers.getConfig(
|
|
475
|
-
{id: newConfig.id, capabilityAgent});
|
|
476
|
-
} catch(e) {
|
|
477
|
-
err = e;
|
|
478
|
-
}
|
|
479
|
-
should.exist(err);
|
|
480
|
-
should.not.exist(result);
|
|
481
|
-
err.status.should.equal(403);
|
|
482
|
-
err.data.type.should.equal('NotAllowedError');
|
|
483
|
-
|
|
484
|
-
// retrieve the config to confirm update was effective
|
|
485
|
-
err = null;
|
|
486
|
-
result = null;
|
|
487
|
-
try {
|
|
488
|
-
result = await helpers.getConfig(
|
|
489
|
-
{id: newConfig.id, capabilityAgent: capabilityAgent2});
|
|
490
|
-
} catch(e) {
|
|
491
|
-
err = e;
|
|
492
|
-
}
|
|
493
|
-
assertNoError(err);
|
|
494
|
-
should.exist(result);
|
|
495
|
-
result.should.eql(expectedConfig);
|
|
496
|
-
});
|
|
497
|
-
it('returns NotAllowedError for invalid source IP', async () => {
|
|
498
|
-
const capabilityAgent2 = await CapabilityAgent.fromSecret(
|
|
499
|
-
{secret: 's2', handle: 'h2'});
|
|
500
|
-
|
|
501
|
-
const ipAllowList = ['8.8.8.8/32'];
|
|
502
|
-
|
|
503
|
-
let err;
|
|
504
|
-
let result;
|
|
505
|
-
try {
|
|
506
|
-
result = await helpers.createConfig(
|
|
507
|
-
{capabilityAgent, ipAllowList, zcaps});
|
|
508
|
-
} catch(e) {
|
|
509
|
-
err = e;
|
|
510
|
-
}
|
|
511
|
-
assertNoError(err);
|
|
512
|
-
should.exist(result);
|
|
513
|
-
result.should.have.property('id');
|
|
514
|
-
result.should.have.property('sequence');
|
|
515
|
-
result.sequence.should.equal(0);
|
|
516
|
-
const {id: capabilityAgentId} = capabilityAgent;
|
|
517
|
-
result.should.have.property('controller');
|
|
518
|
-
result.controller.should.equal(capabilityAgentId);
|
|
519
|
-
|
|
520
|
-
const {id: url} = result;
|
|
521
|
-
const newConfig = {
|
|
522
|
-
controller: capabilityAgent2.id,
|
|
523
|
-
id: url,
|
|
524
|
-
ipAllowList,
|
|
525
|
-
meterId: result.meterId,
|
|
526
|
-
sequence: 1,
|
|
527
|
-
zcaps
|
|
528
|
-
};
|
|
529
|
-
|
|
530
|
-
err = null;
|
|
531
|
-
result = null;
|
|
532
|
-
try {
|
|
533
|
-
const zcapClient = helpers.createZcapClient({capabilityAgent});
|
|
534
|
-
result = await zcapClient.write({url, json: newConfig});
|
|
535
|
-
} catch(e) {
|
|
536
|
-
err = e;
|
|
537
|
-
}
|
|
538
|
-
should.not.exist(result);
|
|
539
|
-
should.exist(err);
|
|
540
|
-
err.status.should.equal(403);
|
|
541
|
-
err.data.type.should.equal('NotAllowedError');
|
|
542
|
-
});
|
|
543
|
-
}); // updates with ipAllowList
|
|
544
|
-
}); // end update config
|
|
545
|
-
|
|
546
|
-
describe('revocations', () => {
|
|
547
|
-
it('throws error with invalid zcap when revoking', async () => {
|
|
548
|
-
const config = await helpers.createConfig({capabilityAgent, zcaps});
|
|
549
|
-
const zcap = {
|
|
550
|
-
'@context': ['https://w3id.org/zcap/v1'],
|
|
551
|
-
id: 'urn:uuid:895d985c-8e20-11ec-b82f-10bf48838a41',
|
|
552
|
-
proof: {}
|
|
553
|
-
};
|
|
554
|
-
|
|
555
|
-
const url =
|
|
556
|
-
`${config.id}/zcaps/revocations/${encodeURIComponent(zcap.id)}`;
|
|
557
|
-
|
|
558
|
-
let err;
|
|
559
|
-
let result;
|
|
560
|
-
try {
|
|
561
|
-
result = await httpClient.post(url, {agent, json: zcap});
|
|
562
|
-
} catch(e) {
|
|
563
|
-
err = e;
|
|
564
|
-
}
|
|
565
|
-
should.exist(err);
|
|
566
|
-
should.not.exist(result);
|
|
567
|
-
err.data.type.should.equal('ValidationError');
|
|
568
|
-
err.data.message.should.equal(
|
|
569
|
-
'A validation error occured in the \'Delegated ZCAP\' validator.');
|
|
570
|
-
});
|
|
571
|
-
it('revokes a zcap', async () => {
|
|
572
|
-
const config = await helpers.createConfig({capabilityAgent, zcaps});
|
|
573
|
-
|
|
574
|
-
const capabilityAgent2 = await CapabilityAgent.fromSecret(
|
|
575
|
-
{secret: 's2', handle: 'h2'});
|
|
576
|
-
|
|
577
|
-
const zcap = await helpers.delegate({
|
|
578
|
-
controller: capabilityAgent2.id,
|
|
579
|
-
invocationTarget: config.id,
|
|
580
|
-
delegator: capabilityAgent
|
|
581
|
-
});
|
|
582
|
-
|
|
583
|
-
// zcap should work to get config
|
|
584
|
-
const zcapClient = helpers.createZcapClient(
|
|
585
|
-
{capabilityAgent: capabilityAgent2});
|
|
586
|
-
const {data} = await zcapClient.read({capability: zcap});
|
|
587
|
-
data.should.have.keys([
|
|
588
|
-
'controller', 'id', 'sequence', 'meterId', 'zcaps'
|
|
589
|
-
]);
|
|
590
|
-
data.id.should.equal(config.id);
|
|
591
|
-
|
|
592
|
-
// revoke zcap
|
|
593
|
-
await helpers.revokeDelegatedCapability({
|
|
594
|
-
serviceObjectId: config.id,
|
|
595
|
-
capabilityToRevoke: zcap,
|
|
596
|
-
invocationSigner: capabilityAgent.getSigner()
|
|
597
|
-
});
|
|
598
|
-
|
|
599
|
-
// now getting config should fail
|
|
600
|
-
let err;
|
|
601
|
-
try {
|
|
602
|
-
await zcapClient.read({capability: zcap});
|
|
603
|
-
} catch(e) {
|
|
604
|
-
err = e;
|
|
605
|
-
}
|
|
606
|
-
should.exist(err);
|
|
607
|
-
err.data.type.should.equal('NotAllowedError');
|
|
608
|
-
});
|
|
609
|
-
}); // end revocations
|
|
610
|
-
|
|
611
|
-
describe('contexts', () => {
|
|
612
|
-
it('fails to inserts a context due to bad zcap', async () => {
|
|
613
|
-
const config = await helpers.createConfig({capabilityAgent, zcaps});
|
|
614
|
-
|
|
615
|
-
// insert `context`
|
|
616
|
-
const contextId = 'https://test.example/v1';
|
|
617
|
-
const context = {'@context': {term: 'https://test.example#term'}};
|
|
618
|
-
const client = helpers.createZcapClient({capabilityAgent});
|
|
619
|
-
const url = `${config.id}/contexts`;
|
|
620
|
-
|
|
621
|
-
// intentionally bad root zcap here; the root zcap must be for the
|
|
622
|
-
// service object config, not `/contexts` URL as it is set here
|
|
623
|
-
const rootZcap = `urn:zcap:root:${encodeURIComponent(url)}`;
|
|
624
|
-
|
|
625
|
-
let err;
|
|
626
|
-
try {
|
|
627
|
-
await client.write({
|
|
628
|
-
url, json: {id: contextId, context},
|
|
629
|
-
capability: rootZcap
|
|
630
|
-
});
|
|
631
|
-
} catch(e) {
|
|
632
|
-
err = e;
|
|
633
|
-
}
|
|
634
|
-
should.exist(err);
|
|
635
|
-
err.data.type.should.equal('NotAllowedError');
|
|
636
|
-
});
|
|
637
|
-
it('inserts a context', async () => {
|
|
638
|
-
const config = await helpers.createConfig({capabilityAgent, zcaps});
|
|
639
|
-
const rootZcap = `urn:zcap:root:${encodeURIComponent(config.id)}`;
|
|
640
|
-
|
|
641
|
-
// insert `context`
|
|
642
|
-
const contextId = 'https://test.example/v1';
|
|
643
|
-
const context = {'@context': {term: 'https://test.example#term'}};
|
|
644
|
-
const client = helpers.createZcapClient({capabilityAgent});
|
|
645
|
-
const url = `${config.id}/contexts`;
|
|
646
|
-
|
|
647
|
-
let err;
|
|
648
|
-
let response;
|
|
649
|
-
try {
|
|
650
|
-
response = await client.write({
|
|
651
|
-
url, json: {id: contextId, context},
|
|
652
|
-
capability: rootZcap
|
|
653
|
-
});
|
|
654
|
-
} catch(e) {
|
|
655
|
-
err = e;
|
|
656
|
-
}
|
|
657
|
-
assertNoError(err);
|
|
658
|
-
should.exist(response);
|
|
659
|
-
should.exist(response.data);
|
|
660
|
-
response.data.should.deep.equal({
|
|
661
|
-
id: 'https://test.example/v1',
|
|
662
|
-
context,
|
|
663
|
-
sequence: 0
|
|
664
|
-
});
|
|
665
|
-
});
|
|
666
|
-
it('throws error on no "context"', async () => {
|
|
667
|
-
const config = await helpers.createConfig({capabilityAgent, zcaps});
|
|
668
|
-
const rootZcap = `urn:zcap:root:${encodeURIComponent(config.id)}`;
|
|
669
|
-
|
|
670
|
-
const contextId = 'https://test.example/v1';
|
|
671
|
-
const client = helpers.createZcapClient({capabilityAgent});
|
|
672
|
-
const url = `${config.id}/contexts`;
|
|
673
|
-
|
|
674
|
-
let err;
|
|
675
|
-
let result;
|
|
676
|
-
try {
|
|
677
|
-
await client.write({url, json: {id: contextId}, capability: rootZcap});
|
|
678
|
-
} catch(e) {
|
|
679
|
-
err = e;
|
|
680
|
-
}
|
|
681
|
-
should.exist(err);
|
|
682
|
-
should.not.exist(result);
|
|
683
|
-
err.data.type.should.equal('ValidationError');
|
|
684
|
-
err.data.message.should.equal(
|
|
685
|
-
'A validation error occured in the \'createContextBody\' validator.');
|
|
686
|
-
});
|
|
687
|
-
it('updates a context', async () => {
|
|
688
|
-
const config = await helpers.createConfig({capabilityAgent, zcaps});
|
|
689
|
-
const rootZcap = `urn:zcap:root:${encodeURIComponent(config.id)}`;
|
|
690
|
-
|
|
691
|
-
// insert `context`
|
|
692
|
-
const contextId = 'https://test.example/v1';
|
|
693
|
-
const context = {'@context': {term: 'https://test.example#term'}};
|
|
694
|
-
const client = helpers.createZcapClient({capabilityAgent});
|
|
695
|
-
let url = `${config.id}/contexts`;
|
|
696
|
-
await client.write({
|
|
697
|
-
url, json: {id: contextId, context},
|
|
698
|
-
capability: rootZcap
|
|
699
|
-
});
|
|
700
|
-
|
|
701
|
-
// update `context`
|
|
702
|
-
context['@context'].term2 = 'https://test.example#term2';
|
|
703
|
-
url = `${url}/${encodeURIComponent(contextId)}`;
|
|
704
|
-
let err;
|
|
705
|
-
let response;
|
|
706
|
-
try {
|
|
707
|
-
response = await client.write({
|
|
708
|
-
url, json: {id: contextId, context, sequence: 1},
|
|
709
|
-
capability: rootZcap
|
|
710
|
-
});
|
|
711
|
-
} catch(e) {
|
|
712
|
-
err = e;
|
|
713
|
-
}
|
|
714
|
-
assertNoError(err);
|
|
715
|
-
should.exist(response);
|
|
716
|
-
should.exist(response.data);
|
|
717
|
-
response.data.should.deep.equal({
|
|
718
|
-
id: 'https://test.example/v1',
|
|
719
|
-
context,
|
|
720
|
-
sequence: 1
|
|
721
|
-
});
|
|
722
|
-
});
|
|
723
|
-
it('fails to update a context with wrong sequence', async () => {
|
|
724
|
-
const config = await helpers.createConfig({capabilityAgent, zcaps});
|
|
725
|
-
const rootZcap = `urn:zcap:root:${encodeURIComponent(config.id)}`;
|
|
726
|
-
|
|
727
|
-
// insert `context`
|
|
728
|
-
const contextId = 'https://test.example/v1';
|
|
729
|
-
const context = {'@context': {term: 'https://test.example#term'}};
|
|
730
|
-
const client = helpers.createZcapClient({capabilityAgent});
|
|
731
|
-
let url = `${config.id}/contexts`;
|
|
732
|
-
await client.write({
|
|
733
|
-
url, json: {id: contextId, context},
|
|
734
|
-
capability: rootZcap
|
|
735
|
-
});
|
|
736
|
-
|
|
737
|
-
// update `context`
|
|
738
|
-
context['@context'].term2 = 'https://test.example#term2';
|
|
739
|
-
url = `${url}/${encodeURIComponent(contextId)}`;
|
|
740
|
-
let err;
|
|
741
|
-
let response;
|
|
742
|
-
try {
|
|
743
|
-
response = await client.write({
|
|
744
|
-
url, json: {id: contextId, context, sequence: 10},
|
|
745
|
-
capability: rootZcap
|
|
746
|
-
});
|
|
747
|
-
} catch(e) {
|
|
748
|
-
err = e;
|
|
749
|
-
}
|
|
750
|
-
should.exist(err);
|
|
751
|
-
should.not.exist(response);
|
|
752
|
-
err.data.type.should.equal('InvalidStateError');
|
|
753
|
-
});
|
|
754
|
-
it('gets a context', async () => {
|
|
755
|
-
const config = await helpers.createConfig({capabilityAgent, zcaps});
|
|
756
|
-
const rootZcap = `urn:zcap:root:${encodeURIComponent(config.id)}`;
|
|
757
|
-
|
|
758
|
-
// insert `context`
|
|
759
|
-
const contextId = 'https://test.example/v1';
|
|
760
|
-
const context = {'@context': {term: 'https://test.example#term'}};
|
|
761
|
-
const client = helpers.createZcapClient({capabilityAgent});
|
|
762
|
-
let url = `${config.id}/contexts`;
|
|
763
|
-
await client.write({
|
|
764
|
-
url, json: {id: contextId, context},
|
|
765
|
-
capability: rootZcap
|
|
766
|
-
});
|
|
767
|
-
|
|
768
|
-
url = `${url}/${encodeURIComponent(contextId)}`;
|
|
769
|
-
let err;
|
|
770
|
-
let response;
|
|
771
|
-
try {
|
|
772
|
-
response = await client.read({
|
|
773
|
-
url, capability: rootZcap
|
|
774
|
-
});
|
|
775
|
-
} catch(e) {
|
|
776
|
-
err = e;
|
|
777
|
-
}
|
|
778
|
-
assertNoError(err);
|
|
779
|
-
should.exist(response);
|
|
780
|
-
should.exist(response.data);
|
|
781
|
-
response.data.should.deep.equal({
|
|
782
|
-
id: 'https://test.example/v1',
|
|
783
|
-
context,
|
|
784
|
-
sequence: 0
|
|
785
|
-
});
|
|
786
|
-
});
|
|
787
|
-
it('gets a context with a context document loader', async () => {
|
|
788
|
-
const config = await helpers.createConfig({capabilityAgent, zcaps});
|
|
789
|
-
const rootZcap = `urn:zcap:root:${encodeURIComponent(config.id)}`;
|
|
790
|
-
|
|
791
|
-
// insert `context`
|
|
792
|
-
const contextId = 'https://test.example/v1';
|
|
793
|
-
const context = {'@context': {term: 'https://test.example#term'}};
|
|
794
|
-
const client = helpers.createZcapClient({capabilityAgent});
|
|
795
|
-
const url = `${config.id}/contexts`;
|
|
796
|
-
await client.write({
|
|
797
|
-
url, json: {id: contextId, context},
|
|
798
|
-
capability: rootZcap
|
|
799
|
-
});
|
|
800
|
-
|
|
801
|
-
const documentLoader = await createContextDocumentLoader({
|
|
802
|
-
config, serviceType
|
|
803
|
-
});
|
|
804
|
-
|
|
805
|
-
let err;
|
|
806
|
-
let result;
|
|
807
|
-
try {
|
|
808
|
-
result = await documentLoader(contextId);
|
|
809
|
-
} catch(e) {
|
|
810
|
-
err = e;
|
|
811
|
-
}
|
|
812
|
-
assertNoError(err);
|
|
813
|
-
should.exist(result);
|
|
814
|
-
should.exist(result.documentUrl);
|
|
815
|
-
should.exist(result.document);
|
|
816
|
-
result.documentUrl.should.equal(contextId);
|
|
817
|
-
result.document.should.deep.equal(context);
|
|
818
|
-
});
|
|
819
|
-
it('fails to get a context with wrong meta type', async () => {
|
|
820
|
-
const config = await helpers.createConfig({capabilityAgent, zcaps});
|
|
821
|
-
const rootZcap = `urn:zcap:root:${encodeURIComponent(config.id)}`;
|
|
822
|
-
|
|
823
|
-
// insert `context`
|
|
824
|
-
const contextId = 'https://test.example/v1';
|
|
825
|
-
const context = {'@context': {term: 'https://test.example#term'}};
|
|
826
|
-
const client = helpers.createZcapClient({capabilityAgent});
|
|
827
|
-
const url = `${config.id}/contexts`;
|
|
828
|
-
await client.write({
|
|
829
|
-
url, json: {id: contextId, context},
|
|
830
|
-
capability: rootZcap
|
|
831
|
-
});
|
|
832
|
-
|
|
833
|
-
// get context successfully
|
|
834
|
-
const documentLoader = await createContextDocumentLoader({
|
|
835
|
-
config, serviceType
|
|
836
|
-
});
|
|
837
|
-
|
|
838
|
-
let err;
|
|
839
|
-
let result;
|
|
840
|
-
try {
|
|
841
|
-
result = await documentLoader(contextId);
|
|
842
|
-
} catch(e) {
|
|
843
|
-
err = e;
|
|
844
|
-
}
|
|
845
|
-
assertNoError(err);
|
|
846
|
-
should.exist(result);
|
|
847
|
-
should.exist(result.documentUrl);
|
|
848
|
-
should.exist(result.document);
|
|
849
|
-
result.documentUrl.should.equal(contextId);
|
|
850
|
-
result.document.should.deep.equal(context);
|
|
851
|
-
|
|
852
|
-
// now erroneously update context to new meta type
|
|
853
|
-
const docStore = await documentStores.get({config, serviceType});
|
|
854
|
-
await docStore.upsert({
|
|
855
|
-
content: {id: contextId, context},
|
|
856
|
-
meta: {type: 'different'}
|
|
857
|
-
});
|
|
858
|
-
|
|
859
|
-
try {
|
|
860
|
-
await documentLoader(contextId);
|
|
861
|
-
} catch(e) {
|
|
862
|
-
err = e;
|
|
863
|
-
}
|
|
864
|
-
should.exist(err);
|
|
865
|
-
err.name.should.equal('NotFoundError');
|
|
866
|
-
});
|
|
867
|
-
}); // end contexts
|
|
868
|
-
});
|