- aggiornato la Guida Completa e Breve di RISO. - pagina per ricevere i RIS. - sistemato problema creazione nuovi Circuiti (admin non corretti). - corretto giro delle email, invitante, invitato e ricezione msg su telegram.
152 lines
3.2 KiB
JavaScript
152 lines
3.2 KiB
JavaScript
/**
|
|
* Security Middleware
|
|
* Handles rate limiting, IP blocking, and failed login attempts
|
|
*/
|
|
|
|
// Dictionary to track failed login attempts
|
|
const failedLoginAttempts = {};
|
|
|
|
// Constants
|
|
const MAX_FAILED_ATTEMPTS = 30;
|
|
const BLOCK_DURATION = 30 * 60 * 1000; // 30 minutes
|
|
|
|
/**
|
|
* Block user after too many failed attempts
|
|
*/
|
|
function blockUser(username) {
|
|
failedLoginAttempts[username] = Date.now() + BLOCK_DURATION;
|
|
}
|
|
|
|
/**
|
|
* Check if user is blocked
|
|
*/
|
|
function isUserBlocked(username) {
|
|
const now = Date.now();
|
|
return failedLoginAttempts[username] && failedLoginAttempts[username] > now;
|
|
}
|
|
|
|
/**
|
|
* Clear failed attempts for user (on successful login)
|
|
*/
|
|
function clearFailedAttempts(username) {
|
|
delete failedLoginAttempts[username];
|
|
}
|
|
|
|
/**
|
|
* Middleware to check if user is blocked before login
|
|
*/
|
|
function checkBlocked(req, res, next) {
|
|
const { username } = req.body;
|
|
|
|
console.log('checkBlocked');
|
|
|
|
if (!username) {
|
|
return res.status(400).json({
|
|
message: 'Username mancante',
|
|
});
|
|
}
|
|
|
|
if (isUserBlocked(username)) {
|
|
const text = `Utente bloccato. Riprova più tardi. (username=${username})`;
|
|
console.log(text);
|
|
return res.status(403).json({
|
|
message: 'Utente bloccato. Riprova più tardi.',
|
|
});
|
|
}
|
|
|
|
next();
|
|
}
|
|
|
|
/**
|
|
* Get failed attempts count for a user
|
|
*/
|
|
function getFailedAttempts(username) {
|
|
return failedLoginAttempts[username] || 0;
|
|
}
|
|
|
|
/**
|
|
* Increment failed attempts
|
|
*/
|
|
function incrementFailedAttempts(username) {
|
|
if (typeof failedLoginAttempts[username] === 'number') {
|
|
failedLoginAttempts[username]++;
|
|
} else {
|
|
failedLoginAttempts[username] = 1;
|
|
}
|
|
return failedLoginAttempts[username];
|
|
}
|
|
|
|
/**
|
|
* Check if user should be blocked after this attempt
|
|
*/
|
|
function shouldBlockUser(username) {
|
|
return (failedLoginAttempts[username] || 0) >= MAX_FAILED_ATTEMPTS;
|
|
}
|
|
|
|
/**
|
|
* Middleware to rate limit API requests per IP
|
|
*/
|
|
const requestCounts = {};
|
|
const REQUEST_WINDOW = 60 * 1000; // 1 minute
|
|
const MAX_REQUESTS = 100; // per window
|
|
|
|
function rateLimitByIP(req, res, next) {
|
|
const tools = require('../tools/general');
|
|
const ip = tools.getiPAddressUser(req);
|
|
const now = Date.now();
|
|
|
|
if (!requestCounts[ip]) {
|
|
requestCounts[ip] = {
|
|
count: 1,
|
|
resetTime: now + REQUEST_WINDOW,
|
|
};
|
|
return next();
|
|
}
|
|
|
|
if (now > requestCounts[ip].resetTime) {
|
|
// Reset window
|
|
requestCounts[ip] = {
|
|
count: 1,
|
|
resetTime: now + REQUEST_WINDOW,
|
|
};
|
|
return next();
|
|
}
|
|
|
|
if (requestCounts[ip].count >= MAX_REQUESTS) {
|
|
return res.status(429).json({
|
|
message: 'Troppi tentativi. Riprova più tardi.',
|
|
});
|
|
}
|
|
|
|
requestCounts[ip].count++;
|
|
next();
|
|
}
|
|
|
|
/**
|
|
* Clean up old blocked users (run periodically)
|
|
*/
|
|
function cleanupBlockedUsers() {
|
|
const now = Date.now();
|
|
Object.keys(failedLoginAttempts).forEach((username) => {
|
|
if (typeof failedLoginAttempts[username] === 'number' && failedLoginAttempts[username] < now) {
|
|
delete failedLoginAttempts[username];
|
|
}
|
|
});
|
|
}
|
|
|
|
// Run cleanup every 10 minutes
|
|
setInterval(cleanupBlockedUsers, 10 * 60 * 1000);
|
|
|
|
module.exports = {
|
|
checkBlocked,
|
|
blockUser,
|
|
isUserBlocked,
|
|
clearFailedAttempts,
|
|
getFailedAttempts,
|
|
incrementFailedAttempts,
|
|
shouldBlockUser,
|
|
rateLimitByIP,
|
|
MAX_FAILED_ATTEMPTS,
|
|
BLOCK_DURATION,
|
|
};
|