Changeset 5c373b8 in Klonkt for src/routes/guardian2.js
- Timestamp:
- 07/25/2026 07:51:28 AM (7 weeks ago)
- Branches:
- main
- Children:
- e62f65d
- Parents:
- 28267519
- File:
-
- 1 edited
-
src/routes/guardian2.js (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
src/routes/guardian2.js
r28267519 r5c373b8 129 129 })); 130 130 res.json({ items, following: wardUris.size }); 131 }); 132 133 // ── Follow-gating (FEP-633c §5.3): pending follows on MY wards, for me to 134 // approve. Ward and guardian are co-located on the family Klonkt here, so 135 // the guardian reads its wards' pending follows locally. 136 function wardSlugsOf(site) { 137 const base = (process.env.PUBLIC_BASE_URL || '').replace(/\/+$/, ''); 138 return Guardianship.listWards(site.slug) 139 .map((w) => (w.other_uri.startsWith(base) ? w.other_uri.split('/').pop() : null)) 140 .filter(Boolean); 141 } 142 143 router.get('/api/follow-requests', requireAuth, (req, res) => { 144 const site = siteForUser(req); 145 if (!site) return res.status(404).json({ error: 'no_site' }); 146 const items = []; 147 for (const wardSlug of wardSlugsOf(site)) { 148 for (const f of Guardianship.follows.listForWard(wardSlug)) { 149 items.push({ id: f.id, ward: wardSlug, follower: f.follower_handle || f.follower_name || f.follower_uri, followerIcon: f.follower_icon, created: f.created_at }); 150 } 151 } 152 res.json({ items }); 153 }); 154 155 router.post('/api/follow/:id', requireAuth, express.json({ limit: '4kb' }), async (req, res) => { 156 const site = siteForUser(req); 157 if (!site) return res.status(404).json({ error: 'no_site' }); 158 const base = (process.env.PUBLIC_BASE_URL || '').replace(/\/+$/, ''); 159 const me = AP.actorId(base, site.slug); 160 const decision = req.body?.decision === 'reject' ? 'reject' : 'approve'; 161 const pending = Guardianship.follows.getPending(req.params.id); 162 if (!pending) return res.status(404).json({ error: 'gone' }); 163 // I must actually be a guardian of this ward. 164 const guardians = Guardianship.listGuardians(pending.ward_slug).map((g) => g.other_uri); 165 if (!guardians.includes(me)) return res.status(403).json({ error: 'not_a_guardian' }); 166 const r = Guardianship.follows.decide(pending.id, me, decision, guardians); 167 try { 168 if (r.outcome === 'approved') { await AP.acceptGatedFollow(r.follow); Guardianship.follows.remove(r.follow.id); } 169 else if (r.outcome === 'rejected') { await AP.rejectGatedFollow(r.follow); Guardianship.follows.remove(r.follow.id); } 170 } catch (e) { return res.status(502).json({ error: 'delivery', outcome: r.outcome }); } 171 res.json({ ok: true, outcome: r.outcome }); 131 172 }); 132 173
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)