first commit: Complete phishing test management panel with Node.js backend and React frontend

This commit is contained in:
salvacybersec
2025-11-10 17:00:40 +03:00
commit 19e551f33b
77 changed files with 6677 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
const requireAuth = (req, res, next) => {
if (!req.session || !req.session.userId) {
return res.status(401).json({
success: false,
error: 'Authentication required',
});
}
next();
};
const requireAdmin = (req, res, next) => {
if (!req.session || !req.session.userId || !req.session.isAdmin) {
return res.status(403).json({
success: false,
error: 'Admin access required',
});
}
next();
};
module.exports = {
requireAuth,
requireAdmin,
};

View File

@@ -0,0 +1,49 @@
const logger = require('../config/logger');
const errorHandler = (err, req, res, next) => {
logger.error('Error:', {
message: err.message,
stack: err.stack,
path: req.path,
method: req.method,
});
// Joi validation error
if (err.isJoi) {
return res.status(400).json({
success: false,
error: 'Validation error',
details: err.details.map(d => d.message),
});
}
// Sequelize errors
if (err.name === 'SequelizeValidationError') {
return res.status(400).json({
success: false,
error: 'Validation error',
details: err.errors.map(e => e.message),
});
}
if (err.name === 'SequelizeUniqueConstraintError') {
return res.status(409).json({
success: false,
error: 'Duplicate entry',
details: err.errors.map(e => e.message),
});
}
// Default error
const statusCode = err.statusCode || 500;
const message = err.message || 'Internal server error';
res.status(statusCode).json({
success: false,
error: message,
...(process.env.NODE_ENV === 'development' && { stack: err.stack }),
});
};
module.exports = errorHandler;

View File

@@ -0,0 +1,44 @@
const rateLimit = require('express-rate-limit');
// General API rate limiter
const apiLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100, // Limit each IP to 100 requests per windowMs
message: {
success: false,
error: 'Too many requests, please try again later',
},
standardHeaders: true,
legacyHeaders: false,
});
// Stricter limiter for auth endpoints
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 5, // Limit each IP to 5 login attempts per windowMs
message: {
success: false,
error: 'Too many login attempts, please try again after 15 minutes',
},
standardHeaders: true,
legacyHeaders: false,
});
// Tracking endpoint (public) - more lenient
const trackingLimiter = rateLimit({
windowMs: 1 * 60 * 1000, // 1 minute
max: 10, // 10 requests per minute per IP
message: {
success: false,
error: 'Too many requests',
},
standardHeaders: true,
legacyHeaders: false,
});
module.exports = {
apiLimiter,
authLimiter,
trackingLimiter,
};