The signatureTimeWindow patch was deleted ine52e98c5c(assumed fixed in fork), but the lockfile still pins the fork to v2.10.1 which lacks it. This broke the patch-ap-allow-private-address patch chain: it expected signatureTimeWindow in its OLD_SNIPPET, never matched, and silently skipped — leaving the server without both signatureTimeWindow AND allowPrivateAddress. Without allowPrivateAddress, Fedify's SSRF guard blocks own-site URL resolution (blog.giersig.eu → 10.100.0.10), breaking federation delivery. - Fix patch-ap-allow-private-address to handle fresh v2.10.1 (adds both signatureTimeWindow and allowPrivateAddress in one step) - Restore patch-ap-object-url-trailing-slash (also lost ine52e98c5c) - Add both patches to postinstall and serve scripts Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
82 lines
2.6 KiB
JavaScript
82 lines
2.6 KiB
JavaScript
/**
|
|
* Patch: make the Fedify object dispatcher's post lookup tolerate trailing-slash
|
|
* differences between the AP object URL and the stored post URL.
|
|
*
|
|
* Root cause:
|
|
* setupObjectDispatchers resolvePost() builds postUrl from the {+id} template
|
|
* variable (e.g. "replies/bd78a") and does an exact findOne() match against
|
|
* posts.properties.url. Posts in MongoDB are stored with a trailing slash
|
|
* ("https://blog.giersig.eu/replies/bd78a/"), but the AP object URL returned
|
|
* by the /api/ap-url lookup endpoint has no trailing slash. The exact match
|
|
* fails → Fedify returns 404 → remote instance shows "Could not connect".
|
|
*
|
|
* Fix:
|
|
* Replace the single-value findOne() with a $in query that tries both the
|
|
* bare URL and the URL with a trailing slash appended.
|
|
*/
|
|
|
|
import { access, readFile, writeFile } from "node:fs/promises";
|
|
|
|
const candidates = [
|
|
"node_modules/@rmdes/indiekit-endpoint-activitypub/lib/federation-setup.js",
|
|
"node_modules/@indiekit/indiekit/node_modules/@rmdes/indiekit-endpoint-activitypub/lib/federation-setup.js",
|
|
];
|
|
|
|
const MARKER = "// trailing-slash url fix";
|
|
|
|
const OLD_SNIPPET = ` const postUrl = \`\${publicationUrl.replace(/\\/$/, "")}/\${id}\`;
|
|
const post = await collections.posts.findOne({ "properties.url": postUrl });`;
|
|
|
|
const NEW_SNIPPET = ` const postUrl = \`\${publicationUrl.replace(/\\/$/, "")}/\${id}\`; // trailing-slash url fix
|
|
const post = await collections.posts.findOne({
|
|
"properties.url": { $in: [postUrl, postUrl + "/"] },
|
|
});`;
|
|
|
|
async function exists(filePath) {
|
|
try {
|
|
await access(filePath);
|
|
return true;
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
let checked = 0;
|
|
let patched = 0;
|
|
|
|
for (const filePath of candidates) {
|
|
if (!(await exists(filePath))) {
|
|
continue;
|
|
}
|
|
|
|
checked += 1;
|
|
const source = await readFile(filePath, "utf8");
|
|
|
|
if (source.includes(MARKER)) {
|
|
continue;
|
|
}
|
|
|
|
if (!source.includes(OLD_SNIPPET)) {
|
|
console.log(`[postinstall] patch-ap-object-url-trailing-slash: snippet not found in ${filePath}`);
|
|
continue;
|
|
}
|
|
|
|
const updated = source.replace(OLD_SNIPPET, NEW_SNIPPET);
|
|
|
|
if (updated === source) {
|
|
continue;
|
|
}
|
|
|
|
await writeFile(filePath, updated, "utf8");
|
|
patched += 1;
|
|
console.log(`[postinstall] Applied patch-ap-object-url-trailing-slash to ${filePath}`);
|
|
}
|
|
|
|
if (checked === 0) {
|
|
console.log("[postinstall] patch-ap-object-url-trailing-slash: no target files found");
|
|
} else if (patched === 0) {
|
|
console.log("[postinstall] patch-ap-object-url-trailing-slash: already up to date");
|
|
} else {
|
|
console.log(`[postinstall] patch-ap-object-url-trailing-slash: patched ${patched}/${checked} file(s)`);
|
|
}
|