mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-23 06:59:31 +01:00
feat: add versioned backup export
This commit is contained in:
@@ -1,4 +1,3 @@
|
|||||||
import { sendCheckUserStatusEvent } from "../common.js";
|
|
||||||
import Hashes from "jshashes";
|
import Hashes from "jshashes";
|
||||||
const md5 = new Hashes.MD5();
|
const md5 = new Hashes.MD5();
|
||||||
|
|
||||||
@@ -26,34 +25,29 @@ export default class Backup {
|
|||||||
if (encrypt && !(await sendCheckUserStatusEvent("backup:encrypt"))) return;
|
if (encrypt && !(await sendCheckUserStatusEvent("backup:encrypt"))) return;
|
||||||
|
|
||||||
if (!validTypes.some((t) => t === type))
|
if (!validTypes.some((t) => t === type))
|
||||||
throw new Error(
|
throw new Error("Invalid type. It must be one of 'mobile' or 'web'.");
|
||||||
"Invalid type. It must be one of 'mobile' or 'web' or 'node'."
|
|
||||||
);
|
|
||||||
|
|
||||||
const keys = (await this._db.context.getAllKeys()).filter(
|
const keys = (await this._db.context.getAllKeys()).filter(
|
||||||
(key) => !invalidKeys.some((t) => t === key)
|
(key) => !invalidKeys.some((t) => t === key)
|
||||||
);
|
);
|
||||||
|
|
||||||
const db = Object.fromEntries(await this._db.context.readMulti(keys));
|
let data = Object.fromEntries(await this._db.context.readMulti(keys));
|
||||||
db.h = md5.hex(JSON.stringify(db));
|
|
||||||
db.ht = "md5";
|
|
||||||
|
|
||||||
if (encrypt) {
|
if (encrypt) {
|
||||||
const key = await this._db.user.key();
|
const key = await this._db.user.key();
|
||||||
return JSON.stringify({
|
data = await this._db.context.encrypt(key, JSON.stringify(data));
|
||||||
type,
|
|
||||||
date: Date.now(),
|
|
||||||
data: await this._db.context.encrypt(key, JSON.stringify(db)),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// save backup time
|
// save backup time
|
||||||
await this._db.context.write("lastBackupTime", Date.now());
|
await this._db.context.write("lastBackupTime", Date.now());
|
||||||
|
|
||||||
return JSON.stringify({
|
return JSON.stringify({
|
||||||
|
version: 2,
|
||||||
type,
|
type,
|
||||||
date: Date.now(),
|
date: Date.now(),
|
||||||
data: db,
|
data,
|
||||||
|
hash: md5.hex(JSON.stringify(data)),
|
||||||
|
hash_type: "md5",
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,16 +69,26 @@ export default class Backup {
|
|||||||
db = JSON.parse(await this._db.context.decrypt(key, db));
|
db = JSON.parse(await this._db.context.decrypt(key, db));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this._verify(db))
|
if (!this._verify(backup))
|
||||||
throw new Error("Backup file has been tempered, aborting...");
|
throw new Error("Backup file has been tempered, aborting...");
|
||||||
|
// TODO add a proper restoration system.
|
||||||
|
// for (let key in db) {
|
||||||
|
// let value = db[key];
|
||||||
|
// if (value && value.dateEdited) {
|
||||||
|
// value.dateEdited = Date.now();
|
||||||
|
// }
|
||||||
|
|
||||||
for (let key in db) {
|
// const oldValue = await this._db.context.read(oldValue);
|
||||||
let value = db[key];
|
|
||||||
if (value && value.dateEdited) {
|
// let finalValue = oldValue || value;
|
||||||
value.dateEdited = Date.now();
|
// if (typeof value === "object") {
|
||||||
}
|
// finalValue = Array.isArray(value)
|
||||||
await this._db.context.write(key, value);
|
// ? [...value, ...oldValue]
|
||||||
}
|
// : { ...value, ...oldValue };
|
||||||
|
// }
|
||||||
|
|
||||||
|
// await this._db.context.write(key, finalValue);
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
_validate(backup) {
|
_validate(backup) {
|
||||||
@@ -96,14 +100,11 @@ export default class Backup {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_verify(db) {
|
_verify(backup) {
|
||||||
const hash = db.h;
|
const { hash, hash_type, data: db } = backup;
|
||||||
const hash_type = db.ht;
|
|
||||||
delete db.h;
|
|
||||||
delete db.ht;
|
|
||||||
switch (hash_type) {
|
switch (hash_type) {
|
||||||
case "md5": {
|
case "md5": {
|
||||||
return hash == md5.hex(JSON.stringify(db));
|
return hash === md5.hex(JSON.stringify(db));
|
||||||
}
|
}
|
||||||
default: {
|
default: {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
Reference in New Issue
Block a user