openvibers/openvibe.mediahub Commits
agent.json: what a watch page's id is, and that it never changes meaning (AGT-4) (#279)
Changes
@@@ -13,5 +13,11 @@ module.exports = {policy: {auth: ['none', 'Network OIDC'],rateLimit: 'The public watch pages are not rate-limited by the app; the playlist API is limited to 120 reads a minute and 3,000 an hour per caller',++ // What an id in a watch page's address is, and that it never changes meaning (AGT-4). The ids are OpenVibe.Media's:++ // its vods and clips tables number them with a PostgreSQL identity column (migrations/0001_initial.sql).++ stableIds: [++ { kind: 'recording', url: 'https://openvibe.video/v/{id}', id: 'OpenVibe.Media\'s recording id, a positive integer from an identity column: never reused or renumbered, even after the recording is deleted', gone: 'a deleted, private or missing recording answers 404, never another recording' },++ { kind: 'clip', url: 'https://openvibe.video/c/{id}', id: 'OpenVibe.Media\'s clip id, the same kind of integer: never reused or renumbered', gone: 'a deleted, private or missing clip answers 404, never another clip' },++ ],},};@@@ -75,6 +75,9 @@ function vreq(base, path, { method = 'GET', cookie, host = 'openvibe.video', accassert.strictEqual(d.llms, 'https://openvibe.video/llms.txt');assert.strictEqual(d.sitemap, 'https://openvibe.video/sitemap.xml');assert.deepStrictEqual(d.policy.auth, ['none', 'Network OIDC']);++ // AGT-4: the id rule of the watch pages, as the pages behave (a private or missing id is a 404 below).++ assert.deepStrictEqual(d.policy.stableIds.map((x) => [x.kind, x.url]), [['recording', 'https://openvibe.video/v/{id}'], ['clip', 'https://openvibe.video/c/{id}']]);++ assert.ok(d.policy.stableIds.every((x) => /never reused/.test(x.id) && /404/.test(x.gone)));const drive = await vreq(t.base, '/.well-known/agent.json', { host: 'openvibe.download' });assert.strictEqual(drive.status, 200, 'the drive answers with its own manifest');const dd = JSON.parse(drive.text);@@@ -130,6 +133,7 @@ function vreq(base, path, { method = 'GET', cookie, host = 'openvibe.video', accassert.strictEqual((await vreq(t.base, '/v/103.md')).status, 404, 'a private recording is not a twin');assert.strictEqual((await vreq(t.base, '/v/999.md')).status, 404, 'nor is a missing one');assert.strictEqual((await vreq(t.base, '/v/999')).status, 404, 'and the page is a real 404');++ assert.strictEqual((await vreq(t.base, '/v/103')).status, 404, 'a private recording\'s page is a 404 to anyone else, as the manifest says');});await live.close();
@@ -13,5 +13,11 @@ module.exports = {
@@ -13,5 +13,11 @@ module.exports = {
policy: {
policy: {
auth: ['none', 'Network OIDC'],
auth: ['none', 'Network OIDC'],
rateLimit: 'The public watch pages are not rate-limited by the app; the playlist API is limited to 120 reads a minute and 3,000 an hour per caller',
rateLimit: 'The public watch pages are not rate-limited by the app; the playlist API is limited to 120 reads a minute and 3,000 an hour per caller',
+ // What an id in a watch page's address is, and that it never changes meaning (AGT-4). The ids are OpenVibe.Media's:
+ // its vods and clips tables number them with a PostgreSQL identity column (migrations/0001_initial.sql).
+ stableIds: [
+ { kind: 'recording', url: 'https://openvibe.video/v/{id}', id: 'OpenVibe.Media\'s recording id, a positive integer from an identity column: never reused or renumbered, even after the recording is deleted', gone: 'a deleted, private or missing recording answers 404, never another recording' },
+ { kind: 'clip', url: 'https://openvibe.video/c/{id}', id: 'OpenVibe.Media\'s clip id, the same kind of integer: never reused or renumbered', gone: 'a deleted, private or missing clip answers 404, never another clip' },
+ ],
},
},
};
};
@@ -75,6 +75,9 @@ function vreq(base, path, { method = 'GET', cookie, host = 'openvibe.video', acc
@@ -75,6 +75,9 @@ function vreq(base, path, { method = 'GET', cookie, host = 'openvibe.video', acc
assert.strictEqual(d.llms, 'https://openvibe.video/llms.txt');
assert.strictEqual(d.llms, 'https://openvibe.video/llms.txt');
assert.strictEqual(d.sitemap, 'https://openvibe.video/sitemap.xml');
assert.strictEqual(d.sitemap, 'https://openvibe.video/sitemap.xml');
assert.deepStrictEqual(d.policy.auth, ['none', 'Network OIDC']);
assert.deepStrictEqual(d.policy.auth, ['none', 'Network OIDC']);
+ // AGT-4: the id rule of the watch pages, as the pages behave (a private or missing id is a 404 below).
+ assert.deepStrictEqual(d.policy.stableIds.map((x) => [x.kind, x.url]), [['recording', 'https://openvibe.video/v/{id}'], ['clip', 'https://openvibe.video/c/{id}']]);
+ assert.ok(d.policy.stableIds.every((x) => /never reused/.test(x.id) && /404/.test(x.gone)));
const drive = await vreq(t.base, '/.well-known/agent.json', { host: 'openvibe.download' });
const drive = await vreq(t.base, '/.well-known/agent.json', { host: 'openvibe.download' });
assert.strictEqual(drive.status, 200, 'the drive answers with its own manifest');
assert.strictEqual(drive.status, 200, 'the drive answers with its own manifest');
const dd = JSON.parse(drive.text);
const dd = JSON.parse(drive.text);
@@ -130,6 +133,7 @@ function vreq(base, path, { method = 'GET', cookie, host = 'openvibe.video', acc
@@ -130,6 +133,7 @@ function vreq(base, path, { method = 'GET', cookie, host = 'openvibe.video', acc
assert.strictEqual((await vreq(t.base, '/v/103.md')).status, 404, 'a private recording is not a twin');
assert.strictEqual((await vreq(t.base, '/v/103.md')).status, 404, 'a private recording is not a twin');
assert.strictEqual((await vreq(t.base, '/v/999.md')).status, 404, 'nor is a missing one');
assert.strictEqual((await vreq(t.base, '/v/999.md')).status, 404, 'nor is a missing one');
assert.strictEqual((await vreq(t.base, '/v/999')).status, 404, 'and the page is a real 404');
assert.strictEqual((await vreq(t.base, '/v/999')).status, 404, 'and the page is a real 404');
+ assert.strictEqual((await vreq(t.base, '/v/103')).status, 404, 'a private recording\'s page is a 404 to anyone else, as the manifest says');
});
});
await live.close();
await live.close();