Skip to content

Commit

Permalink
core: fix legacy backup restoration
Browse files Browse the repository at this point in the history
  • Loading branch information
thecodrr committed May 7, 2024
1 parent 79f20d1 commit 68d06ff
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 22 deletions.
62 changes: 51 additions & 11 deletions packages/core/src/database/backup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,12 @@ import { CURRENT_DATABASE_VERSION } from "../common.js";
import Migrator from "./migrator.js";
import Database from "../api/index.js";
import {
Attachment,
Item,
MaybeDeletedItem,
Note,
Notebook,
Relation,
ValueOf,
isDeleted
} from "../types.js";
Expand All @@ -36,6 +38,7 @@ import { DatabaseCollection } from "./index.js";
import { DefaultColors } from "../collections/colors.js";
import { toChunks } from "../utils/array.js";
import { logger } from "../logger.js";
import { clone } from "../utils/clone.js";

type BackupDataItem = MaybeDeletedItem<Item> | string[];
type BackupPlatform = "web" | "mobile" | "node";
Expand Down Expand Up @@ -92,10 +95,44 @@ function isEncryptedBackup(
return "encrypted" in backup ? backup.encrypted : isCipher(backup.data);
}

function isLegacyBackupFile(
backup: LegacyBackupFile | BackupFile
): backup is LegacyBackupFile {
return backup.version <= 5.8;
/**
* Due to a bug in v3.0, legacy backups were created with version set to 6.1
* while their actual data was at version 5.9. This caused various issues when
* restoring such a backup.
* This function tries to work around that bug by detecting the version based on
* the actual data.
*/
function isLegacyBackup(data: BackupDataItem[]) {
const note = data.find(
(c): c is Note => !isDeleted(c) && !Array.isArray(c) && c.type === "note"
);
if (note)
return (
"color" in note ||
"notebooks" in note ||
"tags" in note ||
"locked" in note
);

const notebook = data.find(
(c): c is Notebook =>
!isDeleted(c) && !Array.isArray(c) && c.type === "notebook"
);
if (notebook) return "topics" in notebook;

const attachment = data.find(
(c): c is Attachment =>
!isDeleted(c) && !Array.isArray(c) && c.type === "attachment"
);
if (attachment) return "noteIds" in attachment;

const relation = data.find(
(c): c is Relation =>
!isDeleted(c) && !Array.isArray(c) && c.type === "relation"
);
if (relation) return "from" in relation || "to" in relation;

return false;
}

const MAX_CHUNK_SIZE = 10 * 1024 * 1024;
Expand Down Expand Up @@ -221,7 +258,7 @@ export default class Backup {
yield {
path: `${chunkIndex++}-${encrypt ? "encrypted" : "plain"}-${hash}`,
data: `{
"version": ${CURRENT_DATABASE_VERSION},
"version": 5.9,
"type": "${type}",
"date": ${Date.now()},
"data": ${itemsJSON},
Expand Down Expand Up @@ -397,13 +434,16 @@ export default class Backup {

if (!data) throw new Error("No data found.");

const normalizedData: BackupDataItem[] = Array.isArray(data)
? (data as BackupDataItem[])
: typeof data === "object"
? Object.values(data)
: [];
await this.migrateData(
Array.isArray(data)
? (data as BackupDataItem[])
: typeof data === "object"
? Object.values(data)
: [],
backup.version
normalizedData,
backup.version === 6.1 && isLegacyBackup(normalizedData)
? 5.9
: backup.version
);
}

Expand Down
22 changes: 11 additions & 11 deletions packages/core/src/database/migrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
} from "../types";
import { IndexedCollection } from "./indexed-collection";
import { SQLCollection } from "./sql-collection";
import { logger } from "../logger";

export type RawItem = MaybeDeletedItem<Item>;
type MigratableCollection = {
Expand Down Expand Up @@ -136,10 +137,16 @@ class Migrator {
for (let i = 0; i < items.length; ++i) {
const item = items[i];
// can be true due to corrupted data.
if (Array.isArray(item)) continue;
if (Array.isArray(item)) {
logger.debug("Skipping item during migration to SQLite", {
table,
version,
item
});
continue;
}
if (!item) continue;

const itemId = item.id;
let migrated = await migrateItem(
item,
version,
Expand All @@ -161,14 +168,7 @@ class Migrator {
);
}

if (migrated === true) {
toAdd.push(item);

// if id changed after migration, we need to delete the old one.
if (item.id !== itemId) {
// await collection.deleteItem(itemId);
}
}
if (migrated !== "skip") toAdd.push(item);
}

if (toAdd.length > 0) {
Expand Down Expand Up @@ -217,7 +217,7 @@ class Migrator {
);
}

if (!migrated) continue;
if (!migrated || migrated === "skip") continue;

toAdd.push(item);

Expand Down

0 comments on commit 68d06ff

Please sign in to comment.