From eee05a4d01f71cad3f766f634b084e7b9f46f33d Mon Sep 17 00:00:00 2001 From: zadam Date: Thu, 16 Mar 2023 12:11:00 +0100 Subject: [PATCH] blob WIP --- .../0215__move_content_into_blobs.js | 2 +- db/migrations/0217__note_attachments.sql | 13 ++++---- src/becca/becca.js | 2 +- src/becca/entities/bnote.js | 2 +- src/becca/entities/bnote_attachment.js | 30 +++++++++++-------- src/becca/entities/bnote_revision.js | 2 +- src/becca/entity_constructor.js | 2 +- src/public/app/widgets/note_detail.js | 2 +- src/routes/api/sync.js | 2 +- src/services/consistency_checks.js | 2 +- src/services/export/zip.js | 1 + src/services/import/zip.js | 7 +++-- src/services/ws.js | 2 +- 13 files changed, 37 insertions(+), 32 deletions(-) diff --git a/db/migrations/0215__move_content_into_blobs.js b/db/migrations/0215__move_content_into_blobs.js index 4bd6b6d46..e447e9c30 100644 --- a/db/migrations/0215__move_content_into_blobs.js +++ b/db/migrations/0215__move_content_into_blobs.js @@ -1,4 +1,4 @@ -const sql = require("../../src/services/sql.js"); +const sql = require("../../src/services/sql"); module.exports = () => { const sql = require("../../src/services/sql"); const utils = require("../../src/services/utils"); diff --git a/db/migrations/0217__note_attachments.sql b/db/migrations/0217__note_attachments.sql index 374ace9b6..9ca952ba9 100644 --- a/db/migrations/0217__note_attachments.sql +++ b/db/migrations/0217__note_attachments.sql @@ -1,16 +1,15 @@ CREATE TABLE IF NOT EXISTS "note_attachments" ( noteAttachmentId TEXT not null primary key, - noteId TEXT not null, - name TEXT not null, + parentId TEXT not null, + role TEXT not null, mime TEXT not null, + title TEXT not null, isProtected INT not null DEFAULT 0, blobId TEXT not null, utcDateModified TEXT not null, isDeleted INT not null, - `deleteId` TEXT DEFAULT NULL); + deleteId TEXT DEFAULT NULL); -CREATE INDEX IDX_note_attachments_name - on note_attachments (name); -CREATE UNIQUE INDEX IDX_note_attachments_noteId_name - on note_attachments (noteId, name); +CREATE UNIQUE INDEX IDX_note_attachments_parentId_role + on note_attachments (parentId, role); diff --git a/src/becca/becca.js b/src/becca/becca.js index 91fdcbb61..72b325266 100644 --- a/src/becca/becca.js +++ b/src/becca/becca.js @@ -125,7 +125,7 @@ class Becca { getNoteAttachment(noteAttachmentId) { const row = sql.getRow("SELECT * FROM note_attachments WHERE noteAttachmentId = ?", [noteAttachmentId]); - const BNoteAttachment = require("./entities/bnote_attachment.js"); // avoiding circular dependency problems + const BNoteAttachment = require("./entities/bnote_attachment"); // avoiding circular dependency problems return row ? new BNoteAttachment(row) : null; } diff --git a/src/becca/entities/bnote.js b/src/becca/entities/bnote.js index c867ca0d7..4707720f6 100644 --- a/src/becca/entities/bnote.js +++ b/src/becca/entities/bnote.js @@ -8,7 +8,7 @@ const dateUtils = require('../../services/date_utils'); const entityChangesService = require('../../services/entity_changes'); const AbstractBeccaEntity = require("./abstract_becca_entity"); const BNoteRevision = require("./bnote_revision"); -const BNoteAttachment = require("./bnote_attachment.js"); +const BNoteAttachment = require("./bnote_attachment"); const TaskContext = require("../../services/task_context"); const dayjs = require("dayjs"); const utc = require('dayjs/plugin/utc'); diff --git a/src/becca/entities/bnote_attachment.js b/src/becca/entities/bnote_attachment.js index 5931814db..e568b358a 100644 --- a/src/becca/entities/bnote_attachment.js +++ b/src/becca/entities/bnote_attachment.js @@ -17,27 +17,31 @@ const AbstractBeccaEntity = require("./abstract_becca_entity"); class BNoteAttachment extends AbstractBeccaEntity { static get entityName() { return "note_attachments"; } static get primaryKeyName() { return "noteAttachmentId"; } - static get hashedProperties() { return ["noteAttachmentId", "noteId", "name", "content", "utcDateModified"]; } + static get hashedProperties() { return ["noteAttachmentId", "parentId", "role", "mime", "title", "utcDateModified"]; } constructor(row) { super(); - if (!row.noteId) { + if (!row.parentId?.trim()) { throw new Error("'noteId' must be given to initialize a NoteAttachment entity"); - } - - if (!row.name) { - throw new Error("'name' must be given to initialize a NoteAttachment entity"); + } else if (!row.role?.trim()) { + throw new Error("'role' must be given to initialize a NoteAttachment entity"); + } else if (!row.mime?.trim()) { + throw new Error("'mime' must be given to initialize a NoteAttachment entity"); + } else if (!row.title?.trim()) { + throw new Error("'title' must be given to initialize a NoteAttachment entity"); } /** @type {string} needs to be set at the initialization time since it's used in the .setContent() */ - this.noteAttachmentId = row.noteAttachmentId || `${this.noteId}_${this.name}`; + this.noteAttachmentId = row.noteAttachmentId || `${this.noteId}_${this.name}`; // FIXME + /** @type {string} either noteId or noteRevisionId to which this attachment belongs */ + this.parentId = row.parentId; /** @type {string} */ - this.noteId = row.noteId; - /** @type {string} */ - this.name = row.name; + this.role = row.role; /** @type {string} */ this.mime = row.mime; + /** @type {string} */ + this.title = row.title; /** @type {boolean} */ this.isProtected = !!row.isProtected; /** @type {string} */ @@ -45,7 +49,7 @@ class BNoteAttachment extends AbstractBeccaEntity { } getNote() { - return becca.notes[this.noteId]; + return becca.notes[this.parentId]; } /** @returns {boolean} true if the note has string content (not binary) */ @@ -127,7 +131,7 @@ class BNoteAttachment extends AbstractBeccaEntity { throw new Error(`Name must be alphanumerical, "${this.name}" given.`); } - this.noteAttachmentId = `${this.noteId}_${this.name}`; + this.noteAttachmentId = `${this.noteId}_${this.name}`; // FIXME super.beforeSaving(); @@ -137,7 +141,7 @@ class BNoteAttachment extends AbstractBeccaEntity { getPojo() { return { noteAttachmentId: this.noteAttachmentId, - noteId: this.noteId, + parentId: this.parentId, name: this.name, mime: this.mime, isProtected: !!this.isProtected, diff --git a/src/becca/entities/bnote_revision.js b/src/becca/entities/bnote_revision.js index c5f5c466f..d0fe74cdc 100644 --- a/src/becca/entities/bnote_revision.js +++ b/src/becca/entities/bnote_revision.js @@ -120,7 +120,7 @@ class BNoteRevision extends AbstractBeccaEntity { this.blobId = utils.hashedBlobId(content); - const blobAlreadyExists = !sql.getValue('SELECT 1 FROM blobs WHERE blobId = ?', [this.blobId]); + const blobAlreadyExists = !!sql.getValue('SELECT 1 FROM blobs WHERE blobId = ?', [this.blobId]); if (!blobAlreadyExists) { const pojo = { diff --git a/src/becca/entity_constructor.js b/src/becca/entity_constructor.js index 39d3af197..ba87fa0f1 100644 --- a/src/becca/entity_constructor.js +++ b/src/becca/entity_constructor.js @@ -1,6 +1,6 @@ const BNote = require('./entities/bnote'); const BNoteRevision = require('./entities/bnote_revision'); -const BNoteAttachment = require("./entities/bnote_attachment.js"); +const BNoteAttachment = require("./entities/bnote_attachment"); const BBranch = require('./entities/bbranch'); const BAttribute = require('./entities/battribute'); const BRecentNote = require('./entities/brecent_note'); diff --git a/src/public/app/widgets/note_detail.js b/src/public/app/widgets/note_detail.js index 890e819b0..bef368ba2 100644 --- a/src/public/app/widgets/note_detail.js +++ b/src/public/app/widgets/note_detail.js @@ -112,7 +112,7 @@ export default class NoteDetailWidget extends NoteContextAwareWidget { const files = [...e.originalEvent.dataTransfer.files]; // chrome has issue that dataTransfer.files empties after async operation - const importService = await import("../services/import.js"); + const importService = await import('../services/import.js'); importService.uploadFiles(activeNote.noteId, files, { safeImport: true, diff --git a/src/routes/api/sync.js b/src/routes/api/sync.js index 77ca19938..92373acf7 100644 --- a/src/routes/api/sync.js +++ b/src/routes/api/sync.js @@ -12,7 +12,7 @@ const syncOptions = require('../../services/sync_options'); const dateUtils = require('../../services/date_utils'); const utils = require('../../services/utils'); const ws = require('../../services/ws'); -const becca = require("../../becca/becca.js"); +const becca = require("../../becca/becca"); async function testSync() { try { diff --git a/src/services/consistency_checks.js b/src/services/consistency_checks.js index 6d47e33b0..0f7f04abf 100644 --- a/src/services/consistency_checks.js +++ b/src/services/consistency_checks.js @@ -217,7 +217,7 @@ class ConsistencyChecks { this.findAndFixIssues(` SELECT noteAttachmentId, note_attachments.noteId AS noteId FROM note_attachments - LEFT JOIN notes USING (noteId) + LEFT JOIN notes ON notes.noteId = note_attachments.parentId WHERE notes.noteId IS NULL AND note_attachments.isDeleted = 0`, ({noteAttachmentId, noteId}) => { diff --git a/src/services/export/zip.js b/src/services/export/zip.js index f7a246a4b..7b5c49427 100644 --- a/src/services/export/zip.js +++ b/src/services/export/zip.js @@ -338,6 +338,7 @@ ${markdownContent}`; taskContext.increaseProgressCount(); for (const attachmentMeta of noteMeta.attachments || []) { + // FIXME const noteAttachment = note.getNoteAttachmentByName(attachmentMeta.name); const content = noteAttachment.getContent(); diff --git a/src/services/import/zip.js b/src/services/import/zip.js index 01f2654c5..1effc29d0 100644 --- a/src/services/import/zip.js +++ b/src/services/import/zip.js @@ -14,7 +14,7 @@ const treeService = require("../tree"); const yauzl = require("yauzl"); const htmlSanitizer = require('../html_sanitizer'); const becca = require("../../becca/becca"); -const BNoteAttachment = require("../../becca/entities/bnote_attachment.js"); +const BNoteAttachment = require("../../becca/entities/bnote_attachment"); /** * @param {TaskContext} taskContext @@ -380,8 +380,9 @@ async function importZip(taskContext, fileBuffer, importRootNote) { if (attachmentMeta) { const noteAttachment = new BNoteAttachment({ - noteId, - name: attachmentMeta.name, + parentId: noteId, + title: attachmentMeta.title, + role: attachmentMeta.role, mime: attachmentMeta.mime }); diff --git a/src/services/ws.js b/src/services/ws.js index ac054b8f4..9d0266b5b 100644 --- a/src/services/ws.js +++ b/src/services/ws.js @@ -135,7 +135,7 @@ function fillInAdditionalProperties(entityChange) { if (!entityChange.entity) { entityChange.entity = sql.getRow(`SELECT * FROM options WHERE name = ?`, [entityChange.entityId]); } - } else if (entityChange.entityName === 'blob') { + } else if (entityChange.entityName === 'blobs') { entityChange.noteIds = sql.getColumn("SELECT noteId FROM notes WHERE blobId = ? AND isDeleted = 0", [entityChange.entityId]); }