Includes MFA-capable authentication, session and CSRF security, password recovery, listing lifecycle and ownership rules, inventory image metadata, local ImageStorage, migrations, tests, and implementation status documentation. Verification: npm test (62 passing) and integration suite (14 passing).
41 lines
1.4 KiB
JavaScript
41 lines
1.4 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import { randomUUID } from 'node:crypto';
|
|
import test from 'node:test';
|
|
|
|
import { createRedisConnection } from '../../src/infrastructure/redis/client.js';
|
|
import { createRedisLoginRateLimiter } from '../../src/modules/auth/services/login-rate-limiter.js';
|
|
|
|
const redisUrl = process.env.TEST_REDIS_URL;
|
|
|
|
if (!redisUrl) {
|
|
throw new Error('TEST_REDIS_URL is required to run integration tests.');
|
|
}
|
|
|
|
test('shares login attempts across limiter instances', async () => {
|
|
const redis = await createRedisConnection(redisUrl);
|
|
const keyPrefix = `pokemon-inventory:test:auth:${randomUUID()}:`;
|
|
|
|
try {
|
|
const firstLimiter = createRedisLoginRateLimiter({
|
|
keyPrefix,
|
|
maxAttempts: 2,
|
|
redisClient: redis.client,
|
|
});
|
|
const secondLimiter = createRedisLoginRateLimiter({
|
|
keyPrefix,
|
|
maxAttempts: 2,
|
|
redisClient: redis.client,
|
|
});
|
|
|
|
assert.deepEqual(await firstLimiter.consume('198.51.100.8'), { allowed: true });
|
|
assert.deepEqual(await secondLimiter.consume('198.51.100.8'), { allowed: true });
|
|
|
|
const blockedAttempt = await firstLimiter.consume('198.51.100.8');
|
|
|
|
assert.equal(blockedAttempt.allowed, false);
|
|
assert.ok(blockedAttempt.retryAfterSeconds > 0);
|
|
assert.deepEqual(await secondLimiter.consume('198.51.100.9'), { allowed: true });
|
|
} finally {
|
|
await redis.close();
|
|
}
|
|
}); |