From ef484c069d89a2a4b1653f5e3d8fb0853218a88f Mon Sep 17 00:00:00 2001 From: svemagie <869694+svemagie@users.noreply.github.com> Date: Sun, 8 Mar 2026 04:57:27 +0100 Subject: [PATCH] Remove legacy redirect patches and session auto-continue patch --- README.md | 7 +- package.json | 4 +- scripts/patch-indieauth-devmode-guard.mjs | 53 -------------- scripts/patch-session-login-autocontinue.mjs | 74 -------------------- start.example.sh | 1 - 5 files changed, 3 insertions(+), 136 deletions(-) delete mode 100644 scripts/patch-session-login-autocontinue.mjs diff --git a/README.md b/README.md index c4d35b40..077f6ec4 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,6 @@ ## Admin login - The IndieKit admin uses root auth/session paths (for example: `/session/login`, `/auth`, `/auth/new-password`). -- Legacy `/admin` request paths are normalized to root login redirects (for example `/admin/posts` -> `/session/login?redirect=/posts`) to avoid post-login dead-end targets. -- Legacy auth/session aliases are redirected directly (for example `/admin/auth/new-password` -> `/auth/new-password`, `/admin/session/login` -> `/session/login`). -- Legacy redirect query targets are normalized as well (for example `/session/login?redirect=/admin/posts` becomes post-login redirect to `/posts`). -- Login page now auto-continues to the password consent screen by default. Add `?noautocontinue=1` to `/session/login` if you want to keep the manual button step. - Login uses `PASSWORD_SECRET` (bcrypt hash), not `INDIEKIT_PASSWORD`. - If no `PASSWORD_SECRET` exists yet, open `/auth/new-password` once to generate it. - If login is blocked because `PASSWORD_SECRET` is missing/invalid, set `INDIEKIT_ALLOW_PASSWORD_SETUP=1` temporarily, restart, generate a new hash via `/auth/new-password`, set `PASSWORD_SECRET` to that hash, then remove `INDIEKIT_ALLOW_PASSWORD_SETUP`. @@ -73,7 +69,7 @@ - `start.sh` is intentionally ignored by Git (`.gitignore`) so server secrets are not committed. - Use `start.example.sh` as the tracked template and keep real credentials in environment variables (or `.env` on the server). - Startup scripts parse `.env` with the `dotenv` parser (not shell `source`), so values containing spaces are handled safely. -- Startup scripts run preflight + patch helpers before boot (`scripts/preflight-production-security.mjs`, `scripts/preflight-mongo-connection.mjs`, `scripts/patch-lightningcss.mjs`, `scripts/patch-endpoint-media-scope.mjs`, `scripts/patch-endpoint-media-sharp-runtime.mjs`, `scripts/patch-frontend-sharp-runtime.mjs`, `scripts/patch-endpoint-files-upload-route.mjs`, `scripts/patch-endpoint-files-upload-locales.mjs`, `scripts/patch-frontend-serviceworker-file.mjs`, `scripts/patch-conversations-collection-guards.mjs`, `scripts/patch-indieauth-devmode-guard.mjs`, `scripts/patch-session-login-autocontinue.mjs`). +- Startup scripts run preflight + patch helpers before boot (`scripts/preflight-production-security.mjs`, `scripts/preflight-mongo-connection.mjs`, `scripts/patch-lightningcss.mjs`, `scripts/patch-endpoint-media-scope.mjs`, `scripts/patch-endpoint-media-sharp-runtime.mjs`, `scripts/patch-frontend-sharp-runtime.mjs`, `scripts/patch-endpoint-files-upload-route.mjs`, `scripts/patch-endpoint-files-upload-locales.mjs`, `scripts/patch-frontend-serviceworker-file.mjs`, `scripts/patch-conversations-collection-guards.mjs`, `scripts/patch-indieauth-devmode-guard.mjs`). - The production security preflight blocks startup on insecure auth/session configuration and catches empty-password bcrypt hashes. - One-time recovery mode is available with `INDIEKIT_ALLOW_PASSWORD_SETUP=1` to bootstrap/reset `PASSWORD_SECRET` when locked out. Remove this flag after setting a valid hash. - The media scope patch fixes a known upstream issue where file uploads can fail if the token scope is `create update delete` without explicit `media`. @@ -84,4 +80,3 @@ - The frontend serviceworker patch ensures `@indiekit/frontend/lib/serviceworker.js` exists at runtime to avoid ENOENT in the offline/service worker route. - The conversations guard patch prevents `Cannot read properties of undefined (reading 'find')` when the `conversation_items` collection is temporarily unavailable. - The indieauth dev-mode guard patch prevents accidental production auth bypass by requiring explicit `INDIEKIT_ALLOW_DEV_AUTH=1` to enable dev auto-login. -- The session login auto-continue patch redirects from the intermediate `/session/login` screen to the password consent form automatically (with optional `?noautocontinue=1` override). diff --git a/package.json b/package.json index 6ff22cac..9b03ea31 100644 --- a/package.json +++ b/package.json @@ -4,8 +4,8 @@ "description": "", "main": "index.js", "scripts": { - "postinstall": "node scripts/patch-lightningcss.mjs && node scripts/patch-endpoint-media-scope.mjs && node scripts/patch-endpoint-media-sharp-runtime.mjs && node scripts/patch-frontend-sharp-runtime.mjs && node scripts/patch-endpoint-files-upload-route.mjs && node scripts/patch-endpoint-files-upload-locales.mjs && node scripts/patch-frontend-serviceworker-file.mjs && node scripts/patch-conversations-collection-guards.mjs && node scripts/patch-indieauth-devmode-guard.mjs && node scripts/patch-session-login-autocontinue.mjs", - "serve": "export NODE_ENV=${NODE_ENV:-production} INDIEKIT_DEBUG=${INDIEKIT_DEBUG:-0} && node scripts/preflight-production-security.mjs && node scripts/preflight-mongo-connection.mjs && node scripts/patch-lightningcss.mjs && node scripts/patch-endpoint-media-scope.mjs && node scripts/patch-endpoint-media-sharp-runtime.mjs && node scripts/patch-frontend-sharp-runtime.mjs && node scripts/patch-endpoint-files-upload-route.mjs && node scripts/patch-endpoint-files-upload-locales.mjs && node scripts/patch-frontend-serviceworker-file.mjs && node scripts/patch-conversations-collection-guards.mjs && node scripts/patch-indieauth-devmode-guard.mjs && node scripts/patch-session-login-autocontinue.mjs && node node_modules/@indiekit/indiekit/bin/cli.js serve --config indiekit.config.mjs", + "postinstall": "node scripts/patch-lightningcss.mjs && node scripts/patch-endpoint-media-scope.mjs && node scripts/patch-endpoint-media-sharp-runtime.mjs && node scripts/patch-frontend-sharp-runtime.mjs && node scripts/patch-endpoint-files-upload-route.mjs && node scripts/patch-endpoint-files-upload-locales.mjs && node scripts/patch-frontend-serviceworker-file.mjs && node scripts/patch-conversations-collection-guards.mjs && node scripts/patch-indieauth-devmode-guard.mjs", + "serve": "export NODE_ENV=${NODE_ENV:-production} INDIEKIT_DEBUG=${INDIEKIT_DEBUG:-0} && node scripts/preflight-production-security.mjs && node scripts/preflight-mongo-connection.mjs && node scripts/patch-lightningcss.mjs && node scripts/patch-endpoint-media-scope.mjs && node scripts/patch-endpoint-media-sharp-runtime.mjs && node scripts/patch-frontend-sharp-runtime.mjs && node scripts/patch-endpoint-files-upload-route.mjs && node scripts/patch-endpoint-files-upload-locales.mjs && node scripts/patch-frontend-serviceworker-file.mjs && node scripts/patch-conversations-collection-guards.mjs && node scripts/patch-indieauth-devmode-guard.mjs && node node_modules/@indiekit/indiekit/bin/cli.js serve --config indiekit.config.mjs", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [], diff --git a/scripts/patch-indieauth-devmode-guard.mjs b/scripts/patch-indieauth-devmode-guard.mjs index 10910938..a02092e0 100644 --- a/scripts/patch-indieauth-devmode-guard.mjs +++ b/scripts/patch-indieauth-devmode-guard.mjs @@ -14,43 +14,6 @@ const newDevModeCode = `if (devMode && process.env.INDIEKIT_ALLOW_DEV_AUTH === " request.session.scope = "create update delete media"; } else if (!process.env.PASSWORD_SECRET) {`; -const newCallbackRedirectCode = ` const { redirect } = request.query; - const requestedRedirect = - typeof redirect === "string" ? redirect : ""; - const normalizedRedirect = - requestedRedirect === "/admin" - ? "/" - : requestedRedirect.replace(/^\\/admin(?=\\/)/, ""); - this.redirectUri = normalizedRedirect - ? \`\${callbackUrl}?redirect=\${normalizedRedirect}\` - : \`\${callbackUrl}\`;`; - -const oldCallbackRedirectRegex = - /const \{ redirect \} = request\.query;\n\s+this\.redirectUri = redirect\n\s+\? `\$\{callbackUrl\}\?redirect=\$\{redirect\}`\n\s+: `\$\{callbackUrl\}`;/m; - -const newLoginRedirectCode = ` if (request.method === "GET") { - const directAlias = request.originalUrl.replace( - /^\\/admin\\/(auth|session)(?=\\/|$)/, - "/$1", - ); - if (directAlias !== request.originalUrl) { - return response.redirect(directAlias); - } - - const loginRedirect = - request.originalUrl === "/admin" - ? "/" - : request.originalUrl.replace(/^\\/admin(?=\\/)/, ""); - return response.redirect( - \`/session/login?redirect=\${loginRedirect}\`, - ); - }`; - -const oldLoginRedirectRegexes = [ - /if \(request\.method === "GET"\) \{\n\s+return response\.redirect\(\n\s+`\/session\/login\?redirect=\$\{request\.originalUrl\}`,\n\s+\);\n\s+\}/m, - /if \(request\.method === "GET"\) \{\n\s+const loginRedirect =[\s\S]*?`\/session\/login\?redirect=\$\{loginRedirect\}`,\n\s+\);\n\s+\}/m, -]; - async function exists(path) { try { await access(path); @@ -77,22 +40,6 @@ for (const filePath of candidates) { updated = updated.replace(oldDevModeCode, newDevModeCode); } - if ( - !updated.includes("const normalizedRedirect =") && - oldCallbackRedirectRegex.test(updated) - ) { - updated = updated.replace(oldCallbackRedirectRegex, newCallbackRedirectCode); - } - - if (!updated.includes("const directAlias = request.originalUrl.replace(")) { - for (const regex of oldLoginRedirectRegexes) { - if (regex.test(updated)) { - updated = updated.replace(regex, newLoginRedirectCode); - break; - } - } - } - if (updated !== source) { await writeFile(filePath, updated, "utf8"); patched += 1; diff --git a/scripts/patch-session-login-autocontinue.mjs b/scripts/patch-session-login-autocontinue.mjs deleted file mode 100644 index 1fd44b64..00000000 --- a/scripts/patch-session-login-autocontinue.mjs +++ /dev/null @@ -1,74 +0,0 @@ -import { access, readFile, writeFile } from "node:fs/promises"; - -const candidates = [ - "node_modules/@indiekit/indiekit/views/session/login.njk", -]; - -const oldBlock = ` {{ button({ - text: __("session.login.submit"), - classes: "button--block" - }) | indent(2) }} -{% endblock %}`; - -const newBlock = ` {{ button({ - text: __("session.login.submit"), - classes: "button--block" - }) | indent(2) }} - - - - -{% endblock %}`; - -async function exists(path) { - try { - await access(path); - 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("noautocontinue")) { - continue; - } - - if (!source.includes(oldBlock)) { - continue; - } - - const updated = source.replace(oldBlock, newBlock); - await writeFile(filePath, updated, "utf8"); - patched += 1; -} - -if (checked === 0) { - console.log("[postinstall] No session login templates found"); -} else if (patched === 0) { - console.log("[postinstall] session login auto-continue already patched"); -} else { - console.log(`[postinstall] Patched session login auto-continue in ${patched} file(s)`); -} diff --git a/start.example.sh b/start.example.sh index 20d7ca54..6116fc41 100644 --- a/start.example.sh +++ b/start.example.sh @@ -55,6 +55,5 @@ unset DEBUG /usr/local/bin/node scripts/patch-frontend-serviceworker-file.mjs /usr/local/bin/node scripts/patch-conversations-collection-guards.mjs /usr/local/bin/node scripts/patch-indieauth-devmode-guard.mjs -/usr/local/bin/node scripts/patch-session-login-autocontinue.mjs exec /usr/local/bin/node node_modules/@indiekit/indiekit/bin/cli.js serve --config indiekit.config.mjs