From 39d007e34f8ee9b995a94427ef683e3b65f2241a Mon Sep 17 00:00:00 2001 From: andrei-mihnea-cerbu Date: Wed, 13 Nov 2024 13:33:03 +0200 Subject: [PATCH] network chunk v12 --- UC/src/network/operation_codes.ts | 40 ++++++ .../network/operations_base/operation_base.ts | 43 ------ .../operations_base/operation_handler.ts | 20 +-- .../operations_custom/auth_operations.ts | 97 +++++--------- .../operations_custom/ceo_operations.ts | 28 +--- .../department_operations.ts | 123 ++++-------------- .../operations_custom/general_operations.ts | 50 ++++--- .../operations_custom/key_operations.ts | 73 ++--------- .../operations_custom/user_operations.ts | 123 +++--------------- .../tcp_server_communicator.ts | 9 +- .../tcp_client_communicator.ts | 3 + .../tcp_server_communicator.ts | 9 +- 12 files changed, 182 insertions(+), 436 deletions(-) create mode 100644 UC/src/network/operation_codes.ts delete mode 100644 UC/src/network/operations_base/operation_base.ts diff --git a/UC/src/network/operation_codes.ts b/UC/src/network/operation_codes.ts new file mode 100644 index 0000000..7f6edb1 --- /dev/null +++ b/UC/src/network/operation_codes.ts @@ -0,0 +1,40 @@ +export let operationCodes = { + // General Operations + HEARTBEAT: 'HEARTBEAT', + ALIVE: 'ALIVE', + SET_PUBLIC_KEY: 'SET_PUBLIC_KEY', + SET_AES_KEY: 'SET_AES_KEY', + RESET_DATABASE: 'RESET_DATABASE', + OK: 'OK', + ERR: 'ERR', + END: 'END', + UNKNOWN_COMMAND: 'UNKNOWN_COMMAND', + + // Auth Operations + LOGIN: 'LOGIN', + SIGN_UP: 'SIGN_UP', + RESET_PASSWORD: 'RESET_PASSWORD', + + FIND_BY_EMAIL: 'FIND_BY_EMAIL', + MODIFY_USER: 'MODIFY_USER', + + GET_DEPARTMENTS: 'GET_DEPARTMENTS', + CREATE_DEPARTMENT: 'CREATE_DEPARTMENT', + MODIFY_DEPARTMENT: 'MODIFY_DEPARTMENT', + DELETE_DEPARTMENT: 'DELETE_DEPARTMENT', + + GET_USERS: 'GET_USERS', + FIND_KEY_BY_USER_ID: 'FIND_KEY_BY_USER_ID', + SEND_ANNOUNCEMENT: 'SEND_ANNOUNCEMENT', + + GET_USER_INFORMATION: 'GET_USER_INFORMATION', + CLEAR_BACKUP: 'CLEAR_BACKUP', + BACKUP_FILE: 'BACKUP_FILE', + SHARE_FILE: 'SHARE_FILE', + CLEAR_DEPARTMENT: 'CLEAR_DEPARTMENT', + DEPARTMENT_FILE: 'DEPARTMENT_FILE', + IS_BACKUP_CREATED: 'IS_BACKUP_CREATED', + GET_BACKUP_STRUCTURE: 'GET_BACKUP_STRUCTURE', + REQ_FILE_FROM_BACKUP: 'REQ_FILE_FROM_BACKUP', + DECRYPT_AND_SAVE_OLD_BACKUP_FILE: 'DECRYPT_AND_SAVE_OLD_BACKUP_FILE', +}; \ No newline at end of file diff --git a/UC/src/network/operations_base/operation_base.ts b/UC/src/network/operations_base/operation_base.ts deleted file mode 100644 index d0d62da..0000000 --- a/UC/src/network/operations_base/operation_base.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { ParsedMessage } from '../message_handler'; -import { OperationHandler } from './operation_handler'; -import { OperationPlugin } from './operation_plugin'; - -export abstract class OperationBase implements OperationPlugin { - // Shared operation codes - public static readonly operationCodes = { - OK: 'OK', - ERR: 'ERR', - END: 'END', - }; - - // Default handler for OK operation - public static handleOk(parsedMessage: ParsedMessage): ParsedMessage { - console.log('OK operation received'); - return parsedMessage; // Typically, you would just acknowledge with OK, returning as-is - } - - // Default handler for ERR operation - public static handleErr(parsedMessage: ParsedMessage): ParsedMessage { - console.log('ERR operation received: ', parsedMessage.metaInfo?.message || 'No error details provided'); - return parsedMessage; // Typically, you would log the error and return - } - - // Default handler for END operation - public static handleEnd(parsedMessage: ParsedMessage): ParsedMessage { - console.log('END operation received'); - return { - operationCode: OperationBase.operationCodes.END, - metaInfo: { message: 'Connection ended.' }, - }; - } - - // Register the common OK, ERR, and END handlers - public static registerCommonOperations(operationHandler: OperationHandler): void { - operationHandler.registerHandler(OperationBase.operationCodes.OK, OperationBase.handleOk); - operationHandler.registerHandler(OperationBase.operationCodes.ERR, OperationBase.handleErr); - operationHandler.registerHandler(OperationBase.operationCodes.END, OperationBase.handleEnd); - } - - // Abstract register method that will be implemented by subclasses - public abstract register(operationHandler: OperationHandler): void; -} diff --git a/UC/src/network/operations_base/operation_handler.ts b/UC/src/network/operations_base/operation_handler.ts index 0f0b10f..4b9a2f2 100644 --- a/UC/src/network/operations_base/operation_handler.ts +++ b/UC/src/network/operations_base/operation_handler.ts @@ -2,14 +2,14 @@ import { ParsedMessage, MessageHandler } from '../message_handler'; import { OperationPlugin } from './operation_plugin'; -type OperationHandlerFunction = (parsedMessage: ParsedMessage) => ParsedMessage; +// Define handler function type to return Promise +type OperationHandlerFunction = (parsedMessage: ParsedMessage) => Promise; export class OperationHandler { private static instance: OperationHandler; private handlers: { [operationCode: string]: OperationHandlerFunction } = {}; private constructor() { - // Register only the unknown command handler on initialization this.registerHandler('UNKNOWN_COMMAND', this.handleUnknownCommand); } @@ -26,30 +26,24 @@ export class OperationHandler { this.handlers[operationCode] = handler; } - // Handle operation request - public handleOperation(rawMessage: string): ParsedMessage { - // Parse and validate the message + // Handle operation request asynchronously + public async handleOperation(rawMessage: string): Promise { const parsedMessage = MessageHandler.parseMessage(rawMessage); if (!parsedMessage || !MessageHandler.validateMessage(parsedMessage)) { return this.handleUnknownCommand(parsedMessage); } - // Dispatch the handler for the given operation code + // Retrieve the handler for the operation code and invoke it asynchronously const handler = this.handlers[parsedMessage.operationCode]; if (handler) { - return handler(parsedMessage); + return await handler(parsedMessage); } else { return this.handleUnknownCommand(parsedMessage); } } - // Get all registered operation codes - public getAvailableOperationCodes(): string[] { - return Object.keys(this.handlers); - } - // Default handler for unknown commands - private handleUnknownCommand(parsedMessage?: ParsedMessage): ParsedMessage { + private async handleUnknownCommand(parsedMessage: ParsedMessage): Promise { return { operationCode: 'UNKNOWN_COMMAND', metaInfo: { message: 'Unknown command received.' }, diff --git a/UC/src/network/operations_custom/auth_operations.ts b/UC/src/network/operations_custom/auth_operations.ts index 580fe35..0a8d7ea 100644 --- a/UC/src/network/operations_custom/auth_operations.ts +++ b/UC/src/network/operations_custom/auth_operations.ts @@ -1,14 +1,14 @@ import { ParsedMessage } from '../message_handler'; -import {userDatabase, departmentDatabase, keyDatabase} from '../../db_managers/db'; -import { OperationBase } from '../operations_base/operation_base'; +import { userDatabase, departmentDatabase, keyDatabase } from '../../db_managers/db'; import { OperationHandler } from '../operations_base/operation_handler'; +import { OperationPlugin } from '../operations_base/operation_plugin'; +import {operationCodes} from "../operation_codes"; -export class AuthOperations extends OperationBase { +export class AuthOperations implements OperationPlugin { public static readonly operationCodes = { - ...OperationBase.operationCodes, LOGIN: 'LOGIN', SIGN_UP: 'SIGN_UP', - RESET_PASSWORD: 'RESET_PASSWORD' + RESET_PASSWORD: 'RESET_PASSWORD', }; // Utility function to validate email format @@ -17,95 +17,82 @@ export class AuthOperations extends OperationBase { return emailRegex.test(email); } - // Utility function to validate password strength (min 8 chars, at least 1 number and 1 special char) + // Utility function to validate password strength private static isStrongPassword(password: string): boolean { const passwordRegex = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[@$!%*#?&])[A-Za-z\d@$!%*#?&]{8,}$/; return passwordRegex.test(password); } - // Utility function to check name is not empty private static isValidName(name: string): boolean { return name.trim().length > 0; } - private static isValidAppType(app_type: string){ - const app_types = ['client', 'ceo', 'admin']; - return app_types.includes(app_type); + private static isValidAppType(app_type: string): boolean { + const appTypes = ['client', 'ceo', 'admin']; + return appTypes.includes(app_type); } // Handle Login operation with validation - public static handleLogin(parsedMessage: ParsedMessage): ParsedMessage { + public static async handleLogin(parsedMessage: ParsedMessage): Promise { const { email, password, app_type } = parsedMessage.metaInfo || {}; - // Check if email and password are provided if (!email || !password || !app_type) { return { - operationCode: OperationBase.operationCodes.ERR, - metaInfo: { message: 'Both email and password are required.' }, + operationCode: operationCodes.ERR, + metaInfo: { message: 'Email, password, and app_type are required.' }, }; } - // Verify email and password with the database const result = userDatabase.verifyCredentials(email, password, app_type); - - // Handle the case where the credentials are incorrect if (!result.success) { return { - operationCode: OperationBase.operationCodes.ERR, + operationCode: operationCodes.ERR, metaInfo: { message: result.message }, }; } return { - operationCode: OperationBase.operationCodes.OK, + operationCode: operationCodes.OK, metaInfo: { message: 'Login successful.' }, }; } // Handle SignUp operation with validation - public static handleSignUp(parsedMessage: ParsedMessage): ParsedMessage { + public static async handleSignUp(parsedMessage: ParsedMessage): Promise { const { name, email, password, departmentId, app_type } = parsedMessage.metaInfo || {}; - // Validate name if (!AuthOperations.isValidName(name)) { return { - operationCode: OperationBase.operationCodes.ERR, - metaInfo: { message: 'Invalid name. Please provide a valid name.' }, + operationCode: operationCodes.ERR, + metaInfo: { message: 'Invalid name.' }, }; } - // Validate email format if (!AuthOperations.isValidEmail(email)) { return { - operationCode: OperationBase.operationCodes.ERR, + operationCode: operationCodes.ERR, metaInfo: { message: 'Invalid email format.' }, }; } - // Validate password strength if (!AuthOperations.isStrongPassword(password)) { return { - operationCode: OperationBase.operationCodes.ERR, - metaInfo: { - message: 'Weak password. It must be at least 8 characters long, contain at least 1 letter, 1 number, and 1 special character.', - }, + operationCode: operationCodes.ERR, + metaInfo: { message: 'Weak password.' }, }; } if (!AuthOperations.isValidAppType(app_type)) { return { - operationCode: OperationBase.operationCodes.ERR, - metaInfo: { - message: 'Not valid app_type.', - }, + operationCode: operationCodes.ERR, + metaInfo: { message: 'Invalid app type.' }, }; } - // Check if user with this email already exists const existingUser = userDatabase.findByEmail(email); if (existingUser) { return { - operationCode: OperationBase.operationCodes.ERR, + operationCode: operationCodes.ERR, metaInfo: { message: 'Email already in use.' }, }; } @@ -113,71 +100,57 @@ export class AuthOperations extends OperationBase { const existingUserByName = userDatabase.getAllUsers().find((user) => user.name === name); if (existingUserByName) { return { - operationCode: OperationBase.operationCodes.ERR, + operationCode: operationCodes.ERR, metaInfo: { message: 'Name already in use.' }, }; } - // Validate department ID const departmentEntry = departmentDatabase.findById(departmentId); if (!departmentEntry) { return { - operationCode: OperationBase.operationCodes.ERR, + operationCode: operationCodes.ERR, metaInfo: { message: 'Invalid department.' }, }; } - // Create new user in the database const newUser = userDatabase.createUser(name, email, password, departmentEntry.id, app_type); - - // Create a key for the new user keyDatabase.createKey(newUser.id); return { - operationCode: OperationBase.operationCodes.OK, - metaInfo: { - message: 'User created successfully.', - userId: newUser.id, - }, + operationCode: operationCodes.OK, + metaInfo: { message: 'User created successfully.', userId: newUser.id }, }; } // Handle Reset Password operation - public static handleResetPassword(parsedMessage: ParsedMessage): ParsedMessage { + public static async handleResetPassword(parsedMessage: ParsedMessage): Promise { const { email, newPassword, app_type } = parsedMessage.metaInfo || {}; if (!AuthOperations.isStrongPassword(newPassword)) { return { - operationCode: OperationBase.operationCodes.ERR, - metaInfo: { - message: 'Weak password. It must be at least 8 characters long, contain at least 1 letter, 1 number, and 1 special character.', - }, + operationCode: operationCodes.ERR, + metaInfo: { message: 'Weak password.' }, }; } - // Logic to reset password (could be sending a reset link, or generating a temp password) const resetResult = userDatabase.resetPassword(email, newPassword, app_type); - if (resetResult.success) { return { - operationCode: OperationBase.operationCodes.OK, - metaInfo: { message: 'Password reset successfully. Please check your email for instructions.' }, + operationCode: operationCodes.OK, + metaInfo: { message: 'Password reset successfully.' }, }; } else { return { - operationCode: OperationBase.operationCodes.ERR, + operationCode: operationCodes.ERR, metaInfo: { message: 'Failed to reset password.' }, }; } } - // Register specific operations for AuthOperations + // Register operations with the OperationHandler public register(operationHandler: OperationHandler): void { operationHandler.registerHandler(AuthOperations.operationCodes.LOGIN, AuthOperations.handleLogin); operationHandler.registerHandler(AuthOperations.operationCodes.SIGN_UP, AuthOperations.handleSignUp); - operationHandler.registerHandler(AuthOperations.operationCodes.RESET_PASSWORD, AuthOperations.handleResetPassword) - - // Register common OK, ERR, and END operations from the base class - OperationBase.registerCommonOperations(operationHandler); + operationHandler.registerHandler(AuthOperations.operationCodes.RESET_PASSWORD, AuthOperations.handleResetPassword); } } diff --git a/UC/src/network/operations_custom/ceo_operations.ts b/UC/src/network/operations_custom/ceo_operations.ts index c912961..1f46c20 100644 --- a/UC/src/network/operations_custom/ceo_operations.ts +++ b/UC/src/network/operations_custom/ceo_operations.ts @@ -1,42 +1,28 @@ import { ParsedMessage } from '../message_handler'; -import { OperationBase } from '../operations_base/operation_base'; -import { - departmentDatabase, - keyDatabase, - userDatabase -} from '../../db_managers/db'; +import { departmentDatabase, keyDatabase, userDatabase } from '../../db_managers/db'; import { OperationHandler } from '../operations_base/operation_handler'; +import { OperationPlugin } from '../operations_base/operation_plugin'; +import { operationCodes} from "../operation_codes"; -export class CeoOperations extends OperationBase { +export class CeoOperations implements OperationPlugin { public static readonly operationCodes = { - ...OperationBase.operationCodes, // Inherit common operation codes (OK, ERR, END) RESET_DATABASE: 'RESET_DATABASE', }; - // Handle reset database operation - public static handleResetDatabase(): ParsedMessage { + public static async handleResetDatabase(): Promise { console.log('Resetting the database...'); - departmentDatabase.cleanTable(); userDatabase.cleanTable(); keyDatabase.cleanTable(); - - // Create the departments departmentDatabase.createDepartment('Worker'); return { - operationCode: CeoOperations.operationCodes.OK, - metaInfo: { - message: 'Database reset successfully.', - }, + operationCode: operationCodes.OK, + metaInfo: { message: 'Database reset successfully.' }, }; } - // Register general operations with the OperationHandler public register(operationHandler: OperationHandler): void { operationHandler.registerHandler(CeoOperations.operationCodes.RESET_DATABASE, CeoOperations.handleResetDatabase); - - // Register common operations inherited from the base class - OperationBase.registerCommonOperations(operationHandler); } } diff --git a/UC/src/network/operations_custom/department_operations.ts b/UC/src/network/operations_custom/department_operations.ts index de28189..4acd5eb 100644 --- a/UC/src/network/operations_custom/department_operations.ts +++ b/UC/src/network/operations_custom/department_operations.ts @@ -1,129 +1,54 @@ import { ParsedMessage } from '../message_handler'; -import {departmentDatabase} from '../../db_managers/db'; -import { OperationBase } from '../operations_base/operation_base'; +import { departmentDatabase } from '../../db_managers/db'; import { OperationHandler } from '../operations_base/operation_handler'; +import { OperationPlugin } from '../operations_base/operation_plugin'; +import { operationCodes } from "../operation_codes"; -export class DepartmentOperations extends OperationBase { +export class DepartmentOperations implements OperationPlugin { public static readonly operationCodes = { - ...OperationBase.operationCodes, GET_DEPARTMENTS: 'GET_DEPARTMENTS', CREATE_DEPARTMENT: 'CREATE_DEPARTMENT', MODIFY_DEPARTMENT: 'MODIFY_DEPARTMENT', DELETE_DEPARTMENT: 'DELETE_DEPARTMENT', - FIND_DEPARTMENT_BY_ID: 'FIND_DEPARTMENT_BY_ID' + FIND_DEPARTMENT_BY_ID: 'FIND_DEPARTMENT_BY_ID', }; - // Get all departments - public static handleGetDepartments(): ParsedMessage { + public static async handleGetDepartments(): Promise { const departments = departmentDatabase.getAllDepartments(); - return { - operationCode: DepartmentOperations.operationCodes.OK, - metaInfo: { departments }, - }; + return { operationCode: operationCodes.OK, metaInfo: { departments } }; } - public static handleGetDepartmentById(parsedMessage: ParsedMessage): ParsedMessage { + public static async handleGetDepartmentById(parsedMessage: ParsedMessage): Promise { const { id } = parsedMessage.metaInfo || {}; - - if(!id){ - return { - operationCode: DepartmentOperations.operationCodes.ERR, - metaInfo: { message: 'Id is required.' }, - }; - } - - const user = departmentDatabase.findById(id); - return { - operationCode: user === null ? DepartmentOperations.operationCodes.ERR : DepartmentOperations.operationCodes.OK, - metaInfo: user === null ? { message: 'Department not found.' } : { message: user } - } + const department = departmentDatabase.findById(id); + return department + ? { operationCode: operationCodes.OK, metaInfo: { department } } + : { operationCode: operationCodes.ERR, metaInfo: { message: 'Department not found.' } }; } - // Create a new department - public static handleCreateDepartment(parsedMessage: ParsedMessage): ParsedMessage { - // @ts-ignore - const { departmentName } = parsedMessage.metaInfo; - - // Check if department name is provided - if (!departmentName) { - return { - operationCode: DepartmentOperations.operationCodes.ERR, - metaInfo: { message: 'Department name is required.' }, - }; - } - - // Check if the department already exists - const existingDepartment = departmentDatabase.findByName(departmentName); - if (existingDepartment) { - return { - operationCode: DepartmentOperations.operationCodes.ERR, - metaInfo: { message: 'Department already exists.' }, - }; - } - - // Create the new department - const newDepartment = departmentDatabase.createDepartment(departmentName); - - return { - operationCode: DepartmentOperations.operationCodes.OK, - metaInfo: { message: 'Department created successfully.', departmentId: newDepartment.id }, - }; + public static async handleCreateDepartment(parsedMessage: ParsedMessage): Promise { + const { departmentName } = parsedMessage.metaInfo || {}; + const department = departmentDatabase.createDepartment(departmentName); + return { operationCode: operationCodes.OK, metaInfo: { department } }; } - // Modify an existing department - public static handleModifyDepartment(parsedMessage: ParsedMessage): ParsedMessage { - // @ts-ignore - const { departmentId, newDepartmentName } = parsedMessage.metaInfo; - - // Validate input - if (!departmentId || !newDepartmentName) { - return { - operationCode: DepartmentOperations.operationCodes.ERR, - metaInfo: { message: 'Department ID and new department name are required.' }, - }; - } - - // Modify the department - const isSuccess = departmentDatabase.modifyDepartment(departmentId, newDepartmentName); - - return { - operationCode: isSuccess ? DepartmentOperations.operationCodes.OK : DepartmentOperations.operationCodes.ERR, - metaInfo: { message: isSuccess ? 'Department modified successfully.' : 'Failed to modify department.' }, - }; + public static async handleModifyDepartment(parsedMessage: ParsedMessage): Promise { + const { departmentId, newDepartmentName } = parsedMessage.metaInfo || {}; + const success = departmentDatabase.modifyDepartment(departmentId, newDepartmentName); + return { operationCode: success ? operationCodes.OK : operationCodes.ERR }; } - // Delete an existing department - public static handleDeleteDepartment(parsedMessage: ParsedMessage): ParsedMessage { - // @ts-ignore - const { departmentId } = parsedMessage.metaInfo; - - // Validate input - if (!departmentId) { - return { - operationCode: DepartmentOperations.operationCodes.ERR, - metaInfo: { message: 'Department ID is required.' }, - }; - } - - // Delete the department - const isSuccess = departmentDatabase.deleteDepartment(departmentId); - - return { - operationCode: isSuccess ? DepartmentOperations.operationCodes.OK : DepartmentOperations.operationCodes.ERR, - metaInfo: { message: isSuccess ? 'Department deleted successfully.' : 'Failed to delete department.' }, - }; + public static async handleDeleteDepartment(parsedMessage: ParsedMessage): Promise { + const { departmentId } = parsedMessage.metaInfo || {}; + const success = departmentDatabase.deleteDepartment(departmentId); + return { operationCode: success ? operationCodes.OK : operationCodes.ERR }; } - // Register department operations_base with the OperationHandler public register(operationHandler: OperationHandler): void { - // Register the department operation handlers operationHandler.registerHandler(DepartmentOperations.operationCodes.GET_DEPARTMENTS, DepartmentOperations.handleGetDepartments); operationHandler.registerHandler(DepartmentOperations.operationCodes.CREATE_DEPARTMENT, DepartmentOperations.handleCreateDepartment); operationHandler.registerHandler(DepartmentOperations.operationCodes.MODIFY_DEPARTMENT, DepartmentOperations.handleModifyDepartment); operationHandler.registerHandler(DepartmentOperations.operationCodes.DELETE_DEPARTMENT, DepartmentOperations.handleDeleteDepartment); operationHandler.registerHandler(DepartmentOperations.operationCodes.FIND_DEPARTMENT_BY_ID, DepartmentOperations.handleGetDepartmentById); - - // Register common operations_base inherited from the base class - OperationBase.registerCommonOperations(operationHandler); } } diff --git a/UC/src/network/operations_custom/general_operations.ts b/UC/src/network/operations_custom/general_operations.ts index a9a448f..fd1e5f7 100644 --- a/UC/src/network/operations_custom/general_operations.ts +++ b/UC/src/network/operations_custom/general_operations.ts @@ -1,25 +1,26 @@ import { ParsedMessage } from '../message_handler'; -import { OperationBase } from '../operations_base/operation_base'; import { OperationHandler } from '../operations_base/operation_handler'; import os from 'node:os'; +import {OperationPlugin} from "../operations_base/operation_plugin"; -export class GeneralOperations extends OperationBase { +export class GeneralOperations implements OperationPlugin { public static readonly operationCodes = { - ...OperationBase.operationCodes, // Inherit common operation codes (OK, ERR, END) + OK: 'OK', + ERR: 'ERR', + END: 'END', HEARTBEAT: 'HEARTBEAT', ALIVE: 'ALIVE', SET_PUBLIC_KEY: 'SET_PUBLIC_KEY', - SET_AES_KEY: 'SET_AES_KEY', // New operation for AES key + SET_AES_KEY: 'SET_AES_KEY', }; - // Handle heartbeat operation - public static handleHeartbeat(): ParsedMessage { + // Handle heartbeat operation asynchronously + public static async handleHeartbeat(): Promise { const networkInterfaces = os.networkInterfaces(); let ipAddress = 'Unknown'; for (const iface of Object.values(networkInterfaces)) { - // @ts-ignore - for (const address of iface) { + for (const address of iface!) { if (address.family === 'IPv4' && !address.internal) { ipAddress = address.address; break; @@ -34,13 +35,13 @@ export class GeneralOperations extends OperationBase { }; } - // Handle public key exchange - public static handlePublicKey(parsedMessage: ParsedMessage): ParsedMessage { + // Handle public key exchange asynchronously + public static async handlePublicKey(parsedMessage: ParsedMessage): Promise { const clientPublicKey = parsedMessage.metaInfo?.publicKey; if (clientPublicKey) { return { operationCode: GeneralOperations.operationCodes.SET_PUBLIC_KEY, - metaInfo: { message: clientPublicKey }, + metaInfo: { publicKey: clientPublicKey }, }; } else { return { @@ -50,13 +51,14 @@ export class GeneralOperations extends OperationBase { } } - // Handle AES key exchange - public static handleAESKey(parsedMessage: ParsedMessage): ParsedMessage { + // Handle AES key exchange asynchronously + public static async handleAESKey(parsedMessage: ParsedMessage): Promise { const aesKey = parsedMessage.metaInfo?.aesKey; - if (aesKey) { + const aesIv = parsedMessage.metaInfo?.aesIv; + if (aesKey && aesIv) { return { operationCode: GeneralOperations.operationCodes.SET_AES_KEY, - metaInfo: { message: aesKey }, + metaInfo: { aesKey, aesIv }, }; } else { return { @@ -66,14 +68,22 @@ export class GeneralOperations extends OperationBase { } } + // Default async handler for OK operation + public static async handleOk(parsedMessage: ParsedMessage): Promise { + return parsedMessage; // Acknowledge with OK, returning as-is + } + + // Default async handler for ERR operation + public static async handleErr(parsedMessage: ParsedMessage): Promise { + return parsedMessage; // Log the error and return + } + // Register general operations with the OperationHandler public register(operationHandler: OperationHandler): void { - // Register specific handlers for the general operations operationHandler.registerHandler(GeneralOperations.operationCodes.HEARTBEAT, GeneralOperations.handleHeartbeat); operationHandler.registerHandler(GeneralOperations.operationCodes.SET_PUBLIC_KEY, GeneralOperations.handlePublicKey); - operationHandler.registerHandler(GeneralOperations.operationCodes.SET_AES_KEY, GeneralOperations.handleAESKey); // Register AES key handler - - // Register common operations inherited from the base class - OperationBase.registerCommonOperations(operationHandler); + operationHandler.registerHandler(GeneralOperations.operationCodes.SET_AES_KEY, GeneralOperations.handleAESKey); + operationHandler.registerHandler(GeneralOperations.operationCodes.OK, GeneralOperations.handleOk); + operationHandler.registerHandler(GeneralOperations.operationCodes.ERR, GeneralOperations.handleErr); } } diff --git a/UC/src/network/operations_custom/key_operations.ts b/UC/src/network/operations_custom/key_operations.ts index a7997ea..42a4725 100644 --- a/UC/src/network/operations_custom/key_operations.ts +++ b/UC/src/network/operations_custom/key_operations.ts @@ -1,90 +1,39 @@ import { ParsedMessage } from '../message_handler'; import { keyDatabase } from '../../db_managers/db'; -import { OperationBase } from '../operations_base/operation_base'; import { OperationHandler } from '../operations_base/operation_handler'; +import { OperationPlugin } from '../operations_base/operation_plugin'; +import { operationCodes } from "../operation_codes"; -export class KeyOperations extends OperationBase { +export class KeyOperations implements OperationPlugin { public static readonly operationCodes = { - ...OperationBase.operationCodes, GET_KEYS: 'GET_KEYS', CREATE_KEY: 'CREATE_KEY', DELETE_KEY: 'DELETE_KEY', FIND_KEY_BY_USER_ID: 'FIND_KEY_BY_USER_ID', }; - // Get all keys - public static handleGetKeys(): ParsedMessage { + public static async handleGetKeys(): Promise { const keys = keyDatabase.getAllKeys(); - console.log(keys); - return { - operationCode: KeyOperations.operationCodes.OK, - metaInfo: { keys }, - }; + return { operationCode: operationCodes.OK, metaInfo: { keys } }; } - // Create a key for a user - public static handleCreateKey(parsedMessage: ParsedMessage): ParsedMessage { + public static async handleCreateKey(parsedMessage: ParsedMessage): Promise { const { userId } = parsedMessage.metaInfo || {}; - - if (!userId) { - return { - operationCode: KeyOperations.operationCodes.ERR, - metaInfo: { message: 'User ID is required to create a key.' }, - }; - } - - // Create the key for the user const key = keyDatabase.createKey(userId); - return { - operationCode: KeyOperations.operationCodes.OK, - metaInfo: { key }, - }; + return { operationCode: operationCodes.OK, metaInfo: { key } }; } - // Find a key by user ID - public static handleFindKeyByUserId(parsedMessage: ParsedMessage): ParsedMessage { + public static async handleFindKeyByUserId(parsedMessage: ParsedMessage): Promise { const { userId } = parsedMessage.metaInfo || {}; - - if (!userId) { - return { - operationCode: KeyOperations.operationCodes.ERR, - metaInfo: { message: 'User ID is required.' }, - }; - } - const key = keyDatabase.findByUserId(userId); - return { - operationCode: key === null ? KeyOperations.operationCodes.ERR : KeyOperations.operationCodes.OK, - metaInfo: key === null ? { message: 'Key not found.' } : { key }, - }; + return key + ? { operationCode: operationCodes.OK, metaInfo: { key } } + : { operationCode: operationCodes.ERR, metaInfo: { message: 'Key not found.' } }; } - // Delete a key by user ID - public static handleDeleteKey(parsedMessage: ParsedMessage): ParsedMessage { - const { userId } = parsedMessage.metaInfo || {}; - - if (!userId) { - return { - operationCode: KeyOperations.operationCodes.ERR, - metaInfo: { message: 'User ID is required for deletion.' }, - }; - } - - const isSuccess = keyDatabase.deleteKeysByUserId(userId); - return { - operationCode: isSuccess ? KeyOperations.operationCodes.OK : KeyOperations.operationCodes.ERR, - metaInfo: { message: isSuccess ? 'Key deleted successfully.' : 'Failed to delete key.' }, - }; - } - - // Register key operations with the OperationHandler public register(operationHandler: OperationHandler): void { operationHandler.registerHandler(KeyOperations.operationCodes.GET_KEYS, KeyOperations.handleGetKeys); operationHandler.registerHandler(KeyOperations.operationCodes.CREATE_KEY, KeyOperations.handleCreateKey); - operationHandler.registerHandler(KeyOperations.operationCodes.DELETE_KEY, KeyOperations.handleDeleteKey); operationHandler.registerHandler(KeyOperations.operationCodes.FIND_KEY_BY_USER_ID, KeyOperations.handleFindKeyByUserId); - - // Register common operations inherited from OperationBase - OperationBase.registerCommonOperations(operationHandler); } } diff --git a/UC/src/network/operations_custom/user_operations.ts b/UC/src/network/operations_custom/user_operations.ts index 8a53903..331883d 100644 --- a/UC/src/network/operations_custom/user_operations.ts +++ b/UC/src/network/operations_custom/user_operations.ts @@ -1,11 +1,11 @@ import { ParsedMessage } from '../message_handler'; -import {userDatabase} from '../../db_managers/db'; -import { OperationBase } from '../operations_base/operation_base'; +import { userDatabase } from '../../db_managers/db'; import { OperationHandler } from '../operations_base/operation_handler'; +import { OperationPlugin } from '../operations_base/operation_plugin'; +import { operationCodes} from "../operation_codes"; -export class UserOperations extends OperationBase { +export class UserOperations implements OperationPlugin { public static readonly operationCodes = { - ...OperationBase.operationCodes, GET_USERS: 'GET_USERS', CREATE_USER: 'CREATE_USER', MODIFY_USER: 'MODIFY_USER', @@ -14,123 +14,30 @@ export class UserOperations extends OperationBase { FIND_BY_EMAIL: 'FIND_BY_EMAIL', }; - // Get all users - public static handleGetUsers(): ParsedMessage { + public static async handleGetUsers(): Promise { const users = userDatabase.getAllUsers(); - console.log(users); - return { - operationCode: UserOperations.operationCodes.OK, - metaInfo: { users }, - }; + return { operationCode: operationCodes.OK, metaInfo: { users } }; } - public static handleGetUserById(parsedMessage: ParsedMessage): ParsedMessage { + public static async handleGetUserById(parsedMessage: ParsedMessage): Promise { const { id } = parsedMessage.metaInfo || {}; - - if(!id){ - return { - operationCode: UserOperations.operationCodes.ERR, - metaInfo: { message: 'Id is required.' }, - }; - } - const user = userDatabase.findById(id); - return { - operationCode: user === null ? UserOperations.operationCodes.ERR : UserOperations.operationCodes.OK, - metaInfo: user === null ? { message: 'User not found.' } : { message: user } - } + return user + ? { operationCode: operationCodes.OK, metaInfo: { user } } + : { operationCode: operationCodes.ERR, metaInfo: { message: 'User not found.' } }; } - public static handleGetUserByEmail(parsedMessage: ParsedMessage) : ParsedMessage{ - const { email } = parsedMessage.metaInfo || {}; - if(!email){ - return { - operationCode: UserOperations.operationCodes.ERR, - metaInfo: { message: 'Email is required.' }, - }; - } - - const user = userDatabase.findByEmail(email); - const response = { - operationCode: user === null ? UserOperations.operationCodes.ERR : UserOperations.operationCodes.OK, - metaInfo: user === null ? { message: 'User not found.' } : user - } - - console.log(response); - return response; - } - - // Modify an existing user - public static handleModifyUser(parsedMessage: ParsedMessage): ParsedMessage { + public static async handleModifyUser(parsedMessage: ParsedMessage): Promise { const { id, name, email, password, departmentId, app_type } = parsedMessage.metaInfo || {}; - - if (!id || !name || !email || !password || !departmentId || !app_type) { - return { - operationCode: UserOperations.operationCodes.ERR, - metaInfo: { message: 'Some information are missing.' }, - }; - } - - const user = userDatabase.findById(id); - if (!user) return { - operationCode: UserOperations.operationCodes.ERR, - metaInfo: { message: 'User not found in the system.' }, - }; - - const listOfUsers = userDatabase.getAllUsers() - - // Check if another user already exists with the same email or name (excluding the current user) - const existingUserByEmail = listOfUsers.find((existingUser) => existingUser.email === email && existingUser.id !== id); - const existingUserByName = listOfUsers.find((existingUser) => existingUser.name === name && existingUser.id !== id); - - if (existingUserByEmail) { - return { - operationCode: UserOperations.operationCodes.ERR, - metaInfo: { message: `Email ${email} is already in use by another user.` }, - }; - } - - if (existingUserByName) { - return { - operationCode: UserOperations.operationCodes.ERR, - metaInfo: { message: `Name ${name} is already in use by another user.` }, - }; - } - - const isSuccess = userDatabase.modifyUser(id, name, email, password, departmentId, app_type); - return { - operationCode: isSuccess ? UserOperations.operationCodes.OK : UserOperations.operationCodes.ERR, - metaInfo: { message: isSuccess ? 'User modified successfully.' : 'Failed to modify user.' }, - }; + const success = userDatabase.modifyUser(id, name, email, password, departmentId, app_type); + return success + ? { operationCode: operationCodes.OK, metaInfo: { message: 'User modified successfully.' } } + : { operationCode: operationCodes.ERR, metaInfo: { message: 'Failed to modify user.' } }; } - // Delete a user by ID - public static handleDeleteUser(parsedMessage: ParsedMessage): ParsedMessage { - const { id } = parsedMessage.metaInfo || {}; - - if (!id) { - return { - operationCode: UserOperations.operationCodes.ERR, - metaInfo: { message: 'User ID is required for deletion.' }, - }; - } - - const isSuccess = userDatabase.deleteUser(id); - return { - operationCode: isSuccess ? UserOperations.operationCodes.OK : UserOperations.operationCodes.ERR, - metaInfo: { message: isSuccess ? 'User deleted successfully.' : 'Failed to delete user.' }, - }; - } - - // Register user operations with the OperationHandler public register(operationHandler: OperationHandler): void { operationHandler.registerHandler(UserOperations.operationCodes.GET_USERS, UserOperations.handleGetUsers); operationHandler.registerHandler(UserOperations.operationCodes.MODIFY_USER, UserOperations.handleModifyUser); - operationHandler.registerHandler(UserOperations.operationCodes.DELETE_USER, UserOperations.handleDeleteUser); operationHandler.registerHandler(UserOperations.operationCodes.FIND_BY_ID, UserOperations.handleGetUserById); - operationHandler.registerHandler(UserOperations.operationCodes.FIND_BY_EMAIL, UserOperations.handleGetUserByEmail); - - // Register common operations inherited from OperationBase - OperationBase.registerCommonOperations(operationHandler); } } diff --git a/UC/src/network/socket_communicator/tcp_server_communicator.ts b/UC/src/network/socket_communicator/tcp_server_communicator.ts index b88a273..655c428 100644 --- a/UC/src/network/socket_communicator/tcp_server_communicator.ts +++ b/UC/src/network/socket_communicator/tcp_server_communicator.ts @@ -2,6 +2,7 @@ import { Socket } from 'net'; import { MessageHandler } from '../message_handler'; import { SocketCommunicatorBase } from './socket_communicator_base'; import { OperationHandler } from '../operations_base/operation_handler'; +import {operationCodes} from "../operation_codes"; export class TcpServerCommunicator extends SocketCommunicatorBase { private readonly socket: Socket; @@ -17,7 +18,7 @@ export class TcpServerCommunicator extends SocketCommunicatorBase { throw new Error('RSA key pair is not available. Please generate RSA key pair.'); } - await this.sendMessage('SET_PUBLIC_KEY', { publicKey: this.publicKey }); + await this.sendMessage(operationCodes.SET_PUBLIC_KEY, { publicKey: this.publicKey }); } async sendAesKey(): Promise { @@ -28,7 +29,7 @@ export class TcpServerCommunicator extends SocketCommunicatorBase { const aesKeyBase64 = this.aesKey.toString('base64'); const aesIvBase64 = this.aesIv.toString('base64'); - await this.sendMessage('SET_AES_KEY', { aesKey: aesKeyBase64, aesIv: aesIvBase64 }); + await this.sendMessage(operationCodes.SET_AES_KEY, { aesKey: aesKeyBase64, aesIv: aesIvBase64 }); } async handleIncomingMessage(incomingMessage: string): Promise { @@ -45,10 +46,10 @@ export class TcpServerCommunicator extends SocketCommunicatorBase { let outgoingMessage: string; switch (operationCode) { - case 'SET_PUBLIC_KEY': + case operationCodes.SET_PUBLIC_KEY: outgoingMessage = Buffer.from(message, 'utf-8').toString('base64'); break; - case 'SET_AES_KEY': + case operationCodes.SET_AES_KEY: outgoingMessage = this.encryptWithRsa(message); break; default: diff --git a/User/src/network/socket_communicator/tcp_client_communicator.ts b/User/src/network/socket_communicator/tcp_client_communicator.ts index 3b1a5a3..4974773 100644 --- a/User/src/network/socket_communicator/tcp_client_communicator.ts +++ b/User/src/network/socket_communicator/tcp_client_communicator.ts @@ -22,16 +22,19 @@ export class TcpClientCommunicator extends SocketCommunicatorBase { } setServerPublicKey(publicKey: string): void { + console.log('\n\nSetting server public key\n\n'); this.publicKey = publicKey; } setAesKey(aesKey: string, aesIv: string): void { + console.log('\n\nSetting AES key\n\n'); this.aesKey = Buffer.from(aesKey, 'base64'); this.aesIv = Buffer.from(aesIv, 'base64'); } async handleIncomingMessage(incomingMessage: string): Promise { let messageToProcess; + if (this.aesKey && this.aesIv) { messageToProcess = this.decryptWithAes(incomingMessage); } else if (this.publicKey) { diff --git a/User/src/network/socket_communicator/tcp_server_communicator.ts b/User/src/network/socket_communicator/tcp_server_communicator.ts index b88a273..655c428 100644 --- a/User/src/network/socket_communicator/tcp_server_communicator.ts +++ b/User/src/network/socket_communicator/tcp_server_communicator.ts @@ -2,6 +2,7 @@ import { Socket } from 'net'; import { MessageHandler } from '../message_handler'; import { SocketCommunicatorBase } from './socket_communicator_base'; import { OperationHandler } from '../operations_base/operation_handler'; +import {operationCodes} from "../operation_codes"; export class TcpServerCommunicator extends SocketCommunicatorBase { private readonly socket: Socket; @@ -17,7 +18,7 @@ export class TcpServerCommunicator extends SocketCommunicatorBase { throw new Error('RSA key pair is not available. Please generate RSA key pair.'); } - await this.sendMessage('SET_PUBLIC_KEY', { publicKey: this.publicKey }); + await this.sendMessage(operationCodes.SET_PUBLIC_KEY, { publicKey: this.publicKey }); } async sendAesKey(): Promise { @@ -28,7 +29,7 @@ export class TcpServerCommunicator extends SocketCommunicatorBase { const aesKeyBase64 = this.aesKey.toString('base64'); const aesIvBase64 = this.aesIv.toString('base64'); - await this.sendMessage('SET_AES_KEY', { aesKey: aesKeyBase64, aesIv: aesIvBase64 }); + await this.sendMessage(operationCodes.SET_AES_KEY, { aesKey: aesKeyBase64, aesIv: aesIvBase64 }); } async handleIncomingMessage(incomingMessage: string): Promise { @@ -45,10 +46,10 @@ export class TcpServerCommunicator extends SocketCommunicatorBase { let outgoingMessage: string; switch (operationCode) { - case 'SET_PUBLIC_KEY': + case operationCodes.SET_PUBLIC_KEY: outgoingMessage = Buffer.from(message, 'utf-8').toString('base64'); break; - case 'SET_AES_KEY': + case operationCodes.SET_AES_KEY: outgoingMessage = this.encryptWithRsa(message); break; default: