aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/register.ts4
-rw-r--r--lib/reserved.ts31
-rw-r--r--routes/users.ts4
3 files changed, 35 insertions, 4 deletions
diff --git a/lib/register.ts b/lib/register.ts
index e140947b..a9e9d7f7 100644
--- a/lib/register.ts
+++ b/lib/register.ts
@@ -4,6 +4,7 @@ import { db, s } from "$lib/db";
import { l, warn } from "$lib/logging";
import { fail } from "$lib/utils";
import { assertNameFree } from "$lib/names";
+import { isReserved } from "$lib/reserved";
import { bytesToHex, randomBytes } from "@noble/hashes/utils";
import { got } from "got";
import { getPublicKey, nip19 } from "nostr-tools";
@@ -16,12 +17,11 @@ export default async (user, ip) => {
let { password, pubkey, username } = user;
l("registering", username);
- const reserved = ["ecash"];
if (!username) fail("Username required");
username = username.toLowerCase().replace(/\s/g, "");
if (!valid.test(username))
fail("Usernames can only have letters and numbers");
- if (reserved.includes(username)) fail("Invalid username");
+ if (isReserved(username)) fail("Invalid username");
if (username.includes("undefined")) fail("Invalid username");
const id = v4();
diff --git a/lib/reserved.ts b/lib/reserved.ts
new file mode 100644
index 00000000..df5f0d43
--- /dev/null
+++ b/lib/reserved.ts
@@ -0,0 +1,31 @@
+// Usernames nobody may register or rename into. A coinos username is also a
+// lightning address, so a name that reads as ours lets an account collect
+// payments meant for the service: "mint" was claimed within days of the ecash
+// redesign freeing it (2026-09-18) and took payments addressed to
+// [email protected] until it was renamed.
+//
+// Checked on registration (lib/register.ts) and on rename (routes/users.ts).
+// Names already held by the v3 registrar are refused separately, by
+// assertNameFree in lib/names.ts.
+export const reserved = [
+ "admin",
+ "administrator",
+ "ark",
+ "cash",
+ "coinos",
+ "ecash",
+ "fund",
+ "help",
+ "info",
+ "lightning",
+ "mint",
+ "pool",
+ "root",
+ "security",
+ "support",
+ "system",
+ "wallet",
+];
+
+export const isReserved = (username: string) =>
+ reserved.includes(String(username || "").toLowerCase().replace(/\s/g, ""));
diff --git a/routes/users.ts b/routes/users.ts
index cbd2079d..431425b4 100644
--- a/routes/users.ts
+++ b/routes/users.ts
@@ -9,6 +9,7 @@ import { mail, templates } from "$lib/mail";
import { getNostrUser, getProfile, serverPubkey2 } from "$lib/nostr";
import register from "$lib/register";
import { assertNameFree } from "$lib/names";
+import { isReserved } from "$lib/reserved";
import { emit } from "$lib/sockets";
import upload from "$lib/upload";
import { bail, fail, fields, getUser, pick } from "$lib/utils";
@@ -271,11 +272,10 @@ export default {
const { confirm, password, pin, newpin } = body;
const username = body?.username?.toLowerCase().replace(/\s/g, "");
- const reserved = ["ecash"];
const valid = /^[\p{L}\p{N}]{2,24}$/u;
if (!valid.test(username))
fail("Usernames can only have letters and numbers");
- if (reserved.includes(username)) fail("Invalid username");
+ if (isReserved(username)) fail("Invalid username");
if (username?.includes("undefined")) fail("Invalid username");
let exists;