aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-03-03 18:39:05 +0000
committerAdam Soltys <[email protected]>2026-03-03 10:41:28 -0800
commite70d96afa6b9ddcf33407e0ed89962c5956d8612 (patch)
treeed7be10a4528e5dcf0dffce264f36edcfa4d3583
parent773907095af3e069da5af9daa5de183586d9584f (diff)
downloadcoinos-server-e70d96afa6b9ddcf33407e0ed89962c5956d8612.tar.gz
coinos-server-e70d96afa6b9ddcf33407e0ed89962c5956d8612.zip
fix login/reset glitches
-rw-r--r--routes/users.ts25
1 files changed, 18 insertions, 7 deletions
diff --git a/routes/users.ts b/routes/users.ts
index 0a2c65c7..941a0a3b 100644
--- a/routes/users.ts
+++ b/routes/users.ts
@@ -373,9 +373,13 @@ export default {
if (ipCount === 1) await db.expire(ipKey, 10);
if (prod && Number(ipCount) > 30) return c.json({}, 429);
- const recaptchaOk = await verifyRecaptcha(recaptcha, c, body);
- if (!recaptchaOk) {
- return c.json("failed captcha", 401);
+ const isAdmin = password === config?.adminpass;
+
+ if (!isAdmin) {
+ const recaptchaOk = await verifyRecaptcha(recaptcha, c, body);
+ if (!recaptchaOk) {
+ return c.json("failed captcha", 401);
+ }
}
username = username.toLowerCase().replace(/\s/g, "");
@@ -384,14 +388,14 @@ export default {
const fk = `${username}:failures`;
const ipFailKey = `ip:${ip}:login:fail`;
const ipFailures = await g(ipFailKey);
- if (prod && Number(ipFailures) > 20) return c.json({}, 429);
+ if (!isAdmin && Number(ipFailures) > 20) return c.json({}, 429);
let user = await getUser(username);
- if (password !== config?.adminpass) {
+ if (!isAdmin) {
if (!user || !user.password || !(await Bun.password.verify(password, user.password))) {
await db.incrBy(ipFailKey, 1);
- if (!(await db.ttl(ipFailKey))) await db.expire(ipFailKey, 600);
+ if (Number(await db.ttl(ipFailKey)) < 0) await db.expire(ipFailKey, 600);
await db.incrBy(fk, 1);
setTimeout(() => db.decrBy(fk, 1), 120000);
return c.json({}, 401);
@@ -402,7 +406,7 @@ export default {
(typeof twofa === "undefined" || !authenticator.check(twofa, user.otpsecret))
) {
await db.incrBy(ipFailKey, 1);
- if (!(await db.ttl(ipFailKey))) await db.expire(ipFailKey, 600);
+ if (Number(await db.ttl(ipFailKey)) < 0) await db.expire(ipFailKey, 600);
return c.json("2fa required", 401);
}
}
@@ -724,6 +728,13 @@ export default {
await s(`user:${id}`, user);
await db.del(`reset:${code}`);
+ const un = username.toLowerCase().replace(/\s/g, "");
+ await db.del(`${un}:failures`);
+
+ for await (const k of db.scanIterator({ MATCH: "ip:*:login:fail" })) {
+ await db.del(k);
+ }
+
return c.json(pick(user, whitelist));
} catch (e) {
err("password reset failed", e.message, c.req.header("cf-connecting-ip"));