diff options
author | Raphael Kabo <raphael.kabo@theguardian.com> | 2024-07-16 13:24:20 +0100 |
---|---|---|
committer | Raphael Kabo <raphael.kabo@theguardian.com> | 2024-07-16 13:24:20 +0100 |
commit | ee6ee9aef071162b86c72aea21da483b0bb3e050 (patch) | |
tree | dd2db415da188707a718c4c52708b75a94e2f376 /src/routes | |
parent | edf113e18cd05edd51e9da96b2a8004382cda83a (diff) |
fix: router bug in activitypub router
We had a middleware applied in the activitypub router which would return 404 for all routes if activitypub wasn't enabled. Unfortunately due to the way Express works, that middleware also applied to every route below that router's routes in the base router chain. Instead, we now apply the middleware specifically to the individual routes in the activitypub file.
Diffstat (limited to 'src/routes')
-rw-r--r-- | src/routes/activitypub.ts | 284 |
1 files changed, 150 insertions, 134 deletions
diff --git a/src/routes/activitypub.ts b/src/routes/activitypub.ts index fc61dd7..5f141ec 100644 --- a/src/routes/activitypub.ts +++ b/src/routes/activitypub.ts @@ -21,71 +21,79 @@ const send404IfNotFederated = ( next(); }; -router.use(send404IfNotFederated); - // return the JSON for the featured/pinned post for this event -router.get("/:eventID/featured", (req: Request, res: Response) => { - const { eventID } = req.params; - const featured = { - "@context": "https://www.w3.org/ns/activitystreams", - id: `https://${res.locals.config?.general.domain}/${eventID}/featured`, - type: "OrderedCollection", - orderedItems: [createFeaturedPost(eventID)], - }; - if (acceptsActivityPub(req)) { - res.header("Content-Type", "application/activity+json").send(featured); - } else { - res.header("Content-Type", "application/json").send(featured); - } -}); +router.get( + "/:eventID/featured", + send404IfNotFederated, + (req: Request, res: Response) => { + const { eventID } = req.params; + const featured = { + "@context": "https://www.w3.org/ns/activitystreams", + id: `https://${res.locals.config?.general.domain}/${eventID}/featured`, + type: "OrderedCollection", + orderedItems: [createFeaturedPost(eventID)], + }; + if (acceptsActivityPub(req)) { + res.header("Content-Type", "application/activity+json").send( + featured, + ); + } else { + res.header("Content-Type", "application/json").send(featured); + } + }, +); // return the JSON for a given activitypub message -router.get("/:eventID/m/:hash", async (req: Request, res: Response) => { - const { hash, eventID } = req.params; - const id = `https://${res.locals.config?.general.domain}/${eventID}/m/${hash}`; +router.get( + "/:eventID/m/:hash", + send404IfNotFederated, + async (req: Request, res: Response) => { + const { hash, eventID } = req.params; + const id = `https://${res.locals.config?.general.domain}/${eventID}/m/${hash}`; - try { - const event = await Event.findOne({ - id: eventID, - }); - if (!event) { - return res.status(404).render("404", frontendConfig(res)); - } else { - if (!event.activityPubMessages) { + try { + const event = await Event.findOne({ + id: eventID, + }); + if (!event) { return res.status(404).render("404", frontendConfig(res)); - } - const message = event.activityPubMessages.find( - (el) => el.id === id, - ); - if (message) { - if (acceptsActivityPub(req)) { - res.header( - "Content-Type", - "application/activity+json", - ).send(JSON.parse(message.content || "{}")); + } else { + if (!event.activityPubMessages) { + return res.status(404).render("404", frontendConfig(res)); + } + const message = event.activityPubMessages.find( + (el) => el.id === id, + ); + if (message) { + if (acceptsActivityPub(req)) { + res.header( + "Content-Type", + "application/activity+json", + ).send(JSON.parse(message.content || "{}")); + } else { + res.header("Content-Type", "application/json").send( + JSON.parse(message.content || "{}"), + ); + } } else { - res.header("Content-Type", "application/json").send( - JSON.parse(message.content || "{}"), - ); + return res.status(404).render("404", frontendConfig(res)); } - } else { - return res.status(404).render("404", frontendConfig(res)); } + } catch (err) { + addToLog( + "getActivityPubMessage", + "error", + "Attempt to get Activity Pub Message for " + + id + + " failed with error: " + + err, + ); + return res.status(404).render("404", frontendConfig(res)); } - } catch (err) { - addToLog( - "getActivityPubMessage", - "error", - "Attempt to get Activity Pub Message for " + - id + - " failed with error: " + - err, - ); - return res.status(404).render("404", frontendConfig(res)); - } -}); + }, +); -router.get("/.well-known/nodeinfo", (req, res) => { +router.get("/.well-known/nodeinfo", send404IfNotFederated, (req, res) => { if (!res.locals.config?.general.is_federated) { return res.status(404).render("404", frontendConfig(res)); } @@ -103,94 +111,102 @@ router.get("/.well-known/nodeinfo", (req, res) => { ).send(nodeInfo); }); -router.get("/.well-known/nodeinfo/2.2", async (req, res) => { - const eventCount = await Event.countDocuments(); +router.get( + "/.well-known/nodeinfo/2.2", + send404IfNotFederated, + async (req, res) => { + const eventCount = await Event.countDocuments(); - if (!res.locals.config?.general.is_federated) { - return res.status(404).render("404", frontendConfig(res)); - } - const nodeInfo = { - version: "2.2", - instance: { - name: res.locals.config?.general.site_name, - description: - "Federated, no-registration, privacy-respecting event hosting.", - }, - software: { - name: "Gathio", - version: process.env.npm_package_version || "unknown", - repository: "https://github.com/lowercasename/gathio", - homepage: "https://gath.io", - }, - protocols: ["activitypub"], - services: { - inbound: [], - outbound: [], - }, - openRegistrations: true, - usage: { - users: { - total: eventCount, + if (!res.locals.config?.general.is_federated) { + return res.status(404).render("404", frontendConfig(res)); + } + const nodeInfo = { + version: "2.2", + instance: { + name: res.locals.config?.general.site_name, + description: + "Federated, no-registration, privacy-respecting event hosting.", }, - }, - }; - res.header( - "Content-Type", - 'application/json; profile="http://nodeinfo.diaspora.software/ns/schema/2.1#"', - ).send(nodeInfo); -}); - -router.get("/.well-known/webfinger", async (req, res) => { - let resource = req.query.resource as string; - if (!resource || !resource.includes("acct:")) { - return res - .status(400) - .send( - 'Bad request. Please make sure "acct:USER@DOMAIN" is what you are sending as the "resource" query parameter.', - ); - } else { - // "foo@domain" - let activityPubAccount = resource.replace("acct:", ""); - // "foo" - let eventID = activityPubAccount.replace(/@.*/, ""); + software: { + name: "Gathio", + version: process.env.npm_package_version || "unknown", + repository: "https://github.com/lowercasename/gathio", + homepage: "https://gath.io", + }, + protocols: ["activitypub"], + services: { + inbound: [], + outbound: [], + }, + openRegistrations: true, + usage: { + users: { + total: eventCount, + }, + }, + }; + res.header( + "Content-Type", + 'application/json; profile="http://nodeinfo.diaspora.software/ns/schema/2.1#"', + ).send(nodeInfo); + }, +); + +router.get( + "/.well-known/webfinger", + send404IfNotFederated, + async (req, res) => { + let resource = req.query.resource as string; + if (!resource || !resource.includes("acct:")) { + return res + .status(400) + .send( + 'Bad request. Please make sure "acct:USER@DOMAIN" is what you are sending as the "resource" query parameter.', + ); + } else { + // "foo@domain" + let activityPubAccount = resource.replace("acct:", ""); + // "foo" + let eventID = activityPubAccount.replace(/@.*/, ""); - try { - const event = await Event.findOne({ id: eventID }); + try { + const event = await Event.findOne({ id: eventID }); - if (!event) { - return res.status(404).render("404", frontendConfig(res)); - } else { - if (acceptsActivityPub(req)) { - res.header( - "Content-Type", - "application/activity+json", - ).send( - createWebfinger( - eventID, - res.locals.config?.general.domain, - ), - ); + if (!event) { + return res.status(404).render("404", frontendConfig(res)); } else { - res.header("Content-Type", "application/json").send( - createWebfinger( - eventID, - res.locals.config?.general.domain, - ), - ); + if (acceptsActivityPub(req)) { + res.header( + "Content-Type", + "application/activity+json", + ).send( + createWebfinger( + eventID, + res.locals.config?.general.domain, + ), + ); + } else { + res.header("Content-Type", "application/json").send( + createWebfinger( + eventID, + res.locals.config?.general.domain, + ), + ); + } } + } catch (err) { + addToLog( + "renderWebfinger", + "error", + `Attempt to render webfinger for ${resource} failed with error: ${err}`, + ); + return res.status(404).render("404", frontendConfig(res)); } - } catch (err) { - addToLog( - "renderWebfinger", - "error", - `Attempt to render webfinger for ${resource} failed with error: ${err}`, - ); - return res.status(404).render("404", frontendConfig(res)); } - } -}); + }, +); -router.get("/:eventID/followers", async (req, res) => { +router.get("/:eventID/followers", send404IfNotFederated, async (req, res) => { const eventID = req.params.eventID; try { |