client for test

This commit is contained in:
andrei-mihnea-cerbu
2025-02-04 20:08:56 +02:00
parent dcf505c89b
commit 885627213e
20 changed files with 158 additions and 240 deletions
+72 -35
View File
@@ -1,16 +1,15 @@
import jsonfile from 'jsonfile' import jsonfile from 'jsonfile'
import { promises as fs } from 'fs' import { promises as fs } from 'fs'
import { v4 as uuidv4 } from 'uuid' import { v4 as uuidv4 } from 'uuid'
import { MemoryManager } from './helpers/memory_manager' import { DatabaseScheme } from './schemes/database_scheme'
import { QueueManager, FileItemTask } from './helpers/queue_manager' import { FileItemTask } from './schemes/local_resources_scheme'
const defaultData = { const defaultData: DatabaseScheme = {
app_config: { app_config: {
app_type: 'client', app_type: 'client',
user_info: { user_info: {
id: '', id: '',
email: '', email: '',
password: '',
departmentId: '', departmentId: '',
name: '', name: '',
}, },
@@ -25,6 +24,7 @@ const defaultData = {
network: { network: {
usersInLan: [], usersInLan: [],
serverIp: '', serverIp: '',
announcement: '',
}, },
local_resources: { local_resources: {
directory_schemes: { directory_schemes: {
@@ -32,18 +32,18 @@ const defaultData = {
department: { id: uuidv4(), path: '', structure: {}, totalSize: 0 }, department: { id: uuidv4(), path: '', structure: {}, totalSize: 0 },
shared: { id: uuidv4(), path: '', structure: {}, totalSize: 0 }, shared: { id: uuidv4(), path: '', structure: {}, totalSize: 0 },
}, },
task_schemes: {
send_file_queue: [],
receive_file_queue: [],
},
}, },
} }
export class JsonDatabase<T, Q> { export class Database {
private readonly filePath: string private readonly filePath: string
private memoryStore: MemoryManager<Q>
private queueStore: QueueManager
constructor(filePath: string) { constructor(filePath: string) {
this.filePath = filePath this.filePath = filePath
this.memoryStore = new MemoryManager<Q>()
this.queueStore = new QueueManager()
// Ensure the file exists and is not empty // Ensure the file exists and is not empty
this.ensureFileExists().then(() => { this.ensureFileExists().then(() => {
@@ -76,12 +76,12 @@ export class JsonDatabase<T, Q> {
} }
// Read JSON from file // Read JSON from file
async read(): Promise<T> { async read(): Promise<DatabaseScheme> {
try { try {
return await jsonfile.readFile(this.filePath) return await jsonfile.readFile(this.filePath)
} catch (error: any) { } catch (error: any) {
if (error.code === 'ENOENT') { if (error.code === 'ENOENT') {
return defaultData as T // Return defaultData if file does not exist return defaultData
} }
throw error throw error
} }
@@ -89,53 +89,90 @@ export class JsonDatabase<T, Q> {
// Update JSON file with atomic write // Update JSON file with atomic write
async update( async update(
updateCallback: (data: Awaited<T>) => Awaited<T> | Promise<Awaited<T>>, updateCallback: (
data: Awaited<DatabaseScheme>,
) => Awaited<DatabaseScheme> | Promise<Awaited<DatabaseScheme>>,
): Promise<void> { ): Promise<void> {
let data = await this.read() let data = await this.read()
data = await updateCallback(data) data = await updateCallback(data)
await jsonfile.writeFile(this.filePath, data, { spaces: 2 }) await jsonfile.writeFile(this.filePath, data, { spaces: 2 })
} }
// Generate and return a new UUID // **Queue Methods Integrated Here**
generateUUID(): string {
return uuidv4() /** Push a task to the send queue */
async pushToSendQueue(task: FileItemTask): Promise<void> {
await this.update((data) => {
data.local_resources.task_schemes.send_file_queue.push(task)
return data
})
} }
// MemoryStore Operations /** Push a task to the receive queue */
setMemory(uuid: string, value: Q): void { async pushToReceiveQueue(task: FileItemTask): Promise<void> {
this.memoryStore.set(uuid, value) await this.update((data) => {
data.local_resources.task_schemes.receive_file_queue.push(task)
return data
})
} }
getMemory(uuid: string): Q | undefined { /** Pop (remove) the first task from the send queue */
return this.memoryStore.get(uuid) async popFromSendQueue(): Promise<FileItemTask | undefined> {
let poppedTask: FileItemTask | undefined
await this.update((data) => {
poppedTask = data.local_resources.task_schemes.send_file_queue.shift()
return data
})
return poppedTask
} }
deleteMemory(uuid: string): boolean { /** Pop (remove) the first task from the receive queue */
return this.memoryStore.delete(uuid) async popFromReceiveQueue(): Promise<FileItemTask | undefined> {
let poppedTask: FileItemTask | undefined
await this.update((data) => {
poppedTask = data.local_resources.task_schemes.receive_file_queue.shift()
return data
})
return poppedTask
} }
hasMemory(uuid: string): boolean { /** View the first task in the send queue without removing it */
return this.memoryStore.has(uuid) async seekSendQueue(): Promise<FileItemTask | undefined> {
const data = await this.read()
return data.local_resources.task_schemes.send_file_queue[0]
} }
// Queue Operations /** View the first task in the receive queue without removing it */
pushQueue(task: FileItemTask): void { async seekReceiveQueue(): Promise<FileItemTask | undefined> {
this.queueStore.push(task) const data = await this.read()
return data.local_resources.task_schemes.receive_file_queue[0]
} }
popQueue(): FileItemTask | undefined { /** Get the length of the send queue */
return this.queueStore.pop() async sendQueueSize(): Promise<number> {
const data = await this.read()
return data.local_resources.task_schemes.send_file_queue.length
} }
seekQueue(): FileItemTask | undefined { /** Get the length of the receive queue */
return this.queueStore.seek() async receiveQueueSize(): Promise<number> {
const data = await this.read()
return data.local_resources.task_schemes.receive_file_queue.length
} }
queueSize(): number { /** Clear all tasks from the send queue */
return this.queueStore.size() async clearSendQueue(): Promise<void> {
await this.update((data) => {
data.local_resources.task_schemes.send_file_queue = []
return data
})
} }
clearQueue(): void { /** Clear all tasks from the receive queue */
this.queueStore.clear() async clearReceiveQueue(): Promise<void> {
await this.update((data) => {
data.local_resources.task_schemes.receive_file_queue = []
return data
})
} }
} }
@@ -1,42 +0,0 @@
export class MemoryManager<T> {
private storage: Map<string, T>
constructor() {
this.storage = new Map<string, T>()
}
// Set a value in the memory store
set(uuid: string, value: T): void {
this.storage.set(uuid, value)
}
// Get a value from the memory store
get(uuid: string): T | undefined {
return this.storage.get(uuid)
}
// Check if a key exists
has(uuid: string): boolean {
return this.storage.has(uuid)
}
// Delete a key-value pair
delete(uuid: string): boolean {
return this.storage.delete(uuid)
}
// Get all keys
keys(): string[] {
return Array.from(this.storage.keys())
}
// Get all values
values(): T[] {
return Array.from(this.storage.values())
}
// Clear all stored values
clear(): void {
this.storage.clear()
}
}
@@ -1,38 +0,0 @@
export interface FileItemTask {
ip: string
path: string
userName: string
}
export class QueueManager {
private queue: FileItemTask[]
constructor() {
this.queue = []
}
// Add a new task to the queue
push(task: FileItemTask): void {
this.queue.push(task)
}
// Remove and return the first task (FIFO)
pop(): FileItemTask | undefined {
return this.queue.shift()
}
// View the first task without removing it
seek(): FileItemTask | undefined {
return this.queue[0]
}
// Get queue length
size(): number {
return this.queue.length
}
// Clear all tasks
clear(): void {
this.queue = []
}
}
@@ -1,5 +1,6 @@
export interface LocalResourcesScheme { export interface LocalResourcesScheme {
directory_schemes: DirectorySchemes directory_schemes: DirectorySchemes
task_schemes: TaskSchemes
} }
export interface DirectorySchemes { export interface DirectorySchemes {
@@ -14,3 +15,14 @@ export interface DirectoryInfo {
structure: any structure: any
totalSize: number totalSize: number
} }
export interface TaskSchemes {
send_file_queue: FileItemTask[]
receive_file_queue: FileItemTask[]
}
export interface FileItemTask {
ip: string
path: string
userName: string
}
+3 -4
View File
@@ -4,20 +4,19 @@ import { FileEncryptor } from './file_encryptor'
import { TcpCommunicator } from './tcp_communicator' import { TcpCommunicator } from './tcp_communicator'
import { operationCodes } from '../network/operation_codes' import { operationCodes } from '../network/operation_codes'
import { ParsedMessage } from '../network/message_handler' import { ParsedMessage } from '../network/message_handler'
import { JsonDatabase } from '../database/database' import { Database } from '../database/database'
import { DatabaseScheme } from '../database/schemes/database_scheme'
import { NetworkUserScheme } from '../database/schemes/network_scheme' import { NetworkUserScheme } from '../database/schemes/network_scheme'
export class BackupManager { export class BackupManager {
private fileEncryptor: FileEncryptor | null = null private fileEncryptor: FileEncryptor | null = null
private readonly db: JsonDatabase<DatabaseScheme, any> private readonly db: Database
private readonly clientPort: number private readonly clientPort: number
private isBusy: boolean = false private isBusy: boolean = false
private intervalId: NodeJS.Timeout | null = null private intervalId: NodeJS.Timeout | null = null
private stopRequested: boolean = false private stopRequested: boolean = false
constructor(pathToDatabaseFile: string, clientPort: number) { constructor(pathToDatabaseFile: string, clientPort: number) {
this.db = new JsonDatabase(pathToDatabaseFile) this.db = new Database(pathToDatabaseFile)
this.clientPort = clientPort this.clientPort = clientPort
} }
+3 -4
View File
@@ -4,11 +4,10 @@ import path from 'path'
import fs from 'fs' import fs from 'fs'
import crypto from 'crypto' import crypto from 'crypto'
import { ParsedMessage } from '../network/message_handler' import { ParsedMessage } from '../network/message_handler'
import { JsonDatabase } from '../database/database' import { Database } from '../database/database'
import { DatabaseScheme } from '../database/schemes/database_scheme'
export class BackupRetrievalWorker { export class BackupRetrievalWorker {
private db: JsonDatabase<DatabaseScheme, any> private db: Database
private readonly clientPort: number private readonly clientPort: number
private readonly destinationPath: string private readonly destinationPath: string
private encryptionKey: Buffer | null = null private encryptionKey: Buffer | null = null
@@ -18,7 +17,7 @@ export class BackupRetrievalWorker {
private isBusy: boolean = false private isBusy: boolean = false
constructor(pathToDatabaseFile: string, clientPort: number, destinationPath: string) { constructor(pathToDatabaseFile: string, clientPort: number, destinationPath: string) {
this.db = new JsonDatabase<DatabaseScheme, any>(pathToDatabaseFile) this.db = new Database(pathToDatabaseFile)
this.clientPort = clientPort this.clientPort = clientPort
this.destinationPath = destinationPath this.destinationPath = destinationPath
} }
+3 -4
View File
@@ -3,11 +3,10 @@ import path from 'path'
import { TcpCommunicator } from './tcp_communicator' import { TcpCommunicator } from './tcp_communicator'
import { operationCodes } from '../network/operation_codes' import { operationCodes } from '../network/operation_codes'
import { ParsedMessage } from '../network/message_handler' import { ParsedMessage } from '../network/message_handler'
import { JsonDatabase } from '../database/database' import { Database } from '../database/database'
import { DatabaseScheme } from '../database/schemes/database_scheme'
export class DepartmentSharer { export class DepartmentSharer {
private readonly db: JsonDatabase<DatabaseScheme, any> private readonly db: Database
private departmentDirectory: string | null = null private departmentDirectory: string | null = null
private readonly clientPort: number private readonly clientPort: number
private isBusy: boolean = false private isBusy: boolean = false
@@ -16,7 +15,7 @@ export class DepartmentSharer {
private intervalId: NodeJS.Timeout | null = null private intervalId: NodeJS.Timeout | null = null
constructor(pathToDatabaseFile: string, clientPort: number) { constructor(pathToDatabaseFile: string, clientPort: number) {
this.db = new JsonDatabase(pathToDatabaseFile) this.db = new Database(pathToDatabaseFile)
this.clientPort = clientPort this.clientPort = clientPort
} }
+3 -4
View File
@@ -1,15 +1,14 @@
import { promises as fs, watch, FSWatcher } from 'fs' import { promises as fs, watch, FSWatcher } from 'fs'
import path from 'path' import path from 'path'
import { JsonDatabase } from '../database/database' import { Database } from '../database/database'
import { DatabaseScheme } from '../database/schemes/database_scheme'
export class DirectoryWatcher { export class DirectoryWatcher {
private readonly watchers: Map<string, FSWatcher> // Stores watchers with directory ID as the key private readonly watchers: Map<string, FSWatcher> // Stores watchers with directory ID as the key
private readonly db: JsonDatabase<DatabaseScheme, any> private readonly db: Database
private totalSizes: Map<string, number> // Stores total sizes per directory ID private totalSizes: Map<string, number> // Stores total sizes per directory ID
constructor(pathToDatabaseFile: string) { constructor(pathToDatabaseFile: string) {
this.db = new JsonDatabase<DatabaseScheme, any>(pathToDatabaseFile) this.db = new Database(pathToDatabaseFile)
this.watchers = new Map<string, FSWatcher>() this.watchers = new Map<string, FSWatcher>()
this.totalSizes = new Map<string, number>() this.totalSizes = new Map<string, number>()
} }
+7 -7
View File
@@ -3,8 +3,7 @@ import path from 'path'
import { TcpCommunicator } from './tcp_communicator' import { TcpCommunicator } from './tcp_communicator'
import { operationCodes } from '../network/operation_codes' import { operationCodes } from '../network/operation_codes'
import { ParsedMessage } from '../network/message_handler' import { ParsedMessage } from '../network/message_handler'
import { JsonDatabase } from '../database/database' import { Database } from '../database/database'
import { DatabaseScheme } from '../database/schemes/database_scheme'
interface FileSendTask { interface FileSendTask {
ip: string ip: string
@@ -13,7 +12,7 @@ interface FileSendTask {
} }
export class FileSharer { export class FileSharer {
private readonly db: JsonDatabase<DatabaseScheme, any> private readonly db: Database
private readonly clientPort: number private readonly clientPort: number
private isBusy: boolean = false private isBusy: boolean = false
private tcpCommunicator: TcpCommunicator | null = null private tcpCommunicator: TcpCommunicator | null = null
@@ -21,7 +20,7 @@ export class FileSharer {
private intervalId: NodeJS.Timeout | null = null private intervalId: NodeJS.Timeout | null = null
constructor(pathToDatabaseFile: string, clientPort: number) { constructor(pathToDatabaseFile: string, clientPort: number) {
this.db = new JsonDatabase(pathToDatabaseFile) this.db = new Database(pathToDatabaseFile)
this.clientPort = clientPort this.clientPort = clientPort
} }
@@ -43,8 +42,9 @@ export class FileSharer {
// Method to process the queue // Method to process the queue
private async processQueue(): Promise<void> { private async processQueue(): Promise<void> {
for (let i = 0; i < this.db.queueSize(); i++) { const queueSize = await this.db.sendQueueSize()
const task = this.db.popQueue() for (let i = 0; i < queueSize; i++) {
const task = await this.db.popFromSendQueue()
if (task) { if (task) {
this.log(`Processing task for file: ${task.path} to IP: ${task.ip}`) this.log(`Processing task for file: ${task.path} to IP: ${task.ip}`)
const success = await this.sendFile(task) const success = await this.sendFile(task)
@@ -54,7 +54,7 @@ export class FileSharer {
`Failed to send file: ${task.path} to IP: ${task.ip}. Re-adding to queue.`, `Failed to send file: ${task.path} to IP: ${task.ip}. Re-adding to queue.`,
'error', 'error',
) )
this.db.pushQueue(task) await this.db.pushToSendQueue(task)
} else { } else {
this.log(`File sent successfully: ${task.path} to IP: ${task.ip}`) this.log(`File sent successfully: ${task.path} to IP: ${task.ip}`)
} }
+3 -4
View File
@@ -2,11 +2,10 @@ import { UdpClient } from '../network/udp/udp_client'
import { TcpCommunicator } from './tcp_communicator' import { TcpCommunicator } from './tcp_communicator'
import { operationCodes } from '../network/operation_codes' import { operationCodes } from '../network/operation_codes'
import { ParsedMessage } from '../network/message_handler' import { ParsedMessage } from '../network/message_handler'
import { JsonDatabase } from '../database/database' import { Database } from '../database/database'
import { DatabaseScheme } from '../database/schemes/database_scheme'
export class NetworkScanner { export class NetworkScanner {
private db: JsonDatabase<DatabaseScheme, any> private db: Database
private readonly udpPort: number private readonly udpPort: number
private readonly tcpPort: number private readonly tcpPort: number
private readonly okPage: string private readonly okPage: string
@@ -27,7 +26,7 @@ export class NetworkScanner {
errorPage: string, errorPage: string,
databaseResetPage: string, databaseResetPage: string,
) { ) {
this.db = new JsonDatabase<DatabaseScheme, any>(pathToDatabaseFile) this.db = new Database(pathToDatabaseFile)
this.udpPort = udpPort this.udpPort = udpPort
this.tcpPort = tcpPort this.tcpPort = tcpPort
this.okPage = okPage this.okPage = okPage
+9 -10
View File
@@ -1,18 +1,17 @@
import { JsonDatabase } from '../database/database' import { Database } from '../database/database'
import { DatabaseScheme } from '../database/schemes/database_scheme'
import { NetworkUserScheme } from '../database/schemes/network_scheme' import { NetworkUserScheme } from '../database/schemes/network_scheme'
import { TcpCommunicator } from './tcp_communicator' import { TcpCommunicator } from './tcp_communicator'
import { operationCodes } from '../network/operation_codes' import { operationCodes } from '../network/operation_codes'
import { ParsedMessage } from '../network/message_handler' import { ParsedMessage } from '../network/message_handler'
export class UsersInfoFetcher { export class UsersInfoFetcher {
private db: JsonDatabase<DatabaseScheme, any> private db: Database
private tcpCommunicator: TcpCommunicator | null = null private tcpCommunicator: TcpCommunicator | null = null
private readonly clientPort: number private readonly clientPort: number
private intervalId: NodeJS.Timeout | null = null private intervalId: NodeJS.Timeout | null = null
constructor(pathToDatabaseFile: string, clientPort: number) { constructor(pathToDatabaseFile: string, clientPort: number) {
this.db = new JsonDatabase(pathToDatabaseFile) this.db = new Database(pathToDatabaseFile)
this.clientPort = clientPort this.clientPort = clientPort
this.tcpCommunicator = null this.tcpCommunicator = null
} }
@@ -39,21 +38,21 @@ export class UsersInfoFetcher {
const response = await this.waitForResponse() const response = await this.waitForResponse()
if (response && response.metaInfo) { if (response && response.metaInfo) {
await this.db.update((dbData) => { await this.db.update((data) => {
const userIndex = dbData.network.usersInLan.findIndex((user) => user.ip === ip) const userIndex = data.network.usersInLan.findIndex((user) => user.ip === ip)
if (userIndex !== -1) { if (userIndex !== -1) {
// @ts-ignore // @ts-ignore
dbData.network.usersInLan[userIndex].id = response.metaInfo.id data.network.usersInLan[userIndex].id = response.metaInfo.id
// @ts-ignore // @ts-ignore
dbData.network.usersInLan[userIndex].name = response.metaInfo.name data.network.usersInLan[userIndex].name = response.metaInfo.name
// @ts-ignore // @ts-ignore
dbData.network.usersInLan[userIndex].departmentId = response.metaInfo.departmentId data.network.usersInLan[userIndex].departmentId = response.metaInfo.departmentId
} else { } else {
this.log(`User with IP ${ip} not found in the database.`, 'error') this.log(`User with IP ${ip} not found in the database.`, 'error')
} }
return dbData return data
}) })
} }
-8
View File
@@ -1,8 +0,0 @@
export interface FileItemTask {
ip: string
path: string
userName: string
}
export const compareFnFileItemTask = (task1: FileItemTask, task2: FileItemTask) =>
task1.ip === task2.ip && task1.path === task2.path
-15
View File
@@ -1,15 +0,0 @@
interface PoolRequest {
type: PoolOperation // Renamed to PoolOperation
clientId: string // Add clientId to the request
data: PoolDataBundle
}
interface PoolDataBundle {
port?: number
ip?: string
operationCode?: string // Keep operationCode here
metaInfo?: { [key: string]: any }
fileContent?: Buffer
}
type PoolOperation = 'open' | 'send' | 'close' // Define the allowed PoolOperations
-5
View File
@@ -1,5 +0,0 @@
interface RegisteredClient {
id: string
ip: string
port: number
}
-6
View File
@@ -1,6 +0,0 @@
// Define a type for the message structure
interface WorkerMessage {
type: 'changeContent' | 'showAlert' | 'log'
page?: string
message?: string
}
+6 -8
View File
@@ -1,17 +1,16 @@
import { JsonDatabase } from '../database/database' import { Database } from '../database/database'
import { DatabaseScheme } from '../database/schemes/database_scheme' import { DatabaseScheme } from '../database/schemes/database_scheme'
import path from 'path' import path from 'path'
import { EncryptionKeyScheme, UserInfoScheme } from '../database/schemes/app_config_scheme' import { EncryptionKeyScheme, UserInfoScheme } from '../database/schemes/app_config_scheme'
import { FileItemTask } from '../database/helpers/queue_manager' import {DirectoryInfo, DirectorySchemes, FileItemTask} from '../database/schemes/local_resources_scheme'
import { DirectoryInfo, DirectorySchemes } from '../database/schemes/local_resources_scheme'
const pathToDatabaseFile = path.join(__dirname, '..', 'database.json') const pathToDatabaseFile = path.join(__dirname, '..', 'database.json')
class IpcDatabaseHandler { class IpcDatabaseHandler {
private readonly db: JsonDatabase<DatabaseScheme, any> private readonly db: Database
constructor(pathToDatabaseFile: string) { constructor(pathToDatabaseFile: string) {
this.db = new JsonDatabase(pathToDatabaseFile) this.db = new Database(pathToDatabaseFile)
} }
async getAppType(): Promise<string> { async getAppType(): Promise<string> {
@@ -86,8 +85,7 @@ class IpcDatabaseHandler {
}) })
return true return true
} } catch (e) {
catch (e) {
return false return false
} }
} }
@@ -125,7 +123,7 @@ class IpcDatabaseHandler {
} }
async addTaskToSendFileQueue(task: FileItemTask) { async addTaskToSendFileQueue(task: FileItemTask) {
this.db.pushQueue(task) await this.db.pushToSendQueue(task)
} }
async resetInternalDatabase(): Promise<boolean> { async resetInternalDatabase(): Promise<boolean> {
+3 -4
View File
@@ -1,8 +1,7 @@
import { TcpCommunicator } from '../helpers/tcp_communicator' import { TcpCommunicator } from '../helpers/tcp_communicator'
import dotenv from 'dotenv' import dotenv from 'dotenv'
import path from 'path' import path from 'path'
import { JsonDatabase } from '../database/database' import { Database } from '../database/database'
import { DatabaseScheme } from '../database/schemes/database_scheme'
import { operationCodes } from '../network/operation_codes' import { operationCodes } from '../network/operation_codes'
dotenv.config({ path: path.join(__dirname, '..', '..', '.env') }) dotenv.config({ path: path.join(__dirname, '..', '..', '.env') })
@@ -10,12 +9,12 @@ const pathToDatabaseFile = path.join(__dirname, '..', 'database.json')
class IpcUCHandler { class IpcUCHandler {
private readonly TCP_PORT: number private readonly TCP_PORT: number
private readonly db: JsonDatabase<DatabaseScheme, any> private readonly db: Database
private tcpCommunicator: TcpCommunicator | null = null private tcpCommunicator: TcpCommunicator | null = null
constructor(pathToDatabaseFile: string) { constructor(pathToDatabaseFile: string) {
this.TCP_PORT = process.env.TCP_PORT ? parseInt(process.env.TCP_PORT) : 41234 this.TCP_PORT = process.env.TCP_PORT ? parseInt(process.env.TCP_PORT) : 41234
this.db = new JsonDatabase(pathToDatabaseFile) this.db = new Database(pathToDatabaseFile)
} }
async openUcSocket(): Promise<boolean> { async openUcSocket(): Promise<boolean> {
+3 -5
View File
@@ -2,15 +2,13 @@ import { app, BrowserWindow, ipcMain, IpcMainInvokeEvent } from 'electron'
import path from 'path' import path from 'path'
import { promises as fs } from 'fs' import { promises as fs } from 'fs'
import dotenv from 'dotenv' import dotenv from 'dotenv'
import { v4 as uuidv4 } from 'uuid'
import { WorkerManager } from '../helpers/worker_manager' import { WorkerManager } from '../helpers/worker_manager'
import { DirectoryWatcher } from '../helpers/directory_watcher' import { DirectoryWatcher } from '../helpers/directory_watcher'
import { WindowManager } from '../helpers/window_manager' import { WindowManager } from '../helpers/window_manager'
import os from 'os' import os from 'os'
import { JsonDatabase } from '../database/database' import { Database } from '../database/database'
import { DatabaseScheme } from '../database/schemes/database_scheme'
// Load environment variables // Load environment variables
dotenv.config({ path: path.join(__dirname, '..', '..', '.env') }) dotenv.config({ path: path.join(__dirname, '..', '..', '.env') })
@@ -21,7 +19,7 @@ const HOST = getLocalIp()
let mainWindow: BrowserWindow | null = null let mainWindow: BrowserWindow | null = null
let windowManager: WindowManager | null = null let windowManager: WindowManager | null = null
let db: JsonDatabase<DatabaseScheme, any> | null = null let db: Database | null = null
let workerManager: WorkerManager | null = null let workerManager: WorkerManager | null = null
let directoryWatcher: DirectoryWatcher | null = null let directoryWatcher: DirectoryWatcher | null = null
let announcementWatcher: NodeJS.Timeout | null = null let announcementWatcher: NodeJS.Timeout | null = null
@@ -129,7 +127,7 @@ app.whenReady().then(async () => {
windowManager = new WindowManager(mainWindow, pathToPagesDir) windowManager = new WindowManager(mainWindow, pathToPagesDir)
workerManager = new WorkerManager(pathToWorkerDir, windowManager) workerManager = new WorkerManager(pathToWorkerDir, windowManager)
db = new JsonDatabase<DatabaseScheme, any>(pathToDatabaseFile) db = new Database(pathToDatabaseFile)
await db.update((data) => { await db.update((data) => {
data.app_config.server_found = false data.app_config.server_found = false
+3 -3
View File
@@ -1,11 +1,10 @@
import { contextBridge, ipcRenderer } from 'electron' import { contextBridge, ipcRenderer } from 'electron'
import { FileItemTask } from '../interfaces/file_item_task'
import { ipcDatabaseHandler } from '../ipc-handlers/database_handler' import { ipcDatabaseHandler } from '../ipc-handlers/database_handler'
import { EncryptionKeyScheme, UserInfoScheme } from '../database/schemes/app_config_scheme' import { EncryptionKeyScheme, UserInfoScheme } from '../database/schemes/app_config_scheme'
import { ipcUCHandler } from '../ipc-handlers/uc_handler' import { ipcUCHandler } from '../ipc-handlers/uc_handler'
import { ParsedMessage } from '../network/message_handler' import { ParsedMessage } from '../network/message_handler'
import { NetworkUserScheme } from '../database/schemes/network_scheme' import { NetworkUserScheme } from '../database/schemes/network_scheme'
import { DirectoryInfo, DirectorySchemes } from "../database/schemes/local_resources_scheme"; import {DirectoryInfo, DirectorySchemes, FileItemTask} from '../database/schemes/local_resources_scheme'
contextBridge.exposeInMainWorld('databaseAPI', { contextBridge.exposeInMainWorld('databaseAPI', {
getAppType: (): Promise<string> => ipcDatabaseHandler.getAppType(), getAppType: (): Promise<string> => ipcDatabaseHandler.getAppType(),
@@ -19,7 +18,8 @@ contextBridge.exposeInMainWorld('databaseAPI', {
ipcDatabaseHandler.writeUserInfo(userInfo), ipcDatabaseHandler.writeUserInfo(userInfo),
writeEncryptionKey: (encryptionKey: EncryptionKeyScheme): Promise<boolean> => writeEncryptionKey: (encryptionKey: EncryptionKeyScheme): Promise<boolean> =>
ipcDatabaseHandler.writeEncryptionKey(encryptionKey), ipcDatabaseHandler.writeEncryptionKey(encryptionKey),
writeDirectoryPath: (id: string, path: string): Promise<boolean> => ipcDatabaseHandler.writeDirectoryPath(id, path), writeDirectoryPath: (id: string, path: string): Promise<boolean> =>
ipcDatabaseHandler.writeDirectoryPath(id, path),
addTaskToSendFileQueue: (task: FileItemTask): Promise<void> => addTaskToSendFileQueue: (task: FileItemTask): Promise<void> =>
ipcDatabaseHandler.addTaskToSendFileQueue(task), ipcDatabaseHandler.addTaskToSendFileQueue(task),
resetInternalDatabase: (): Promise<boolean> => ipcDatabaseHandler.resetInternalDatabase(), resetInternalDatabase: (): Promise<boolean> => ipcDatabaseHandler.resetInternalDatabase(),
@@ -4,8 +4,10 @@ import { operationCodes } from '../operation_codes'
import path from 'path' import path from 'path'
import fs from 'fs/promises' import fs from 'fs/promises'
import checkDiskSpace from 'check-disk-space' import checkDiskSpace from 'check-disk-space'
import { JsonManager } from '../../helpers/json_manager'
import { OperationPlugin } from '../operations_base/operation_plugin' import { OperationPlugin } from '../operations_base/operation_plugin'
import {Database} from "../../database/database";
const pathToDatabaseFile = path.join(__dirname, '..', '..', 'database.json')
export class UserToUserOperations implements OperationPlugin { export class UserToUserOperations implements OperationPlugin {
public static readonly operationCodes = { public static readonly operationCodes = {
@@ -46,12 +48,14 @@ export class UserToUserOperations implements OperationPlugin {
} }
} }
const jsonManager = new JsonManager( const database = new Database(pathToDatabaseFile)
path.join(__dirname, '..', '..', 'json_files', 'application.json'),
)
try { try {
await jsonManager.writeValue('announcement', parsedMessage.metaInfo.message) await database.update((data: any) => {
console.log(`Announcement saved: ${parsedMessage.metaInfo.message}`) if(!parsedMessage.metaInfo) return data;
data.app_config.announcement = parsedMessage.metaInfo.message
return data
})
return { operationCode: operationCodes.OK, metaInfo: { message: 'Announcement saved.' } } return { operationCode: operationCodes.OK, metaInfo: { message: 'Announcement saved.' } }
} catch (error: any) { } catch (error: any) {
console.error(`Error saving announcement: ${error.message}`) console.error(`Error saving announcement: ${error.message}`)
@@ -62,11 +66,10 @@ export class UserToUserOperations implements OperationPlugin {
public static async handleGetUserInformation( public static async handleGetUserInformation(
parsedMessage: ParsedMessage, parsedMessage: ParsedMessage,
): Promise<ParsedMessage> { ): Promise<ParsedMessage> {
const jsonManager = new JsonManager( const database = new Database(pathToDatabaseFile)
path.join(__dirname, '..', '..', 'json_files', 'userConfig.json'),
)
try { try {
const userInfo = await jsonManager.readValue('user_info') const data = await database.read()
const userInfo = data.app_config.user_info
return { operationCode: operationCodes.OK, metaInfo: userInfo } return { operationCode: operationCodes.OK, metaInfo: userInfo }
} catch (error: any) { } catch (error: any) {
console.error(`Error fetching user info: ${error.message}`) console.error(`Error fetching user info: ${error.message}`)
@@ -154,18 +157,16 @@ export class UserToUserOperations implements OperationPlugin {
return { operationCode: operationCodes.ERR, metaInfo: { message: 'Missing share info.' } } return { operationCode: operationCodes.ERR, metaInfo: { message: 'Missing share info.' } }
} }
const jsonManager = new JsonManager( const database = new Database(pathToDatabaseFile)
path.join(__dirname, '..', '..', 'json_files', 'application.json'),
)
const { userName, relativeFilePath } = parsedMessage.metaInfo const { userName, relativeFilePath } = parsedMessage.metaInfo
try { try {
const appInfo = await jsonManager.readValue('shareDirectory') const data = await database.read()
const shareDirectory = appInfo?.path || '' const shareDirectory = data.local_resources.directory_schemes.shared.path
console.log(`\n\nShare directory: ${shareDirectory}\n\n`) console.log(`\n\nShare directory: ${shareDirectory}\n\n`)
if (!shareDirectory) { if (!shareDirectory || shareDirectory === '') {
return { return {
operationCode: operationCodes.ERR, operationCode: operationCodes.ERR,
metaInfo: { message: 'Share directory missing.' }, metaInfo: { message: 'Share directory missing.' },
@@ -175,6 +176,11 @@ export class UserToUserOperations implements OperationPlugin {
const fullFilePath = path.join(shareDirectory, userName, relativeFilePath) const fullFilePath = path.join(shareDirectory, userName, relativeFilePath)
await fs.mkdir(path.dirname(fullFilePath), { recursive: true }) await fs.mkdir(path.dirname(fullFilePath), { recursive: true })
await fs.writeFile(fullFilePath, parsedMessage.fileContent as Buffer) await fs.writeFile(fullFilePath, parsedMessage.fileContent as Buffer)
await database.pushToReceiveQueue({
ip: '',
path: fullFilePath,
userName,
})
console.log(`File shared: ${fullFilePath}`) console.log(`File shared: ${fullFilePath}`)
return { return {
@@ -195,14 +201,12 @@ export class UserToUserOperations implements OperationPlugin {
return { operationCode: operationCodes.ERR, metaInfo: { message: 'Missing user name.' } } return { operationCode: operationCodes.ERR, metaInfo: { message: 'Missing user name.' } }
} }
const jsonManager = new JsonManager( const database = new Database(pathToDatabaseFile)
path.join(__dirname, '..', '..', 'json_files', 'application.json'),
)
const { userName } = parsedMessage.metaInfo const { userName } = parsedMessage.metaInfo
try { try {
const appInfo = await jsonManager.readValue('departmentDirectory') const data = await database.read()
const departmentDir = appInfo?.path || '' const departmentDir = data.local_resources.directory_schemes.department.path
const userDepartmentDir = path.join(departmentDir, '..', 'DEPARTMENT_SHARE', userName) const userDepartmentDir = path.join(departmentDir, '..', 'DEPARTMENT_SHARE', userName)
try { try {
@@ -245,19 +249,9 @@ export class UserToUserOperations implements OperationPlugin {
} }
// Path to the application.json to read the shareDirectory field // Path to the application.json to read the shareDirectory field
const pathToApplicationJson = path.join(__dirname, '..', '..', 'json_files', 'application.json') const database = new Database(pathToDatabaseFile)
const jsonManager = new JsonManager(pathToApplicationJson) const data = await database.read()
let appInfo = data.local_resources.directory_schemes.department
// Read application configuration asynchronously
let appInfo
try {
appInfo = await jsonManager.readValue('departmentDirectory')
} catch (error: any) {
return {
operationCode: operationCodes.ERR,
metaInfo: { message: `Error reading application config: ${error.message}` },
}
}
if (!appInfo || !appInfo.path) { if (!appInfo || !appInfo.path) {
return { return {