Files
adventureland/docker/patch-auto-verify-email.js
anima 3de09009d6
build container / build (push) Failing after 1m25s
fix mail verify
2026-11-02 02:16:44 +01:00

107 lines
4.1 KiB
JavaScript

#!/usr/bin/env node
// Local patch: optional email auto-verification for self-hosted servers.
//
// Adventure Land normally emails a verification link after signup. A
// self-hosted server without SES/SMTP cannot deliver it, so every new account
// stays "Not Verified" (luck/gold -25%) until an admin verifies it manually.
//
// With options.auto_verify_email enabled, this patch:
// - marks new accounts verified before they are saved,
// - verifies existing accounts on their next login,
// - keeps accounts verified when they change their email address,
// - skips the verification emails that cannot be delivered.
//
// Upstream behaviour is unchanged when the option is absent or false. Every
// edit is idempotent and fails loudly if the anchor is gone.
const fs = require("node:fs");
const path = require("node:path");
const app = path.resolve(process.argv[2] || "/app");
const file = path.join(app, "api.js");
let source = fs.readFileSync(file, "utf8");
// `options` is always present in production, but some upstream tests load
// api.js without it. Keep the patched code loadable there too.
const autoVerify = 'typeof options !== "undefined" && options.auto_verify_email';
function fail(message) {
console.error("patch-auto-verify-email: " + message);
process.exit(1);
}
function edit(label, from, to) {
if (source.includes(to)) {
console.log("patch-auto-verify-email: " + label + " already patched");
return;
}
const occurrences = source.split(from).length - 1;
if (occurrences !== 1) {
fail(label + ": expected 1 occurrence of the anchor, found " + occurrences);
}
source = source.replace(from, to);
console.log("patch-auto-verify-email: patched " + label);
}
// 1. Existing accounts: verify them when they log in.
edit(
"login",
`\t\t\t\t\tR.auth = get_new_auth(R.user);
\t\t\t\t\tawait tx_save(R.user);`,
`\t\t\t\t\t// Local: keep accounts verified without an email service.
\t\t\t\t\tif (${autoVerify}) R.user.info.verified = true;
\t\t\t\t\tR.auth = get_new_auth(R.user);
\t\t\t\t\tawait tx_save(R.user);`,
);
// 2. New accounts: set the flag before the user document is written.
edit(
"signup",
`\t\t\t\tblobs: ["info"],
\t\t\t};
\t\t\tR.auth = get_new_auth(R.user);`,
`\t\t\t\tblobs: ["info"],
\t\t\t};
\t\t\t// Local: new accounts are verified immediately without an email service.
\t\t\tif (${autoVerify}) R.user.info.verified = true;
\t\t\tR.auth = get_new_auth(R.user);`,
);
// 3. Signup: do not try to send a verification email when auto-verify is on.
edit(
"signup email",
`\tset_cookie(args.res, options.cookie_key, get_id(R.user) + "-" + R.auth, domain.domain);
\tsend_verification_email(domain, R.user);
\targs.res.infs.push({ type: "success", message: phrase_html("server.api.signup_complete") });`,
`\tset_cookie(args.res, options.cookie_key, get_id(R.user) + "-" + R.auth, domain.domain);
\tif (!(${autoVerify})) send_verification_email(domain, R.user);
\targs.res.infs.push({ type: "success", message: phrase_html("server.api.signup_complete") });`,
);
// 4. Email changes: keep the account verified.
edit(
"email change verification",
`\t\t\tif (gf(R.user, "verified", 0)) delete R.user.info.verified;`,
`\t\t\t// Local: keep the account verified after an email change.
\t\t\tif (${autoVerify}) R.user.info.verified = true;
\t\t\telse if (gf(R.user, "verified", 0)) delete R.user.info.verified;`,
);
// 5. Email changes: skip the verification email and its "re-sent" message.
edit(
"email change email",
`\tif (R.failed) return { failed: true, reason: R.reason || "operation_failed" };
\tsend_verification_email(domain, R.user);
\targs.res.infs.push({ type: "success", message: phrase_html("server.api.email_changed_verification_email_re_sent_refresh_the_page") });`,
`\tif (R.failed) return { failed: true, reason: R.reason || "operation_failed" };
\tif (${autoVerify}) {
\t\targs.res.infs.push({ type: "success", message: phrase_html("server.api.setting_changed") });
\t} else {
\t\tsend_verification_email(domain, R.user);
\t\targs.res.infs.push({ type: "success", message: phrase_html("server.api.email_changed_verification_email_re_sent_refresh_the_page") });
\t}`,
);
fs.writeFileSync(file, source);
console.log("patch-auto-verify-email: wrote " + file);