network chunk v12
This commit is contained in:
@@ -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',
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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<ParsedMessage>
|
||||
type OperationHandlerFunction = (parsedMessage: ParsedMessage) => Promise<ParsedMessage>;
|
||||
|
||||
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<ParsedMessage> {
|
||||
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<ParsedMessage> {
|
||||
return {
|
||||
operationCode: 'UNKNOWN_COMMAND',
|
||||
metaInfo: { message: 'Unknown command received.' },
|
||||
|
||||
@@ -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<ParsedMessage> {
|
||||
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<ParsedMessage> {
|
||||
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<ParsedMessage> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ParsedMessage> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ParsedMessage> {
|
||||
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<ParsedMessage> {
|
||||
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<ParsedMessage> {
|
||||
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<ParsedMessage> {
|
||||
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<ParsedMessage> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ParsedMessage> {
|
||||
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<ParsedMessage> {
|
||||
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<ParsedMessage> {
|
||||
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<ParsedMessage> {
|
||||
return parsedMessage; // Acknowledge with OK, returning as-is
|
||||
}
|
||||
|
||||
// Default async handler for ERR operation
|
||||
public static async handleErr(parsedMessage: ParsedMessage): Promise<ParsedMessage> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ParsedMessage> {
|
||||
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<ParsedMessage> {
|
||||
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<ParsedMessage> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<ParsedMessage> {
|
||||
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<ParsedMessage> {
|
||||
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<ParsedMessage> {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<void> {
|
||||
@@ -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<void> {
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user