const fs = require('fs').promises; // Ensure you use the promise-based API const path = require('path'); const { decryptFileInPlace, encryptFileInPlace, encryptFileWithKey, decryptFileWithKey} = require("../src/main/aes_encrypt"); const {lockFile, unlockFile} = require("../helpers/lock_mechanism"); function extractFilePaths(directoryStructure) { let paths = []; const traverse = (dir, currentPath) => { Object.keys(dir).forEach(key => { if (key === 'files') { dir[key].forEach(file => paths.push(path.join(currentPath, file))); } else { traverse(dir[key], path.join(currentPath, key)); } }); }; traverse(directoryStructure, ''); return paths; } async function fetchFiles(ip, filePaths) { let results = {}; for (const filePath of filePaths) { const url = `http://${ip}:3000/file_path`; try { const response = await fetch(url, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ filePath }) }); if (!response.ok) throw new Error(`HTTP status ${response.status}`); const arrayBuffer = await response.arrayBuffer(); // Fetch the response as an ArrayBuffer results[filePath] = Buffer.from(arrayBuffer); } catch (error) { console.error(`Error fetching ${filePath}:`, error); results[filePath] = null; } } return results; } async function removeDirectory(directoryPath) { try { // Check if the directory exists const stats = await fs.stat(directoryPath); if (!stats.isDirectory()) { console.log('The specified path is not a directory.'); return; } // Read all the contents of the directory const files = await fs.readdir(directoryPath); // Loop through each file/directory and delete them for (const file of files) { const currentPath = path.join(directoryPath, file); const currentStats = await fs.stat(currentPath); if (currentStats.isDirectory()) { // Recursive call for directories await removeDirectory(currentPath); } else { // Delete file await fs.unlink(currentPath); } } // Finally, delete the directory itself await fs.rmdir(directoryPath); //console.log(`Directory removed: ${directoryPath}`); } catch (error) { console.error(`Error removing directory: ${error.message}`); } } async function decryptUserSystemConfig() { const configPath = path.join(__dirname, '..', 'usersInSystem.json'); await lockFile(configPath); await decryptFileInPlace(configPath); } async function encryptUserSystemConfig(){ const configPath = path.join(__dirname, '..', 'usersInSystem.json'); await unlockFile(configPath); await encryptFileInPlace(configPath); } async function processBackup() { await decryptUserSystemConfig(); const usersConfigPath = path.join(__dirname, '..', 'usersInSystem.json'); const backupConfigPath = path.join(__dirname, '..', 'backupSchemes.json'); const baseBackupDirPath = path.join(__dirname, '..', 'backup_directories'); try { // Read and parse the users configuration const usersData = await fs.readFile(usersConfigPath, 'utf8'); const usersConfig = JSON.parse(usersData); // Read and parse the backup configuration const backupData = await fs.readFile(backupConfigPath, 'utf8'); const jsonData = JSON.parse(backupData); for (const key in jsonData) { const userBackupDir = path.join(baseBackupDirPath, key); await removeDirectory(userBackupDir); const node = jsonData[key]; const directoryStructure = JSON.parse(node.directoryStructure); const filePaths = extractFilePaths(directoryStructure); const files = await fetchFiles(node.ip, filePaths); await fs.mkdir(userBackupDir, { recursive: true }); // Find the encryption key for the user's department let encryptionKey = ''; for (const dept in usersConfig) { if (usersConfig[dept].users.includes(key)) { encryptionKey = usersConfig[dept].key; break; } } for (const file in files) { if (files[file]) { const fullPath = path.join(userBackupDir, file); await fs.mkdir(path.dirname(fullPath), { recursive: true }); await fs.writeFile(fullPath, files[file]); // Write the binary data // Encrypt the file in place after writing it if (encryptionKey) { await encryptFileWithKey(fullPath, encryptionKey); } } } } } catch (error) { console.error('Failed to read or process the JSON file:', error); } await encryptUserSystemConfig(); } async function getAllFilePaths(dirPath) { let filePaths = []; async function recurse(currentPath) { const entries = await fs.readdir(currentPath, { withFileTypes: true }); // Create promises for each entry and process them in parallel const entryPromises = entries.map(async (entry) => { const resolvedPath = path.join(currentPath, entry.name); if (entry.isDirectory()) { // If it's a directory, recurse into it await recurse(resolvedPath); } else { // If it's a file, add it to the file paths array filePaths.push(resolvedPath); } }); // Wait for all promises to complete await Promise.all(entryPromises); } await recurse(dirPath); return filePaths; } async function decryptUserFilesToDirectory(destinationDir) { await decryptUserSystemConfig(); // Ensure user config is decrypted const usersConfigPath = path.join(__dirname, '..', 'usersInSystem.json'); const usersConfig = JSON.parse(await fs.readFile(usersConfigPath, 'utf8')); const sourceDir = path.join(__dirname, '..', 'backup_directories'); try { for (const department in usersConfig) { const { key, users } = usersConfig[department]; for (const userId of users) { const userDir = path.join(sourceDir, userId); try { const files = await getAllFilePaths(userDir); for (const filePath of files) { const stats = await fs.stat(filePath); if (stats.isFile()) { // Extract the part of the file path after the userId const relativePath = path.relative(userDir, filePath); // Construct the destination file path const destinationFilePath = path.join(destinationDir, userId, relativePath); await fs.mkdir(path.dirname(destinationFilePath), { recursive: true }); // Decrypt the file in its original location await decryptFileWithKey(filePath, key); // Copy the decrypted file to the destination directory await fs.copyFile(filePath, destinationFilePath); console.log(`Decrypted file copied to: ${destinationFilePath}`); // Re-encrypt the file in its original location (optional) await encryptFileWithKey(filePath, key); } } } catch (error) { console.error(`Error processing files for user ${userId}: ${error.message}`); } } } } catch (error) { console.error(`Error processing decryption: ${error.message}`); } } processBackup(); decryptUserFilesToDirectory("C:\\Users\\Andrei Cerbu\\Documents\\decrypted");