Changeset b1d5f3f in Klonkt for src/routes
- Timestamp:
- 10/24/2026 11:48:41 AM (26 hours ago)
- Branches:
- main
- Children:
- 5d0d3f35
- Parents:
- 61d52ed
- File:
-
- 1 edited
-
src/routes/activitypub.js (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/routes/activitypub.js
r61d52ed rb1d5f3f 21 21 import * as Guardianship from '../services/guardianship/index.js'; 22 22 import * as ConversationKey from '../services/conversation-key.js'; 23 import * as IdentityProof from '../services/IdentityProof.js'; 23 24 import * as Migration from '../services/MigrationService.js'; 24 25 import { getPrimarySite } from '../middleware/site.js'; … … 1029 1030 }, 1030 1031 }); 1032 // ── Identiteitsbewijzen (FEP-c390, shaer-jpxj) ──────────────────── 1033 // 1034 // De eigenaar biedt een verklaring aan die met een sleutel van ELDERS is 1035 // ondertekend: "did:key:... is ook deze actor". Deze server ondertekent niets; 1036 // hij controleert (IdentityProof.checkStatement) en publiceert onder 1037 // `attachment` op de actor, waar iedereen hem zelf kan nalopen. 1038 // 1039 // Eén per did:key: een nieuwe verklaring met dezelfde sleutel vervangt de 1040 // vorige, want een verhuizing of een vernieuwde datum is dezelfde bewering. 1041 // Een handvol is genoeg; meer is geen identiteit meer maar een verzameling. 1042 const MAX_IDENTITY_PROOFS = 3; 1043 function readProofs(site) { 1044 try { const a = JSON.parse(site.identity_proofs || '[]'); return Array.isArray(a) ? a : []; } catch { return []; } 1045 } 1046 function writeProofs(site, list) { 1047 db.prepare('UPDATE sites SET identity_proofs = ? WHERE id = ?').run(list.length ? JSON.stringify(list) : null, site.id); 1048 // De volgers horen dat de actor veranderde; anders blijft hun kopie de oude. 1049 const vers = db.prepare('SELECT * FROM sites WHERE id = ?').get(site.id); 1050 if (vers) AP.deliverActorUpdate(vers).catch((e) => console.warn('[c390] actor-update:', e && e.message)); 1051 } 1052 router.post('/ap/users/:slug/identityProofs', express.json({ limit: '16kb', type: ['application/json', 'application/activity+json', 'application/ld+json'] }), (req, res) => { 1053 const auth = OAuth.verifyBearer(req.headers.authorization); 1054 if (!auth || auth.site.slug !== req.params.slug) return res.status(403).end(); 1055 const base = baseUrl(req); 1056 const me = AP.actorId(base, auth.site.slug); 1057 const stmt = req.body; 1058 const uitslag = IdentityProof.checkStatement(stmt, me); 1059 if (!uitslag.ok) return res.status(422).json({ error: uitslag.error }); 1060 const site = db.prepare('SELECT * FROM sites WHERE id = ?').get(auth.site.id); 1061 const rest = readProofs(site).filter((b) => b && b.subject !== uitslag.subject); 1062 if (rest.length >= MAX_IDENTITY_PROOFS) return res.status(409).json({ error: 'too_many_identity_proofs', max: MAX_IDENTITY_PROOFS }); 1063 writeProofs(site, [...rest, stmt]); 1064 res.status(201).json({ subject: uitslag.subject, alsoKnownAs: me }); 1065 }); 1066 router.delete('/ap/users/:slug/identityProofs', (req, res) => { 1067 const auth = OAuth.verifyBearer(req.headers.authorization); 1068 if (!auth || auth.site.slug !== req.params.slug) return res.status(403).end(); 1069 const subject = String(req.query.subject || ''); 1070 if (!IdentityProof.publicKeyFromDidKey(subject)) return res.status(400).json({ error: 'subject must be an Ed25519 did:key' }); 1071 const site = db.prepare('SELECT * FROM sites WHERE id = ?').get(auth.site.id); 1072 const voor = readProofs(site); 1073 const na = voor.filter((b) => b && b.subject !== subject); 1074 if (na.length === voor.length) return res.status(404).json({ error: 'no_such_identity_proof' }); 1075 writeProofs(site, na); 1076 res.status(204).end(); 1077 }); 1078 1031 1079 router.post('/ap/users/:slug/uploadMedia', (req, res) => { 1032 1080 const auth = OAuth.verifyBearer(req.headers.authorization);
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)