Update user data handling in UserIDMiddlewareAD.js and refactor getUserData function
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
2024-04-17 17:00:04 +02:00
parent 7a02f2682c
commit 06b1936840
9 changed files with 163 additions and 118 deletions

View File

@@ -15,7 +15,6 @@ async function getUserData() {
async function checkUserExistsAD(req, res, next) { async function checkUserExistsAD(req, res, next) {
let userData = await getUserData(); let userData = await getUserData();
console.log('User data:', userData);
if (Array.isArray(req.user)) { if (Array.isArray(req.user)) {
req.user = req.user.find(u => u._json && u._json.sAMAccountName); req.user = req.user.find(u => u._json && u._json.sAMAccountName);

View File

@@ -4,19 +4,14 @@ const { logger, logRequestInfo, ErrorLogger, authLogger } = require('../config/l
const debug = require('debug')('app:authMiddleware'); const debug = require('debug')('app:authMiddleware');
const authMiddleware = async (req, res, next) => { const authMiddleware = async (req, res, next) => {
debug('Checking if user is authenticated...');
if (req.isAuthenticated() || (req.session && req.session.user && req.session.user.name)) { if (req.isAuthenticated() || (req.session && req.session.user && req.session.user.name)) {
debug('User is authenticated, reading user data...');
const data = await fs.promises.readFile(path.join(__dirname, '../data', 'user.json'), 'utf8'); const data = await fs.promises.readFile(path.join(__dirname, '../data', 'user.json'), 'utf8');
const users = JSON.parse(data); const users = JSON.parse(data);
debug('User data:', users);
const user = users.find(user => user.name === (req.session.user && req.session.user.name)); const user = users.find(user => user.name === (req.session.user && req.session.user.name));
debug('User name from session:', req.session.user && req.session.user.name);
if (!user) { if (!user) {
authLogger.info('User is not authenticated and user name is not set'); authLogger.info('User is not authenticated and user name is not set');
debug('User not found in user data, redirecting to login...');
return res.redirect('/auth/login'); return res.redirect('/auth/login');
} }
@@ -25,11 +20,9 @@ const authMiddleware = async (req, res, next) => {
authLogger.info(`Login successfully completed, logged in user is: id=${user.id}, name=${user.name}, role=${user.role}, IP: ${req.ip}, User Agent: ${req.headers['user-agent']}`); authLogger.info(`Login successfully completed, logged in user is: id=${user.id}, name=${user.name}, role=${user.role}, IP: ${req.ip}, User Agent: ${req.headers['user-agent']}`);
} }
debug('Setting user data in session and locals...');
res.locals.user = user; res.locals.user = user;
req.session.user = user; req.session.user = user;
req.userData = user; req.userData = user;
debug('User data set, calling next middleware...');
return next(); return next();
} else { } else {
authLogger.info(`Authentication failed for IP: ${req.ip}, User Agent: ${req.headers['user-agent']}. Redirecting to login.`); authLogger.info(`Authentication failed for IP: ${req.ip}, User Agent: ${req.headers['user-agent']}. Redirecting to login.`);

View File

@@ -3,16 +3,20 @@ const winston = require('winston');
const DailyRotateFile = require('winston-daily-rotate-file'); const DailyRotateFile = require('winston-daily-rotate-file');
const logPrefix = (label) => { const logPrefix = (label) => {
if (label === 'server') { if (label === 'server') {
return '[\x1b[32mServer\x1b[0m] '; return '[🖥️ \x1b[32mServer\x1b[0m] ';
} else if (label === 'client') { } else if (label === 'client') {
return '[\x1b[34mClient\x1b[0m] '; return '[🌐 \x1b[34mClient\x1b[0m] ';
} else if (label === 'Internal-Server-Error') { } else if (label === 'Internal-Server-Error') {
return '[\x1b[38;5;9mInternal-Error\x1b[0m] '; return '[❗️ \x1b[38;5;9mInternal-Error\x1b[0m] ';
} else if (label === 'Authentification') { } else if (label === 'Authentification') {
return '[\x1b[33mAuthentification\x1b[0m] '; return '[🔒 \x1b[33mAuthentification\x1b[0m] ';
} } else if (label === 'Suspicious Request') {
return ''; return '[⚠️ \x1b[38;5;208mSuspicious Request\x1b[0m] ';
}else if (label === 'API Request') {
return '[⚙️ \x1b[38;5;9mAPI Request\x1b[0m] ';
}
return '';
}; };
const createDailyRotateFileTransport = () => { const createDailyRotateFileTransport = () => {
@@ -20,7 +24,7 @@ const createDailyRotateFileTransport = () => {
filename: 'logs/log-%DATE%.log', filename: 'logs/log-%DATE%.log',
datePattern: 'YYYY-MM-DD', datePattern: 'YYYY-MM-DD',
zippedArchive: false, zippedArchive: false,
maxSize: '20m', maxSize: '20m',
maxFiles: '14d' maxFiles: '14d'
}); });
}; };
@@ -32,11 +36,11 @@ const logger = winston.createLogger({
format.printf(info => { format.printf(info => {
const { timestamp, level, label, message } = info; const { timestamp, level, label, message } = info;
const prefix = logPrefix(label); const prefix = logPrefix(label);
return `[${timestamp}] ${prefix}${message}`; return `${prefix}[\x1b[36m${timestamp}\x1b[0m] ${message}`;
}) })
), ),
transports: [ transports: [
new winston.transports.Console(), new winston.transports.Console(),
createDailyRotateFileTransport() createDailyRotateFileTransport()
] ]
}); });
@@ -48,11 +52,11 @@ const ErrorLogger = winston.createLogger({
format.printf(info => { format.printf(info => {
const { timestamp, level, label, message } = info; const { timestamp, level, label, message } = info;
const prefix = logPrefix(label); const prefix = logPrefix(label);
return `[${timestamp}] ${prefix}${message}`; return `${prefix}[\x1b[36m${timestamp}\x1b[0m] ${message}`;
}) })
), ),
transports: [ transports: [
new winston.transports.Console(), new winston.transports.Console(),
createDailyRotateFileTransport() createDailyRotateFileTransport()
] ]
}); });
@@ -64,7 +68,7 @@ const clientLogger = winston.createLogger({
format.printf(info => { format.printf(info => {
const { timestamp, level, label, message } = info; const { timestamp, level, label, message } = info;
const prefix = logPrefix(label); const prefix = logPrefix(label);
return `[${timestamp}] ${prefix}${message}`; return `${prefix}[\x1b[36m${timestamp}\x1b[0m] ${message}`;
}) })
), ),
transports: [ transports: [
@@ -80,7 +84,23 @@ const authLogger = winston.createLogger({
format.printf(info => { format.printf(info => {
const { timestamp, level, label, message } = info; const { timestamp, level, label, message } = info;
const prefix = logPrefix(label); const prefix = logPrefix(label);
return `[${timestamp}] ${prefix}${message}`; return `${prefix}[\x1b[36m${timestamp}\x1b[0m] ${message}`;
})
),
transports: [
new winston.transports.Console(),
createDailyRotateFileTransport()
]
});
const suspiciousLogger = winston.createLogger({
format: format.combine(
format.label({ label: 'Suspicious Request' }),
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
format.printf(info => {
const { timestamp, level, label, message } = info;
const prefix = logPrefix(label);
return `${prefix}[\x1b[36m${timestamp}\x1b[0m] ${message}`;
}) })
), ),
transports: [ transports: [
@@ -92,10 +112,36 @@ const authLogger = winston.createLogger({
const logRequestInfo = (req, res, next) => { const logRequestInfo = (req, res, next) => {
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress; const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
const userAgent = req.headers['user-agent']; const userAgent = req.headers['user-agent'];
req.log = clientLogger; req.log = clientLogger;
req.log.info(`[${ip}] - ${userAgent} - ${req.method} ${req.url}`); req.log.info(`[${ip}] - ${userAgent} - ${req.method} ${req.url}`);
next(); next();
}; };
const apiLogger = winston.createLogger({
format: format.combine(
format.label({ label: 'API Request' }),
format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
format.printf(info => {
const { timestamp, level, label, message } = info;
const prefix = logPrefix(label);
return `${prefix}[\x1b[36m${timestamp}\x1b[0m] ${message}`;
})
),
transports: [
new winston.transports.Console(),
createDailyRotateFileTransport()
]
});
module.exports = { logger, clientLogger, ErrorLogger, logRequestInfo, authLogger }; const logApiRequest = (req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
apiLogger.info(`[${ip}] - ${req.method} ${req.originalUrl} - ${res.statusCode} - ${duration}ms`);
});
next();
};
module.exports = { logger, clientLogger, ErrorLogger, logRequestInfo, authLogger, suspiciousLogger, logApiRequest };

View File

@@ -1,8 +1,12 @@
version: '3.8' version: '3'
services: services:
cdn-app-insider: app:
image: swiftlogiclabs/cdn-app-insider:latest image: swiftlogiclabs/cdn-app-insider
restart: unless-stopped volumes:
container_name: cdn-app-container - data-volume:/app/data
ports: - report-volume:/app/report
- "5053:5053" - cdn-files-volume:/app/cdn-files
volumes:
data-volume:
report-volume:
cdn-files-volume:

View File

@@ -1,57 +0,0 @@
{
"routes": [
"/routes/index.js",
"/routes/auth.js",
"/routes/dpanel.js",
"/routes/attachments.js"
],
"controllers": [
"/controllers/paramController.js"
],
"models": [
"/models/AuthUser.js",
"/models/paramModel.js",
"/models/Passport-ActiveDirectory.js",
"/models/Passport-Discord.js",
"/models/updateHelper.js",
"/models/updateManager.js",
"/models/reportManager.js",
"/models/Usermanager.js"
],
"views": [
"/views/AuthLogin.ejs",
"/views/dashboard.ejs",
"/views/acces-denied.ejs",
"/views/error-recovery.ejs",
"/views/file-not-found.ejs",
"/views/folder.ejs",
"/views/parametres.ejs",
"/views/unauthorized.ejs",
"/views/paramAdmin.ejs",
"/views/paramAdminPrivacy&Security.ejs",
"/views/paramAdminStats&Logs.ejs",
"/views/paramAdminSetup.ejs",
"/views/paramAdminUser.ejs",
"/views/password-check.ejs",
"/views/paramAdmin.ejs",
"/views/file-expired.ejs",
"/views/upload.ejs"
],
"config": [
"/config/logs.js"
],
"Middleware": [
"/Middleware/authMiddleware.js",
"/Middleware/checkUpdate.js",
"/Middleware/UserIDMiddlewareAD.js",
"/Middleware/UserIDMiddlewareDiscord.js"
],
"json-file": [
"/package.json",
"/package-lock.json",
"/user.json",
"/files.json",
"/file-info.json",
"/setup.json"
]
}

60
models/banModel.js Normal file
View File

@@ -0,0 +1,60 @@
const fs = require('fs');
const path = require('path');
const { suspiciousLogger } = require('../config/logs');
const BAN_LEVELS = [10, 30, 60, Infinity];
const SUSPICIOUS_REQUEST_LIMIT = 5;
const BAN_FILE_PATH = path.join(__dirname, '..', 'data', 'banUser.json');
const logAndBanSuspiciousActivity = async (req, res, next) => {
const ip = req.headers['cf-connecting-ip'] || req.headers['x-forwarded-for'] || req.connection.remoteAddress;
const url = `${req.protocol}://${req.get('host')}${req.originalUrl}`;
if (req.originalUrl === '/auth/activedirectory', "/favicon.ico" && req.method === 'POST') {
next();
return;
}
let bans;
try {
if (!fs.existsSync(BAN_FILE_PATH)) {
fs.writeFileSync(BAN_FILE_PATH, JSON.stringify({}));
}
bans = JSON.parse(fs.readFileSync(BAN_FILE_PATH));
} catch (err) {
bans = {};
}
let ban = bans[ip];
if (ban) {
const timeSinceLastRequest = Date.now() - ban.lastRequestTime;
if (timeSinceLastRequest < 60 * 1000) {
ban.suspiciousRequestCount++;
} else {
ban.suspiciousRequestCount = 1;
}
if (ban.suspiciousRequestCount >= SUSPICIOUS_REQUEST_LIMIT) {
ban.level++;
ban.suspiciousRequestCount = 0;
ban.banUntil = Date.now() + BAN_LEVELS[ban.level % BAN_LEVELS.length] * 60 * 1000;
}
ban.lastRequestTime = Date.now();
} else {
bans[ip] = { level: 0, banUntil: Date.now(), suspiciousRequestCount: 1, lastRequestTime: Date.now() };
ban = bans[ip];
}
fs.writeFileSync(BAN_FILE_PATH, JSON.stringify(bans));
if (ban && Date.now() < ban.banUntil) {
res.status(403).json({ message: 'You are banned. Please try again later.' });
return;
}
suspiciousLogger.info(`Suspicious request from IP: ${ip} tried to access ${req.method} ${url}`);
next();
};
module.exports = { logAndBanSuspiciousActivity };

View File

@@ -3,7 +3,7 @@ const path = require('path');
const { logger, ErrorLogger, logRequestInfo } = require('../config/logs'); const { logger, ErrorLogger, logRequestInfo } = require('../config/logs');
const dataFolderPath = path.join(__dirname, '../data'); const dataFolderPath = path.join(__dirname, '../data');
const filesToCreate = ['setup.json', 'user.json', 'file_info.json', 'banData.json']; const filesToCreate = ['setup.json', 'user.json', 'file_info.json', 'banUser.json'];
filesToCreate.forEach((fileName) => { filesToCreate.forEach((fileName) => {
const filePath = path.join(dataFolderPath, fileName); const filePath = path.join(dataFolderPath, fileName);

View File

@@ -1,5 +1,7 @@
const express = require('express'); const express = require('express');
const router = express.Router(); const router = express.Router();
const { logAndBanSuspiciousActivity } = require('../models/banModel.js');
const { logApiRequest } = require('../config/logs.js');
const indexRoute = require('./index.js'); const indexRoute = require('./index.js');
const DpanelDashboardRoute = require('./Dpanel/Dashboard/index.js'); const DpanelDashboardRoute = require('./Dpanel/Dashboard/index.js');
@@ -42,21 +44,22 @@ router.use('/dpanel/dashboard/admin/settingsetup', AdminSettingSetupDpanelRoute)
router.use('/dpanel/dashboard/admin/stats-logs', AdminStatsLogsDpanelRoute);; router.use('/dpanel/dashboard/admin/stats-logs', AdminStatsLogsDpanelRoute);;
router.use('/dpanel/dashboard/admin/Privacy-Security', AdminPrivacySecurityDpanelRoute); router.use('/dpanel/dashboard/admin/Privacy-Security', AdminPrivacySecurityDpanelRoute);
router.use('/api/dpanel/dashboard/newfolder', NewFolderRoute); router.use('/api/dpanel/dashboard/newfolder', logApiRequest, NewFolderRoute);
router.use('/api/dpanel/dashboard/rename', RenameFileRoute); router.use('/api/dpanel/dashboard/rename', logApiRequest, RenameFileRoute);
router.use('/api/dpanel/dashboard/delete', DeleteFileRoute); router.use('/api/dpanel/dashboard/delete', logApiRequest, DeleteFileRoute);
router.use('/api/dpanel/dashboard/movefile', MoveFileRoute); router.use('/api/dpanel/dashboard/movefile', logApiRequest, MoveFileRoute);
router.use('/api/dpanel/upload', UploadRoute); router.use('/api/dpanel/upload', logApiRequest, UploadRoute);
router.use('/api/dpanel/dashboard/admin/update-role', UpdateRoleAdminRoute); router.use('/api/dpanel/dashboard/admin/update-role', logApiRequest, UpdateRoleAdminRoute);
router.use('/api/dpanel/dashboard/admin/update-setup', UpdateSetupAdminRoute); router.use('/api/dpanel/dashboard/admin/update-setup', logApiRequest, UpdateSetupAdminRoute);
router.use('/api/dpanel/dashboard/deletefolder', DeleteFolderRoute); router.use('/api/dpanel/dashboard/deletefolder', logApiRequest, DeleteFolderRoute);
router.use('/api/dpanel/dashboard/deletefile/', DeleteFileFolderRoute); router.use('/api/dpanel/dashboard/deletefile/', logApiRequest,DeleteFileFolderRoute);
router.use('/auth/login', loginRoute); router.use('/auth/login', loginRoute);
router.use('/auth/logout', logoutRoute); router.use('/auth/logout', logoutRoute);
router.use('/auth/activedirectory', activeDirectoryRoute); router.use('/auth/activedirectory', activeDirectoryRoute);
router.use('/auth/discord', discordRoute); router.use('/auth/discord', discordRoute);
router.use('/*', indexRoute)
router.use('/*', logAndBanSuspiciousActivity, indexRoute);
module.exports = router; module.exports = router;

View File

@@ -4,19 +4,22 @@ const passport = require('passport');
const bodyParser = require('body-parser'); const bodyParser = require('body-parser');
const { logger, logRequestInfo, ErrorLogger } = require('./config/logs'); const { logger, logRequestInfo, ErrorLogger } = require('./config/logs');
const path = require("path"); const path = require("path");
require('dotenv').config();
const { version } = require('./package.json'); const { version } = require('./package.json');
const axios = require('axios'); const axios = require('axios');
const app = express();
const flash = require('connect-flash'); const flash = require('connect-flash');
const crypto = require('crypto'); const crypto = require('crypto');
const fs = require('fs'); const fs = require('fs');
const SystemReport = require('./models/reportManager.js'); const SystemReport = require('./models/reportManager.js');
const routes = require('./routes/routes.js');
const cron = require('node-cron');
require('dotenv').config();
const app = express();
require('./models/fileCreated.js'); require('./models/fileCreated.js');
let setup; let setup;
try { try {
setup = JSON.parse(fs.readFileSync(path.join('/data', 'setup.json'), 'utf8')); setup = JSON.parse(fs.readFileSync(path.join(__dirname, 'data', 'setup.json'), 'utf8'));
} catch (err) { } catch (err) {
console.error('Error reading setup.json:', err); console.error('Error reading setup.json:', err);
process.exit(1); process.exit(1);
@@ -33,8 +36,10 @@ if (setup.ldap !== undefined) {
app.use(express.static(path.join(__dirname, 'public'))); app.use(express.static(path.join(__dirname, 'public')));
app.get(['/data/user.json', '/data/file_info.json', '/data/setup.json'], (req, res) => { app.get(['/data/user.json', '/data/file_info.json', '/data/setup.json'], (req, res) => {
res.status(403).json({ error: 'Access Denied. You do not have permission to access this resource.' }); res.status(403).json({ error: 'Access Denied. You do not have permission to access this resource.' });
});app.use(express.urlencoded({ extended: true })); });
app.use(express.urlencoded({ extended: true }));
function generateSecretKey() { function generateSecretKey() {
return crypto.randomBytes(64).toString('hex'); return crypto.randomBytes(64).toString('hex');
@@ -54,7 +59,6 @@ app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json()); app.use(bodyParser.json());
app.use(flash()); app.use(flash());
const routes = require('./routes/routes.js');
app.use('/public', express.static(path.join(__dirname, 'public'))); app.use('/public', express.static(path.join(__dirname, 'public')));
app.set('view engine', 'ejs'); app.set('view engine', 'ejs');
app.set('views', __dirname + '/views'); app.set('views', __dirname + '/views');
@@ -62,13 +66,12 @@ app.use(routes);
app.use(logRequestInfo); app.use(logRequestInfo);
const cron = require('node-cron');
cron.schedule('00 03 * * *', async () => { cron.schedule('00 03 * * *', async () => {
try { try {
const report = await SystemReport.generate(); const report = await SystemReport.generate();
if (report !== null) { if (report !== null) {
logger.info('System error report generated successfully'); logger.info('System error report generated successfully');
} }
} catch (err) { } catch (err) {
ErrorLogger.error('Error generating report :', err); ErrorLogger.error('Error generating report :', err);
@@ -77,7 +80,7 @@ cron.schedule('00 03 * * *', async () => {
cron.schedule('0 * * * *', async () => { cron.schedule('0 * * * *', async () => {
try { try {
const fileInfoData = await fs.promises.readFile(path.join(__dirname,'/data/', 'file_info.json'), 'utf8'); const fileInfoData = await fs.promises.readFile(path.join(__dirname, '/data/', 'file_info.json'), 'utf8');
const fileInfo = JSON.parse(fileInfoData); const fileInfo = JSON.parse(fileInfoData);
const now = new Date(); const now = new Date();
@@ -112,15 +115,9 @@ app.listen(PORT, () => {
console.clear(); console.clear();
if (logger) { if (logger) {
logger.info(`🚀 Your server is available and running on port ${PORT}`); logger.info(`🚀 Your server is available and running on port ${PORT}`);
logger.info(`⚜️ Application developed by Dinawo, part of the SwiftLogic Labs group`); logger.info(`⚜️ Application developed by Dinawo, part of the SwiftLogic Labs group`);
logger.info(`♨️ Version: ${version}`); logger.info(`♨️ Version: ${version}`);
console.log(''); console.log('');
const filesData = fs.readFileSync('files.json', 'utf8');
const files = JSON.parse(filesData);
const numberOfFiles = Object.values(files).flat().length;
logger.info(`🔰 Number of files activated during server startup: ${numberOfFiles}`);
} else { } else {
console.error('🔴 Logger is not initialized'); console.error('🔴 Logger is not initialized');
} }