157 lines
4.1 KiB
TypeScript
157 lines
4.1 KiB
TypeScript
import { FileBackupsDevice, FileBackupsMapping } from '@web/Application/Device/DesktopSnjsExports'
|
|
import { AppState } from 'app/application'
|
|
import { StoreKeys } from '../Store'
|
|
import {
|
|
ensureDirectoryExists,
|
|
moveDirContents,
|
|
openDirectoryPicker,
|
|
readJSONFile,
|
|
writeFile,
|
|
writeJSONFile,
|
|
} from '../Utils/FileUtils'
|
|
import { FileDownloader } from './FileDownloader'
|
|
import { shell } from 'electron'
|
|
|
|
export const FileBackupsConstantsV1 = {
|
|
Version: '1.0.0',
|
|
MetadataFileName: 'metadata.sn.json',
|
|
BinaryFileName: 'file.encrypted',
|
|
}
|
|
|
|
export class FilesBackupManager implements FileBackupsDevice {
|
|
constructor(private appState: AppState) {}
|
|
|
|
public isFilesBackupsEnabled(): Promise<boolean> {
|
|
return Promise.resolve(this.appState.store.get(StoreKeys.FileBackupsEnabled))
|
|
}
|
|
|
|
public async enableFilesBackups(): Promise<void> {
|
|
const currentLocation = await this.getFilesBackupsLocation()
|
|
|
|
if (!currentLocation) {
|
|
const result = await this.changeFilesBackupsLocation()
|
|
|
|
if (!result) {
|
|
return
|
|
}
|
|
}
|
|
|
|
this.appState.store.set(StoreKeys.FileBackupsEnabled, true)
|
|
|
|
const mapping = this.getMappingFileFromDisk()
|
|
|
|
if (!mapping) {
|
|
await this.saveFilesBackupsMappingFile(this.defaultMappingFileValue())
|
|
}
|
|
}
|
|
|
|
public disableFilesBackups(): Promise<void> {
|
|
this.appState.store.set(StoreKeys.FileBackupsEnabled, false)
|
|
|
|
return Promise.resolve()
|
|
}
|
|
|
|
public async changeFilesBackupsLocation(): Promise<string | undefined> {
|
|
const newPath = await openDirectoryPicker()
|
|
|
|
if (!newPath) {
|
|
return undefined
|
|
}
|
|
|
|
const oldPath = await this.getFilesBackupsLocation()
|
|
|
|
if (oldPath) {
|
|
await moveDirContents(oldPath, newPath)
|
|
}
|
|
|
|
this.appState.store.set(StoreKeys.FileBackupsLocation, newPath)
|
|
|
|
return newPath
|
|
}
|
|
|
|
public getFilesBackupsLocation(): Promise<string> {
|
|
return Promise.resolve(this.appState.store.get(StoreKeys.FileBackupsLocation))
|
|
}
|
|
|
|
private getMappingFileLocation(): string {
|
|
const base = this.appState.store.get(StoreKeys.FileBackupsLocation)
|
|
return `${base}/info.json`
|
|
}
|
|
|
|
private async getMappingFileFromDisk(): Promise<FileBackupsMapping | undefined> {
|
|
return readJSONFile<FileBackupsMapping>(this.getMappingFileLocation())
|
|
}
|
|
|
|
private defaultMappingFileValue(): FileBackupsMapping {
|
|
return { version: FileBackupsConstantsV1.Version, files: {} }
|
|
}
|
|
|
|
async getFilesBackupsMappingFile(): Promise<FileBackupsMapping> {
|
|
const data = await this.getMappingFileFromDisk()
|
|
|
|
if (!data) {
|
|
return this.defaultMappingFileValue()
|
|
}
|
|
|
|
return data
|
|
}
|
|
|
|
async openFilesBackupsLocation(): Promise<void> {
|
|
const location = await this.getFilesBackupsLocation()
|
|
|
|
void shell.openPath(location)
|
|
}
|
|
|
|
async saveFilesBackupsMappingFile(file: FileBackupsMapping): Promise<'success' | 'failed'> {
|
|
await writeJSONFile(this.getMappingFileLocation(), file)
|
|
|
|
return 'success'
|
|
}
|
|
|
|
async saveFilesBackupsFile(
|
|
uuid: string,
|
|
metaFile: string,
|
|
downloadRequest: {
|
|
chunkSizes: number[]
|
|
valetToken: string
|
|
url: string
|
|
},
|
|
): Promise<'success' | 'failed'> {
|
|
const backupsDir = await this.getFilesBackupsLocation()
|
|
|
|
const fileDir = `${backupsDir}/${uuid}`
|
|
const metaFilePath = `${fileDir}/${FileBackupsConstantsV1.MetadataFileName}`
|
|
const binaryPath = `${fileDir}/${FileBackupsConstantsV1.BinaryFileName}`
|
|
|
|
await ensureDirectoryExists(fileDir)
|
|
|
|
await writeFile(metaFilePath, metaFile)
|
|
|
|
const downloader = new FileDownloader(
|
|
downloadRequest.chunkSizes,
|
|
downloadRequest.valetToken,
|
|
downloadRequest.url,
|
|
binaryPath,
|
|
)
|
|
|
|
const result = await downloader.run()
|
|
|
|
if (result === 'success') {
|
|
const mapping = await this.getFilesBackupsMappingFile()
|
|
|
|
mapping.files[uuid] = {
|
|
backedUpOn: new Date(),
|
|
absolutePath: fileDir,
|
|
relativePath: uuid,
|
|
metadataFileName: FileBackupsConstantsV1.MetadataFileName,
|
|
binaryFileName: FileBackupsConstantsV1.BinaryFileName,
|
|
version: FileBackupsConstantsV1.Version,
|
|
}
|
|
|
|
await this.saveFilesBackupsMappingFile(mapping)
|
|
}
|
|
|
|
return result
|
|
}
|
|
}
|