chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:39:12 +08:00
commit d8dcd5f6d1
8604 changed files with 2479390 additions and 0 deletions
+112
View File
@@ -0,0 +1,112 @@
import { describe, it, beforeEach } from "node:test";
import assert from "node:assert/strict";
import { mock } from "node:test";
import {
checkLoginGuard,
clearLoginAttempts,
recordLoginFailure,
resetLoginGuardForTests,
getLoginGuardSizeForTests,
LOGIN_GUARD_TUNABLES,
} from "../../../src/server/auth/loginGuard";
describe("loginGuard", () => {
beforeEach(() => {
resetLoginGuardForTests();
});
it("is a no-op when bruteForceProtection is disabled", () => {
for (let i = 0; i < 20; i++) {
const decision = recordLoginFailure("1.2.3.4", { enabled: false });
assert.equal(decision.allowed, true);
}
assert.equal(checkLoginGuard("1.2.3.4", { enabled: false }).allowed, true);
});
it("allows the first attempts up to threshold-1, locks on the threshold hit", () => {
const ip = "10.0.0.1";
for (let i = 0; i < LOGIN_GUARD_TUNABLES.FAILURE_THRESHOLD - 1; i++) {
const dec = recordLoginFailure(ip, { enabled: true });
assert.equal(dec.allowed, true, `attempt #${i + 1} should still be allowed`);
}
const lockingHit = recordLoginFailure(ip, { enabled: true });
assert.equal(lockingHit.allowed, false);
assert.ok((lockingHit.retryAfterSeconds || 0) > 0);
const subsequent = checkLoginGuard(ip, { enabled: true });
assert.equal(subsequent.allowed, false);
assert.ok((subsequent.retryAfterSeconds || 0) > 0);
});
it("scopes lockouts per IP", () => {
const ipA = "10.0.0.1";
const ipB = "10.0.0.2";
for (let i = 0; i < LOGIN_GUARD_TUNABLES.FAILURE_THRESHOLD; i++) {
recordLoginFailure(ipA, { enabled: true });
}
assert.equal(checkLoginGuard(ipA, { enabled: true }).allowed, false);
assert.equal(checkLoginGuard(ipB, { enabled: true }).allowed, true);
});
it("clearLoginAttempts releases the lock for that IP only", () => {
const ip = "10.0.0.7";
for (let i = 0; i < LOGIN_GUARD_TUNABLES.FAILURE_THRESHOLD; i++) {
recordLoginFailure(ip, { enabled: true });
}
assert.equal(checkLoginGuard(ip, { enabled: true }).allowed, false);
clearLoginAttempts(ip);
assert.equal(checkLoginGuard(ip, { enabled: true }).allowed, true);
});
it("treats null/undefined ip as a single bucket", () => {
for (let i = 0; i < LOGIN_GUARD_TUNABLES.FAILURE_THRESHOLD; i++) {
recordLoginFailure(null, { enabled: true });
}
assert.equal(checkLoginGuard(undefined, { enabled: true }).allowed, false);
});
it("prunes expired, unlocked entries so the attempts map does not grow without bound", () => {
mock.timers.enable({ apis: ["Date"] });
try {
// Many distinct IPs each fail once (single, unlocked attempts).
for (let i = 0; i < 300; i++) {
recordLoginFailure(`9.${Math.floor(i / 256)}.${i % 256}.1`, { enabled: true });
}
assert.ok(getLoginGuardSizeForTests() > 256, "entries should accumulate before pruning");
// Advance past the sliding window so all those entries are expired + unlocked.
mock.timers.tick(LOGIN_GUARD_TUNABLES.WINDOW_MS + 1000);
// The next failure (map size > threshold) triggers the opportunistic prune.
recordLoginFailure("1.1.1.1", { enabled: true });
// Only the fresh entry should remain; the stale ones were reaped.
assert.equal(getLoginGuardSizeForTests(), 1);
} finally {
mock.timers.reset();
}
});
it("never prunes a still-locked entry", () => {
mock.timers.enable({ apis: ["Date"] });
try {
const lockedIp = "5.5.5.5";
for (let i = 0; i < LOGIN_GUARD_TUNABLES.FAILURE_THRESHOLD; i++) {
recordLoginFailure(lockedIp, { enabled: true });
}
assert.equal(checkLoginGuard(lockedIp, { enabled: true }).allowed, false);
// Fill past the prune threshold with unlocked entries, then trigger a prune
// while still inside the lockout window.
for (let i = 0; i < 300; i++) {
recordLoginFailure(`8.${Math.floor(i / 256)}.${i % 256}.1`, { enabled: true });
}
recordLoginFailure("2.2.2.2", { enabled: true });
// The locked IP must still be locked (not reaped).
assert.equal(checkLoginGuard(lockedIp, { enabled: true }).allowed, false);
} finally {
mock.timers.reset();
}
});
});