mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-07 04:12:04 +00:00
Merge pull request #1294 from MBombeck/fix/throttle-test-clock
fix(auth): read a remembered browser's expiry on the throttle's clock
This commit is contained in:
2 files changed
+23
-10
No files matched your search
@@ -125,6 +125,15 @@ describe("waitAfter", () => {
|
||||
});
|
||||
});
|
||||
|
||||
/** The owner's browser, remembered as a trusted device until `expiresAt`. */
|
||||
function rememberBrowser(expiresAt: Date) {
|
||||
deviceCookie = "device-token";
|
||||
vi.mocked(prisma.trustedDevice.findUnique).mockResolvedValue({
|
||||
userId: "owner-1",
|
||||
expiresAt,
|
||||
} as never);
|
||||
}
|
||||
|
||||
describe("somebody guessing from two addresses", () => {
|
||||
async function tenGuesses() {
|
||||
const answers: string[] = [];
|
||||
@@ -159,18 +168,20 @@ describe("somebody guessing from two addresses", () => {
|
||||
|
||||
it("the owner's remembered browser still gets through", async () => {
|
||||
await tenGuesses();
|
||||
deviceCookie = "device-token";
|
||||
// The device's expiry is compared against the wall clock, not the mocked
|
||||
// rate-limit clock `now`, so it is anchored to the wall clock too: an
|
||||
// expiry fixed relative to `now` expired for real once the calendar
|
||||
// passed it.
|
||||
vi.mocked(prisma.trustedDevice.findUnique).mockResolvedValue({
|
||||
userId: "owner-1",
|
||||
expiresAt: new Date(Date.now() + 30 * 86_400_000),
|
||||
} as never);
|
||||
// The device's expiry is read against the same clock as the wait, the
|
||||
// mocked `now`. It used to be compared with `new Date()`, which the mock
|
||||
// does not reach, so this expiry ran out for real on 2026-10-26 at noon
|
||||
// UTC, 30 days after `now`, and the test failed from then on.
|
||||
rememberBrowser(new Date(now + 30 * 86_400_000));
|
||||
expect(await guess("203.0.113.51", { right: true })).toBe("checked");
|
||||
});
|
||||
|
||||
it("a remembered browser whose device has expired is throttled like anyone", async () => {
|
||||
await tenGuesses();
|
||||
rememberBrowser(new Date(now - 1));
|
||||
expect(await guess("203.0.113.52", { right: true })).toBe("waiting");
|
||||
});
|
||||
|
||||
it("an address the account signed in from is no exemption: a guesser can claim it", async () => {
|
||||
// A session of the owner's from this address. The guesser shares the
|
||||
// network, or names the address in a forwarding header; either way the
|
||||
|
||||
@@ -67,7 +67,9 @@ export async function knownSignInSource(
|
||||
userId: string,
|
||||
request: Request,
|
||||
): Promise<KnownSource | null> {
|
||||
const now = new Date();
|
||||
// The same clock as the throttle's own wait (`Date.now()`), so one instant
|
||||
// decides both.
|
||||
const now = new Date(Date.now());
|
||||
|
||||
let deviceToken: string | undefined;
|
||||
try {
|
||||
|
||||
Reference in new issue
Block a user