openvibers/openvibe.community Commits

agent.json: what a paste's address is (AGT-4) (#250)

OP OpenVibers committed 10 days ago · cdf91a371f · 2 files, +22 −0

policy.stableIds: /p/{slug} is given to one paste only, ever: a deleted paste keeps its slug (soft
delete) and an erased one's is retired (#249). A deleted, erased or missing paste answers 404. The
test ties the claim to store.js and account-data.js.

Changes

ddiff --git a/server/agent-descriptor.js b/server/agent-descriptor.js
iindex 082fc70..f18add7 100644
---- a/server/agent-descriptor.js
++++ b/server/agent-descriptor.js
@@@ -14,5 +14,10 @@ module.exports = {
policy: {
auth: ['none', 'Network OIDC', 'bearer'],
rateLimit: 'The public pages are not limited by the app; /api is limited to 120 requests a minute per address and sign-in attempts to 60 per 15 minutes',
++ // What a paste's address is, and that it never changes meaning (AGT-4): server/pastes/store.js gives a slug to one
++ // paste only, ever: a deleted paste keeps it (soft delete), and an erased one's is retired (migration 0014).
++ stableIds: [
++ { kind: 'paste', url: 'https://openvibe.community/p/{slug}', id: 'a generated slug (adjective-noun-number for a public paste, longer and secret for an unlisted or private one): given to one paste only, never again, even after it is deleted or its author\'s account is erased', gone: 'a deleted, erased or missing paste answers 404, never another paste' },
++ ],
},
};
ddiff --git a/test/agent-stable-ids.test.js b/test/agent-stable-ids.test.js
nnew file mode 100644
iindex 0000000..f640868
---- /dev/null
++++ b/test/agent-stable-ids.test.js
@@@ -0,0 +1,17 @@
++'use strict';
++// AGT-4: agent.json says what a paste's address is, and the store keeps it to one paste.
++const assert = require('assert');
++const fs = require('fs');
++const path = require('path');
++const { agentManifest } = require('openvibe-shared/agent-layer');
++
++const ids = agentManifest(require('../server/agent-descriptor')).policy.stableIds;
++assert.deepStrictEqual(ids.map((x) => [x.kind, x.url]), [['paste', 'https://openvibe.community/p/{slug}']]);
++const store = fs.readFileSync(path.join(__dirname, '..', 'server', 'pastes', 'store.js'), 'utf8');
++// Generation asks slugTaken, which counts every paste row (deleted ones included) and every retired slug.
++assert.match(store, /SELECT 1 FROM pastes WHERE slug = \? UNION ALL SELECT 1 FROM retired_paste_slugs WHERE slug_hash = \?/);
++assert.match(store, /const taken = \{ get: \(slug\) => slugTaken\(db, slug\) \};/);
++// The only hard delete of a paste retires its slug first.
++const erase = fs.readFileSync(path.join(__dirname, '..', 'server', 'identity', 'account-data.js'), 'utf8');
++assert.match(erase, /retireSlug\(db, p\.slug\);\s*\n\s*await db\.prepare\('DELETE FROM pastes WHERE id = \?'\)/);
++console.log('agent stable ids: ok');