core: remove orphaned attachments in trash cleanup method

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
This commit is contained in:
01zulfi
2026-02-04 13:13:56 +05:00
parent e381e54bb7
commit 4a158b2547
5 changed files with 35 additions and 7 deletions

View File

@@ -24,6 +24,7 @@ import {
SerializedKeyPair
} from "@notesnook/crypto";
import { IStorage } from "../src/interfaces.js";
import { randomBytes } from "crypto";
export class NodeStorageInterface implements IStorage {
storage = {};
@@ -112,7 +113,7 @@ export class NodeStorageInterface implements IStorage {
password: string,
salt?: string | undefined
): Promise<SerializedKey> {
return { password, salt };
return { password, salt: salt || randomBytes(16).toString("base64") };
}
generateCryptoKeyPair(): Promise<SerializedKeyPair> {

View File

@@ -23,7 +23,8 @@ import {
notebookTest,
TEST_NOTE,
TEST_NOTEBOOK,
databaseTest
databaseTest,
loginFakeUser
} from "./utils/index.js";
import { test, expect } from "vitest";
@@ -384,3 +385,20 @@ test("permanently deleted note should not have note fields", () =>
"synced"
]);
}));
test("trash cleanup should remove orphaned attachments", () =>
databaseTest().then(async (db) => {
await loginFakeUser(db);
const hash = await db.attachments.save(
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg==",
"image/png",
"test.png"
);
if (!hash) throw new Error("Failed to create attachment");
await db.trash.cleanup();
expect(await db.attachments.exists(hash)).toBe(false);
expect(await db.attachments.orphaned.count()).toBe(0);
}));

View File

@@ -109,18 +109,17 @@ function delay(ms: number) {
async function loginFakeUser(db) {
const email = "johndoe@example.com";
const password = "password";
const userSalt = randomBytes(16).toString("base64");
await db.storage().deriveCryptoKey({
password: "password",
password,
salt: userSalt
});
const userEncryptionKey = await db.storage().getCryptoKey(`_uk_@${email}`);
const key = await db.crypto().generateRandomKey();
const attachmentsKey = await db
.storage()
.encrypt({ password: userEncryptionKey }, JSON.stringify(key));
.encrypt({ password, salt: userSalt }, JSON.stringify(key));
await db.user.setUser({
email,

View File

@@ -574,6 +574,14 @@ export class Attachments implements ICollection {
);
return this.key;
}
async removeOrphaned() {
for await (const attachment of this.db.attachments.orphaned.iterate()) {
try {
await this.db.attachments.remove(attachment.hash, false);
} catch (error) {}
}
}
}
export function getOutputType(attachment: Attachment): DataFormat {

View File

@@ -121,8 +121,10 @@ export default class Trash {
},
{ noteIds: [] as string[], notebookIds: [] as string[] }
);
await this._delete(noteIds, notebookIds);
await this.db.attachments.removeOrphaned();
await this.buildCache();
}