From c7a6cd8964c18f6d23ad88d16f6350f6db479c2c Mon Sep 17 00:00:00 2001 From: Abdullah Atta Date: Thu, 14 Sep 2023 18:54:15 +0500 Subject: [PATCH] core: minor updates and fixes --- packages/core/__tests__/backup.test.js | 11 +++++----- packages/core/src/collections/tags.ts | 6 ++++++ packages/core/src/database/backup.ts | 28 ++++++++++++++------------ packages/core/src/utils/id.ts | 3 ++- 4 files changed, 28 insertions(+), 20 deletions(-) diff --git a/packages/core/__tests__/backup.test.js b/packages/core/__tests__/backup.test.js index b8e542f8a..15b0e3949 100644 --- a/packages/core/__tests__/backup.test.js +++ b/packages/core/__tests__/backup.test.js @@ -24,7 +24,7 @@ import v56BackupCopy from "./__fixtures__/backup.v5.6.json"; import v58BackupCopy from "./__fixtures__/backup.v5.8.json"; import qclone from "qclone"; import { test, expect, describe } from "vitest"; -import { makeId } from "../src/utils/id"; +import { getId, makeId } from "../src/utils/id"; test("export backup", () => notebookTest().then(async ({ db }) => { @@ -79,7 +79,7 @@ test("import backup", () => exp.push(file); } - await db.storage.clear(); + await db.storage().clear(); await db.backup.import(JSON.parse(exp[1].data)); expect(db.notebooks.notebook(id).data.id).toBe(id); })); @@ -94,7 +94,7 @@ test("import encrypted backup", () => exp.push(file); } - await db.storage.clear(); + await db.storage().clear(); await db.backup.import(JSON.parse(exp[1].data), "password"); expect(db.notebooks.notebook(id).data.id).toBe(id); })); @@ -108,7 +108,7 @@ test("import tempered backup", () => exp.push(file); } - await db.storage.clear(); + await db.storage().clear(); const backup = JSON.parse(exp[1].data); backup.data += "hello"; await expect(db.backup.import(backup)).rejects.toThrow(/tempered/); @@ -198,7 +198,7 @@ describe.each([ return databaseTest().then(async (db) => { await db.backup.import(qclone(data)); - const keys = await db.storage.getAllKeys(); + const keys = await db.storage().getAllKeys(); for (let key in data.data) { const item = data.data[key]; if (item && !item.type && item.deleted) continue; @@ -209,7 +209,6 @@ describe.each([ key === "token" ) continue; - expect(keys.some((k) => k.startsWith(key))).toBeTruthy(); } }); diff --git a/packages/core/src/collections/tags.ts b/packages/core/src/collections/tags.ts index 92b90ba56..3a8ee704d 100644 --- a/packages/core/src/collections/tags.ts +++ b/packages/core/src/collections/tags.ts @@ -38,6 +38,12 @@ export class Tags implements ICollection { return this.collection.get(id); } + find(idOrTitle: string) { + return this.all.find( + (tag) => tag.title === idOrTitle || tag.id === idOrTitle + ); + } + async merge(remoteTag: MaybeDeletedItem) { if (!remoteTag) return; diff --git a/packages/core/src/database/backup.ts b/packages/core/src/database/backup.ts index 374079461..a540851da 100644 --- a/packages/core/src/database/backup.ts +++ b/packages/core/src/database/backup.ts @@ -178,6 +178,7 @@ export default class Backup { while (chunks.length > 0) { const chunk = chunks.pop(); + if (!chunk) break; const items = await this.db.storage().readMulti(chunk); items.forEach(([id, item]) => { @@ -282,7 +283,7 @@ export default class Backup { 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..."); if ("compressed" in backup && typeof decryptedData === "string") @@ -342,10 +343,6 @@ export default class Backup { if ("sessionContentId" in item && item.type !== "session") (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"); // since items in trash can have their own set of migrations, // we have to run the migration again to account for that. @@ -395,7 +392,13 @@ export default class Backup { if (item.type === "settings") await this.db.storage().write("settings", item); 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]; if (collectionKey) { toAdd[collectionKey] = toAdd[collectionKey] || []; @@ -423,17 +426,16 @@ export default class Backup { ); } - private verify(backup: BackupFile | LegacyUnencryptedBackupFile) { - const { hash, hash_type, data } = backup; + private verify( + backup: BackupFile | LegacyUnencryptedBackupFile, + data: string | Record + ) { + const { hash, hash_type } = backup; switch (hash_type) { case "md5": { return ( hash === - SparkMD5.hash( - "compressed" in backup && backup.compressed - ? data - : JSON.stringify(data) - ) + SparkMD5.hash(typeof data === "string" ? data : JSON.stringify(data)) ); } default: { diff --git a/packages/core/src/utils/id.ts b/packages/core/src/utils/id.ts index 1abc527ea..daece54b6 100644 --- a/packages/core/src/utils/id.ts +++ b/packages/core/src/utils/id.ts @@ -21,7 +21,8 @@ import SparkMD5 from "spark-md5"; import ObjectID from "./object-id"; 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(); }