| 1 | // De eigenaarspoort (Robins wens, 18-8): met approve_followers aan wordt een
|
|---|
| 2 | // inkomende Follow NIET auto-geaccepteerd maar vastgehouden tot de eigenaar
|
|---|
| 3 | // beslist op /connect — zodat niemand een klonkt ongevraagd aan een hub of
|
|---|
| 4 | // ander verzamelplatform kan hangen. Zonder de instelling verandert er niets.
|
|---|
| 5 | //
|
|---|
| 6 | // De fetch is gestubd: het gaat om de poort, niet om echte HTTP.
|
|---|
| 7 | import { test, after } from 'node:test';
|
|---|
| 8 | import assert from 'node:assert/strict';
|
|---|
| 9 |
|
|---|
| 10 | process.env.DATABASE_PATH = ':memory:';
|
|---|
| 11 | process.env.PUBLIC_BASE_URL = 'https://klonkt.test';
|
|---|
| 12 |
|
|---|
| 13 | const dbMod = await import('../src/config/database.js');
|
|---|
| 14 | const db = dbMod.default;
|
|---|
| 15 | dbMod.initializeDatabase();
|
|---|
| 16 | const APmod = await import('../src/services/ActivityPubService.js');
|
|---|
| 17 | const AP = APmod.default;
|
|---|
| 18 | const G = await import('../src/services/guardianship/index.js');
|
|---|
| 19 |
|
|---|
| 20 | db.prepare("INSERT INTO users (id, username, email, password_hash, role) VALUES ('u1','u1','u1@t','x','god')").run();
|
|---|
| 21 | db.prepare("INSERT INTO sites (id, slug, title, owner_id, is_public, approve_followers) VALUES ('s1','dev','Dev','u1',1,1)").run();
|
|---|
| 22 | db.prepare("INSERT INTO sites (id, slug, title, owner_id, is_public, approve_followers) VALUES ('s2','open','Open','u1',1,0)").run();
|
|---|
| 23 |
|
|---|
| 24 | // IP-literal: safeFetch slaat dan de DNS-lookup over en de stub vangt de rest.
|
|---|
| 25 | const HUB = 'https://203.0.113.77/ap/actor';
|
|---|
| 26 | const echteFetch = globalThis.fetch;
|
|---|
| 27 | globalThis.fetch = async () => new Response(JSON.stringify({
|
|---|
| 28 | id: HUB, type: 'Application', preferredUsername: 'hub', inbox: `${HUB}/inbox`,
|
|---|
| 29 | }), { status: 200, headers: { 'content-type': 'application/activity+json' } });
|
|---|
| 30 | after(() => { globalThis.fetch = echteFetch; });
|
|---|
| 31 |
|
|---|
| 32 | const follow = (slug) => AP.handleInbox({
|
|---|
| 33 | body: {
|
|---|
| 34 | '@context': 'https://www.w3.org/ns/activitystreams',
|
|---|
| 35 | id: `${HUB}#follow-${slug}`, type: 'Follow', actor: HUB,
|
|---|
| 36 | object: `https://klonkt.test/ap/users/${slug}`,
|
|---|
| 37 | },
|
|---|
| 38 | headers: {}, get: () => undefined, socket: {},
|
|---|
| 39 | }, slug, { id: HUB });
|
|---|
| 40 |
|
|---|
| 41 | const volgers = (slug) =>
|
|---|
| 42 | db.prepare('SELECT COUNT(*) c FROM ap_followers WHERE slug = ? AND actor_uri = ?').get(slug, HUB).c;
|
|---|
| 43 |
|
|---|
| 44 | test('approve_followers aan: de Follow wacht op de eigenaar', async () => {
|
|---|
| 45 | await follow('dev');
|
|---|
| 46 | assert.equal(volgers('dev'), 0, 'geen auto-accept');
|
|---|
| 47 | const wachtend = G.follows.listForWard('dev');
|
|---|
| 48 | assert.equal(wachtend.length, 1);
|
|---|
| 49 | assert.equal(wachtend[0].follower_uri, HUB);
|
|---|
| 50 | assert.equal(wachtend[0].status, 'pending');
|
|---|
| 51 | });
|
|---|
| 52 |
|
|---|
| 53 | test('goedkeuren: volger erbij, wachtrij leeg', async () => {
|
|---|
| 54 | const pending = G.follows.listForWard('dev')[0];
|
|---|
| 55 | await AP.acceptGatedFollow(pending);
|
|---|
| 56 | G.follows.remove(pending.id);
|
|---|
| 57 | assert.equal(volgers('dev'), 1);
|
|---|
| 58 | assert.equal(G.follows.listForWard('dev').length, 0);
|
|---|
| 59 | });
|
|---|
| 60 |
|
|---|
| 61 | test('zonder de instelling blijft auto-accept gewoon werken', async () => {
|
|---|
| 62 | await follow('open');
|
|---|
| 63 | assert.equal(volgers('open'), 1);
|
|---|
| 64 | });
|
|---|
| 65 |
|
|---|
| 66 | test('de actor adverteert manuallyApprovesFollowers eerlijk', () => {
|
|---|
| 67 | const dicht = db.prepare("SELECT * FROM sites WHERE slug = 'dev'").get();
|
|---|
| 68 | const open = db.prepare("SELECT * FROM sites WHERE slug = 'open'").get();
|
|---|
| 69 | const build = APmod.buildActor || AP.buildActor;
|
|---|
| 70 | assert.equal(build('https://klonkt.test', dicht).manuallyApprovesFollowers, true);
|
|---|
| 71 | assert.equal(build('https://klonkt.test', open).manuallyApprovesFollowers, false);
|
|---|
| 72 | });
|
|---|