mirror of
https://github.com/svemagie/indiekit-endpoint-activitypub.git
synced 2026-04-02 15:44:58 +02:00
Fedify 2.1.0 upgrade: - Upgrade @fedify/fedify, @fedify/redis, @fedify/debugger to ^2.1.0 - Remove as:Endpoints type-stripping workaround (fixed upstream, fedify#576) - Wire onUnverifiedActivity handler for Delete from actors with gone keys FEP implementations: - FEP-5feb: Add indexable + discoverable to actor (search indexing consent) - FEP-f1d5/0151: Enrich NodeInfo 2.1 with metadata, staff accounts, repo info - FEP-4f05: Soft delete with Tombstone — deleted posts serve 410 + Tombstone JSON-LD with formerType, published, deleted timestamps. New ap_tombstones collection + lib/storage/tombstones.js - FEP-3b86: Activity Intents — WebFinger links for Follow/Create/Like/Announce intents, authorize_interaction routes by intent parameter - FEP-8fcf: Collection Sync outbound via Fedify syncCollection (documented that receiving side is not yet implemented)
60 lines
2.0 KiB
JavaScript
60 lines
2.0 KiB
JavaScript
/**
|
|
* Authorize Interaction controller — handles the remote follow / authorize
|
|
* interaction flow for ActivityPub federation.
|
|
*
|
|
* Supports:
|
|
* - OStatus subscribe template (legacy remote follow via ?uri=...)
|
|
* - FEP-3b86 Activity Intents (via ?uri=...&intent=follow|create|like|announce)
|
|
*
|
|
* Flow:
|
|
* 1. Missing uri → render error page
|
|
* 2. Unauthenticated → redirect to login, then back here
|
|
* 3. Authenticated → route to appropriate page based on intent
|
|
*/
|
|
|
|
export function authorizeInteractionController(plugin) {
|
|
return async (req, res) => {
|
|
const uri = req.query.uri || req.query.acct;
|
|
const intent = req.query.intent || "";
|
|
|
|
if (!uri) {
|
|
return res.status(400).render("activitypub-authorize-interaction", {
|
|
title: "Authorize Interaction",
|
|
mountPath: plugin.options.mountPath,
|
|
error: "Missing uri parameter",
|
|
});
|
|
}
|
|
|
|
// Clean up acct: prefix if present
|
|
const resource = uri.replace(/^acct:/, "");
|
|
|
|
// Check authentication — if not logged in, redirect to login
|
|
// then back to this page after auth
|
|
const session = req.session;
|
|
if (!session?.access_token) {
|
|
const params = `uri=${encodeURIComponent(uri)}${intent ? `&intent=${intent}` : ""}`;
|
|
const returnUrl = `${plugin.options.mountPath}/authorize_interaction?${params}`;
|
|
return res.redirect(
|
|
`/session/login?redirect=${encodeURIComponent(returnUrl)}`,
|
|
);
|
|
}
|
|
|
|
const mp = plugin.options.mountPath;
|
|
const encodedUrl = encodeURIComponent(resource);
|
|
|
|
// Route based on intent (FEP-3b86)
|
|
switch (intent) {
|
|
case "follow":
|
|
return res.redirect(`${mp}/admin/reader/profile?url=${encodedUrl}`);
|
|
case "create":
|
|
return res.redirect(`${mp}/admin/reader/compose?replyTo=${encodedUrl}`);
|
|
case "like":
|
|
case "announce":
|
|
return res.redirect(`${mp}/admin/reader/post?url=${encodedUrl}`);
|
|
default:
|
|
// Default: resolve to remote profile page
|
|
return res.redirect(`${mp}/admin/reader/profile?url=${encodedUrl}`);
|
|
}
|
|
};
|
|
}
|