source: Klonkt/test/c2s-collections.test.js@ 2d2fd8c

main
Last change on this file since 2d2fd8c was 4407c67, checked in by Robin <roboburr@…>, 7 weeks ago

Feature: C2S owner can read own followers/following (klonkt-demo-6kc)

The followers and following collections stay count-only for the public
(privacy), but a request carrying a C2S bearer scoped to that site (the account
owner) now returns the real actor URIs, so a client (Shaer) can build a friends
list. This was the one gap keeping the Shaer app's orbit empty against a real
Klonkt (it worked against the shaer-daemon, which serves the full lists).

  • buildFollowers/buildFollowing take an optional items array: when present, orderedItems carries the URIs and totalItems reflects them; otherwise count-only as before.
  • The two GET routes verify a bearer (OAuth.verifyBearer) and, when it is scoped to the requested slug, return the full list from ap_followers.actor_uri / ap_following.actor_uri (status=accepted); everyone else gets count-only. A private site's owner can read it even when it is not publicly listed.

3 new builder tests (count-only vs owner items vs empty owner list); 83 green.
Live-verified: owner bearer -> real URIs (alice/bob) in orderedItems; no bearer
-> orderedItems empty with the count intact; a token for another slug does not
unlock it.

Co-Authored-By: Claude Opus 4.8 <noreply@…>

  • Property mode set to 100644
File size: 1.6 KB
Line 
1// C2S owner collections: followers/following are count-only by default, but
2// carry the real actor URIs when the account owner asks (klonkt-demo-6kc).
3// The route-level bearer gate is verified live; here we cover the builders.
4
5import { test } from 'node:test';
6import assert from 'node:assert/strict';
7
8process.env.DATABASE_PATH = ':memory:';
9process.env.PUBLIC_BASE_URL = 'https://klonkt.test';
10
11const dbMod = await import('../src/config/database.js');
12dbMod.initializeDatabase();
13const AP = await import('../src/services/ActivityPubService.js');
14
15const base = 'https://klonkt.test';
16const site = { slug: 'me', primary_slug: 'me' };
17
18test('followers/following are count-only when no items are passed', () => {
19 const f = AP.buildFollowers(base, site, 7);
20 assert.equal(f.type, 'OrderedCollection');
21 assert.equal(f.totalItems, 7);
22 assert.deepEqual(f.orderedItems, []);
23
24 const g = AP.buildFollowing(base, site, 3);
25 assert.equal(g.totalItems, 3);
26 assert.deepEqual(g.orderedItems, []);
27});
28
29test('the owner view carries the real actor URIs', () => {
30 const uris = ['https://a.test/actor', 'https://b.test/actor'];
31 const f = AP.buildFollowers(base, site, 999, uris);
32 assert.deepEqual(f.orderedItems, uris);
33 assert.equal(f.totalItems, 2); // reflects the items, not the passed count
34
35 const g = AP.buildFollowing(base, site, 0, uris);
36 assert.deepEqual(g.orderedItems, uris);
37 assert.equal(g.totalItems, 2);
38});
39
40test('an empty owner list is a valid empty collection, not count-only fallback', () => {
41 const f = AP.buildFollowers(base, site, 5, []);
42 assert.equal(f.totalItems, 0);
43 assert.deepEqual(f.orderedItems, []);
44});
Note: See TracBrowser for help on using the repository browser.