diff --git a/UC/backend/src/app.js b/UC/backend/src/app.js
index 0b7849a..c33ac73 100644
--- a/UC/backend/src/app.js
+++ b/UC/backend/src/app.js
@@ -27,6 +27,10 @@ app.set('backupSchemesDB', backupSchemesDB);
app.set('ceoDB', ceoDB);
app.set('adminDB', adminDB);
+app.use('/heartbeat', (req, res) => {
+ return res.status(200).json({message: 'Server ap and running.'});
+})
+
const checkJson = require('./middlewares/checkJson');
const apiKeyValidation = require('./middlewares/apiKeyValidation');
diff --git a/UC/backend/src/db/users.json b/UC/backend/src/db/users.json
index 0637a08..276727e 100644
--- a/UC/backend/src/db/users.json
+++ b/UC/backend/src/db/users.json
@@ -1 +1,9 @@
-[]
\ No newline at end of file
+[
+ {
+ "id": "4659e71f-9bb4-4902-97d8-097efa138333",
+ "name": "Andrei Cerbu",
+ "email": "a@c.com",
+ "password": "5447045dc3cfaafdb49b365e31dad41eb88616b0b1449930e55fd3a70bd8cee4",
+ "department": "Contabili"
+ }
+]
\ No newline at end of file
diff --git a/UC/backend/src/helpers/httpResponses.js b/UC/backend/src/helpers/httpResponses.js
index 176fca9..1519d88 100644
--- a/UC/backend/src/helpers/httpResponses.js
+++ b/UC/backend/src/helpers/httpResponses.js
@@ -33,43 +33,6 @@ const httpStatus = {
SERVICE_UNAVAILABLE: 503
};
-const httpStatusMessages = {
- // Informational
- [httpStatus.CONTINUE]: "Continue",
- [httpStatus.SWITCHING_PROTOCOLS]: "Switching Protocols",
- [httpStatus.PROCESSING]: "Processing",
- // Success
- [httpStatus.OK]: "OK",
- [httpStatus.CREATED]: "Created",
- [httpStatus.ACCEPTED]: "Accepted",
- [httpStatus.NO_CONTENT]: "No Content",
- // Redirection
- [httpStatus.MOVED_PERMANENTLY]: "Moved Permanently",
- [httpStatus.FOUND]: "Found",
- [httpStatus.SEE_OTHER]: "See Other",
- [httpStatus.NOT_MODIFIED]: "Not Modified",
- [httpStatus.TEMPORARY_REDIRECT]: "Temporary Redirect",
-
- // Client Error
- [httpStatus.BAD_REQUEST]: "Bad Request",
- [httpStatus.UNAUTHORIZED]: "Unauthorized",
- [httpStatus.FORBIDDEN]: "Forbidden",
- [httpStatus.NOT_FOUND]: "Not Found",
- [httpStatus.METHOD_NOT_ALLOWED]: "Method Not Allowed",
- [httpStatus.CONFLICT]: "Conflict",
- [httpStatus.GONE]: "Gone",
- [httpStatus.UNSUPPORTED_MEDIA_TYPE]: "Unsupported Media Type",
-
- // Server Error
- [httpStatus.INTERNAL_SERVER_ERROR]: "Internal Server Error",
- [httpStatus.NOT_IMPLEMENTED]: "Not Implemented",
- [httpStatus.SERVICE_UNAVAILABLE]: "Service Unavailable"
-};
-
-const httpHeaders = {
- JSON: { 'name': 'Content-Type', 'value': 'application/json' }
-};
-
-module.exports = {httpStatus, httpStatusMessages, httpHeaders};
\ No newline at end of file
+module.exports = {httpStatus};
\ No newline at end of file
diff --git a/UC/backend/src/helpers/responseHelper.js b/UC/backend/src/helpers/responseHelper.js
deleted file mode 100644
index 42a3bde..0000000
--- a/UC/backend/src/helpers/responseHelper.js
+++ /dev/null
@@ -1,21 +0,0 @@
-const {httpHeaders} = require("./httpResponses");
-
-const headers = {
- [httpHeaders.JSON.name]: httpHeaders.JSON.value
-}
-
-function sendResponse(res, statusCode, message, data = null, headers_parsed = {}) {
- Object.entries(headers).forEach(([key, value]) => {
- res.setHeader(key, value);
- });
-
- // Set headers if provided
- Object.entries(headers_parsed).forEach(([key, value]) => {
- res.setHeader(key, value);
- });
-
- // Send the response with status code, message, and optional data
- res.status(statusCode).json({ message, data });
-}
-
-module.exports = { sendResponse };
\ No newline at end of file
diff --git a/UC/backend/src/middlewares/apiKeyValidation.js b/UC/backend/src/middlewares/apiKeyValidation.js
index c156021..cfa3748 100644
--- a/UC/backend/src/middlewares/apiKeyValidation.js
+++ b/UC/backend/src/middlewares/apiKeyValidation.js
@@ -1,10 +1,9 @@
-const { sendResponse } = require('../helpers/responseHelper');
const {httpStatus, httpStatusMessages} = require('../helpers/httpResponses')
function apiKeyValidation(req, res, next) {
const apiKey = req.headers['x-api-key'];
if (apiKey !== req.app.locals.apiKey) {
- return sendResponse(res, httpStatus.UNAUTHORIZED, httpStatusMessages[httpStatus.UNAUTHORIZED]);
+ return res.status(httpStatus.UNAUTHORIZED).json({message: 'Invalid API key'});
}
next();
}
diff --git a/UC/backend/src/middlewares/checkJson.js b/UC/backend/src/middlewares/checkJson.js
index 32f432f..1446c5f 100644
--- a/UC/backend/src/middlewares/checkJson.js
+++ b/UC/backend/src/middlewares/checkJson.js
@@ -1,5 +1,5 @@
-const { sendResponse } = require('../helpers/responseHelper');
-const {httpStatus, httpStatusMessages} = require("../helpers/httpResponses");
+
+const {httpStatus} = require("../helpers/httpResponses");
function checkJson(req, res, next) {
if(req.method === 'GET'){
@@ -7,7 +7,7 @@ function checkJson(req, res, next) {
}
if (['POST', 'PUT', 'PATCH'].includes(req.method) && req.headers['content-type'] !== 'application/json') {
- return sendResponse(res, httpStatus.BAD_REQUEST, httpStatusMessages[httpStatus.BAD_REQUEST]);
+ return res.status(httpStatus.BAD_REQUEST).json({message: "Body missing in action."});
}
next();
diff --git a/UC/backend/src/models/dirStructureModel.js b/UC/backend/src/models/dirStructureModel.js
index f269bee..2c2d686 100644
--- a/UC/backend/src/models/dirStructureModel.js
+++ b/UC/backend/src/models/dirStructureModel.js
@@ -6,6 +6,10 @@ const dirStructureModel = Joi.object({
'string.empty': 'ID must not be empty',
'string.guid': 'ID must be a valid GUID'
}),
+ ip: Joi.string().ip().required().messages({
+ 'string.ip': 'The IP address "{{#value}}" is not valid.',
+ 'any.required': 'IP address is required.'
+ }),
dir_config: Joi.string().required().messages({
'any.required': 'Directory configuration is required',
'string.empty': 'Directory configuration must not be empty'
diff --git a/UC/backend/src/models/userDepartmentPatchModel.js b/UC/backend/src/models/userDepartmentPatchModel.js
index 5dd2c00..077b078 100644
--- a/UC/backend/src/models/userDepartmentPatchModel.js
+++ b/UC/backend/src/models/userDepartmentPatchModel.js
@@ -5,6 +5,10 @@ const UserDepartmentPatchModel = Joi.object({
'any.required': 'User ID is required',
'string.empty': 'User ID must not be empty',
'string.uuid': 'User ID must be a valid UUID'
+ }),
+ department: Joi.string().required().messages({
+ 'any.required': 'User ID is required',
+ 'string.empty': 'User ID must not be empty',
})
});
diff --git a/UC/backend/src/models/usersRegisterModel.js b/UC/backend/src/models/usersRegisterModel.js
index cef077a..0b49551 100644
--- a/UC/backend/src/models/usersRegisterModel.js
+++ b/UC/backend/src/models/usersRegisterModel.js
@@ -16,10 +16,9 @@ const usersRegisterModel = Joi.object({
'string.min': 'Password must be at least {#limit} characters long',
'string.max': 'Password must be at most {#limit} characters long'
}),
- department: Joi.string().uuid().required().messages({
+ department: Joi.string().required().messages({
'any.required': 'Department ID is required',
- 'string.empty': 'Department ID must not be empty',
- 'string.uuid': 'Department ID must be a valid UUID'
+ 'string.empty': 'Department ID must not be empty'
})
});
diff --git a/UC/backend/src/routes/admin.js b/UC/backend/src/routes/admin.js
index ff93068..8180b3b 100644
--- a/UC/backend/src/routes/admin.js
+++ b/UC/backend/src/routes/admin.js
@@ -48,4 +48,8 @@ router.get('/users', validateBody, (req, res) => {
res.status(httpStatus.OK).json({ message: "Retrieving users info...", data: usersDB.readFile() }) // Corrected to readFile
});
+router.use((req, res) => {
+ return res.status(httpStatus.NOT_FOUND).json({message: "Endpoint not found"});
+})
+
module.exports = router;
diff --git a/UC/backend/src/routes/backup_schemes.js b/UC/backend/src/routes/backup_schemes.js
index aa2d366..526314e 100644
--- a/UC/backend/src/routes/backup_schemes.js
+++ b/UC/backend/src/routes/backup_schemes.js
@@ -1,15 +1,49 @@
const express = require('express');
+const {httpStatus} = require("../helpers/httpResponses");
+const {schemas} = require("../models/schemaMapper");
const router = express.Router();
function validateBody(req, res, next) {
+ let validationSchema = undefined;
+
+ if(req.path === '/' && req.method === 'PATCH'){
+ validationSchema = schemas.dirStructureModelSchema
+ }
+
+ if(validationSchema !== undefined){
+ const {error} = validationSchema.validate(req.body);
+ if(error){
+ const errorMessage = error.details.map(detail => detail.message).join(', ');
+ return res.status(httpStatus.BAD_REQUEST).json({ message: errorMessage });
+ }
+ }
next();
}
router.patch('/', validateBody, (req, res) => {
+ const backupSchemesDB = req.app.get('backupSchemesDB');
const { id, ip, backup_schema, size } = req.body;
+
+ let backupSchemesJson = backupSchemesDB.readFile();
+ backupSchemesJson[id] = {
+ ip: ip,
+ backup_schema: backup_schema,
+ size: size
+ }
+
+ return res.status(httpStatus.OK).json({message: 'Backup schema updated'});
});
router.get('/', validateBody, (req, res) => {
+ const backupSchemesDB = req.app.get('backupSchemesDB');
+ return res.status(httpStatus.OK).json({
+ message: 'Backup Schemes fetched.',
+ data: backupSchemesDB.readFile()
+ });
});
+router.use((req, res) => {
+ return res.status(httpStatus.NOT_FOUND).json({message: "Endpoint not found"});
+})
+
module.exports = router;
diff --git a/UC/backend/src/routes/ceo.js b/UC/backend/src/routes/ceo.js
index 84ba1cd..32301f6 100644
--- a/UC/backend/src/routes/ceo.js
+++ b/UC/backend/src/routes/ceo.js
@@ -184,4 +184,8 @@ router.get('/get_decrypt_keys', (req, res) => {
});
});
+router.use((req, res) => {
+ return res.status(httpStatus.NOT_FOUND).json({message: "Endpoint not found"});
+})
+
module.exports = router;
diff --git a/UC/backend/src/routes/users.js b/UC/backend/src/routes/users.js
index e1651c0..9e7e617 100644
--- a/UC/backend/src/routes/users.js
+++ b/UC/backend/src/routes/users.js
@@ -1,9 +1,11 @@
const express = require('express');
const { v4: uuidv4 } = require('uuid');
+const crypto = require('crypto');
const {schemas} = require('../models/schemaMapper');
const {httpStatus} = require("../helpers/httpResponses");
+
const router = express.Router();
function validateBody(req, res, next) {
@@ -16,6 +18,9 @@ function validateBody(req, res, next) {
case '/login':
validationSchema = schemas.usersLoginModelSchema;
break;
+ case '/validate_ceo_password':
+ validationSchema = schemas.ceoPasswordModelSchema;
+ break;
case '/validate_email':
validationSchema = schemas.emailVerificationSchema;
break;
@@ -24,16 +29,15 @@ function validateBody(req, res, next) {
validationSchema = schemas.usersModifyModelSchema;
}
break;
- case 'change_department':
+ case '/change_department':
validationSchema = schemas.userDepartmentPatchSchema;
break;
default:
validationSchema = undefined;
}
- console.log(validationSchema);
-
if(validationSchema !== undefined){
+ console.log(req.body);
const {error} = validationSchema.validate(req.body);
if(error){
const errorMessage = error.details.map(detail => detail.message).join(', ');
@@ -69,14 +73,35 @@ router.post('/login', validateBody, (req, res) => {
const { email, password } = req.body;
const hashedPassword = crypto.createHash('sha256').update(password).digest('hex');
+ if(usersDB.readFile().length === 0){
+ return res.status(httpStatus.NOT_FOUND).json({message: 'Invalid credentials.'});
+ }
+
if(usersDB.findIndexByKeyValueInArray('email', email) !==
usersDB.findIndexByKeyValueInArray('password', hashedPassword)){
return res.status(httpStatus.NOT_FOUND).json({message: 'Invalid credentials.'});
}
- return res.status(httpStatus.Ok).json({message: 'Logged in.'});
+ const userIndex = usersDB.findIndexByKeyValueInArray('email', email);
+
+ return res.status(httpStatus.OK).json({
+ message: 'Logged in.',
+ data: usersDB.readFile()[userIndex]
+ });
});
+router.post('/validate_ceo_password', validateBody, (req, res) => {
+ const ceoDB = req.app.get('ceoDB');
+ const { password } = req.body;
+
+ const ceoJson = ceoDB.readFile();
+ if(ceoJson.password !== password){
+ return res.status(httpStatus.UNAUTHORIZED).json({message: 'Incorrect CEO password'});
+ }
+
+ return res.status(httpStatus.OK).json({message: 'Password verified.'})
+})
+
router.post('/validate_email', validateBody, (req, res) => {
const usersDB = req.app.get('usersDB');
const { email } = req.body;
@@ -159,7 +184,7 @@ router.patch('/change_department', validateBody, (req, res) => {
usersJson[userIndex] = userInfo
usersDB.writeFile(usersJson);
- return res.status(httpStatus.Ok).json({message: "Department modified."});
+ return res.status(httpStatus.OK).json({message: "Department modified."});
});
router.get('/get_decrypt_keys', (req, res) => {
diff --git a/UC/backend/task_uri.md b/UC/backend/task_uri.md
new file mode 100644
index 0000000..475f640
--- /dev/null
+++ b/UC/backend/task_uri.md
@@ -0,0 +1,21 @@
+Taskuri
+-
+- create form which upon submission set's the ip location (also create a button which can change this one and have to
+create a IPC for retrieving the ip when making the requests).
+- create the encryption process when writing a file on disk / decryption process when reading a file form disk
+- configure endpoint for 'backup_schemes' completely
+- refactor the JS code from all the html to make it with .then statements and show the messages
+from the UC
+- finish the CEO interface
+- create process which will update the backup scheme with:
+
+ - IP
+ - user_id
+ - dir_schema
+ - size
+
+- create process which will fetch the large schema and encryption keys and compare it with the one on local;
+if is the same, hibernate; else, make requests for the files
+- create process which will get the user database and combine it with the ip and at the request will share a
+specific file
+- create process which will decrypt all the files from the backup scheme locally
\ No newline at end of file
diff --git a/User/.idea/encodings.xml b/User/.idea/encodings.xml
new file mode 100644
index 0000000..31b5dc7
--- /dev/null
+++ b/User/.idea/encodings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/User/ipConfig.json b/User/ipConfig.json
new file mode 100644
index 0000000..81d3eb7
--- /dev/null
+++ b/User/ipConfig.json
@@ -0,0 +1 @@
+êÔ—‘Û°ës_žì¢(Ëk´¾K–ô:Ô‚Fn]C‹$
\ No newline at end of file
diff --git a/User/iv.key b/User/iv.key
new file mode 100644
index 0000000..dbf14ed
--- /dev/null
+++ b/User/iv.key
@@ -0,0 +1 @@
+äï§¡’a%l:ðIÇ÷ÑÝ
\ No newline at end of file
diff --git a/User/jobs/backup.js b/User/jobs/backup.js
new file mode 100644
index 0000000..e69de29
diff --git a/User/jobs/decrypt_files.js b/User/jobs/decrypt_files.js
new file mode 100644
index 0000000..e69de29
diff --git a/User/jobs/fetcher.js b/User/jobs/fetcher.js
new file mode 100644
index 0000000..e69de29
diff --git a/User/jobs/receiver.js b/User/jobs/receiver.js
new file mode 100644
index 0000000..e69de29
diff --git a/User/jobs/send_files.js b/User/jobs/send_files.js
new file mode 100644
index 0000000..e69de29
diff --git a/User/loginData.json b/User/loginData.json
new file mode 100644
index 0000000..4b94fa6
Binary files /dev/null and b/User/loginData.json differ
diff --git a/User/secret.key b/User/secret.key
new file mode 100644
index 0000000..c209bc5
--- /dev/null
+++ b/User/secret.key
@@ -0,0 +1 @@
+ª ƒ4¥•ÿØ~n`¤ìƒ'TníoCÀ:%:xØë
\ No newline at end of file
diff --git a/User/src/main/aes_encrypt.js b/User/src/main/aes_encrypt.js
new file mode 100644
index 0000000..aa33b9e
--- /dev/null
+++ b/User/src/main/aes_encrypt.js
@@ -0,0 +1,76 @@
+const crypto = require('crypto');
+const fs = require('fs');
+const path = require('path');
+
+async function readKeyFromFile(filePath) {
+ try {
+ await fs.promises.access(filePath, fs.constants.F_OK);
+ return fs.promises.readFile(filePath); // Use asynchronous readFile
+ } catch(error) {
+ console.error('Error reading key file:', error);
+ return null;
+ }
+}
+
+// Paths to the key files remain the same
+const IV_FILE_PATH = path.join(__dirname, '..', '..', 'iv.key');
+const SECRET_KEY_FILE_PATH = path.join(__dirname, '..', '..', 'secret.key');
+
+async function encryptFileInPlace(filePath) {
+ // Await the resolution of these promises
+ const IV = await readKeyFromFile(IV_FILE_PATH);
+ const SECRET_KEY = await readKeyFromFile(SECRET_KEY_FILE_PATH);
+
+ if (!IV || !SECRET_KEY) {
+ throw new Error('Failed to load IV or Secret Key');
+ }
+
+ const tempEncryptedFilePath = filePath + '.enc'; // Temporary encrypted file
+ return new Promise((resolve, reject) => {
+ const cipher = crypto.createCipheriv('aes-256-cbc', Buffer.from(SECRET_KEY), IV);
+ const input = fs.createReadStream(filePath);
+ const output = fs.createWriteStream(tempEncryptedFilePath);
+
+ input.pipe(cipher).pipe(output);
+
+ output.on('finish', () => {
+ fs.rename(tempEncryptedFilePath, filePath, (err) => {
+ if (err) reject(err);
+ else resolve('File encrypted successfully and replaced original.');
+ });
+ });
+ output.on('error', reject);
+ });
+}
+
+async function decryptFileInPlace(filePath) {
+ // Await the resolution of these promises
+ const IV = await readKeyFromFile(IV_FILE_PATH);
+ const SECRET_KEY = await readKeyFromFile(SECRET_KEY_FILE_PATH);
+
+ if (!IV || !SECRET_KEY) {
+ throw new Error('Failed to load IV or Secret Key');
+ }
+
+ const tempDecryptedFilePath = filePath + '.dec'; // Temporary decrypted file
+ return new Promise((resolve, reject) => {
+ const decipher = crypto.createDecipheriv('aes-256-cbc', Buffer.from(SECRET_KEY), IV);
+ const input = fs.createReadStream(filePath);
+ const output = fs.createWriteStream(tempDecryptedFilePath);
+
+ input.pipe(decipher).pipe(output);
+
+ output.on('finish', () => {
+ fs.rename(tempDecryptedFilePath, filePath, (err) => {
+ if (err) reject(err);
+ else resolve('File decrypted successfully and replaced original.');
+ });
+ });
+ output.on('error', reject);
+ });
+}
+
+module.exports = {
+ encryptFileInPlace,
+ decryptFileInPlace
+}
diff --git a/User/src/main/main.js b/User/src/main/main.js
index 9b9cfb0..c77857f 100644
--- a/User/src/main/main.js
+++ b/User/src/main/main.js
@@ -1,13 +1,57 @@
const { app, BrowserWindow, screen, ipcMain, dialog } = require('electron');
const fs = require('fs');
const path = require('path');
+const crypto = require('crypto');
+const { fork } = require('child_process');
+
+const {encryptFileInPlace, decryptFileInPlace} = require('./aes_encrypt');
const isMac = process.platform === 'darwin';
let html_page = undefined;
let mainWindow = undefined;
let alertWindow = undefined;
-const createMainWindow = ((title, width, height) => {
+let backupProcess = null;
+let receiverProcess = null;
+let fetcherProcess = null;
+
+const create_initial_keys = () => {
+ const SECRET_KEY = crypto.randomBytes(32);
+ const IV = crypto.randomBytes(16);
+
+ const secretKeyPath = path.join(__dirname, '..', '..', 'secret.key');
+ const ivPath = path.join(__dirname, '..', '..', 'iv.key');
+
+ fs.writeFileSync(secretKeyPath, SECRET_KEY);
+ console.log(`Secret Key saved to ${secretKeyPath}`);
+
+ fs.writeFileSync(ivPath, IV);
+ console.log(`IV saved to ${ivPath}`);
+}
+
+const delete_external_files = () => {
+ 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 createMainWindow = (async (title, width, height) => {
mainWindow = new BrowserWindow({
title: title,
width: width,
@@ -19,9 +63,25 @@ const createMainWindow = ((title, width, height) => {
}
});
- html_page = 'login.html';
+ 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) {
+ create_initial_keys();
+ delete_external_files();
+ }
+
+ 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';
+ }
+
//mainWindow.setMenu(null);
- mainWindow.loadFile(path.join(__dirname, '..', 'renderer', 'html', 'login.html'))
+ mainWindow.loadFile(path.join(__dirname, '..', 'renderer', 'html', html_page))
.then(() => {
console.log('Main window loaded!')
})
@@ -79,6 +139,18 @@ app.whenReady().then(() => {
});
});
+app.on('before-quit', () => {
+ if (backupProcess !== null) {
+ backupProcess.kill();
+ }
+ if (receiverProcess !== null) {
+ receiverProcess.kill();
+ }
+ if (fetcherProcess !== null) {
+ fetcherProcess.kill();
+ }
+});
+
app.on('window-all-closed', () => {
if(!isMac){
app.quit();
@@ -89,6 +161,7 @@ ipcMain.handle('write-file', async (event, fileName, content) => {
try {
let filePath = path.join(__dirname, '..', '..', fileName);
await fs.promises.writeFile(filePath, content);
+ await encryptFileInPlace(filePath);
console.log(`File successfully written to ${filePath}`);
return { success: true };
} catch (error) {
@@ -113,8 +186,10 @@ ipcMain.handle('delete-file', async (event, fileName) => {
ipcMain.handle('read-file', async (event, fileName) => {
try {
let filePath = path.join(__dirname, '..', '..', fileName);
-
+ await decryptFileInPlace(filePath);
const content = await fs.promises.readFile(filePath, 'utf-8');
+
+ await encryptFileInPlace(filePath);
return { success: true, content };
} catch (error) {
console.error('Error reading file:', error);
@@ -125,16 +200,7 @@ ipcMain.handle('read-file', async (event, fileName) => {
ipcMain.handle('change-content', async (event, nextPage) => {
try {
html_page = nextPage;
- mainWindow.webContents.executeJavaScript(`
- document.body.classList.add('fade-out');
- `);
-
- await new Promise(resolve => setTimeout(resolve, 1000));
await mainWindow.loadFile(path.join(__dirname, '..', 'renderer', 'html', nextPage));
-
- mainWindow.webContents.executeJavaScript(`
- document.body.classList.add('fade-in');
- `);
return true;
} catch (error) {
console.error('Error changing content:', error);
@@ -197,3 +263,59 @@ ipcMain.on('close-alert-window', () => {
alertWindow = undefined;
}
});
+
+//External processes
+
+ipcMain.handle('start-fetcher', async (event, args) => {
+ if (fetcherProcess === null) {
+ fetcherProcess = fork(path.join(__dirname, '..', '..', 'jobs', 'fetcher.js'), args, { silent: false });
+ fetcherProcess.on('exit', () => {
+ fetcherProcess = null;
+ // Optionally, notify the renderer process that the fetcher has finished
+ });
+ }
+ return true; // Indicate that the operation has started
+});
+
+// Handler to start the backup process
+ipcMain.handle('start-backup', async (event, args) => {
+ if (backupProcess === null) { // Should this be a unique variable for backupProcess instead?
+ backupProcess = fork(path.join(__dirname, '..', '..', 'jobs', 'backup.js'), args, { silent: false });
+ backupProcess.on('exit', () => {
+ backupProcess = null;
+ // Optionally, notify the renderer process that the backup has finished
+ });
+ }
+ return true; // Indicate that the operation has started
+});
+
+// Handler to start the decrypt-files process
+ipcMain.handle('start-decrypt-files', async (event, args) => {
+ const decryptFilesProcess = fork(path.join(__dirname, '..', '..', 'jobs', 'decrypt_files.js'), args, { silent: false });
+ decryptFilesProcess.on('exit', () => {
+ event.sender.send('decrypt-files-finished', true); // Notify renderer process
+ });
+ return true; // Indicate that the operation has started
+});
+
+// Handler to start the send_files process
+ipcMain.handle('start-send_files', async (event, args) => {
+ // This seems to duplicate the 'start-decrypt-files' process; assuming a different script is intended
+ const sendFilesProcess = fork(path.join(__dirname, '..', '..', 'jobs', 'send_files.js'), args, { silent: false });
+ sendFilesProcess.on('exit', () => {
+ event.sender.send('send-files-finished', true); // Notify renderer process
+ });
+ return true; // Indicate that the operation has started
+});
+
+// Handler to start the receiver process
+ipcMain.handle('start-receiver', async (event, args) => {
+ if (receiverProcess === null) {
+ receiverProcess = fork(path.join(__dirname, '..', '..', 'jobs', 'receiver.js'), args, { silent: false });
+ receiverProcess.on('exit', () => {
+ receiverProcess = null;
+ // Optionally, notify the renderer process that the receiver has finished
+ });
+ }
+ return true; // Indicate that the operation has started
+});
diff --git a/User/src/main/preload.js b/User/src/main/preload.js
index 6a718c7..d259984 100644
--- a/User/src/main/preload.js
+++ b/User/src/main/preload.js
@@ -9,5 +9,11 @@ contextBridge.exposeInMainWorld('electronAPI', {
closeAlertWindow: () => ipcRenderer.send('close-alert-window'),
openBackupDirDialog: () => ipcRenderer.invoke('open-backup-dir-dialog'),
openFileDialog: () => ipcRenderer.invoke('open-file-dialog'),
- checkFileExists: (fileName) => ipcRenderer.invoke('check-file-exists', fileName)
+ checkFileExists: (fileName) => ipcRenderer.invoke('check-file-exists', fileName),
+
+ startFetcher: async (args) => ipcRenderer.invoke('start-fetcher', args),
+ startBackup: async (args) => ipcRenderer.invoke('start-backup', args),
+ startDecryptFiles: async (args) => ipcRenderer.invoke('start-decrypt-files', args),
+ startSendFiles: async (args) => ipcRenderer.invoke('start-send_files', args),
+ startReceiver: async (args) => ipcRenderer.invoke('start-receiver', args)
});
\ No newline at end of file
diff --git a/User/src/renderer/css/change_department.css b/User/src/renderer/css/change_department.css
index 2549504..d34a81d 100644
--- a/User/src/renderer/css/change_department.css
+++ b/User/src/renderer/css/change_department.css
@@ -15,6 +15,8 @@ body, html {
}
.container {
+ opacity: 0;
+
display: flex;
flex-direction: row;
justify-content: space-evenly;
diff --git a/User/src/renderer/css/ip_submit.css b/User/src/renderer/css/ip_submit.css
new file mode 100644
index 0000000..1b40e46
--- /dev/null
+++ b/User/src/renderer/css/ip_submit.css
@@ -0,0 +1,98 @@
+body, html {
+ height: 100%;
+ width: 100%;
+ margin: 0;
+ padding: 0;
+
+ font-family: "Roboto", sans-serif;
+ font-weight: 500;
+ font-style: normal;
+
+ background-image: url('../assets/background.png');
+ background-size: cover;
+ background-repeat: no-repeat;
+
+}
+
+.container {
+ opacity: 0;
+
+ display: flex;
+ flex-direction: row;
+ justify-content: space-evenly;
+ align-items: center;
+ min-height: 100vh;
+}
+
+
+.ip-form {
+ background-color: #535C91;
+ opacity: 71;
+ padding: 9vh 3vh 5vh;
+ border-radius: 1rem;
+ box-shadow: 10px 10px 10px rgba(0, 0, 0, 0.9);
+ width: 25%;
+}
+
+.ip-form-title{
+ margin: 0 0 5vh 0;
+ text-align: center;
+}
+
+.ip-form-title h2{
+ color: #FFFFFF;
+ font-size: 5vh;
+ margin: 0;
+ padding: 0;
+}
+
+.ip-form hr{
+ width: 40%;
+}
+
+.ip-form-content{
+ display: flex;
+ flex-wrap: wrap;
+ justify-content: center;
+}
+
+input {
+ text-align: center;
+ color: white;
+ font-weight: bold;
+ font-size: 1.2rem;
+ width: 70%;
+ padding: 1rem;
+ margin: 0.7rem;
+ background-color: #1B1A55;
+ border-radius: 10px;
+}
+
+button {
+ font-weight: bold;
+ width: 35%;
+ font-size: 1rem;
+ padding: 10px;
+ border: none;
+ border-radius: 5px;
+ margin-top: 1rem;
+ cursor: pointer;
+}
+
+button:hover{
+ filter: brightness(85%);
+}
+
+.ip-form-footer{
+ margin-top: 3vh;
+ display: flex;
+ flex-wrap: wrap;
+ align-content: center;
+ align-items: center;
+ justify-content: space-evenly;
+}
+
+button[name="submit"] {
+ background-color: #F44336;
+ color: white;
+}
\ No newline at end of file
diff --git a/User/src/renderer/css/login.css b/User/src/renderer/css/login.css
index 3e04a36..00530ae 100644
--- a/User/src/renderer/css/login.css
+++ b/User/src/renderer/css/login.css
@@ -15,6 +15,8 @@ body, html {
}
.container {
+ opacity: 0;
+
display: flex;
flex-direction: row;
justify-content: space-evenly;
@@ -102,7 +104,7 @@ button[name="submit"] {
color: white;
}
-button[name="signin"] {
+button[name="signup"] {
background-color: #2196F3;
color: white;
}
\ No newline at end of file
diff --git a/User/src/renderer/css/main_menu.css b/User/src/renderer/css/main_menu.css
index 259ac29..54b52d9 100644
--- a/User/src/renderer/css/main_menu.css
+++ b/User/src/renderer/css/main_menu.css
@@ -85,6 +85,8 @@ input {
}
.container {
+ opacity: 0;
+
display: flex;
flex-direction: row;
justify-content: space-evenly;
diff --git a/User/src/renderer/css/profile.css b/User/src/renderer/css/profile.css
index f030018..3197e2e 100644
--- a/User/src/renderer/css/profile.css
+++ b/User/src/renderer/css/profile.css
@@ -15,6 +15,8 @@ body, html {
}
.container {
+ opacity: 0;
+
display: flex;
flex-direction: row;
justify-content: space-evenly;
diff --git a/User/src/renderer/css/sending_file_confirmation.css b/User/src/renderer/css/sending_file_confirmation.css
index 0c2ff31..ea7177f 100644
--- a/User/src/renderer/css/sending_file_confirmation.css
+++ b/User/src/renderer/css/sending_file_confirmation.css
@@ -15,6 +15,8 @@ body, html {
}
.container {
+ opacity: 0;
+
display: flex;
flex-direction: row;
justify-content: space-evenly;
diff --git a/User/src/renderer/css/share_file.css b/User/src/renderer/css/share_file.css
index a4a77ae..128b495 100644
--- a/User/src/renderer/css/share_file.css
+++ b/User/src/renderer/css/share_file.css
@@ -15,6 +15,8 @@ body, html {
}
.container {
+ opacity: 0;
+
display: flex;
flex-direction: row;
justify-content: space-evenly;
diff --git a/User/src/renderer/css/sign_up_confirmation.css b/User/src/renderer/css/sign_up_confirmation.css
index 2dbc893..183c9f9 100644
--- a/User/src/renderer/css/sign_up_confirmation.css
+++ b/User/src/renderer/css/sign_up_confirmation.css
@@ -15,6 +15,8 @@ body, html {
}
.container {
+ opacity: 0;
+
display: flex;
flex-direction: row;
justify-content: space-evenly;
diff --git a/User/src/renderer/css/sign_up_department.css b/User/src/renderer/css/sign_up_department.css
index f15f98a..009caab 100644
--- a/User/src/renderer/css/sign_up_department.css
+++ b/User/src/renderer/css/sign_up_department.css
@@ -15,6 +15,8 @@ body, html {
}
.container {
+ opacity: 0;
+
display: flex;
flex-direction: row;
justify-content: space-evenly;
diff --git a/User/src/renderer/css/sing_up_profile.css b/User/src/renderer/css/sing_up_profile.css
index 43fdc42..9fda52d 100644
--- a/User/src/renderer/css/sing_up_profile.css
+++ b/User/src/renderer/css/sing_up_profile.css
@@ -15,6 +15,8 @@ body, html {
}
.container {
+ opacity: 0;
+
display: flex;
flex-direction: row;
justify-content: space-evenly;
diff --git a/User/src/renderer/html/change_department.html b/User/src/renderer/html/change_department.html
index 61c1445..d8e0564 100644
--- a/User/src/renderer/html/change_department.html
+++ b/User/src/renderer/html/change_department.html
@@ -9,10 +9,11 @@
+
Department Selection
-
+