From 9ac718bea3098c9821ebb24401fc18af5f6b4861 Mon Sep 17 00:00:00 2001 From: andrei-mihnea-cerbu Date: Mon, 22 Apr 2024 16:30:40 +0300 Subject: [PATCH] v2.1 --- CEO/backupSchemes.json | 8 ++- CEO/jobs/backup.js | 1 + CEO/src/main/main.js | 40 ++++++++----- .../html/sending_file_confirmation.html | 42 +------------- .../renderer/js/sending_file_confirmation.js | 54 ++++++++++++++++++ CEO/src/renderer/js/share_file.js | 26 ++++++--- UC/backend/src/app.js | 4 ++ UC/backend/src/db/backup_schemes.json | 13 ++++- UC/backend/src/routes/admin.js | 21 ++++++- User/backupSchemes.json | 11 +++- .../New Microsoft Excel Worksheet.xlsx | Bin 0 -> 6191 bytes .../fisiere/New Microsoft Word Document.docx | Bin 0 -> 13172 bytes User/dirBackup.json | 18 ------ User/dirDepartment.json | 3 - User/dirShare.json | 3 - User/jobs/fetcher.js | 1 + User/loginData.json | 2 +- User/src/main/main.js | 40 ++++++++----- User/src/renderer/html/main_menu.html | 9 +-- .../html/sending_file_confirmation.html | 42 +------------- User/src/renderer/js/main_menu.js | 22 +++++-- .../renderer/js/sending_file_confirmation.js | 54 ++++++++++++++++++ User/src/renderer/js/share_file.js | 24 +++++--- User/usersInSystem.json | Bin 288 -> 336 bytes 24 files changed, 275 insertions(+), 163 deletions(-) create mode 100644 CEO/src/renderer/js/sending_file_confirmation.js create mode 100644 User/backup_directories/7c0ef9d5-23ed-47a6-bfb4-fdcfce436904/backup_dir/fisiere/New Microsoft Excel Worksheet.xlsx create mode 100644 User/backup_directories/7c0ef9d5-23ed-47a6-bfb4-fdcfce436904/backup_dir/fisiere/New Microsoft Word Document.docx delete mode 100644 User/dirBackup.json delete mode 100644 User/dirDepartment.json delete mode 100644 User/dirShare.json create mode 100644 User/src/renderer/js/sending_file_confirmation.js diff --git a/CEO/backupSchemes.json b/CEO/backupSchemes.json index 9e26dfe..c84ae04 100644 --- a/CEO/backupSchemes.json +++ b/CEO/backupSchemes.json @@ -1 +1,7 @@ -{} \ No newline at end of file +{ + "7c0ef9d5-23ed-47a6-bfb4-fdcfce436904": { + "ip": "192.168.0.195", + "directoryStructure": "{\"backup_dir\":{\"files\":[],\"fisiere\":{\"files\":[\"New Microsoft Excel Worksheet.xlsx\",\"New Microsoft Word Document.docx\"]}}}", + "totalSize": 19363 + } +} \ No newline at end of file diff --git a/CEO/jobs/backup.js b/CEO/jobs/backup.js index 3a0c8ae..4b85119 100644 --- a/CEO/jobs/backup.js +++ b/CEO/jobs/backup.js @@ -4,6 +4,7 @@ const path = require('path'); const { decryptFileInPlace, encryptFileInPlace, encryptFileWithKey, decryptFileWithKey} = require("../src/main/aes_encrypt"); const {lockFile, unlockFile} = require("../helpers/lock_mechanism"); + async function decryptAndGetServerIP(filePath) { try { await lockFile(filePath); diff --git a/CEO/src/main/main.js b/CEO/src/main/main.js index 8cc5fcf..388cb49 100644 --- a/CEO/src/main/main.js +++ b/CEO/src/main/main.js @@ -6,7 +6,6 @@ const {fork} = require('child_process'); const {encryptFileInPlace, decryptFileInPlace} = require('./aes_encrypt'); const {lockFile, unlockFile} = require("../../helpers/lock_mechanism"); -//const {decryptUserFilesToDirectory} = require("../../jobs/backup"); const isMac = process.platform === 'darwin'; let html_page = undefined; @@ -18,7 +17,7 @@ let backupProcess = null; let externalEndpointsProcess = null; let sendFileProcess = null; -const create_initial_keys = () => { +const createInitialKeys = () => { const SECRET_KEY = crypto.randomBytes(32); const IV = crypto.randomBytes(16); @@ -32,7 +31,7 @@ const create_initial_keys = () => { console.log(`IV saved to ${ivPath}`); } -const delete_external_files = () => { +const deleteMainComponentsAtErrorStart = () => { const ipConfigPath = path.join(__dirname, '..', '..', 'ipConfig.json'); const loginDataPath = path.join(__dirname, '..', '..', 'loginData.json'); @@ -54,6 +53,28 @@ const delete_external_files = () => { } +const checkForServerConnection = async () => { + const pathToIpConfig = path.join(__dirname, '..', '..', 'ipConfig.json'); + + try { + await fs.promises.access(pathToIpConfig); + + await lockFile(pathToIpConfig); + await decryptFileInPlace(pathToIpConfig); + const ipConfig = await fs.promises.readFile(pathToIpConfig, 'utf-8'); + const { ip } = JSON.parse(ipConfig); + + const response = await fetch(`http://${ip}/heartbeat`); + + await encryptFileInPlace(pathToIpConfig) + await unlockFile(pathToIpConfig); + return response.ok; + } catch (error) { + console.error("Error:", error); + return false; + } +}; + const createMainWindow = (async (title, width, height) => { mainWindow = new BrowserWindow({ title: title, @@ -70,18 +91,11 @@ const createMainWindow = (async (title, width, height) => { 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) { - create_initial_keys(); - delete_external_files(); + createInitialKeys(); + deleteMainComponentsAtErrorStart(); } - html_page = 'ip_config.html'; - - try { - await fs.promises.access(path.join(__dirname, '..', '..', 'ipConfig.json')); - html_page = 'login.html'; - } catch (err) { - html_page = 'ip_submit.html'; - } + html_page = await checkForServerConnection() ? 'login.html' : 'ip_submit.html'; //mainWindow.setMenu(null); mainWindow.loadFile(path.join(__dirname, '..', 'renderer', 'html', html_page)) diff --git a/CEO/src/renderer/html/sending_file_confirmation.html b/CEO/src/renderer/html/sending_file_confirmation.html index 7774872..ca50d3a 100644 --- a/CEO/src/renderer/html/sending_file_confirmation.html +++ b/CEO/src/renderer/html/sending_file_confirmation.html @@ -9,47 +9,7 @@ - + ; Sending file diff --git a/CEO/src/renderer/js/sending_file_confirmation.js b/CEO/src/renderer/js/sending_file_confirmation.js new file mode 100644 index 0000000..f1b46f6 --- /dev/null +++ b/CEO/src/renderer/js/sending_file_confirmation.js @@ -0,0 +1,54 @@ +document.addEventListener("DOMContentLoaded", async function () { + async function performUploads() { + try { + const uploadFile = await window.electronAPI.readFile('usersDestTemp.json'); + const uploadData = JSON.parse(uploadFile.content); + + const uploadPromises = uploadData.users.map(async (user) => { + try { + const formData = new FormData(); + const file = await fetch(uploadData.filePath).then(response => response.blob()); + formData.append('file', file); + formData.append('idUser', user.userId); + formData.append('nameOfFile', user.fileName); + + await timeout(5000); // Timeout to simulate delay or wait + const url = `http://${user.destIp}:${user.destPort}/upload`; + const uploadResponse = await fetch(url, { + method: 'POST', + body: formData + }); + + if (!uploadResponse.ok) { + throw new Error(`HTTP error during file upload to ${user.userId}: status ${uploadResponse.status}`); + } + + return {userId: user.userId, success: true, message: `Upload successful for user ${user.userId}`}; + } catch (error) { + console.error(`Failed to upload for user ${user.userId}:`, error); + return {userId: user.userId, success: false, message: `Upload failed for user ${user.userId}`}; + } + }); + + const results = await Promise.all(uploadPromises); + results.forEach(result => { + if (result.success) { + console.log(result.message); + } + }); + console.log('All files processed. Check the console for detailed results.'); + } catch (error) { + console.error('An error occurred during uploads:', error); + } finally { + await window.electronAPI.deleteFile('usersDestTemp.json'); + } + } + + function timeout(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + await performUploads(); + await timeout(10000); + fadeOut('main_menu.html'); +}); \ No newline at end of file diff --git a/CEO/src/renderer/js/share_file.js b/CEO/src/renderer/js/share_file.js index aa0d0f6..bf2717f 100644 --- a/CEO/src/renderer/js/share_file.js +++ b/CEO/src/renderer/js/share_file.js @@ -4,7 +4,7 @@ document.addEventListener("DOMContentLoaded", async function () { await window.electronAPI.readFile('ipConfig.json') .then(result => { const jsonData = JSON.parse(result.content); - ip = jsonData.ip; + serverIp = jsonData.ip; }) function updateFileName() { @@ -72,8 +72,8 @@ document.addEventListener("DOMContentLoaded", async function () { event.preventDefault(); console.log('Submit button clicked'); - const fileInput = document.getElementById('fileInput'); - if (!fileInput.files.length) { + // Check if pathToFile has content + if (!pathToFile.trim()) { await window.electronAPI.showAlert('File not chosen!') .then(() => console.log('Alert window opened')) .catch(error => console.error('Error showing alert:', error)); @@ -94,13 +94,19 @@ document.addEventListener("DOMContentLoaded", async function () { } const uploadData = { - filePath: fileInput.files[0].path, + filePath: pathToFile, // Use the pathToFile variable users: [] }; for (const userId of selectedUserIds) { try { - const ipResponse = await fetch(`http://${serverIp}/backup_schemes/${userId}`); + const ipResponse = await fetch(`http://${serverIp}/backup_schemes/${userId}`,{ + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'x-api-key': 'uc_api', + } + }); if (!ipResponse.ok) { throw new Error(`Failed to fetch IP address for user ${userId}: status ${ipResponse.status}`); } @@ -109,21 +115,25 @@ document.addEventListener("DOMContentLoaded", async function () { userId, destIp, destPort: 3000, // Static destination port - fileName: fileInput.files[0].name + fileName: pathToFile.split('\\').pop().split('/').pop() }); } catch (error) { console.error('Error fetching user data:', error); } } - window.electronAPI.writeFile('usersDestTemp.json', JSON.stringify(uploadData)) - .then(() => { + window.electronAPI.writeFile('usersDestTemp.json', JSON.stringify(uploadData, null, 2)) + .then(async () => { console.log('File saved successfully'); fadeOut('sending_file_confirmation.html'); }) .catch(error => console.error('Failed to save file:', error)); }); + function timeout(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + fetchUsersAndCreateCheckboxes().then(() => console.log('Page rendered')) }); diff --git a/UC/backend/src/app.js b/UC/backend/src/app.js index 911ae8f..ffccac2 100644 --- a/UC/backend/src/app.js +++ b/UC/backend/src/app.js @@ -52,6 +52,10 @@ app.use('/admin', adminRouter); app.use('/ceo', ceoRouter); app.use('/backup_schemes', backupSchemesRouter); +app.use('/heartbeat', (req, res) => { + return res.status(200).json({message: 'Server ap and running.'}); +}) + app.listen(port, () => { console.log(`Server running on http://localhost:${port}`); }); diff --git a/UC/backend/src/db/backup_schemes.json b/UC/backend/src/db/backup_schemes.json index 9e26dfe..58ecd41 100644 --- a/UC/backend/src/db/backup_schemes.json +++ b/UC/backend/src/db/backup_schemes.json @@ -1 +1,12 @@ -{} \ No newline at end of file +{ + "7c0ef9d5-23ed-47a6-bfb4-fdcfce436904": { + "ip": "192.168.0.195", + "directoryStructure": "{\"backup_dir\":{\"files\":[],\"fisiere\":{\"files\":[\"New Microsoft Excel Worksheet.xlsx\",\"New Microsoft Word Document.docx\"]}}}", + "totalSize": 19363 + }, + "59c712d9-e6dd-438f-aec9-31ca2ae750e6": { + "ip": "192.168.0.195", + "directoryStructure": "{\"backup_dir\":{\"files\":[],\"fisiere\":{\"files\":[\"New Microsoft Excel Worksheet.xlsx\",\"New Microsoft Word Document.docx\"]}}}", + "totalSize": 19363 + } +} \ No newline at end of file diff --git a/UC/backend/src/routes/admin.js b/UC/backend/src/routes/admin.js index 7e71f4b..e6643e0 100644 --- a/UC/backend/src/routes/admin.js +++ b/UC/backend/src/routes/admin.js @@ -1,4 +1,23 @@ -const express = require('express'); +const checkForServerConnection = async () => { + const pathToIpConfig = path.join(__dirname, '..', '..', 'ipConfig.json'); + await lockFile.lock(pathToIpConfig); + try { + await decryptFileInPlace(pathToIpConfig); + const ipConfig = await fs.readFile(pathToIpConfig, 'utf-8'); + const { ip } = JSON.parse(ipConfig); + const response = await fetch(`http://${ip}:5000/heartbeat`); + if (response.ok) { + return true; + } else { + return false; + } + } catch (error) { + console.error("Error:", error); + return false; + } finally { + await lockFile.unlock(pathToIpConfig); + } +};const express = require('express'); const crypto = require('crypto'); const { v4: uuidv4 } = require('uuid'); diff --git a/User/backupSchemes.json b/User/backupSchemes.json index 534d971..58ecd41 100644 --- a/User/backupSchemes.json +++ b/User/backupSchemes.json @@ -1,7 +1,12 @@ { - "4659e71f-9bb4-4902-97d8-097efa138333": { + "7c0ef9d5-23ed-47a6-bfb4-fdcfce436904": { "ip": "192.168.0.195", - "directoryStructure": "{\"to_backup\":{\"files\":[\"fisier_random.txt\"],\"alte fis\":{\"files\":[\"alt fisier.txt\",\"fisier now.txt\",\"New Microsoft Excel Worksheet.xlsx\"]}}}", - "totalSize": 8482 + "directoryStructure": "{\"backup_dir\":{\"files\":[],\"fisiere\":{\"files\":[\"New Microsoft Excel Worksheet.xlsx\",\"New Microsoft Word Document.docx\"]}}}", + "totalSize": 19363 + }, + "59c712d9-e6dd-438f-aec9-31ca2ae750e6": { + "ip": "192.168.0.195", + "directoryStructure": "{\"backup_dir\":{\"files\":[],\"fisiere\":{\"files\":[\"New Microsoft Excel Worksheet.xlsx\",\"New Microsoft Word Document.docx\"]}}}", + "totalSize": 19363 } } \ No newline at end of file diff --git a/User/backup_directories/7c0ef9d5-23ed-47a6-bfb4-fdcfce436904/backup_dir/fisiere/New Microsoft Excel Worksheet.xlsx b/User/backup_directories/7c0ef9d5-23ed-47a6-bfb4-fdcfce436904/backup_dir/fisiere/New Microsoft Excel Worksheet.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..8f3963dcb0b42399fdf781f078060c68cd2b72f6 GIT binary patch literal 6191 zcmV+~7|`b*Z*=p)KeB{@|NC}GZdWpMze?D;a`!u?#UliQ1bIs@|HCDEU-1unAN_aw z9dhA(i?4hYtWl1ONlWjRfzZMBiT_h>f{S1=uo!)m0iqCazvgxNN(Fs6%RZ2vN4cQE zaz%tV$3ryknt!($4MrHn@M$fb2WE~l#q#7kg#r^-3XJGhwJJ}?(|3TP>0tDVDjTup zWpgQiluz%HOUE4!NCCAkhJ2wY#yoEQ-kEx4Fktk{i3b$u>{WWY9;!vx9l7<-0|=$j zp3SMB?jIpg|5S{L1}S8Ixxhs)KXZyp);8OTuPxW^DAzkX8EOHG$U3dO6+>1zPuH~= z4+$uwt1Wz7$$y}LsSdL^Ka=FnrCF-+V|!RdDIQdRne%y7A-b-tCF@KVNIuiKz zT~;aUEHhd^c?RnJofvd61*f@|Up%RtKq#wupW2!xzV|}%N_MUZOYrR8>5(aYh&DhR z;oDlbusUY^C)z2L-_|xiyR zNhkn$;3^! z&ATD;sPd=4wly0ZN(G(dM8c9*?6!$n%SLWsraWK^ZLx8sc`qJVg>-1J%ME2fIeG|m zff93~RN@N_IeES;2vUu^diP-HtTIoV8x@*^uqoO`yev~m&LIZ$?P`C}NM<3=a_N@2 zf^viey@(oei9A7_VHCYs;VK?ju5J@k@Wk6RY>h@UJcoeMicay`y6uvESUBLgbZP}q zm|9nNTNRrCoEwX4wCwO)u(@KKNDuPt*m)N|^XaD$e4I%2CgQs%{_HT7RRG`X`F3*=4CadK69yly({x*EFP{B^KooU+NscxMgc_3_8{$9yCykb9PU z_M|NJ|4@=W=o$I}$!@lC8t4{5m7dS;$c%;r7tdIlU1BA>d+$ zqn8oIZW0#7Idu_?BQqXYOkhum`poL?gPKOj$u+Y06EV*;00(w8fPjIoRzmRqipZ%n z!@Xi4l5O&_1Z=^yDYU?;lu9!=AV&@;>?AcqqS`a8QG$QJmNY$XU(W}|F^)GUQ3}TT zLTfQl|JV_~-Ab|n%-X8I&V{>R6rD8N_9yriMu-YGccA0@;xco z8`d?euk-4|VUD8RwK|VmhEPa-Tk%H1e}DPe^Be#qfdQ=bVLtgdj3m*>Q5=Ekx#$WdewrX)V1`~}FwJ=be-mX);+R;{AW7QB82==6V*p6xYB3*=VOwuT)+Y}*5c61tC(q9vJUN+ z+3HTLstNn5z;_*-ZXe@Ab$05u;`QyR{)e*uFF2E+=Vox_gStFJ6keq zA1w1M{Fa8nW?1TjODV^{P7Z26nt+P!iX^9g-0_T*sq^C@Y_NN+)eLt*Df{cCMIqcy zg|5x--aBe0tKa--AleMHxVB-DqXD~Mbl?n@*|v8zVRgb8*0>0e zzx_9wuR?}%UL5q8x$dPts{#TPz7XuJMf9v4-xF1BMP^v#pXgh%gW>7w>GI7BFZscZ zyrVrj2z4DvL=(*b!1HH%G(lzx9Xq4Ez9nk(2wb_wOZ4ESr+xKKMss z5g43udaRSk?)N^^omLm*(R|&t1X@w2_|Xd@6@>}O6hHCE03U~o__#8;`Ex@K^Bpe@z?v8HbERnXn&9yqzCBq_EcXxFKFK`g<*rW1?l{o8 ziJ(*X0dX+KD1`L3T`ndwPFsoDLXX7`kpXFlyuK{a@`n7%4+-&h4WDWGYH90gk1a{L z3~E|efod*Vi2_5P2#p7G7;aYWyd{Y?i%YE*R_ph*w&Wl{fnG%qHvJXj47S$cd&V@e znN7uHL{(Dc=KAokS4CXkeI*!8Fhc355(QP_y=D zvr!&kHJ^ym{-LX(U8v>o;DP_k^?sq$S7R>dk*wiGO65S%t2zx$;nbqVfAO-h-N*d0~wU~Q8Wv$7{0(hY|J+yjp<+j9= zecRP4+4U2V`{~sUJ1(0HG!^AQ{H;`#(Fv!WNptSp$GE-UE$_T@k zivQpMTj1nr|EojOfoFF(r9CcAZ#D^erSV0u(oz|u7Lfa~px4z}j+`8OAj+0k@>#Dc z3F6$dG?AMrS;>R6K=sagzu05GAmk@*K`W=%S=E0Va~94uBWNA<|I3y`YR4TDb8mg) z;5BDY86#3J^ZS~1^+@y$6dO)H(RScB)6%g9e44^Lmot!4-MTyJHxA%LaHO>{@^AaX zM@XXW0c=SzyG5@8wsJ%8M@IL^+!^*fS26Kk8OSA4oo{X0_aUW_X(b;SvhJO#2`#Mn zqFHmpZ}I~WqtPr7C>ui)iBgZUC8Mk6;=wgZJfTtI;on@2BZ}p|VeS@WN8~N4&qYG8 zjvQGZ`rABWY_)(f`U6Gz=dn-2-(hulZ9+`Wk}C491P7m(7G=9`-S%@i_QKX(;sTja8Rd6JRiXSq9jw zn5-lrzb?jvo?m(0ZJn6gFB0!6!V>LDKkd3kI^13Dp%p%$Y@n|ot)bTl%CX-NQ7)J> zy;xt^QSxl5t9(|px{aZy8A=m&`U$ZQi&KKD1w2*M3=pkys3KGG0*-cnmy&K6K ze82|%8lIAT$9_#F4h?X>5qe_A7YtN8`3>ElKLjL0(SP>=F}wV_F5~OJI8C77JC8&hSzyw}6+ZL-Kg@QGLKHBV0LvnSz#`W%mUEjMf9;$4qEg4yHeZDmj6BqSLIH8sG!e|nzkB$Gs9N-wzYs| zwqtB|toUjP6RMro6`8!}q!t@>HQ{@9VZc>*5FIf*_iO;`-0-_650f7#wD+v%UZl3?GukYUzc@YLPO(dl!~61k^AG$UfTVWgoq6724W z*v$gxO0d5B35C_oU>Et{bZOHu55xXbR6|r}v=b;{XNMGg_n)5xpx4MNhhq^~x7~9u zt^5)g4Hxq;K#eU_Tlb!;EC+!uawdkDF(SD<0KB`s(NBvx#nS*;Fl|;b@Mqu!u+i|* zVEnXzc7{n;<=j(2%`qi^1;zWl?T(^qP(9`Rv9yr)72S2kQU8qS5Q=s;0_&XH6`)p~ zZHS^*u&AQ*$ zqXmVbsAz|aCWLjQka_3R!j+m3*p@c3n{CosI@&C6`K`=R;1s-KSv`6`&iR&G984`8 zGQy-`N(GFTR1s~JV4ts#Po;_*x%@2fL@FDDxrwx*`8UW`$KH53UK4eU5c=CEP$XBc zxwA(h3%qF$IR_~m#S4N8!R|Kp)pCKhMbq#HnTHDM#2OqMjwmD^BLEv->6Sbh`N zQ2P)Zzd$|YvvCK?kEFN~w5t(Y@iB5cs|R8pTpqR<$>t*D|3ud8*`DNM8?aHRS#DxAOx{BG?sid2yywO>&N!yFs z%f+CfmUOmt!-pF-a4#DD{FH+b?wd{zHoJNP!vPb%X6BP(anEs`7Tb!Ic2B>9A@ZhCrgR%Al zVQ0We3Mn$B!U3r~Kcjnf{Snn{%zZ{v+h()js4oA7vDx(BM5TjgMS*sZr%`>wfdJYr zxy+ZQ3|99-DO7e{@N|Sfry<|UF4s~%(VY$N$33LvZBI}(s?GbNEqpee>8p1#AOKAg zOl|zL*wi95=itfM$BaQlhT0r>PuHIVGMtw1bxw9FOL^caBzCS#W&NcgrKGD?s=7C= zu27vshxv6i7Dq!IW2dcDyLX4vY?fSRGU{tuVMx|wmrP`rlR3(^Ni#VNm zja?#SJ-;7`MVAe~N!;Qp{B(9RtVO<(9pFL3`)W6EEw5x8WnAUeb|Y5_V`okE!JjCU z?9i&h&Szh)^~XlOxsOrQ^v|%RF2*S!=_{PsB-k^->JDUE5*eJsr&!1GRKxUA^Fp)N zS8{P^_|ES(MujEc7^Z5dMKJYF-X?wb<*O}j-$`YC-H+<80w(3qVem$H_(9EX?xI{c zZnxcy8d8Ny*X!EkD=VrfowU;?M^O?W1JY3My44(BUEovE_W);r@`g09u4svUqu~0c zbk~!@LWp6-ZM*+yzZUJmSkN5YODQq>c@@S2ZZ%j?HX1Z$6Y?ZkO4DrzSON2;wVI20g-D}Z zIVK|32Dc)-O|i4$Y<`A4LfYSu`(-*TWHG!%M+h=#B!DT_zkJ5tLeUmpN=#9Rt$%+kwiXHyuCXCQz+d=R%L4`01I;nl$Gq! zq|HxU+$J}I9V5u8S>e0PIQ38wS5_yzO*@-%D3hV2^Uryu5QLr17UKE#xA@^rhon69 zGwo>w6zOBeXqEPX%E3D5*?WQBHVIE4<0j2BVH;!O<_ef{2r7=ND=jA))8k;y#TY%V#f9M6gX zMl9}mct=|FB23|3nf25O+{_l{^29Tq&hjE5AzHRyV8w0ZAn$CX8#TXsLobH*;KWI4 zx|#i^BF8>tSUCBnk6fv`p<;Vk6t{DMaQNm1WQsa+NDU8Grb|ag8`7j?ZZtMWp2Gj2smy zxu9g$jCfhv3=-z+_pQvJ8J=k;pq(%6@!96ZsH(KpOQPnvZ_D&wGp_`}DRYI((E;U_ z4*`|goRM?oxoV`Fpa-L^Y}vZ@;g6A$gL0t7(DE))2cE$#OJ~sI0B(0Uy}lF%meM4k Nf3T^Yuro+UHHxJJBk%wK literal 0 HcmV?d00001 diff --git a/User/backup_directories/7c0ef9d5-23ed-47a6-bfb4-fdcfce436904/backup_dir/fisiere/New Microsoft Word Document.docx b/User/backup_directories/7c0ef9d5-23ed-47a6-bfb4-fdcfce436904/backup_dir/fisiere/New Microsoft Word Document.docx new file mode 100644 index 0000000000000000000000000000000000000000..ebcad29d7631870b1546b7a66641979a0c65d8d3 GIT binary patch literal 13172 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 aHn^PV7F(;T68&>pKnFj8sGjnUFm}Z>RE%i= literal 0 HcmV?d00001 diff --git a/User/dirBackup.json b/User/dirBackup.json deleted file mode 100644 index 8731abf..0000000 --- a/User/dirBackup.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "path": "C:\\Users\\Andrei Cerbu\\Documents\\to_backup", - "structure": { - "to_backup": { - "files": [ - "fisier_random.txt" - ], - "alte fis": { - "files": [ - "alt fisier.txt", - "fisier now.txt", - "New Microsoft Excel Worksheet.xlsx" - ] - } - } - }, - "size": 8482 -} \ No newline at end of file diff --git a/User/dirDepartment.json b/User/dirDepartment.json deleted file mode 100644 index bd927e8..0000000 --- a/User/dirDepartment.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "path": "C:\\Users\\Andrei Cerbu\\Documents\\department_shared_files" -} \ No newline at end of file diff --git a/User/dirShare.json b/User/dirShare.json deleted file mode 100644 index 766b39f..0000000 --- a/User/dirShare.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "path": "C:\\Users\\Andrei Cerbu\\Documents\\share_directory" -} \ No newline at end of file diff --git a/User/jobs/fetcher.js b/User/jobs/fetcher.js index 9d91cc2..59ea3b3 100644 --- a/User/jobs/fetcher.js +++ b/User/jobs/fetcher.js @@ -232,3 +232,4 @@ process.on('SIGINT', async () => { } }); +encryptFileInPlace(path.join(__dirname, '..', 'usersDestTemp.json')) diff --git a/User/loginData.json b/User/loginData.json index 05d16f3..d0a73b5 100644 --- a/User/loginData.json +++ b/User/loginData.json @@ -1 +1 @@ -!ĝ.: !r}QXϯ@Ki*u[9J/d-C$njW4"w{^\J  γRAQTc4E'Ivlǚ7E;9j3ıˈ UU1 \ No newline at end of file +5oʾ8cA=6ZėhѫE YFYQ>t݃xFFٝzEoaE CEzȽA\$D*}>}K/ev(ݸE`g.Gܽlç`]SXwwˆUL \ No newline at end of file diff --git a/User/src/main/main.js b/User/src/main/main.js index 8cc5fcf..388cb49 100644 --- a/User/src/main/main.js +++ b/User/src/main/main.js @@ -6,7 +6,6 @@ const {fork} = require('child_process'); const {encryptFileInPlace, decryptFileInPlace} = require('./aes_encrypt'); const {lockFile, unlockFile} = require("../../helpers/lock_mechanism"); -//const {decryptUserFilesToDirectory} = require("../../jobs/backup"); const isMac = process.platform === 'darwin'; let html_page = undefined; @@ -18,7 +17,7 @@ let backupProcess = null; let externalEndpointsProcess = null; let sendFileProcess = null; -const create_initial_keys = () => { +const createInitialKeys = () => { const SECRET_KEY = crypto.randomBytes(32); const IV = crypto.randomBytes(16); @@ -32,7 +31,7 @@ const create_initial_keys = () => { console.log(`IV saved to ${ivPath}`); } -const delete_external_files = () => { +const deleteMainComponentsAtErrorStart = () => { const ipConfigPath = path.join(__dirname, '..', '..', 'ipConfig.json'); const loginDataPath = path.join(__dirname, '..', '..', 'loginData.json'); @@ -54,6 +53,28 @@ const delete_external_files = () => { } +const checkForServerConnection = async () => { + const pathToIpConfig = path.join(__dirname, '..', '..', 'ipConfig.json'); + + try { + await fs.promises.access(pathToIpConfig); + + await lockFile(pathToIpConfig); + await decryptFileInPlace(pathToIpConfig); + const ipConfig = await fs.promises.readFile(pathToIpConfig, 'utf-8'); + const { ip } = JSON.parse(ipConfig); + + const response = await fetch(`http://${ip}/heartbeat`); + + await encryptFileInPlace(pathToIpConfig) + await unlockFile(pathToIpConfig); + return response.ok; + } catch (error) { + console.error("Error:", error); + return false; + } +}; + const createMainWindow = (async (title, width, height) => { mainWindow = new BrowserWindow({ title: title, @@ -70,18 +91,11 @@ const createMainWindow = (async (title, width, height) => { 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) { - create_initial_keys(); - delete_external_files(); + createInitialKeys(); + deleteMainComponentsAtErrorStart(); } - html_page = 'ip_config.html'; - - try { - await fs.promises.access(path.join(__dirname, '..', '..', 'ipConfig.json')); - html_page = 'login.html'; - } catch (err) { - html_page = 'ip_submit.html'; - } + html_page = await checkForServerConnection() ? 'login.html' : 'ip_submit.html'; //mainWindow.setMenu(null); mainWindow.loadFile(path.join(__dirname, '..', 'renderer', 'html', html_page)) diff --git a/User/src/renderer/html/main_menu.html b/User/src/renderer/html/main_menu.html index 7ac28ca..c5b63a1 100644 --- a/User/src/renderer/html/main_menu.html +++ b/User/src/renderer/html/main_menu.html @@ -36,14 +36,15 @@
-
- - -
+
+ + + +
diff --git a/User/src/renderer/html/sending_file_confirmation.html b/User/src/renderer/html/sending_file_confirmation.html index 7774872..ca50d3a 100644 --- a/User/src/renderer/html/sending_file_confirmation.html +++ b/User/src/renderer/html/sending_file_confirmation.html @@ -9,47 +9,7 @@ - + ; Sending file diff --git a/User/src/renderer/js/main_menu.js b/User/src/renderer/js/main_menu.js index bc81839..bc84454 100644 --- a/User/src/renderer/js/main_menu.js +++ b/User/src/renderer/js/main_menu.js @@ -1,8 +1,10 @@ document.addEventListener('DOMContentLoaded', async function () { await insertUsername(); - const backupButton = document.getElementById('backup'); + const backupButton = document.getElementById('backup_dir'); const shareButton = document.getElementById('share_dir'); + const departmentButton = document.getElementById('department_dir'); + const changeDepartmentButton = document.getElementById('change_department'); const changeInfoButton = document.getElementById('change_info'); const shareFileButton = document.getElementById('share_file'); @@ -85,7 +87,17 @@ document.addEventListener('DOMContentLoaded', async function () { console.log('Set backup directory button clicked!'); window.electronAPI.openJsonDirConfigDialog('dirShare.json') - .then(() => console.log('Back-up directory set')) + .then(() => console.log('Share 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))); @@ -142,7 +154,7 @@ document.addEventListener('DOMContentLoaded', async function () { if (!fileExists) { const notificationsDiv = document.getElementById('notifications'); const button = document.createElement('button'); - button.id = 'share_file_alert'; + button.id = 'share_dir_alert'; button.name = 'alert'; button.textContent = 'Set your share directory!'; button.addEventListener('click', handleShareButtonPressed); @@ -193,7 +205,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_dir_alert'); button.remove(); } @@ -206,7 +218,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('department_alert'); button.remove(); } diff --git a/User/src/renderer/js/sending_file_confirmation.js b/User/src/renderer/js/sending_file_confirmation.js new file mode 100644 index 0000000..f1b46f6 --- /dev/null +++ b/User/src/renderer/js/sending_file_confirmation.js @@ -0,0 +1,54 @@ +document.addEventListener("DOMContentLoaded", async function () { + async function performUploads() { + try { + const uploadFile = await window.electronAPI.readFile('usersDestTemp.json'); + const uploadData = JSON.parse(uploadFile.content); + + const uploadPromises = uploadData.users.map(async (user) => { + try { + const formData = new FormData(); + const file = await fetch(uploadData.filePath).then(response => response.blob()); + formData.append('file', file); + formData.append('idUser', user.userId); + formData.append('nameOfFile', user.fileName); + + await timeout(5000); // Timeout to simulate delay or wait + const url = `http://${user.destIp}:${user.destPort}/upload`; + const uploadResponse = await fetch(url, { + method: 'POST', + body: formData + }); + + if (!uploadResponse.ok) { + throw new Error(`HTTP error during file upload to ${user.userId}: status ${uploadResponse.status}`); + } + + return {userId: user.userId, success: true, message: `Upload successful for user ${user.userId}`}; + } catch (error) { + console.error(`Failed to upload for user ${user.userId}:`, error); + return {userId: user.userId, success: false, message: `Upload failed for user ${user.userId}`}; + } + }); + + const results = await Promise.all(uploadPromises); + results.forEach(result => { + if (result.success) { + console.log(result.message); + } + }); + console.log('All files processed. Check the console for detailed results.'); + } catch (error) { + console.error('An error occurred during uploads:', error); + } finally { + await window.electronAPI.deleteFile('usersDestTemp.json'); + } + } + + function timeout(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + await performUploads(); + await timeout(10000); + fadeOut('main_menu.html'); +}); \ No newline at end of file diff --git a/User/src/renderer/js/share_file.js b/User/src/renderer/js/share_file.js index 462fbc9..bf2717f 100644 --- a/User/src/renderer/js/share_file.js +++ b/User/src/renderer/js/share_file.js @@ -72,8 +72,8 @@ document.addEventListener("DOMContentLoaded", async function () { event.preventDefault(); console.log('Submit button clicked'); - const fileInput = document.getElementById('fileInput'); - if (!fileInput.files.length) { + // Check if pathToFile has content + if (!pathToFile.trim()) { await window.electronAPI.showAlert('File not chosen!') .then(() => console.log('Alert window opened')) .catch(error => console.error('Error showing alert:', error)); @@ -94,13 +94,19 @@ document.addEventListener("DOMContentLoaded", async function () { } const uploadData = { - filePath: fileInput.files[0].path, + filePath: pathToFile, // Use the pathToFile variable users: [] }; for (const userId of selectedUserIds) { try { - const ipResponse = await fetch(`http://${serverIp}/backup_schemes/${userId}`); + const ipResponse = await fetch(`http://${serverIp}/backup_schemes/${userId}`,{ + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'x-api-key': 'uc_api', + } + }); if (!ipResponse.ok) { throw new Error(`Failed to fetch IP address for user ${userId}: status ${ipResponse.status}`); } @@ -109,21 +115,25 @@ document.addEventListener("DOMContentLoaded", async function () { userId, destIp, destPort: 3000, // Static destination port - fileName: fileInput.files[0].name + fileName: pathToFile.split('\\').pop().split('/').pop() }); } catch (error) { console.error('Error fetching user data:', error); } } - window.electronAPI.writeFile('usersDestTemp.json', JSON.stringify(uploadData)) - .then(() => { + window.electronAPI.writeFile('usersDestTemp.json', JSON.stringify(uploadData, null, 2)) + .then(async () => { console.log('File saved successfully'); fadeOut('sending_file_confirmation.html'); }) .catch(error => console.error('Failed to save file:', error)); }); + function timeout(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + fetchUsersAndCreateCheckboxes().then(() => console.log('Page rendered')) }); diff --git a/User/usersInSystem.json b/User/usersInSystem.json index e59098ab76c7abca4dad557c41e58c0cb8e22016..0ca30845d9c051c1197bebc1eff7731e972ca689 100644 GIT binary patch literal 336 zcmV-W0k8hV7~RDr=Pzo!OkO<)dXYdkHxqo_w<0eKH0B+7Xv!B&OdvqBV@&)DL^8Cu zucsPhjDT;F4gDy~u!cu3>NUokz+(st6vDu2v?9J=EojW9yIJXcb<^+`vA*EgN^`dI zA-Rh`iQ5!%73sghAQT680=@&eF0zNse9drDDXLXE%nHiV3>*5WBoWpe!K39}f*zZW zth`nq`Kv~vB4{*o(#x3X2r&L%$e06qYGHF!LI|=l;fX?d(BX(+IwvoO$3i$IdUPh% z)8Pu<>kMX9c<+4@Axk3IX8SDIO9Q!-eWL*QPJlxH5y6RB4%~|y#PiWyY5_xF(0~*2$8^O)`WVqF$rH8PwKYf!Wn26AR iB|T4$qtq3~EDORMm;ua}30U5G%GoOr-a~hw_X(y&{p_u*2pH?>F#a-xP!PH6Tc-BEe}%Iz z3gIi2j