Add import/exportUserDataBackup

This commit is contained in:
Sosthene 2025-07-16 17:20:40 +02:00
parent 39d57d4749
commit 848777d751

View File

@ -6,7 +6,7 @@ import ModalService from './modal.service';
import Database from './database.service';
import { navigate } from '../router';
import { storeData, retrieveData, testData } from './storage.service';
import { BackUp } from '~/models/backup.model';
import { UserDataBackUp } from '~/models/backup.model';
import { PDFDocument, rgb, StandardFonts } from 'pdf-lib';
export const U32_MAX = 4294967295;
@ -1210,48 +1210,68 @@ export default class Services {
this.notifications = notifications;
}
async importJSON(backup: BackUp): Promise<void> {
const device = JSON.stringify(backup.device);
public async importUserDataBackup(backup: UserDataBackUp): Promise<void> {
try {
if (typeof backup.user_data.device === 'string') {
throw new Error('Must decrypt backup first');
}
// Reset current device
await this.resetDevice();
// Reset current device
await this.resetDevice();
await this.saveDeviceInDatabase(backup.user_data.device);
await this.saveDeviceInDatabase(device);
this.restoreDevice(backup.user_data.device);
this.restoreDevice(device);
const secretsStore = backup.user_data.secrets as SecretsStore;
await this.restoreSecretsFromBackUp(secretsStore);
// TODO restore secrets and processes from file
const secretsStore = backup.secrets;
await this.restoreSecretsFromBackUp(secretsStore);
const processes = backup.processes;
await this.restoreProcessesFromBackUp(processes);
const processes = backup.user_data.processes as Record<string, Process>;
await this.restoreProcessesFromBackUp(processes);
} catch (e) {
// TODO reset everything
throw new Error(`Failed to import user data backup: ${e}`);
}
}
public async createBackUp(): Promise<BackUp | null> {
// Get the device from indexedDB
const deviceStr = await this.getDeviceFromDatabase();
if (!deviceStr) {
console.error('No device loaded');
return null;
public async exportUserDataBackup(password: string | undefined | null): Promise<UserDataBackUp> {
try {
const userData = {
device: this.dumpDeviceFromMemory(),
secrets: await this.getAllSecrets(),
processes: await this.getProcesses(),
};
// Now hash the content of user data to produce a checksum
const textAsBuffer = new TextEncoder().encode(JSON.stringify(userData));
const hashBuffer = await window.crypto.subtle.digest("SHA-256", textAsBuffer);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hash = hashArray
.map((item) => item.toString(16).padStart(2, "0"))
.join("");
if (password) {
// We'll let the sdk handle the pbkdf and encryption
// this.sdkClient.encrypt_backup_data(password, JSON.stringify(userData));
// metadata.encrypted = true;
// userData
// textAsBuffer = enc.encode(cipher);
throw new Error('Encryption not implemented yet');
}
const metadata = {
encrypted: false,
checksum: hash,
}
return {
version: 1,
exported_at: new Date(),
user_data: userData,
metadata,
}
} catch (e) {
throw new Error(`Failed to export user data backup: ${e}`);
}
const device: Device = JSON.parse(deviceStr);
// Get the processes
const processes = await this.getProcesses();
// Get the shared secrets
const secrets = await this.getAllSecrets();
// Create a backup object
const backUp = {
device: device,
secrets: secrets,
processes: processes,
};
return backUp;
}
// Device 1 wait Device 2
@ -1490,6 +1510,11 @@ export default class Services {
const membersList = this.getAllMembers();
try {
const res = this.sdkClient.request_data(processId, stateIds, roles, membersList);
// If ciphers_to_send is empty, it means that there's nobody to ask the data to
if (res.ciphers_to_send.length === 0) {
console.warn('Data unavailable from peers');
return;
}
await this.handleApiReturn(res);
} catch (e) {
console.error(e);