diff --git a/CEO/backup_directories/59c712d9-e6dd-438f-aec9-31ca2ae750e6/backup_dir/fisiere/New Microsoft Excel Worksheet.xlsx b/CEO/backup_directories/59c712d9-e6dd-438f-aec9-31ca2ae750e6/backup_dir/fisiere/New Microsoft Excel Worksheet.xlsx deleted file mode 100644 index d8b87bb..0000000 Binary files a/CEO/backup_directories/59c712d9-e6dd-438f-aec9-31ca2ae750e6/backup_dir/fisiere/New Microsoft Excel Worksheet.xlsx and /dev/null differ diff --git a/CEO/backup_directories/59c712d9-e6dd-438f-aec9-31ca2ae750e6/backup_dir/fisiere/New Microsoft Word Document.docx b/CEO/backup_directories/59c712d9-e6dd-438f-aec9-31ca2ae750e6/backup_dir/fisiere/New Microsoft Word Document.docx deleted file mode 100644 index ff94689..0000000 Binary files a/CEO/backup_directories/59c712d9-e6dd-438f-aec9-31ca2ae750e6/backup_dir/fisiere/New Microsoft Word Document.docx and /dev/null differ diff --git a/CEO/backup_directories/7c0ef9d5-23ed-47a6-bfb4-fdcfce436904/backup_dir/fisiere/New Microsoft Excel Worksheet.xlsx b/CEO/backup_directories/7c0ef9d5-23ed-47a6-bfb4-fdcfce436904/backup_dir/fisiere/New Microsoft Excel Worksheet.xlsx deleted file mode 100644 index 8f3963d..0000000 Binary files a/CEO/backup_directories/7c0ef9d5-23ed-47a6-bfb4-fdcfce436904/backup_dir/fisiere/New Microsoft Excel Worksheet.xlsx and /dev/null differ diff --git a/CEO/backup_directories/7c0ef9d5-23ed-47a6-bfb4-fdcfce436904/backup_dir/fisiere/New Microsoft Word Document.docx b/CEO/backup_directories/7c0ef9d5-23ed-47a6-bfb4-fdcfce436904/backup_dir/fisiere/New Microsoft Word Document.docx deleted file mode 100644 index ebcad29..0000000 Binary files a/CEO/backup_directories/7c0ef9d5-23ed-47a6-bfb4-fdcfce436904/backup_dir/fisiere/New Microsoft Word Document.docx and /dev/null differ diff --git a/CEO/filesReceived.json b/CEO/filesReceived.json new file mode 100644 index 0000000..45ae4b1 --- /dev/null +++ b/CEO/filesReceived.json @@ -0,0 +1 @@ +riº6Û‘Ñ»Û2d²–{ŽùãÇÛë%`nT´`ÐÄs \ No newline at end of file diff --git a/CEO/jobs/external_endpoints.js b/CEO/jobs/external_endpoints.js index 5a8fe16..73d3dc4 100644 --- a/CEO/jobs/external_endpoints.js +++ b/CEO/jobs/external_endpoints.js @@ -1,15 +1,15 @@ const express = require('express'); const fs = require('fs'); -const multer = require('multer'); const fsExtra = require('fs-extra'); const path = require('path'); const Joi = require('joi'); const { httpStatus } = require('../helpers/http_status'); const {lockFile, unlockFile} = require("../helpers/lock_mechanism"); +const {decryptFileInPlace, encryptFileInPlace} = require("../src/main/aes_encrypt"); const app = express(); app.use(express.json()); -app.use('/share_file', express.raw({ type: 'application/octet-stream', limit: 'Infinity' })); + const server = require('http').createServer(app); const connections = []; @@ -93,66 +93,82 @@ app.post('/file_path', async (req, res) => { async function addFilePathToJson(filePath) { const jsonFilePath = path.join(__dirname, '..', 'filesReceived.json'); + let data = { receivedFiles: [] }; try { - let data = { receivedFiles: [] }; - if (await fsExtra.pathExists(jsonFilePath)) { + // Check if the JSON file exists + const fileExists = await fsExtra.pathExists(jsonFilePath); + + if (fileExists) { await lockFile(jsonFilePath); + await decryptFileInPlace(jsonFilePath); data = await fsExtra.readJson(jsonFilePath); - }else{ + } else { + await fsExtra.writeJson(jsonFilePath, data, { spaces: 2 }); await lockFile(jsonFilePath); } - data.receivedFiles.push(filePath); + if (data.receivedFiles.findIndex(existingFilePath => existingFilePath === filePath) === -1) { + data.receivedFiles.push(filePath); + } + // Write the updated data back to the file await fsExtra.writeJson(jsonFilePath, data, { spaces: 2 }); + // Unlock the file after updating await unlockFile(jsonFilePath); + await encryptFileInPlace(jsonFilePath); console.log('File path added successfully.'); } catch (error) { console.error('Error updating JSON file:', error); - throw error; // Rethrow the error for further handling if necessary + await encryptFileInPlace(jsonFilePath); + await unlockFile(jsonFilePath); } } -const storage = multer.diskStorage({ - destination: function (req, file, cb) { - const baseDir = path.join(__dirname, '..', 'uploads', req.body.idUser); // Temp storage location - fsExtra.ensureDirSync(baseDir); - cb(null, baseDir); - }, - filename: function (req, file, cb) { - cb(null, req.body.nameOfFile); // Using directly assuming it has been validated already +app.use('/share_file', express.raw({ + type: 'application/octet-stream', + limit: '50mb' +})); + +async function getShareDir(filePath) { + try { + await lockFile(filePath); + + const fileContent = await fs.promises.readFile(filePath, 'utf8'); + const jsonData = JSON.parse(fileContent); + const path = jsonData.path; + + await unlockFile(filePath); + return path; + } catch (error) { + console.error('An error occurred:', error); + return null; } -}); +} -const upload = multer({ storage: storage }).single('file'); -// Route for file upload -app.post('/upload', async (req, res) => { - const shareFileSchema = Joi.object({ - idUser: Joi.string().required(), - nameOfFile: Joi.string().required(), - sizeOfFile: Joi.number().required() - }); +app.post('/share_file', async (req, res) => { + // Extract metadata from headers + const idUser = req.headers['x-iduser']; + const nameOfFile = req.headers['x-nameoffile']; + const sizeOfFile = req.headers['x-sizeoffile']; + + // You might want to validate the metadata here + if (!idUser || !nameOfFile || !sizeOfFile) { + return res.status(httpStatus.BAD_REQUEST).json({message: 'Missing metadata headers'}); + } + + // Construct the file path using the metadata + const shareDirPath = await getShareDir(path.join(__dirname, '..', 'dirShare.json')); + const baseDir = path.join(shareDirPath, idUser); + fsExtra.ensureDirSync(baseDir); + + const filePath = path.join(baseDir, nameOfFile); try { - const { error, value } = shareFileSchema.validate(req.body); - if (error) { - return res.status(httpStatus.BAD_REQUEST).send(`Validation error: ${error.message}`); - } - - await upload(req, res, async (err) => { - if (err instanceof multer.MulterError) { - res.status(httpStatus.INTERNAL_SERVER_ERROR).send(`Multer error: ${err.message}`); - return; - } else if (err) { - res.status(httpStatus.BAD_REQUEST).send(`Upload error: ${err.message}`); - return; - } - - // File upload logic - res.status(httpStatus.OK).json({ message: 'Upload successful.' }); - }); + fs.writeFileSync(filePath, req.body); + await addFilePathToJson(filePath); + res.status(httpStatus.OK).json({ message: 'Upload successful.' }); } catch (error) { console.error('Error during file upload:', error); res.status(httpStatus.INTERNAL_SERVER_ERROR).json({ message: 'Internal server error.' }); diff --git a/CEO/src/main/main.js b/CEO/src/main/main.js index 6cbedb3..3e38464 100644 --- a/CEO/src/main/main.js +++ b/CEO/src/main/main.js @@ -1,4 +1,4 @@ -const {app, BrowserWindow, screen, ipcMain, dialog} = require('electron'); +const {app, BrowserWindow, screen, ipcMain, dialog, shell} = require('electron'); const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); @@ -6,6 +6,7 @@ const {fork} = require('child_process'); const {encryptFileInPlace, decryptFileInPlace} = require('./aes_encrypt'); const {lockFile, unlockFile} = require("../../helpers/lock_mechanism"); +const exec = require("nodemon/lib/config/exec"); const isMac = process.platform === 'darwin'; let html_page = undefined; @@ -31,32 +32,11 @@ const createInitialKeys = () => { console.log(`IV saved to ${ivPath}`); } -const deleteMainComponentsAtErrorStart = () => { - const ipConfigPath = path.join(__dirname, '..', '..', 'ipConfig.json'); - const loginDataPath = path.join(__dirname, '..', '..', 'loginData.json'); - - fs.unlink(ipConfigPath, (err) => { - if (err) { - console.error('Error deleting file:', err); - return; - } - console.log('File deleted successfully: ' + 'ipConfig.json'); - }); - - fs.unlink(loginDataPath, (err) => { - if (err) { - console.error('Error deleting file:', err); - return; - } - console.log('File deleted successfully: ' + 'loginData.json'); - }); - -} - const checkForServerConnection = async () => { const pathToIpConfig = path.join(__dirname, '..', '..', 'ipConfig.json'); try { + console.log('Checking for server connection'); await fs.promises.access(pathToIpConfig); await lockFile(pathToIpConfig); @@ -71,17 +51,35 @@ const checkForServerConnection = async () => { return response.ok; } catch (error) { console.error("Error:", error); - return false; - } finally{ try{ fs.unlinkSync(pathToIpConfig); } catch{ } + return false; } }; +async function runStartupChecks() { + try { + await fs.promises.access(path.join(__dirname, '..', '..', 'secret.key'), fs.constants.F_OK); + await fs.promises.access(path.join(__dirname, '..', '..', 'iv.key'), fs.constants.F_OK); + } catch (err) { + console.error("Startup error detected:", err); + + // Run the npm clean script + await exec('npm run clean', { cwd: path.join(__dirname, '..', '..') }, (error, stdout, stderr) => { + if (error) { + console.error('Error occurred while running npm run clean:', stderr); + return; + } + console.log('npm run clean output:', stdout); + createInitialKeys(); + }); + } +} + const createMainWindow = (async (title, width, height) => { mainWindow = new BrowserWindow({ title: title, @@ -94,14 +92,7 @@ const createMainWindow = (async (title, width, height) => { } }); - try { - await fs.promises.access(path.join(__dirname, '..', '..', 'secret.key'), fs.constants.F_OK); - await fs.promises.access(path.join(__dirname, '..', '..', 'iv.key'), fs.constants.F_OK); - } catch (err) { - createInitialKeys(); - deleteMainComponentsAtErrorStart(); - } - + await runStartupChecks(); html_page = await checkForServerConnection() ? 'login.html' : 'ip_submit.html'; //mainWindow.setMenu(null); @@ -392,3 +383,40 @@ ipcMain.handle('decrypt-backup-files', async(event, destPath) => { }); } }) + +// Handle showing a file in the system file explorer +ipcMain.handle('show-file-in-explorer', async (event, filePath) => { + try { + // Ensure the file exists before attempting to show it + await fs.promises.access(filePath, fs.constants.F_OK); + shell.showItemInFolder(filePath); // Opens the file explorer and highlights the file + return true; + } catch (error) { + console.error('File does not exist:', error); + return false + } +}); + +// Handle removing a path from 'filesReceived.json' +ipcMain.handle('remove-path-from-received-files', async (event, filePath) => { + try { + const jsonFilePath = path.join(__dirname, '..', '..', 'filesReceived.json'); + await lockFile(jsonFilePath); + await decryptFileInPlace(jsonFilePath); + const data = await fs.promises.readFile(jsonFilePath, 'utf8'); + + const jsonData = JSON.parse(data); + + // Filter out the specified file path + jsonData.receivedFiles = jsonData.receivedFiles.filter(file => file !== filePath); + + await fs.promises.writeFile(jsonFilePath, JSON.stringify(jsonData, null, 2), 'utf8'); + await encryptFileInPlace(jsonFilePath); + await unlockFile(jsonFilePath); + + return true; + } catch (error) { + console.error('Error updating filesReceived.json:', error); + throw new Error('Failed to update received files list.'); + } +}); diff --git a/CEO/src/main/preload.js b/CEO/src/main/preload.js index 2aec160..a1ac5ca 100644 --- a/CEO/src/main/preload.js +++ b/CEO/src/main/preload.js @@ -14,5 +14,8 @@ contextBridge.exposeInMainWorld('electronAPI', { startMainProcesses: async (args) => ipcRenderer.invoke('start-main-processes', args), killBeforeLogout: async() => ipcRenderer.invoke('kill-before-logout'), - decryptFiles: async(destPath) => ipcRenderer.invoke('decrypt-backup-files', destPath) + decryptFiles: async(destPath) => ipcRenderer.invoke('decrypt-backup-files', destPath), + + showFileInExplorer: (filePath) => ipcRenderer.invoke('show-file-in-explorer', filePath), + removePathFromReceivedFiles: (filePath) => ipcRenderer.invoke('remove-path-from-received-files', filePath) }); \ No newline at end of file diff --git a/CEO/src/renderer/js/login.js b/CEO/src/renderer/js/login.js index 76c7bc8..2109265 100644 --- a/CEO/src/renderer/js/login.js +++ b/CEO/src/renderer/js/login.js @@ -18,7 +18,6 @@ document.addEventListener('DOMContentLoaded', async function () { await window.electronAPI.readFile('loginData.json') .then(async result => { const loginData = JSON.parse(result.content); - console.log(loginData); const {email, password} = loginData; await fetch(`http://${ip}/ceo/login`, { diff --git a/CEO/src/renderer/js/main_menu.js b/CEO/src/renderer/js/main_menu.js index 8335dd0..737a480 100644 --- a/CEO/src/renderer/js/main_menu.js +++ b/CEO/src/renderer/js/main_menu.js @@ -1,5 +1,6 @@ document.addEventListener('DOMContentLoaded', async function () { await insertUsername(); + setInterval(loadReceivedFiles, 3000); // Call loadReceivedFiles every 5000 ms (5 seconds) const backupButton = document.getElementById('backup'); const shareButton = document.getElementById('share_dir'); @@ -11,6 +12,53 @@ document.addEventListener('DOMContentLoaded', async function () { const decryptButton = document.getElementById('decrypt'); const logoutButton = document.getElementById('logout'); + async function loadReceivedFiles() { + const checkFileReceived = await window.electronAPI.checkFileExists('filesReceived.json'); + if (!checkFileReceived) { + return; + } + + try { + const fileData = await window.electronAPI.readFile('filesReceived.json'); + const filesJson = JSON.parse(fileData.content); + const receivedFiles = filesJson.receivedFiles; + + const notificationsDiv = document.getElementById('notifications'); + const existingButtons = Array.from(notificationsDiv.children).map(button => button.getAttribute('data-filepath')); + + receivedFiles.forEach(filePath => { + // Check if the button for this file path already exists + if (!existingButtons.includes(filePath)) { + const button = document.createElement('button'); + button.setAttribute('data-filepath', filePath); // Set a custom attribute to track the file path + button.name = 'notification'; + button.textContent = 'You received a file'; + button.addEventListener('click', () => handleFileReceivedButtonPressed(filePath, button)); + notificationsDiv.appendChild(button); + } + }); + } catch (error) { + console.error('Error loading received files:', error); + } + } + + async function handleFileReceivedButtonPressed(filePath, button) { + console.log('Notification button clicked!'); + + // Open file in file explorer + await window.electronAPI.showFileInExplorer(filePath) + .then(() => console.log('File explorer opened')) + .catch(error => console.error('Error opening file explorer:', error)); + + // Remove the button + button.remove(); + + // Call to remove the path from the JSON file + await window.electronAPI.removePathFromReceivedFiles(filePath) + .then(() => console.log('Path removed from received files')) + .catch(error => console.error('Error removing path:', error)); + } + checkDirBackupFileExists() .then(() => console.log('verificare backupDir facuta')); @@ -134,7 +182,7 @@ document.addEventListener('DOMContentLoaded', async function () { .then(() => console.log('Alert window opened')) .catch(error => console.error('Error showing alert:', error))); - const button = document.getElementById('backup_alert'); + const button = document.getElementById('share_alert'); button.remove(); } diff --git a/UC/backend/src/db/backup_schemes.json b/UC/backend/src/db/backup_schemes.json index 97eca47..0bbe8e8 100644 --- a/UC/backend/src/db/backup_schemes.json +++ b/UC/backend/src/db/backup_schemes.json @@ -1,6 +1,6 @@ { "7c0ef9d5-23ed-47a6-bfb4-fdcfce436904": { - "ip": "192.168.0.253", + "ip": "192.168.0.195", "directoryStructure": "{\"backup_dir\":{\"files\":[],\"fisiere\":{\"files\":[\"New Microsoft Excel Worksheet.xlsx\",\"New Microsoft Word Document.docx\"]}}}", "totalSize": 19363 }, diff --git a/User/jobs/external_endpoints.js b/User/jobs/external_endpoints.js index 58e1126..73d3dc4 100644 --- a/User/jobs/external_endpoints.js +++ b/User/jobs/external_endpoints.js @@ -93,24 +93,35 @@ app.post('/file_path', async (req, res) => { async function addFilePathToJson(filePath) { const jsonFilePath = path.join(__dirname, '..', 'filesReceived.json'); + let data = { receivedFiles: [] }; try { - let data = { receivedFiles: [] }; - if (await fsExtra.pathExists(jsonFilePath)) { + // Check if the JSON file exists + const fileExists = await fsExtra.pathExists(jsonFilePath); + + if (fileExists) { await lockFile(jsonFilePath); + await decryptFileInPlace(jsonFilePath); data = await fsExtra.readJson(jsonFilePath); - }else{ + } else { + await fsExtra.writeJson(jsonFilePath, data, { spaces: 2 }); await lockFile(jsonFilePath); } - data.receivedFiles.push(filePath); + if (data.receivedFiles.findIndex(existingFilePath => existingFilePath === filePath) === -1) { + data.receivedFiles.push(filePath); + } + // Write the updated data back to the file await fsExtra.writeJson(jsonFilePath, data, { spaces: 2 }); + // Unlock the file after updating await unlockFile(jsonFilePath); + await encryptFileInPlace(jsonFilePath); console.log('File path added successfully.'); } catch (error) { console.error('Error updating JSON file:', error); - throw error; // Rethrow the error for further handling if necessary + await encryptFileInPlace(jsonFilePath); + await unlockFile(jsonFilePath); } } @@ -119,18 +130,16 @@ app.use('/share_file', express.raw({ limit: '50mb' })); -async function decryptAndGetShareDir(filePath) { +async function getShareDir(filePath) { try { await lockFile(filePath); - await decryptFileInPlace(filePath); const fileContent = await fs.promises.readFile(filePath, 'utf8'); const jsonData = JSON.parse(fileContent); - const serverIP = jsonData.path; + const path = jsonData.path; - await encryptFileInPlace(filePath) await unlockFile(filePath); - return serverIP; + return path; } catch (error) { console.error('An error occurred:', error); return null; @@ -146,18 +155,19 @@ app.post('/share_file', async (req, res) => { // You might want to validate the metadata here if (!idUser || !nameOfFile || !sizeOfFile) { - return res.status(httpStatus.BAD_REQUEST).send('Missing metadata headers'); + return res.status(httpStatus.BAD_REQUEST).json({message: 'Missing metadata headers'}); } // Construct the file path using the metadata - const shareDirPath = await decryptAndGetShareDir(path.join(__dirname, '..', 'shareDir.json')); + const shareDirPath = await getShareDir(path.join(__dirname, '..', 'dirShare.json')); const baseDir = path.join(shareDirPath, idUser); fsExtra.ensureDirSync(baseDir); - const filePath = path.join(shareDirPath, nameOfFile); + const filePath = path.join(baseDir, nameOfFile); try { fs.writeFileSync(filePath, req.body); + await addFilePathToJson(filePath); res.status(httpStatus.OK).json({ message: 'Upload successful.' }); } catch (error) { console.error('Error during file upload:', error); diff --git a/User/src/main/main.js b/User/src/main/main.js index a5d2755..3e38464 100644 --- a/User/src/main/main.js +++ b/User/src/main/main.js @@ -1,4 +1,4 @@ -const {app, BrowserWindow, screen, ipcMain, dialog} = require('electron'); +const {app, BrowserWindow, screen, ipcMain, dialog, shell} = require('electron'); const fs = require('fs'); const path = require('path'); const crypto = require('crypto'); @@ -6,6 +6,7 @@ const {fork} = require('child_process'); const {encryptFileInPlace, decryptFileInPlace} = require('./aes_encrypt'); const {lockFile, unlockFile} = require("../../helpers/lock_mechanism"); +const exec = require("nodemon/lib/config/exec"); const isMac = process.platform === 'darwin'; let html_page = undefined; @@ -31,32 +32,11 @@ const createInitialKeys = () => { console.log(`IV saved to ${ivPath}`); } -const deleteMainComponentsAtErrorStart = () => { - const ipConfigPath = path.join(__dirname, '..', '..', 'ipConfig.json'); - const loginDataPath = path.join(__dirname, '..', '..', 'loginData.json'); - - fs.unlink(ipConfigPath, (err) => { - if (err) { - console.error('Error deleting file:', err); - return; - } - console.log('File deleted successfully: ' + 'ipConfig.json'); - }); - - fs.unlink(loginDataPath, (err) => { - if (err) { - console.error('Error deleting file:', err); - return; - } - console.log('File deleted successfully: ' + 'loginData.json'); - }); - -} - const checkForServerConnection = async () => { const pathToIpConfig = path.join(__dirname, '..', '..', 'ipConfig.json'); try { + console.log('Checking for server connection'); await fs.promises.access(pathToIpConfig); await lockFile(pathToIpConfig); @@ -71,10 +51,35 @@ const checkForServerConnection = async () => { return response.ok; } catch (error) { console.error("Error:", error); + try{ + fs.unlinkSync(pathToIpConfig); + } + catch{ + + } return false; } }; +async function runStartupChecks() { + try { + await fs.promises.access(path.join(__dirname, '..', '..', 'secret.key'), fs.constants.F_OK); + await fs.promises.access(path.join(__dirname, '..', '..', 'iv.key'), fs.constants.F_OK); + } catch (err) { + console.error("Startup error detected:", err); + + // Run the npm clean script + await exec('npm run clean', { cwd: path.join(__dirname, '..', '..') }, (error, stdout, stderr) => { + if (error) { + console.error('Error occurred while running npm run clean:', stderr); + return; + } + console.log('npm run clean output:', stdout); + createInitialKeys(); + }); + } +} + const createMainWindow = (async (title, width, height) => { mainWindow = new BrowserWindow({ title: title, @@ -87,14 +92,7 @@ const createMainWindow = (async (title, width, height) => { } }); - try { - await fs.promises.access(path.join(__dirname, '..', '..', 'secret.key'), fs.constants.F_OK); - await fs.promises.access(path.join(__dirname, '..', '..', 'iv.key'), fs.constants.F_OK); - } catch (err) { - createInitialKeys(); - deleteMainComponentsAtErrorStart(); - } - + await runStartupChecks(); html_page = await checkForServerConnection() ? 'login.html' : 'ip_submit.html'; //mainWindow.setMenu(null); @@ -336,7 +334,7 @@ ipcMain.handle('start-main-processes', async (event, args) => { }); } - if (externalEndpointsProcess) { + if (!externalEndpointsProcess) { externalEndpointsProcess = fork(path.join(__dirname, '..', '..', 'jobs', 'external_endpoints.js'), args, { silent: false }); externalEndpointsProcess.on('exit', () => { externalEndpointsProcess = null; @@ -385,3 +383,40 @@ ipcMain.handle('decrypt-backup-files', async(event, destPath) => { }); } }) + +// Handle showing a file in the system file explorer +ipcMain.handle('show-file-in-explorer', async (event, filePath) => { + try { + // Ensure the file exists before attempting to show it + await fs.promises.access(filePath, fs.constants.F_OK); + shell.showItemInFolder(filePath); // Opens the file explorer and highlights the file + return true; + } catch (error) { + console.error('File does not exist:', error); + return false + } +}); + +// Handle removing a path from 'filesReceived.json' +ipcMain.handle('remove-path-from-received-files', async (event, filePath) => { + try { + const jsonFilePath = path.join(__dirname, '..', '..', 'filesReceived.json'); + await lockFile(jsonFilePath); + await decryptFileInPlace(jsonFilePath); + const data = await fs.promises.readFile(jsonFilePath, 'utf8'); + + const jsonData = JSON.parse(data); + + // Filter out the specified file path + jsonData.receivedFiles = jsonData.receivedFiles.filter(file => file !== filePath); + + await fs.promises.writeFile(jsonFilePath, JSON.stringify(jsonData, null, 2), 'utf8'); + await encryptFileInPlace(jsonFilePath); + await unlockFile(jsonFilePath); + + return true; + } catch (error) { + console.error('Error updating filesReceived.json:', error); + throw new Error('Failed to update received files list.'); + } +}); diff --git a/User/src/main/preload.js b/User/src/main/preload.js index 2aec160..a1ac5ca 100644 --- a/User/src/main/preload.js +++ b/User/src/main/preload.js @@ -14,5 +14,8 @@ contextBridge.exposeInMainWorld('electronAPI', { startMainProcesses: async (args) => ipcRenderer.invoke('start-main-processes', args), killBeforeLogout: async() => ipcRenderer.invoke('kill-before-logout'), - decryptFiles: async(destPath) => ipcRenderer.invoke('decrypt-backup-files', destPath) + decryptFiles: async(destPath) => ipcRenderer.invoke('decrypt-backup-files', destPath), + + showFileInExplorer: (filePath) => ipcRenderer.invoke('show-file-in-explorer', filePath), + removePathFromReceivedFiles: (filePath) => ipcRenderer.invoke('remove-path-from-received-files', filePath) }); \ No newline at end of file diff --git a/User/src/renderer/js/main_menu.js b/User/src/renderer/js/main_menu.js index bc84454..737a480 100644 --- a/User/src/renderer/js/main_menu.js +++ b/User/src/renderer/js/main_menu.js @@ -1,68 +1,64 @@ document.addEventListener('DOMContentLoaded', async function () { await insertUsername(); + setInterval(loadReceivedFiles, 3000); // Call loadReceivedFiles every 5000 ms (5 seconds) - const backupButton = document.getElementById('backup_dir'); + const backupButton = document.getElementById('backup'); const shareButton = document.getElementById('share_dir'); - const departmentButton = document.getElementById('department_dir'); - const changeDepartmentButton = document.getElementById('change_department'); + const manageDepartmentButton = document.getElementById('manage_department'); + const manageUsersButton = document.getElementById('manage_users'); const changeInfoButton = document.getElementById('change_info'); const shareFileButton = document.getElementById('share_file'); const decryptButton = document.getElementById('decrypt'); const logoutButton = document.getElementById('logout'); - const overlay = document.getElementById('overlay'); - const ceoBackButton = document.getElementById('back_button'); - const ceoSubmitButton = document.getElementById('submit_button'); + async function loadReceivedFiles() { + const checkFileReceived = await window.electronAPI.checkFileExists('filesReceived.json'); + if (!checkFileReceived) { + return; + } - let ip = ''; - await window.electronAPI.readFile('ipConfig.json') - .then(result => { - const jsonData = JSON.parse(result.content); - ip = jsonData.ip; - }) + try { + const fileData = await window.electronAPI.readFile('filesReceived.json'); + const filesJson = JSON.parse(fileData.content); + const receivedFiles = filesJson.receivedFiles; - let triggerSource = ''; + const notificationsDiv = document.getElementById('notifications'); + const existingButtons = Array.from(notificationsDiv.children).map(button => button.getAttribute('data-filepath')); - function handleOverlayOpen(buttonId) { - overlay.style.display = 'block'; - triggerSource = buttonId; // Remember the button that triggered the overlay - console.log(`${buttonId} button clicked!`); + receivedFiles.forEach(filePath => { + // Check if the button for this file path already exists + if (!existingButtons.includes(filePath)) { + const button = document.createElement('button'); + button.setAttribute('data-filepath', filePath); // Set a custom attribute to track the file path + button.name = 'notification'; + button.textContent = 'You received a file'; + button.addEventListener('click', () => handleFileReceivedButtonPressed(filePath, button)); + notificationsDiv.appendChild(button); + } + }); + } catch (error) { + console.error('Error loading received files:', error); + } } - ceoBackButton.addEventListener('click', function () { - overlay.style.display = 'none'; - }); + async function handleFileReceivedButtonPressed(filePath, button) { + console.log('Notification button clicked!'); - ceoSubmitButton.addEventListener('click', async function (event) { - event.preventDefault(); - const password = document.getElementById('ceo_password').value; + // Open file in file explorer + await window.electronAPI.showFileInExplorer(filePath) + .then(() => console.log('File explorer opened')) + .catch(error => console.error('Error opening file explorer:', error)); - await fetch(`http://${ip}/users/validate_ceo_password`, { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - 'x-api-key': 'uc_api', - }, - body: JSON.stringify({ - password: password - }) - }).then(async result => { - const data = await result.json(); - if (!result.ok) { - throw new Error(data.message); - } - if (triggerSource === 'change_department') { - fadeOut('change_department.html'); - } else if (triggerSource === 'decrypt') { - console.log('astept decryptarea') - fadeOut('decrypting_backup.html'); - } - }) + // Remove the button + button.remove(); + + // Call to remove the path from the JSON file + await window.electronAPI.removePathFromReceivedFiles(filePath) + .then(() => console.log('Path removed from received files')) + .catch(error => console.error('Error removing path:', error)); + } - overlay.style.display = 'none'; - triggerSource = ''; - }); checkDirBackupFileExists() .then(() => console.log('verificare backupDir facuta')); @@ -70,9 +66,6 @@ document.addEventListener('DOMContentLoaded', async function () { checkShareDirFileExists() .then(() => console.log('verificare ShareDir facuta')); - checkDepartmentDirFileExists() - .then(() => {console.log('verificare departmentDir facuta')}) - backupButton.addEventListener('click', function () { console.log('Set backup directory button clicked!'); @@ -87,20 +80,14 @@ document.addEventListener('DOMContentLoaded', async function () { console.log('Set backup directory button clicked!'); window.electronAPI.openJsonDirConfigDialog('dirShare.json') - .then(() => console.log('Share directory set')) + .then(() => console.log('Back-up directory set')) .catch(async error => await window.electronAPI.showAlert(error.message) .then(() => console.log('Alert window opened')) .catch(error => console.error('Error showing alert:', error))); }); - departmentButton.addEventListener('click', function () { - console.log('Set backup directory button clicked!'); - - window.electronAPI.openJsonDirConfigDialog('dirDepartment.json') - .then(() => console.log('Department directory set')) - .catch(async error => await window.electronAPI.showAlert(error.message) - .then(() => console.log('Alert window opened')) - .catch(error => console.error('Error showing alert:', error))); + manageUsersButton.addEventListener('click', async function(){ + fadeOut('manage_users.html'); }); changeInfoButton.addEventListener('click', function () { @@ -108,12 +95,13 @@ document.addEventListener('DOMContentLoaded', async function () { fadeOut('profile.html'); }); - changeDepartmentButton.addEventListener('click', function () { - handleOverlayOpen('change_department'); + decryptButton.addEventListener('click', function () { + fadeOut('decrypting_backup.html'); }); - decryptButton.addEventListener('click', function () { - handleOverlayOpen('decrypt'); + changeInfoButton.addEventListener('click', function () { + console.log('Change your info button clicked!'); + fadeOut('profile.html'); }); shareFileButton.addEventListener('click', function () { @@ -121,6 +109,10 @@ document.addEventListener('DOMContentLoaded', async function () { fadeOut('share_file.html'); }); + manageDepartmentButton.addEventListener('click', function() { + fadeOut('manage_departments.html'); + }) + logoutButton.addEventListener('click', async function () { console.log('Logout button clicked!'); await window.electronAPI.killBeforeLogout(); @@ -128,6 +120,9 @@ document.addEventListener('DOMContentLoaded', async function () { fadeOut('login.html'); }); + decryptButton.addEventListener('click', async function (){ + + }); async function checkDirBackupFileExists() { try { // Make an IPC call to check file existence @@ -154,7 +149,7 @@ document.addEventListener('DOMContentLoaded', async function () { if (!fileExists) { const notificationsDiv = document.getElementById('notifications'); const button = document.createElement('button'); - button.id = 'share_dir_alert'; + button.id = 'share_file_alert'; button.name = 'alert'; button.textContent = 'Set your share directory!'; button.addEventListener('click', handleShareButtonPressed); @@ -165,24 +160,6 @@ document.addEventListener('DOMContentLoaded', async function () { } } - async function checkDepartmentDirFileExists() { - try { - const fileExists = await window.electronAPI.checkFileExists('dirDepartment.json'); - - if (!fileExists) { - const notificationsDiv = document.getElementById('notifications'); - const button = document.createElement('button'); - button.id = 'department_alert'; - button.name = 'alert'; - button.textContent = 'Set your department directory!'; - button.addEventListener('click', handleDepartmentButtonPressed); - notificationsDiv.appendChild(button); - } - } catch (error) { - console.error('Error checking file existence:', error); - } - } - async function handleBackupButtonPressed() { console.log('Button clicked!'); @@ -205,20 +182,7 @@ document.addEventListener('DOMContentLoaded', async function () { .then(() => console.log('Alert window opened')) .catch(error => console.error('Error showing alert:', error))); - const button = document.getElementById('share_dir_alert'); - button.remove(); - } - - async function handleDepartmentButtonPressed() { - console.log('Button clicked!'); - - await window.electronAPI.openJsonDirConfigDialog('dirDepartment.json') - .then(() => console.log('Department directory set')) - .catch(async error => await window.electronAPI.showAlert(error.message) - .then(() => console.log('Alert window opened')) - .catch(error => console.error('Error showing alert:', error))); - - const button = document.getElementById('department_alert'); + const button = document.getElementById('share_alert'); button.remove(); }