+9
-1
@@ -59,13 +59,21 @@ COPY docker/patch-attribution.js /tmp/patch-attribution.js
|
|||||||
RUN node /tmp/patch-attribution.js /app/htmls/contents/account_help.html
|
RUN node /tmp/patch-attribution.js /app/htmls/contents/account_help.html
|
||||||
|
|
||||||
# Local patch: custom game values and elements (docker/patch-custom-game.js).
|
# Local patch: custom game values and elements (docker/patch-custom-game.js).
|
||||||
# Hooks the loader into main.js and the game server, makes the Lone Wolf rates
|
# Hooks the loader into main.js and the game server, makes the e.g. Lone Wolf rates
|
||||||
# data-driven, and merges phrase overrides into the language catalogs. The
|
# data-driven, and merges phrase overrides into the language catalogs. The
|
||||||
# loader itself is copied to /app/docker/ in the runtime stage; the custom file
|
# loader itself is copied to /app/docker/ in the runtime stage; the custom file
|
||||||
# is mounted at runtime from ./files/custom.
|
# is mounted at runtime from ./files/custom.
|
||||||
COPY docker/patch-custom-game.js /tmp/patch-custom-game.js
|
COPY docker/patch-custom-game.js /tmp/patch-custom-game.js
|
||||||
RUN node /tmp/patch-custom-game.js /app
|
RUN node /tmp/patch-custom-game.js /app
|
||||||
|
|
||||||
|
# Local patch: optional email auto-verification (docker/patch-auto-verify-email.js).
|
||||||
|
# A self-hosted server without SES cannot deliver verification links, so every
|
||||||
|
# new account would stay "Not Verified". The patch marks accounts verified at
|
||||||
|
# signup and login when options.auto_verify_email is enabled; without the
|
||||||
|
# option the upstream behaviour is unchanged.
|
||||||
|
COPY docker/patch-auto-verify-email.js /tmp/patch-auto-verify-email.js
|
||||||
|
RUN node /tmp/patch-auto-verify-email.js /app
|
||||||
|
|
||||||
|
|
||||||
FROM ${NODE_IMAGE} AS runtime
|
FROM ${NODE_IMAGE} AS runtime
|
||||||
|
|
||||||
|
|||||||
@@ -139,6 +139,12 @@ passt.
|
|||||||
Backend und Game-Server ein und macht die Lone-Wolf-Raten datengetrieben (siehe
|
Backend und Game-Server ein und macht die Lone-Wolf-Raten datengetrieben (siehe
|
||||||
„Spieldaten anpassen“). Fehlt ein Anker, bricht der Build ebenfalls ab.
|
„Spieldaten anpassen“). Fehlt ein Anker, bricht der Build ebenfalls ab.
|
||||||
|
|
||||||
|
`docker/patch-auto-verify-email.js` markiert bei aktivem
|
||||||
|
`options.auto_verify_email` neue Konten beim Signup und bestehende beim nächsten
|
||||||
|
Login als verifiziert und überspringt die Verifikationsmail. Ohne den Schalter
|
||||||
|
bleibt das Upstream-Verhalten unverändert. Auch dieser Patch bricht den Build
|
||||||
|
ab, wenn ein Anker in `api.js` fehlt.
|
||||||
|
|
||||||
## Spieldaten anpassen (`files/custom/game.js`)
|
## Spieldaten anpassen (`files/custom/game.js`)
|
||||||
|
|
||||||
Werte bestehender Elemente und neue Elemente lassen sich ohne Quelltextänderung
|
Werte bestehender Elemente und neue Elemente lassen sich ohne Quelltextänderung
|
||||||
@@ -183,12 +189,13 @@ Custom-Datei zurückgesetzt werden; dann den Game-Server neu starten.
|
|||||||
|
|
||||||
## Gut zu wissen
|
## Gut zu wissen
|
||||||
|
|
||||||
- **E-Mail-Verifizierung:** AWS SES ist nicht konfiguriert. Beim Registrieren
|
- **E-Mail-Verifizierung:** AWS SES ist nicht konfiguriert. Deshalb setzt
|
||||||
erscheint im Backend-Log `send_email error InvalidClientTokenId`. Das ist
|
`options.auto_verify_email: true` neue Konten beim Signup und bestehende beim
|
||||||
erwartet – die Registrierung funktioniert trotzdem, es wird nur keine Mail
|
nächsten Login auf „verifiziert“; die Verifikationsmail wird übersprungen. Der
|
||||||
verschickt. Bis zur Verifizierung hängt das Konto an „Not Verified“
|
„Not Verified“-Debuff (Gold/Glück −25 %) tritt damit nicht mehr auf. Auf
|
||||||
(Gold/Glück −25 %). Der Verifizierungslink funktioniert auch ohne Mailversand;
|
`false` gestellt, gilt wieder der Upstream-Ablauf: Im Backend-Log erscheint
|
||||||
er lässt sich in MongoDB nachsehen:
|
`send_email error InvalidClientTokenId`, und der Verifizierungslink muss
|
||||||
|
manuell geöffnet werden:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
docker compose exec al-mongo mongosh --quiet adventureland --eval \
|
docker compose exec al-mongo mongosh --quiet adventureland --eval \
|
||||||
@@ -197,7 +204,18 @@ Custom-Datei zurückgesetzt werden; dann den Game-Server neu starten.
|
|||||||
```
|
```
|
||||||
|
|
||||||
Link im Browser öffnen, danach neu einloggen. Alternativ `info.verified` direkt
|
Link im Browser öffnen, danach neu einloggen. Alternativ `info.verified` direkt
|
||||||
auf `true` setzen (siehe Admin-Befehl oben).
|
auf `true` setzen (siehe Admin-Befehl oben). Die `/ev`-Route bleibt in beiden
|
||||||
|
Fällen funktionsfähig.
|
||||||
|
|
||||||
|
- **Tutorial-Belohnung (`c0`):** Jedes Konto mit `auth_id` (Steam/MAS) kann nach
|
||||||
|
abgeschlossenem Tutorial einmal `c0` abholen. Die Belohnung ist ein zufälliger
|
||||||
|
kosmetischer Look aus dem `cosmo0`-Pool (über 100 Varianten). Der Game-Server
|
||||||
|
prüft dafür `player.verified` **und** `player.auth_id`
|
||||||
|
(`node/server.js:5272`). Bei reinen Web-Accounts ohne Steam/MAS bleibt
|
||||||
|
`auth_id` leer, deshalb ist die Belohnung trotz Auto-Verifizierung weiterhin
|
||||||
|
gesperrt. Die alten Klassen-Belohnungen (`creward`) sind in
|
||||||
|
`design/classes.js` auskommentiert und werden vom Client nicht angefragt;
|
||||||
|
Hardcore-Rewards gelten nur auf dem Hardcore-Server.
|
||||||
|
|
||||||
- **„Authorization Failure“ (Gold/Glück −85 %, XP −20 %):** Das ist die
|
- **„Authorization Failure“ (Gold/Glück −85 %, XP −20 %):** Das ist die
|
||||||
DRM-Prüfung des Game-Servers. Sie verlangt für jedes Konto ab 2019 eine
|
DRM-Prüfung des Game-Servers. Sie verlangt für jedes Konto ab 2019 eine
|
||||||
|
|||||||
@@ -0,0 +1,106 @@
|
|||||||
|
#!/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);
|
||||||
@@ -50,7 +50,11 @@ module.exports = {
|
|||||||
port: 8090,
|
port: 8090,
|
||||||
close_timeout: 4000,
|
close_timeout: 4000,
|
||||||
ip_limit: 3,
|
ip_limit: 3,
|
||||||
character_limit: 18,
|
character_limit: 3,
|
||||||
|
// Without an email service, mark new accounts as verified at signup and
|
||||||
|
// keep existing accounts verified on login. Set to false to restore the
|
||||||
|
// upstream verification flow (requires AWS SES).
|
||||||
|
auto_verify_email: true,
|
||||||
fast_sdk: 0,
|
fast_sdk: 0,
|
||||||
machines: machines,
|
machines: machines,
|
||||||
servers: servers,
|
servers: servers,
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# fallback script for mail verify
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
JS='db.user.find({}, {"info.email": 1, "info.everification": 1}).forEach((u) =>
|
||||||
|
print("http://localhost:8090/ev/" + u._id + "/" + u.info.everification))'
|
||||||
|
|
||||||
|
docker compose exec -T al-mongo mongosh --quiet adventureland --eval "$JS" \
|
||||||
|
| while IFS= read -r url; do
|
||||||
|
[[ "$url" == http* ]] || continue
|
||||||
|
code=$(curl -s -o /dev/null -w '%{http_code}' "$url")
|
||||||
|
echo "$code $url"
|
||||||
|
done
|
||||||
Reference in New Issue
Block a user