backup added
This commit is contained in:
@@ -65,7 +65,7 @@ async function restoreBackup() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Call the IPC method to initiate the backup retrieval process
|
// Call the IPC method to initiate the backup retrieval process
|
||||||
window.electronAPI.startBackupRetrieval(destinationPath);
|
window.uiAPI.startBackupRetrieval(destinationPath);
|
||||||
|
|
||||||
// Switch the content to the 'backup_retrieve' page
|
// Switch the content to the 'backup_retrieve' page
|
||||||
fadeOut('backup_retrieve');
|
fadeOut('backup_retrieve');
|
||||||
@@ -133,6 +133,8 @@ async function loadReceivedFiles() {
|
|||||||
// Read the shareDirectory from applicationInfo
|
// Read the shareDirectory from applicationInfo
|
||||||
const shareDirData = await window.databaseAPI.getDirectoryInfo(shareDirId);
|
const shareDirData = await window.databaseAPI.getDirectoryInfo(shareDirId);
|
||||||
|
|
||||||
|
console.log('Loading received files:', shareDirData);
|
||||||
|
|
||||||
const notificationsDiv = document.getElementById('notifications');
|
const notificationsDiv = document.getElementById('notifications');
|
||||||
const existingButtons = Array.from(notificationsDiv.children).map(button => button.getAttribute('data-filepath'));
|
const existingButtons = Array.from(notificationsDiv.children).map(button => button.getAttribute('data-filepath'));
|
||||||
|
|
||||||
|
|||||||
@@ -33,9 +33,10 @@ export class BackupRetrievalWorker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async start(): Promise<void> {
|
async start(): Promise<void> {
|
||||||
if (!this.stopRequested) return
|
if (this.stopRequested) return
|
||||||
this.isBusy = true
|
this.isBusy = true
|
||||||
try {
|
try {
|
||||||
|
this.log('Start successfully. Retrieving backup.')
|
||||||
const data = await this.db.read()
|
const data = await this.db.read()
|
||||||
const userInfo = data.app_config.user_info
|
const userInfo = data.app_config.user_info
|
||||||
const encryptionKey = data.app_config.encryption_key
|
const encryptionKey = data.app_config.encryption_key
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ 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 { Database } from '../database/database'
|
import { Database } from '../database/database'
|
||||||
|
import {NetworkUserScheme} from "../database/schemes/network_scheme";
|
||||||
|
|
||||||
export class DepartmentSharer {
|
export class DepartmentSharer {
|
||||||
private readonly db: Database
|
private readonly db: Database
|
||||||
@@ -46,9 +47,13 @@ export class DepartmentSharer {
|
|||||||
const activeUsers = data.network.usersInLan
|
const activeUsers = data.network.usersInLan
|
||||||
this.departmentDirectory = departmentStructure.path
|
this.departmentDirectory = departmentStructure.path
|
||||||
|
|
||||||
|
if(departmentStructure.path === ''){
|
||||||
|
throw new Error('Department directory not set.')
|
||||||
|
}
|
||||||
|
|
||||||
// Filter users who belong to the same department
|
// Filter users who belong to the same department
|
||||||
const departmentUsers = activeUsers.filter(
|
const departmentUsers = activeUsers.filter(
|
||||||
(user: any) => user.user_info.departmentId === departmentId,
|
(user: NetworkUserScheme) => user.departmentId === departmentId,
|
||||||
)
|
)
|
||||||
if (departmentUsers.length === 0) {
|
if (departmentUsers.length === 0) {
|
||||||
throw new Error('No users found in the same department.')
|
throw new Error('No users found in the same department.')
|
||||||
@@ -101,8 +106,6 @@ export class DepartmentSharer {
|
|||||||
if (!this.tcpCommunicator) return
|
if (!this.tcpCommunicator) return
|
||||||
const unsentFiles = Object.keys(files)
|
const unsentFiles = Object.keys(files)
|
||||||
|
|
||||||
console.log(`\n\n${unsentFiles}\n\n`)
|
|
||||||
|
|
||||||
for (const fileName of unsentFiles) {
|
for (const fileName of unsentFiles) {
|
||||||
const filePath = files[fileName]
|
const filePath = files[fileName]
|
||||||
|
|
||||||
@@ -135,8 +138,6 @@ export class DepartmentSharer {
|
|||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
||||||
console.log(`\n\nSending file: ${fileName} to ${userName}\n\n`)
|
|
||||||
|
|
||||||
const response = await this.waitForResponse()
|
const response = await this.waitForResponse()
|
||||||
if (!response || response.operationCode !== operationCodes.OK) {
|
if (!response || response.operationCode !== operationCodes.OK) {
|
||||||
this.log(`Failed to send file: ${fileName}`, 'error')
|
this.log(`Failed to send file: ${fileName}`, 'error')
|
||||||
@@ -162,8 +163,6 @@ export class DepartmentSharer {
|
|||||||
while (this.isBusy) {
|
while (this.isBusy) {
|
||||||
await new Promise((resolve) => setTimeout(resolve, 100))
|
await new Promise((resolve) => setTimeout(resolve, 100))
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('[BackupManager] Stopped successfully.')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async waitForResponse(): Promise<ParsedMessage | null> {
|
private async waitForResponse(): Promise<ParsedMessage | null> {
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ export class FileSharer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.log('Queue processed successfully.')
|
||||||
this.isBusy = false // Reset busy flag after the queue is processed
|
this.isBusy = false // Reset busy flag after the queue is processed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,119 +0,0 @@
|
|||||||
import fs from 'fs'
|
|
||||||
import path from 'path'
|
|
||||||
|
|
||||||
export class JsonManager {
|
|
||||||
private readonly filePath: string
|
|
||||||
private readonly lockFilePath: string
|
|
||||||
|
|
||||||
constructor(filePath: string) {
|
|
||||||
const dir = path.dirname(filePath)
|
|
||||||
|
|
||||||
// Check if the directory exists, throw error if it doesn't
|
|
||||||
if (!fs.existsSync(dir)) {
|
|
||||||
throw new Error(`The directory does not exist: ${dir}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.filePath = filePath
|
|
||||||
this.lockFilePath = `${filePath}.lock` // Define the lock file path
|
|
||||||
|
|
||||||
// If the file doesn't exist, create it
|
|
||||||
if (!fs.existsSync(filePath)) {
|
|
||||||
fs.writeFileSync(filePath, JSON.stringify({}, null, 2), 'utf8')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method to acquire a lock (create .lock file)
|
|
||||||
private async acquireLock(): Promise<void> {
|
|
||||||
while (fs.existsSync(this.lockFilePath)) {
|
|
||||||
// Wait until the lock file is released
|
|
||||||
await new Promise((resolve) => setTimeout(resolve, 100)) // 100ms delay before retrying
|
|
||||||
}
|
|
||||||
// Create the lock file
|
|
||||||
fs.writeFileSync(this.lockFilePath, '')
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method to release the lock (delete .lock file)
|
|
||||||
private releaseLock(): void {
|
|
||||||
if (fs.existsSync(this.lockFilePath)) {
|
|
||||||
fs.unlinkSync(this.lockFilePath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read a value by key from the JSON file with a lock
|
|
||||||
public async readValue(key: string): Promise<any | null> {
|
|
||||||
await this.acquireLock() // Acquire the lock
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!fs.existsSync(this.filePath)) return null
|
|
||||||
|
|
||||||
const data = JSON.parse(fs.readFileSync(this.filePath, 'utf8'))
|
|
||||||
return data[key] !== undefined ? data[key] : null
|
|
||||||
} catch (err: any) {
|
|
||||||
console.error(`Error reading from JSON file: ${err.message}`)
|
|
||||||
return null
|
|
||||||
} finally {
|
|
||||||
this.releaseLock() // Always release the lock after the operation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write a key-value pair to the JSON file with a lock
|
|
||||||
public async writeValue(key: string, value: any): Promise<boolean> {
|
|
||||||
await this.acquireLock() // Acquire the lock
|
|
||||||
|
|
||||||
try {
|
|
||||||
let data: { [key: string]: any } = {}
|
|
||||||
|
|
||||||
if (fs.existsSync(this.filePath)) {
|
|
||||||
data = JSON.parse(fs.readFileSync(this.filePath, 'utf8'))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update the key with the new value
|
|
||||||
data[key] = value
|
|
||||||
|
|
||||||
fs.writeFileSync(this.filePath, JSON.stringify(data, null, 2), 'utf8')
|
|
||||||
return true
|
|
||||||
} catch (err: any) {
|
|
||||||
console.error(`Error writing to JSON file: ${err.message}`)
|
|
||||||
return false
|
|
||||||
} finally {
|
|
||||||
this.releaseLock() // Always release the lock after the operation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove a key-value pair from the JSON file with a lock
|
|
||||||
public async removeValue(key: string): Promise<boolean> {
|
|
||||||
await this.acquireLock() // Acquire the lock
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (!fs.existsSync(this.filePath)) return false
|
|
||||||
|
|
||||||
const data = JSON.parse(fs.readFileSync(this.filePath, 'utf8'))
|
|
||||||
if (data[key] !== undefined) {
|
|
||||||
delete data[key]
|
|
||||||
fs.writeFileSync(this.filePath, JSON.stringify(data, null, 2), 'utf8')
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
} catch (err: any) {
|
|
||||||
console.error(`Error removing key from JSON file: ${err.message}`)
|
|
||||||
return false
|
|
||||||
} finally {
|
|
||||||
this.releaseLock() // Always release the lock after the operation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset the JSON file by clearing all data with a lock
|
|
||||||
public async resetFile(): Promise<boolean> {
|
|
||||||
await this.acquireLock() // Acquire the lock
|
|
||||||
|
|
||||||
try {
|
|
||||||
fs.writeFileSync(this.filePath, JSON.stringify({}, null, 2), 'utf8')
|
|
||||||
return true
|
|
||||||
} catch (err: any) {
|
|
||||||
console.error(`Error resetting JSON file: ${err.message}`)
|
|
||||||
return false
|
|
||||||
} finally {
|
|
||||||
this.releaseLock() // Always release the lock after the operation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -59,7 +59,6 @@ export class NetworkScanner {
|
|||||||
this.log('UC Check running...', 'log', 'startUCCheck')
|
this.log('UC Check running...', 'log', 'startUCCheck')
|
||||||
const udpClient = new UdpClient(this.udpPort)
|
const udpClient = new UdpClient(this.udpPort)
|
||||||
const aliveClients = await udpClient.getTargetClients(operationCodes.ARE_YOU_UC)
|
const aliveClients = await udpClient.getTargetClients(operationCodes.ARE_YOU_UC)
|
||||||
console.log(aliveClients)
|
|
||||||
const data = await this.db.read()
|
const data = await this.db.read()
|
||||||
const foundClient = aliveClients.length > 0
|
const foundClient = aliveClients.length > 0
|
||||||
const serverFound = data.app_config.server_found
|
const serverFound = data.app_config.server_found
|
||||||
@@ -108,7 +107,6 @@ export class NetworkScanner {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
this.log('IP Lookup running...', 'log', 'startUserIPLookup')
|
this.log('IP Lookup running...', 'log', 'startUserIPLookup')
|
||||||
const data = await this.db.read()
|
|
||||||
const udpClient = new UdpClient(this.udpPort)
|
const udpClient = new UdpClient(this.udpPort)
|
||||||
const activeClients = await udpClient.getTargetClients(operationCodes.ARE_YOU_HUMAN)
|
const activeClients = await udpClient.getTargetClients(operationCodes.ARE_YOU_HUMAN)
|
||||||
|
|
||||||
|
|||||||
@@ -51,10 +51,6 @@ contextBridge.exposeInMainWorld('uiAPI', {
|
|||||||
ipcRenderer.invoke('show-file-in-explorer', path),
|
ipcRenderer.invoke('show-file-in-explorer', path),
|
||||||
readAnnouncement: (): Promise<string> => ipcRenderer.invoke('read-announcement'),
|
readAnnouncement: (): Promise<string> => ipcRenderer.invoke('read-announcement'),
|
||||||
closeAnnouncementWindow: (): Promise<void> => ipcRenderer.invoke('close-announcement-window'),
|
closeAnnouncementWindow: (): Promise<void> => ipcRenderer.invoke('close-announcement-window'),
|
||||||
})
|
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld('electronAPI', {
|
|
||||||
// Workers
|
|
||||||
startBackupRetrieval: (destinationPath: string): Promise<void> =>
|
startBackupRetrieval: (destinationPath: string): Promise<void> =>
|
||||||
ipcRenderer.invoke('start-backup-retrieval', destinationPath),
|
ipcRenderer.invoke('start-backup-retrieval', destinationPath),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -158,12 +158,6 @@ 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}`)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
operationCode: operationCodes.OK,
|
operationCode: operationCodes.OK,
|
||||||
|
|||||||
@@ -35,11 +35,9 @@ export class UdpClient {
|
|||||||
|
|
||||||
// Get local machine's IP addresses to exclude
|
// Get local machine's IP addresses to exclude
|
||||||
const localIPs = this.getLocalIPs()
|
const localIPs = this.getLocalIPs()
|
||||||
this.log(`Local IPs to exclude from scan: ${localIPs.join(', ')}`)
|
|
||||||
|
|
||||||
// First, filter active IPs that respond to ping
|
// First, filter active IPs that respond to ping
|
||||||
const activeIps = await this.filterActiveIps(ipRange)
|
const activeIps = await this.filterActiveIps(ipRange)
|
||||||
this.log(`Active IPs in subnet ${subnet}: ${activeIps.join(', ')}`)
|
|
||||||
|
|
||||||
// Send heartbeat to each active IP and keep only those that respond with ALIVE
|
// Send heartbeat to each active IP and keep only those that respond with ALIVE
|
||||||
const aliveClients: any[] = []
|
const aliveClients: any[] = []
|
||||||
@@ -80,10 +78,8 @@ export class UdpClient {
|
|||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
const heartbeatMessage = MessageHandler.formatMessage(heartbeatCode)
|
const heartbeatMessage = MessageHandler.formatMessage(heartbeatCode)
|
||||||
|
|
||||||
this.log(`Sending heartbeat to ${ip}`)
|
|
||||||
this.udpSocket.send(heartbeatMessage, this.port, ip, (err) => {
|
this.udpSocket.send(heartbeatMessage, this.port, ip, (err) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
this.log(`Failed to send heartbeat to ${ip}: ${err.message}`, 'error')
|
|
||||||
resolve({ found: false })
|
resolve({ found: false })
|
||||||
} else {
|
} else {
|
||||||
const timeout = setTimeout(() => {
|
const timeout = setTimeout(() => {
|
||||||
@@ -96,10 +92,8 @@ export class UdpClient {
|
|||||||
clearTimeout(timeout)
|
clearTimeout(timeout)
|
||||||
const parsedMessage = MessageHandler.parseMessage(msg.toString())
|
const parsedMessage = MessageHandler.parseMessage(msg.toString())
|
||||||
if (parsedMessage?.operationCode === operationCodes.ALIVE) {
|
if (parsedMessage?.operationCode === operationCodes.ALIVE) {
|
||||||
this.log(`Received ALIVE response from ${ip}`)
|
|
||||||
resolve({ found: true, data: parsedMessage.metaInfo })
|
resolve({ found: true, data: parsedMessage.metaInfo })
|
||||||
} else {
|
} else {
|
||||||
this.log(`Unexpected response from ${ip}`)
|
|
||||||
resolve({ found: false })
|
resolve({ found: false })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,9 +107,7 @@ export class UdpClient {
|
|||||||
private dropConnection(ip: string): void {
|
private dropConnection(ip: string): void {
|
||||||
try {
|
try {
|
||||||
this.udpSocket.removeAllListeners('message')
|
this.udpSocket.removeAllListeners('message')
|
||||||
this.log(`Dropped connection listeners for ${ip}`)
|
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
this.log(`Error dropping connection to ${ip}: ${err.message}`, 'error')
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,9 +117,7 @@ export class UdpClient {
|
|||||||
for (const iface of Object.values(interfaces)) {
|
for (const iface of Object.values(interfaces)) {
|
||||||
for (const address of iface || []) {
|
for (const address of iface || []) {
|
||||||
if (address.family === 'IPv4' && !address.internal) {
|
if (address.family === 'IPv4' && !address.internal) {
|
||||||
const subnet = address.address.split('.').slice(0, 3).join('.')
|
return address.address.split('.').slice(0, 3).join('.')
|
||||||
this.log(`Detected subnet: ${subnet}`)
|
|
||||||
return subnet
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -140,7 +130,6 @@ export class UdpClient {
|
|||||||
for (let i = 1; i < 255; i++) {
|
for (let i = 1; i < 255; i++) {
|
||||||
ipRange.push(`${subnet}.${i}`)
|
ipRange.push(`${subnet}.${i}`)
|
||||||
}
|
}
|
||||||
this.log(`Generated IP range for subnet ${subnet}`)
|
|
||||||
return ipRange
|
return ipRange
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +147,6 @@ export class UdpClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.log(`Active IPs after pinging: ${activeIps.join(', ')}`)
|
|
||||||
return activeIps
|
return activeIps
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user