auto-deploy-demo/server/utils/loginLimiter.js

123 lines
2.8 KiB
JavaScript
Raw Normal View History

2026-02-23 06:31:59 +00:00
const fs = require('fs');
const path = require('path');
const LOCK_FILE = path.join(__dirname, '../data/login_locks.json');
const DEFAULT_CONFIG = {
maxAttempts: 3,
lockDuration: 10 * 60 * 1000
};
function ensureDataDir() {
const dataDir = path.join(__dirname, '../data');
if (!fs.existsSync(dataDir)) {
fs.mkdirSync(dataDir, { recursive: true });
}
}
function loadLocks() {
ensureDataDir();
try {
if (fs.existsSync(LOCK_FILE)) {
const data = fs.readFileSync(LOCK_FILE, 'utf8');
return JSON.parse(data);
}
} catch (e) {
console.error('Error loading login locks:', e);
}
return { users: {}, config: DEFAULT_CONFIG };
}
function saveLocks(locks) {
ensureDataDir();
try {
fs.writeFileSync(LOCK_FILE, JSON.stringify(locks, null, 2));
} catch (e) {
console.error('Error saving login locks:', e);
}
}
function getLockStatus(username) {
const locks = loadLocks();
const userLock = locks.users[username];
if (!userLock) {
return { locked: false, attempts: 0 };
}
const now = Date.now();
if (userLock.lockedUntil && now < userLock.lockedUntil) {
const remainingMs = userLock.lockedUntil - now;
return {
locked: true,
attempts: userLock.attempts,
lockedUntil: userLock.lockedUntil,
remainingMs: remainingMs
};
}
if (userLock.lockedUntil && now >= userLock.lockedUntil) {
const newLocks = loadLocks();
delete newLocks.users[username];
saveLocks(newLocks);
return { locked: false, attempts: 0 };
}
return { locked: false, attempts: userLock.attempts || 0 };
}
function recordFailedAttempt(username) {
const locks = loadLocks();
const now = Date.now();
if (!locks.users[username]) {
locks.users[username] = { attempts: 0 };
}
const userLock = locks.users[username];
if (userLock.lockedUntil && now >= userLock.lockedUntil) {
userLock.attempts = 0;
userLock.lockedUntil = null;
}
userLock.attempts = (userLock.attempts || 0) + 1;
userLock.lastAttempt = now;
const maxAttempts = locks.config?.maxAttempts || DEFAULT_CONFIG.maxAttempts;
const lockDuration = locks.config?.lockDuration || DEFAULT_CONFIG.lockDuration;
if (userLock.attempts >= maxAttempts) {
userLock.lockedUntil = now + lockDuration;
}
saveLocks(locks);
return getLockStatus(username);
}
function clearLock(username) {
const locks = loadLocks();
delete locks.users[username];
saveLocks(locks);
}
function getConfig() {
const locks = loadLocks();
return locks.config || DEFAULT_CONFIG;
}
function updateConfig(newConfig) {
const locks = loadLocks();
locks.config = { ...DEFAULT_CONFIG, ...newConfig };
saveLocks(locks);
}
module.exports = {
getLockStatus,
recordFailedAttempt,
clearLock,
getConfig,
updateConfig
};