const fsPromises = require('fs').promises; const fs = require('fs'); const path = require('path'); const ip = require('ip'); const {encryptFileInPlace, decryptFileInPlace} = require('../src/main/aes_encrypt'); const {lockFile, unlockFile} = require("../helpers/lock_mechanism"); async function fetchBackupSchemes(serverIp) { // Fetching backup schemes from the server const depResponse = await fetch(`http://${serverIp}/backup_schemes`, { method: 'GET', headers: {'x-api-key': 'uc_api'} }); const backupSchemesJson = await depResponse.json(); const backupSchemes = backupSchemesJson['data']; // Specify the path where the backup schemes will be saved const destPath = path.join(__dirname, '..', 'backupSchemes.json'); // Write the fetched backup schemes to the specified file try { await lockFile(destPath); await fsPromises.writeFile(destPath, JSON.stringify(backupSchemes, null, 2)); // Use null, 2 for pretty formatting await unlockFile(destPath); console.log('Backup schemes saved successfully to', destPath); } catch (error) { console.error('Failed to save backup schemes:', error); } } async function fetchUsersAndDepartments(serverIp) { try { console.log('se asteapta depart'); // Fetch departments const depResponse = await fetch(`http://${serverIp}/users/departments`, { method: 'GET', headers: {'x-api-key': 'uc_api'} }); const departmentsJson = await depResponse.json(); const departments = departmentsJson['data']; console.log('se asteapta users') // Fetch users const userResponse = await fetch(`http://${serverIp}/users`, { method: 'GET', headers: {'x-api-key': 'uc_api'} }); const usersJson = await userResponse.json(); const users = usersJson['data']; // Combine the JSON data const combinedData = Object.values(departments).reduce((acc, {name, key}) => { acc[name] = { key, users: users.filter(user => user.department === name).map(user => user.id) }; return acc; }, {}); // Write combined data to a file const filePath = path.join(__dirname, '..', 'usersInSystem.json'); if(!fs.existsSync(filePath)){ await fsPromises.writeFile(filePath, ''); } await lockFile(filePath); await fsPromises.writeFile(filePath, JSON.stringify(combinedData, null, 2), 'utf8'); await encryptFileInPlace(filePath); await unlockFile(filePath); console.log('Data has been encrypted and saved.'); } catch (error) { console.error('Failed to fetch or process data:', error); } } async function decryptAndGetServerIP(filePath) { try { await lockFile(filePath); await decryptFileInPlace(filePath); const fileContent = await fsPromises.readFile(filePath, 'utf8'); const jsonData = JSON.parse(fileContent); const serverIP = jsonData.ip; await encryptFileInPlace(filePath) await unlockFile(filePath); return serverIP; } catch (error) { console.error('An error occurred:', error); return null; } } async function getDirectoryStructure(dirPath) { const baseName = path.basename(dirPath); const entries = await fsPromises.readdir(dirPath, {withFileTypes: true}); const result = {}; result[baseName] = {files: []}; let totalSize = 0; for (let entry of entries) { const entryPath = path.join(dirPath, entry.name); if (entry.isDirectory()) { // Recursively get structure for subdirectories const {structure, size: subSize} = await getDirectoryStructure(entryPath); result[baseName][entry.name] = structure[Object.keys(structure)[0]]; // Object.keys to fetch the first key name totalSize += subSize; } else { // Add file name to the 'files' array and calculate total size const stats = await fsPromises.stat(entryPath); result[baseName].files.push(entry.name); totalSize += stats.size; } } return {structure: result, size: totalSize}; } async function createBackupScheme(serverIp, structure, size) { let filePath = path.join(__dirname, '..', 'loginData.json'); await lockFile(filePath); await decryptFileInPlace(filePath); const userContent = await fsPromises.readFile(filePath, 'utf8'); const userJson = JSON.parse(userContent); await encryptFileInPlace(filePath) await unlockFile(filePath); // Find the IP address of the machine const machineIP = ip.address(); // Prepare the data to be sent const dataToSend = { id: userJson.id, ip: machineIP, directoryStructure: JSON.stringify(structure), totalSize: size }; const response = await fetch(`http://${serverIp}/backup_schemes`, { method: 'PATCH', headers: { 'Content-Type': 'application/json', 'x-api-key': 'uc_api' }, body: JSON.stringify(dataToSend) }); if (response.ok) { console.log("Backup dir structure submitted.") } else { const data = await response.json() console.log(data.message); } } async function watchDirectoryChanges(serverIp) { async function readBackupConfig(filePath) { await lockFile(filePath); const fileContent = await fsPromises.readFile(filePath, 'utf8'); await unlockFile(filePath); return JSON.parse(fileContent); } async function updateBackupConfig(filePath, structure, size) { const data = { path: filePath, structure: structure, size: size }; await lockFile(filePath); await fsPromises.writeFile(path.join(__dirname, '..', 'dirBackup.json'), JSON.stringify(data, null, 2)); await unlockFile(filePath); } const configPath = path.join(__dirname, '..', 'dirBackup.json'); if(!fs.existsSync(configPath)){ console.log('backupDir file doesn\'t exists'); return; } const backupConfig = await readBackupConfig(configPath); const storedStructure = backupConfig.structure; const {structure: currentStructure, size: currentSize} = await getDirectoryStructure(backupConfig.path); if (JSON.stringify(storedStructure) !== JSON.stringify(currentStructure)) { console.log("Directory structure has changed. Updating backup..."); await createBackupScheme(serverIp, currentStructure, currentSize); await updateBackupConfig(backupConfig.path, currentStructure, currentSize); console.log('FetcherProcess: start backup.'); process.send({type: 'startBackup'}); } else { console.log("No changes detected in the directory structure."); } } let serverIp = null decryptAndGetServerIP(path.join(__dirname, '..', 'ipConfig.json')).then(ip => { serverIp = ip; }); const timeoutInterval = 1 * 20 * 1000 //minutes * seconds * miliseconds setInterval(() => { fetchUsersAndDepartments(serverIp); }, timeoutInterval); setInterval(() => { watchDirectoryChanges(serverIp); }, timeoutInterval); setInterval(() => { fetchBackupSchemes(serverIp); }, timeoutInterval); console.log("fetcher.js process started."); process.on('SIGINT', async () => { console.log('Shutdown signal received in \'fetcher.js\'. Cleaning up...'); try { console.log('Performing cleanup tasks...'); console.log('Cleanup completed successfully.'); } catch (error) { console.error('An error occurred during cleanup:', error); } finally { console.log('Process terminated'); process.exit(0); } });