core: minor updates and fixes

This commit is contained in:
Abdullah Atta
2023-09-14 18:54:15 +05:00
parent 5b537ab470
commit c7a6cd8964
4 changed files with 28 additions and 20 deletions

View File

@@ -24,7 +24,7 @@ import v56BackupCopy from "./__fixtures__/backup.v5.6.json";
import v58BackupCopy from "./__fixtures__/backup.v5.8.json"; import v58BackupCopy from "./__fixtures__/backup.v5.8.json";
import qclone from "qclone"; import qclone from "qclone";
import { test, expect, describe } from "vitest"; import { test, expect, describe } from "vitest";
import { makeId } from "../src/utils/id"; import { getId, makeId } from "../src/utils/id";
test("export backup", () => test("export backup", () =>
notebookTest().then(async ({ db }) => { notebookTest().then(async ({ db }) => {
@@ -79,7 +79,7 @@ test("import backup", () =>
exp.push(file); exp.push(file);
} }
await db.storage.clear(); await db.storage().clear();
await db.backup.import(JSON.parse(exp[1].data)); await db.backup.import(JSON.parse(exp[1].data));
expect(db.notebooks.notebook(id).data.id).toBe(id); expect(db.notebooks.notebook(id).data.id).toBe(id);
})); }));
@@ -94,7 +94,7 @@ test("import encrypted backup", () =>
exp.push(file); exp.push(file);
} }
await db.storage.clear(); await db.storage().clear();
await db.backup.import(JSON.parse(exp[1].data), "password"); await db.backup.import(JSON.parse(exp[1].data), "password");
expect(db.notebooks.notebook(id).data.id).toBe(id); expect(db.notebooks.notebook(id).data.id).toBe(id);
})); }));
@@ -108,7 +108,7 @@ test("import tempered backup", () =>
exp.push(file); exp.push(file);
} }
await db.storage.clear(); await db.storage().clear();
const backup = JSON.parse(exp[1].data); const backup = JSON.parse(exp[1].data);
backup.data += "hello"; backup.data += "hello";
await expect(db.backup.import(backup)).rejects.toThrow(/tempered/); await expect(db.backup.import(backup)).rejects.toThrow(/tempered/);
@@ -198,7 +198,7 @@ describe.each([
return databaseTest().then(async (db) => { return databaseTest().then(async (db) => {
await db.backup.import(qclone(data)); await db.backup.import(qclone(data));
const keys = await db.storage.getAllKeys(); const keys = await db.storage().getAllKeys();
for (let key in data.data) { for (let key in data.data) {
const item = data.data[key]; const item = data.data[key];
if (item && !item.type && item.deleted) continue; if (item && !item.type && item.deleted) continue;
@@ -209,7 +209,6 @@ describe.each([
key === "token" key === "token"
) )
continue; continue;
expect(keys.some((k) => k.startsWith(key))).toBeTruthy(); expect(keys.some((k) => k.startsWith(key))).toBeTruthy();
} }
}); });

View File

@@ -38,6 +38,12 @@ export class Tags implements ICollection {
return this.collection.get(id); return this.collection.get(id);
} }
find(idOrTitle: string) {
return this.all.find(
(tag) => tag.title === idOrTitle || tag.id === idOrTitle
);
}
async merge(remoteTag: MaybeDeletedItem<Tag>) { async merge(remoteTag: MaybeDeletedItem<Tag>) {
if (!remoteTag) return; if (!remoteTag) return;

View File

@@ -178,6 +178,7 @@ export default class Backup {
while (chunks.length > 0) { while (chunks.length > 0) {
const chunk = chunks.pop(); const chunk = chunks.pop();
if (!chunk) break;
const items = await this.db.storage().readMulti(chunk); const items = await this.db.storage().readMulti(chunk);
items.forEach(([id, item]) => { items.forEach(([id, item]) => {
@@ -282,7 +283,7 @@ export default class Backup {
if (!decryptedData) return; if (!decryptedData) return;
if ("hash" in backup && !this.verify(backup)) if ("hash" in backup && !this.verify(backup, decryptedData))
throw new Error("Backup file has been tempered, aborting..."); throw new Error("Backup file has been tempered, aborting...");
if ("compressed" in backup && typeof decryptedData === "string") if ("compressed" in backup && typeof decryptedData === "string")
@@ -342,10 +343,6 @@ export default class Backup {
if ("sessionContentId" in item && item.type !== "session") if ("sessionContentId" in item && item.type !== "session")
(item as any).type = "notehistory"; (item as any).type = "notehistory";
// colors are naively of type "tag" instead of "color" so we have to fix that.
if (item.type === "tag" && COLORS.includes(item.title.toLowerCase()))
(item as any).type = "color";
await migrateItem(item, version, item.type, this.db, "backup"); await migrateItem(item, version, item.type, this.db, "backup");
// since items in trash can have their own set of migrations, // since items in trash can have their own set of migrations,
// we have to run the migration again to account for that. // we have to run the migration again to account for that.
@@ -395,7 +392,13 @@ export default class Backup {
if (item.type === "settings") if (item.type === "settings")
await this.db.storage().write("settings", item); await this.db.storage().write("settings", item);
else { else {
const itemType = "itemType" in item ? item.itemType : item.type; const itemType =
// colors are naively of type "tag" instead of "color" so we have to fix that.
item.type === "tag" && COLORS.includes(item.title.toLowerCase())
? "color"
: "itemType" in item
? item.itemType
: item.type;
const collectionKey = itemTypeToCollectionKey[itemType]; const collectionKey = itemTypeToCollectionKey[itemType];
if (collectionKey) { if (collectionKey) {
toAdd[collectionKey] = toAdd[collectionKey] || []; toAdd[collectionKey] = toAdd[collectionKey] || [];
@@ -423,17 +426,16 @@ export default class Backup {
); );
} }
private verify(backup: BackupFile | LegacyUnencryptedBackupFile) { private verify(
const { hash, hash_type, data } = backup; backup: BackupFile | LegacyUnencryptedBackupFile,
data: string | Record<string, BackupDataItem>
) {
const { hash, hash_type } = backup;
switch (hash_type) { switch (hash_type) {
case "md5": { case "md5": {
return ( return (
hash === hash ===
SparkMD5.hash( SparkMD5.hash(typeof data === "string" ? data : JSON.stringify(data))
"compressed" in backup && backup.compressed
? data
: JSON.stringify(data)
)
); );
} }
default: { default: {

View File

@@ -21,7 +21,8 @@ import SparkMD5 from "spark-md5";
import ObjectID from "./object-id"; import ObjectID from "./object-id";
export function getId(time?: number) { export function getId(time?: number) {
if (time) return ObjectID.createFromTime(time).toHexString(); if (time)
return new ObjectID(new ObjectID().generate(time / 1000)).toHexString();
return new ObjectID().toHexString(); return new ObjectID().toHexString();
} }