Files
CDN-APP-INSIDER/Middlewares/discordWebhookSuspisiousAlertMiddleware.js
Dinawo de8c5ccb84
Some checks failed
continuous-integration/drone/push Build is failing
continuous-integration/drone Build is failing
Update v1.1.1-beta1
2025-06-14 22:01:39 +02:00

118 lines
3.9 KiB
JavaScript

const axios = require('axios');
const fs = require('fs');
const path = require('path');
const setupFilePath = path.join(__dirname, '../data', 'setup.json');
function isIpAllowed(ip, allowedIps) {
return allowedIps.some(allowedIp => {
if (allowedIp.includes('/')) {
const [network, bits] = allowedIp.split('/');
const ipLong = ip2long(ip);
const networkLong = ip2long(network);
const mask = ~(2 ** (32 - bits) - 1);
return (ipLong & mask) === (networkLong & mask);
}
return ip === allowedIp;
});
}
function ip2long(ip) {
return ip.split('.')
.reduce((long, octet) => (long << 8) + parseInt(octet), 0) >>> 0;
}
function sendDiscordWebhook(url, req, statusCode) {
if (!url) {
return;
}
const setupData = JSON.parse(fs.readFileSync(setupFilePath, 'utf-8'));
const allowedIps = setupData[0].allowedIps || [];
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
// Skip monitoring for localhost/local IPs
const localIps = ['127.0.0.1', '::1', 'localhost', '::ffff:127.0.0.1'];
if (localIps.includes(ip)) {
return;
}
// Skip monitoring for Chrome DevTools requests
if (req.originalUrl.includes('.well-known/appspecific/com.chrome.devtools.json')) {
return;
}
// Skip monitoring for legitimate API endpoints
const legitimateEndpoints = [
'/api/dpanel/dashboard/profilpicture',
'/api/dpanel/dashboard/backgroundcustom',
'/api/dpanel/collaboration',
'/api/dpanel/users/search',
'/dpanel/dashboard/profil',
'/build-metadata',
'/api/dpanel/collaboration/add',
'/api/dpanel/collaboration/remove',
'/api/dpanel/collaboration/users'
];
if (legitimateEndpoints.some(endpoint => req.originalUrl.includes(endpoint))) {
return;
}
// Skip monitoring if IP is allowed
if (isIpAllowed(ip, allowedIps)) {
return;
}
// Skip monitoring for authenticated users on dashboard routes
if (req.user && req.originalUrl.startsWith('/dpanel/dashboard')) {
return;
}
const fullUrl = `${req.protocol}://${req.get('host')}${req.originalUrl}`;
const statusEmoji = [200, 302].includes(statusCode) ? '✅' : '❌';
const statusMessage = `**Statut:** ${statusEmoji} (${statusCode})`;
const timestamp = new Date().toLocaleString('fr-FR', { timeZone: 'UTC', hour12: false });
const userAgent = req.get('User-Agent');
const { v4: uuidv4 } = require('uuid');
const webhookId = uuidv4();
const userId = req.user ? req.user.id : 'Inconnu';
const userName = req.user ? req.user.name : 'Inconnu';
const data = {
embeds: [{
title: "📡 Requête API",
description: "Une requête API a été effectuée. Voici les détails :",
color: 16753920,
fields: [{
name: `🔎 Détails de la requête\n\n`,
value: `🔗 **URL:** ${fullUrl}\n\n🚦 ${statusMessage}\n\n🌐 **IP**: ${ip}\n\n🔧 **Méthode**: ${req.method}\n\n⏰ **Heure**: ${timestamp}\n\n🕵️ **Agent utilisateur**: ${userAgent}\n\n👤 **Utilisateur**: ${userName} (*ID: ${userId}*)`,
inline: false
}],
footer: {
text: `📚 Journal des requêtes API | ${webhookId}`
}
}]
};
axios.post(url, data)
.then(response => {
})
.catch(error => {
console.error('Erreur lors de l\'envoi du webhook:', error);
});
}
function discordWebhookSuspisiousAlertMiddleware(req, res, next) {
const setupData = JSON.parse(fs.readFileSync(setupFilePath, 'utf-8'));
res.on('finish', () => {
const discordWebhookUrl = setupData[0].webhooks_discord;
sendDiscordWebhook(discordWebhookUrl, req, res.statusCode);
});
next();
}
module.exports = discordWebhookSuspisiousAlertMiddleware;