const express = require('express'); const fs = require('fs'); const path = require('path'); const router = express.Router(); const fileUpload = require('express-fileupload'); const authMiddleware = require('../Middlewares/authMiddleware'); const { loggers } = require('winston'); const ncp = require('ncp').ncp; const configFile = fs.readFileSync(path.join(__dirname, '../data', 'setup.json'), 'utf-8') const config = JSON.parse(configFile); const bodyParser = require('body-parser'); const crypto = require('crypto'); const os = require('os'); const { getUserData, getSetupData } = require('../Middlewares/watcherMiddleware'); let setupData = getSetupData(); let userData = getUserData(); router.use(bodyParser.json()); router.get('/dashboard', authMiddleware, async (req, res) => { const folderName = req.params.folderName || ''; if (!req.userData || !req.userData.name) { return res.render('error-recovery-file', { error: 'User data is undefined or incomplete' }); } const userId = req.userData.id; const userName = req.userData.name; const downloadDir = path.join('cdn-files', userName); const domain = config.domain || 'mydomain.com'; if (!fs.existsSync(downloadDir)) { fs.mkdirSync(downloadDir, { recursive: true }); } try { fs.accessSync(downloadDir, fs.constants.R_OK | fs.constants.W_OK); } catch (err) { console.error('No access!', err); return res.render('error-recovery-file', { error: 'No access to directory' }); } let fileInfoNames = []; try { const fileInfo = JSON.parse(fs.readFileSync(path.join(__dirname, '../data', 'setup.json'), 'utf-8')) fileInfoNames = fileInfo.map(file => file.fileName); fileInfo.map(/* ... */); } catch (err) { console.error('Error reading file_info.json:', err); } try { const files = await fs.promises.readdir(downloadDir); const folders = files.filter(file => fs.statSync(path.join(downloadDir, file)).isDirectory()); const fileDetails = files.map(file => { const filePath = path.join(downloadDir, file); const stats = fs.statSync(filePath); const fileExtension = path.extname(file).toLowerCase(); const encodedFileName = encodeURIComponent(file); const fileLink = `https://${domain}/attachments/${userId}/${encodedFileName}`; const fileType = stats.isDirectory() ? 'folder' : 'file'; return { name: file, size: stats.size, url: fileLink, extension: fileExtension, type: fileType }; }); const availableExtensions = Array.from(new Set(fileDetails.map(file => file.extension))); res.render('dashboard', { files: fileDetails, folders, extensions: availableExtensions, allFolders: folders, folderName: folderName, fileInfoNames: fileInfoNames }); } catch (err) { console.error('Error reading directory:', err); return res.render('error-recovery-file', { error: err.message }); } }); router.get('/dashboard/folder/:folderName', authMiddleware, async (req, res) => { const userId = req.userData.name; const folderName = req.params.folderName || ''; const folderPath = path.join('cdn-files', userId, folderName); const userFolderPath = path.join('cdn-files', userId); const domain = config.domain || 'mydomain.com'; const currentFolderName = folderName || ''; const data = await fs.readFileSync(path.join(__dirname, '../data', 'setup.json'), 'utf-8') let users; try { users = JSON.parse(data); } catch (error) { console.error('Error parsing setup.json:', error); users = []; } if (!Array.isArray(users)) { console.error('Error: users is not an array. Check the contents of setup.json'); users = []; } const user = users.find(user => user.name === userId); if (!user) { return res.status(500).send('User not found in user.json'); } const userRealId = user.id; const fileInfoData = await fs.readFileSync(path.join(__dirname, '../data', 'file_info.json'), 'utf-8') let fileInfo; try { fileInfo = JSON.parse(fileInfoData); } catch (error) { console.error('Error parsing file_info.json:', error); fileInfo = []; } // Check if fileInfo is an array if (!Array.isArray(fileInfo)) { console.error('Error: fileInfo is not an array. Check the contents of file_info.json'); fileInfo = []; // Default to an empty array to prevent further errors } const fileInfoNames = fileInfo.map(file => file.fileName); fs.readdir(folderPath, { withFileTypes: true }, (err, entries) => { if (err) { console.error('Error reading directory:', err); return res.render('error-recovery-file'); } const folders = entries .filter(entry => entry.isDirectory()) .map(entry => entry.name); fs.readdir(userFolderPath, { withFileTypes: true }, (err, allEntries) => { if (err) { console.error('Error reading user directory:', err); return res.render('error-recovery-file'); } const allFolders = allEntries .filter(entry => entry.isDirectory()) .map(entry => entry.name); const fileDetailsPromises = entries.map(entry => { const filePath = path.join(folderPath, entry.name); return new Promise((resolve, reject) => { fs.stat(filePath, (err, stats) => { if (err) { console.error('Error getting file stats:', err); return reject(err); } const encodedFileName = encodeURIComponent(entry.name); const fileLink = `https://${domain}/attachments/${userRealId}/${encodedFileName}`; const fileType = entry.isDirectory() ? 'folder' : 'file'; resolve({ name: entry.name, size: stats.size, url: fileLink, extension: path.extname(entry.name).toLowerCase(), type: fileType }); }); }); }); Promise.all(fileDetailsPromises) .then(fileDetails => { const availableExtensions = Array.from(new Set(fileDetails.map(file => file.extension))); res.render('folder', { files: fileDetails, folders, allFolders, extensions: availableExtensions, currentFolder: currentFolderName, folderName: folderName, fileInfoNames }); }) .catch(error => { console.error('Error processing file details:', error); res.status(500).send('Erreur lors du traitement des détails des fichiers.'); }); }); }); }); router.post('/dashboard/newfolder', authMiddleware, (req, res) => { try { console.log('Received POST request to create a new folder.'); const userId = req.userData.name; let { folderName } = req.body; console.log('Received folderName:', folderName); if (!folderName || typeof folderName !== 'string') { console.log('Invalid folderName:', folderName); return res.status(400).json({ message: 'Le nom du dossier ne peut pas être vide.' }); } folderName = folderName.trim(); if (!folderName) { console.log('Trimmed folderName is empty.'); return res.status(400).json({ message: 'Le nom du dossier ne peut pas être vide.' }); } const folderPath = path.join('cdn-files', userId, folderName); if (fs.existsSync(folderPath)) { console.log('Folder already exists:', folderPath); return res.status(400).json({ message: 'Le dossier existe déjà.' }); } fs.mkdir(folderPath, (err) => { if (err) { console.error(err); return res.status(500).json({ message: 'Erreur lors de la création du dossier.', error: err }); } console.log('Folder created successfully:', folderPath); res.status(200).json({ message: 'Dossier créé avec succès.' }); }); } catch (error) { console.error('Error creating folder:', error); return res.status(500).json({ message: 'Erreur lors de la création du dossier.', error: error }); } }); router.post('/dashboard/rename', authMiddleware, async (req, res) => { const userId = req.userData.name; const { currentName, newName } = req.body; if (!currentName || !newName) { return res.status(400).send('Both currentName and newName must be provided.'); } const currentPath = path.join('cdn-files', userId || '', currentName); const newPath = path.join('cdn-files', userId, newName); try { await fs.promises.rename(currentPath, newPath); const data = await fs.promise.readFileSync(path.join(__dirname, '../data', 'file_info.json'), 'utf-8') let fileInfo = JSON.parse(data); let found = false; for (let i = 0; i < fileInfo.length; i++) { if (fileInfo[i].fileName === currentName) { fileInfo[i].fileName = newName; found = true; break; } } if (found) { await fs.promises.writeFile(path.join(__dirname, '../data', 'file_info.json'), JSON.stringify(fileInfo, null, 2), 'utf8'); } res.status(200).send('L\'opération a été effectuée avec succès.'); } catch (err) { console.error(err); return res.status(500).send('Erreur lors du changement de nom du fichier.'); } }); router.post('/dashboard/rename/:filePath*', authMiddleware, async (req, res) => { const userId = req.userData.name; const { currentName, newName } = req.body; const filePath = path.join(req.params.filePath, req.params[0] || ''); if (!currentName || !newName) { return res.status(400).send('Both currentName and newName must be provided.'); } const currentPath = path.join('cdn-files', userId || '', filePath, currentName); const newPath = path.join('cdn-files', userId, filePath, newName); try { await fs.promises.rename(currentPath, newPath); const data = await fs.promises.readFile(path.join(__dirname, '../data', 'file_info.json'), 'utf8'); let fileInfo = JSON.parse(data); let found = false; for (let i = 0; i < fileInfo.length; i++) { if (fileInfo[i].fileName === currentName) { fileInfo[i].fileName = newName; found = true; break; } } if (found) { await fs.promises.writeFile(path.join(__dirname, '../data', 'file_info.json'), JSON.stringify(fileInfo, null, 2), 'utf8'); } res.status(200).send('L\'opération a été effectuée avec succès.'); } catch (err) { console.error(err); return res.status(500).send('Erreur lors du changement de nom du fichier.'); } }); router.post('/dashboard/delete', authMiddleware, (req, res) => { const userId = req.userData.name; const { filename } = req.body; if (!userId || !filename) { return res.status(400).json({ message: 'Identifiant d\'utilisateur ou nom de fichier manquant pour la suppression du fichier.' }); } const userFolderPath = path.join('cdn-files', userId); function findAndDeleteFile(folderPath) { const filesInFolder = fs.readdirSync(folderPath); for (const file of filesInFolder) { const filePath = path.join(folderPath, file); if (fs.statSync(filePath).isDirectory()) { findAndDeleteFile(filePath); } else if (file === filename) { try { fs.unlinkSync(filePath); console.log('File deleted:', filePath); return true; } catch (error) { console.error('Error deleting file:', error); return false; } } } return false; } const fileDeleted = findAndDeleteFile(userFolderPath); if (fileDeleted) { res.status(200).json({ status: 'success', message: 'Le fichier a été supprimé avec succès.' }); } else { res.status(404).json({ status: 'error', message: 'Le fichier que vous essayez de supprimer n\'existe pas.' }); } }); const ncpAsync = (source, destination) => { return new Promise((resolve, reject) => { ncp(source, destination, (err) => { if (err) { reject(err); } else { resolve(); } }); }); }; router.post('/dashboard/movefile', authMiddleware, async (req, res) => { const fileName = req.body.fileName; const folderName = req.body.folderName; const data = await fs.readFileSync(path.join(__dirname, '../data', 'user.json.json'), 'utf-8') const users = JSON.parse(data); const user = users.find(user => user.id === req.user.id); if (!user) { console.error('User not found in user.json'); return res.status(500).send('Erreur lors du déplacement du fichier.'); } const userId = user.name; if (!fileName || !userId) { console.error('fileName or userId is undefined'); return res.status(500).send('Erreur lors du déplacement du fichier.'); } const sourcePath = path.join('cdn-files', userId, fileName); let destinationDir; if (folderName && folderName.trim() !== '') { destinationDir = path.join('cdn-files', userId, folderName); } else { destinationDir = path.join('cdn-files', userId); } const destinationPath = path.join(destinationDir, fileName); try { const normalizedSourcePath = path.normalize(sourcePath); console.log('Full Source Path:', normalizedSourcePath); if (fs.existsSync(normalizedSourcePath)) { await fs.promises.access(destinationDir); await ncpAsync(normalizedSourcePath, destinationPath); await fs.promises.unlink(normalizedSourcePath); } else { console.log('File does not exist'); } res.redirect('/dpanel/dashboard'); } catch (err) { console.error(err); return res.status(500).send('Erreur lors du déplacement du fichier.'); } }); router.post('/dashboard/movefile/:folderName', authMiddleware, async (req, res) => { const fileName = req.body.fileName; const newFolderName = req.body.folderName; const oldFolderName = req.params.folderName; const userId = req.user && req.user._json ? req.userData.name : undefined; if (!fileName || !userId || !oldFolderName || !newFolderName) { console.error('fileName, userId, oldFolderName, or newFolderName is undefined'); return res.status(500).send('Erreur lors du déplacement du fichier.'); } const sourcePath = path.join(process.cwd(), 'cdn-files', userId, oldFolderName, fileName); const destinationDir = path.join(process.cwd(), 'cdn-files', userId, newFolderName); const destinationPath = path.join(destinationDir, fileName); try { const normalizedSourcePath = path.normalize(sourcePath); console.log('Full Source Path:', normalizedSourcePath); if (fs.existsSync(normalizedSourcePath)) { await fs.promises.access(destinationDir, fs.constants.W_OK); await fs.promises.rename(normalizedSourcePath, destinationPath); } else { console.log('File does not exist'); } res.redirect('/dpanel/dashboard'); } catch (err) { console.error(err); return res.status(500).send('Erreur lors du déplacement du fichier.'); } }); router.delete('/dashboard/deletefolder/:folderName', authMiddleware, (req, res) => { const userId = req.userData.name; const { filename } = req.body; const userFolderPath = path.join('cdn-files', userId || ''); const folderPath = path.join(userFolderPath, req.params.folderName || ''); if (!fs.existsSync(folderPath)) { return res.status(404).json({ error: 'Le dossier spécifié n\'existe pas.' }); } fs.rmdirSync(folderPath, { recursive: true }); res.json({ deleted: true, success: 'Dossier supprimé avec succès.' }); }); router.delete('/dashboard/deletefolder/:folderName', authMiddleware, (req, res) => { const userId = req.userData.name; const folderName = req.params.folderName; const folderPath = path.join('cdn-files', userId, folderName); fs.rmdir(folderPath, { recursive: true }, (err) => { if (err) { console.error(err); return res.status(500).json({ error: 'Erreur lors de la suppression du dossier.' }); } res.json({ deleted: true, success: 'Dossier supprimé avec succès.' }); }); }); router.post('/dashboard/deletefile/:folderName', authMiddleware, (req, res) => { const userId = req.userData.name; const { filename } = req.body; const userFolderPath = path.join('cdn-files', userId || ''); const filePath = path.join(userFolderPath, req.params.folderName, filename || ''); if (!fs.existsSync(filePath)) { return res.status(404).json({ error: 'Le fichier spécifié n\'existe pas.' }); } fs.unlink(filePath, (err) => { if (err) { console.error(err); return res.status(500).json({ error: 'Erreur lors de la suppression du fichier.' }); } res.json({ deleted: true, success: 'Fichier supprimé avec succès.' }); }); }); router.get('/upload', authMiddleware, (req, res) => { res.render('upload'); }); router.use(fileUpload({ limits: { fileSize: 15 * 1024 * 1024 * 1024 }, })); router.post('/upload', authMiddleware, async (req, res) => { try { if (!req.files || Object.keys(req.files).length === 0) { return res.status(400).send('5410 - Erreur de téléchargement, veuillez retenter ultérieurement.'); } const file = req.files.file; const userId = req.userData.name; const Id = req.userData.id; const uploadDir = path.join('cdn-files', userId); const originalFileName = file.name; const domain = config.domain || 'mydomain.com'; let expiryDate = req.body.expiryDate; let password = req.body.password; if (!fs.existsSync(uploadDir)) { fs.mkdirSync(uploadDir, { recursive: true }); } file.mv(path.join(uploadDir, originalFileName), async (err) => { if (err) { console.error(err); return res.status(500).send({ message: 'Erreur lors du téléchargement du fichier.' }); } const fileExtension = path.extname(originalFileName).toLowerCase(); let encryptedPassword = ''; if (password) { const algorithm = 'aes-256-cbc'; const key = crypto.scryptSync(password, 'salt', 32); const iv = Buffer.alloc(16, 0); const cipher = crypto.createCipheriv(algorithm, key, iv); encryptedPassword = cipher.update('', 'utf8', 'hex'); encryptedPassword += cipher.final('hex'); } const fileInfo = { fileName: originalFileName, expiryDate: expiryDate || '', password: encryptedPassword, Id: Id, path: path.join(uploadDir, originalFileName) }; if (expiryDate || password) { let data = []; if (fs.existsSync(path.join(__dirname, '../data', 'file_info.json'))) { const existingData = await fs.promises.readFile(path.join(__dirname, '../data', 'file_info.json'), 'utf8'); data = JSON.parse(existingData); } data.push(fileInfo); await fs.promises.writeFile(path.join(__dirname, '../data', 'file_info.json'), JSON.stringify(data, null, 2)); } res.redirect('/dpanel/dashboard'); }); } catch (error) { console.error(error); return res.status(500).send({ message: 'Erreur lors du téléchargement du fichier.' }); } }); const User = require('../data/user.json'); const setup = JSON.parse(fs.readFileSync(path.join(__dirname, '../data', 'setup.json'), 'utf-8')); router.get('/dashboard/admin', authMiddleware, async (req, res) => { try { res.render('paramAdmin', { users: User, setup: setup }); } catch (err) { console.error(err); res.status(500).send('Server Error'); } }); router.get('/dashboard/admin/users', authMiddleware, async (req, res) => { try { let currentPage = Number(req.query.page) || 1; let limit = Number(req.query.limit) || 10; let rawdata = fs.readFileSync(path.join(__dirname, '../data/user.json')); let users = JSON.parse(rawdata); let totalUsers = users.length; let pages = Math.ceil(totalUsers / limit); let start = (currentPage - 1) * limit; let end = start + limit; let usersForPage = users.slice(start, end); res.render('paramAdminUser', { users: usersForPage, setup: setup, pages: pages, currentPage: currentPage, limit: limit }); } catch (err) { console.error(err); res.status(500).send('Server Error'); } }); router.get('/dashboard/admin/settingsetup', authMiddleware, async (req, res) => { try { res.render('paramAdminSettingSetup', { users: User, setup: setup }); } catch (err) { console.error(err); res.status(500).send('Server Error'); } }); const osUtils = require('os-utils'); const Convert = require('ansi-to-html'); const convert = new Convert(); router.get('/dashboard/admin/stats-logs', authMiddleware, async (req, res) => { try { const uptime = os.uptime(); const memoryUsage = process.memoryUsage().heapUsed / 1024 / 1024; osUtils.cpuUsage(function(cpuUsage) { fs.readdir('./logs', (err, files) => { if (err) { console.error(err); res.status(500).send('Error reading logs'); return; } const logs = files.map(file => { return fs.promises.readFile(path.join('./logs', file), 'utf8') .then(content => { content = convert.toHtml(content); return { name: file, content: content }; }) .catch(err => { console.error(err); }); }); Promise.all(logs).then(completed => { res.render('paramAdminStats&Logs', { users: User, setup: setup, uptime, memoryUsage, cpuUsage, logs: completed }); }); }); }); } catch (err) { console.error(err); res.status(500).send('Server Error'); } }); router.get('/dashboard/admin/Privacy-Security', authMiddleware, async (req, res) => { try { const files = await fs.promises.readdir('./report'); const reports = files.filter(file => file.endsWith('.json')).map(file => { return fs.promises.readFile(path.join('./report', file), 'utf8') .then(content => { return { name: file, content: content }; }) .catch(err => { console.error(err); }); }); Promise.all([Promise.all(reports)]).then(([completedReports]) => { res.render('paramAdminPrivacy&Security', { users: User, reports: completedReports }); }); } catch (err) { console.error(err); res.status(500).send('Server Error'); } }); router.post('/dashboard/update-role', authMiddleware, async (req, res) => { try { const { id, role } = req.body; const user = User.find(user => user.id === id); if (user) { user.role = role; } fs.writeFileSync(path.join(__dirname, '../data/user.json'), JSON.stringify(User, null, 2)); res.redirect('/dpanel/dashboard/admin'); } catch (err) { console.error(err); res.status(500).send('Server Error'); } }); router.post('/dashboard/update-setup', authMiddleware, async (req, res) => { try { let setup = JSON.parse(fs.readFileSync(path.join(__dirname, '../data', 'setup.json'), 'utf-8')); if (!req.body.ldap || !req.body.ldap.enabled) { delete setup.ldap; } else { setup.ldap = req.body.ldap; } if (!req.body.discord || !req.body.discord.enabled) { delete setup.discord; } else { setup.discord = req.body.discord; } setup.domain = req.body.domain; setup.uptime = req.body.uptime; fs.writeFileSync(path.join(__dirname, '../data', 'setup.json'), 'utf-8'), JSON.stringify(setup, null, 2); res.redirect('/dpanel/dashboard/admin'); } catch (err) { console.error(err); res.status(500).send('Server Error'); } }); module.exports = router;