mirror of
				https://github.com/zadam/trilium.git
				synced 2025-10-31 02:16:05 +01:00 
			
		
		
		
	ancillary => attachment
This commit is contained in:
		| @@ -1,6 +1,6 @@ | ||||
| CREATE TABLE IF NOT EXISTS "note_ancillaries" | ||||
| CREATE TABLE IF NOT EXISTS "note_attachments" | ||||
| ( | ||||
|     noteAncillaryId      TEXT not null primary key, | ||||
|     noteAttachmentId      TEXT not null primary key, | ||||
|     noteId       TEXT not null, | ||||
|     name         TEXT not null, | ||||
|     mime         TEXT not null, | ||||
| @@ -10,7 +10,7 @@ CREATE TABLE IF NOT EXISTS "note_ancillaries" | ||||
|     isDeleted    INT  not null, | ||||
|     `deleteId`    TEXT DEFAULT NULL); | ||||
|  | ||||
| CREATE INDEX IDX_note_ancillaries_name | ||||
|     on note_ancillaries (name); | ||||
| CREATE UNIQUE INDEX IDX_note_ancillaries_noteId_name | ||||
|     on note_ancillaries (noteId, name); | ||||
| CREATE INDEX IDX_note_attachments_name | ||||
|     on note_attachments (name); | ||||
| CREATE UNIQUE INDEX IDX_note_attachments_noteId_name | ||||
|     on note_attachments (noteId, name); | ||||
|   | ||||
| @@ -112,9 +112,9 @@ CREATE TABLE IF NOT EXISTS "recent_notes" | ||||
|     notePath TEXT not null, | ||||
|     utcDateCreated TEXT not null | ||||
| ); | ||||
| CREATE TABLE IF NOT EXISTS "note_ancillaries" | ||||
| CREATE TABLE IF NOT EXISTS "note_attachments" | ||||
| ( | ||||
|     noteAncillaryId      TEXT not null primary key, | ||||
|     noteAttachmentId      TEXT not null primary key, | ||||
|     noteId       TEXT not null, | ||||
|     name         TEXT not null, | ||||
|     mime         TEXT not null, | ||||
| @@ -123,7 +123,7 @@ CREATE TABLE IF NOT EXISTS "note_ancillaries" | ||||
|     isDeleted    INT  not null, | ||||
|     `deleteId`    TEXT DEFAULT NULL); | ||||
|  | ||||
| CREATE INDEX IDX_note_ancillaries_name | ||||
|     on note_ancillaries (name); | ||||
| CREATE UNIQUE INDEX IDX_note_ancillaries_noteId_name | ||||
|     on note_ancillaries (noteId, name); | ||||
| CREATE INDEX IDX_note_attachments_name | ||||
|     on note_attachments (name); | ||||
| CREATE UNIQUE INDEX IDX_note_attachments_noteId_name | ||||
|     on note_attachments (noteId, name); | ||||
|   | ||||
| @@ -121,12 +121,12 @@ class Becca { | ||||
|         return row ? new BNoteRevision(row) : null; | ||||
|     } | ||||
|  | ||||
|     /** @returns {BNoteAncillary|null} */ | ||||
|     getNoteAncillary(noteAncillaryId) { | ||||
|         const row = sql.getRow("SELECT * FROM note_ancillaries WHERE noteAncillaryId = ?", [noteAncillaryId]); | ||||
|     /** @returns {BNoteAttachment|null} */ | ||||
|     getNoteAttachment(noteAttachmentId) { | ||||
|         const row = sql.getRow("SELECT * FROM note_attachments WHERE noteAttachmentId = ?", [noteAttachmentId]); | ||||
|  | ||||
|         const BNoteAncillary = require("./entities/bnote_attachment.js"); // avoiding circular dependency problems | ||||
|         return row ? new BNoteAncillary(row) : null; | ||||
|         const BNoteAttachment = require("./entities/bnote_attachment.js"); // avoiding circular dependency problems | ||||
|         return row ? new BNoteAttachment(row) : null; | ||||
|     } | ||||
|  | ||||
|     /** @returns {BOption|null} */ | ||||
| @@ -151,8 +151,8 @@ class Becca { | ||||
|  | ||||
|         if (entityName === 'note_revisions') { | ||||
|             return this.getNoteRevision(entityId); | ||||
|         } else if (entityName === 'note_ancillaries') { | ||||
|             return this.getNoteAncillary(entityId); | ||||
|         } else if (entityName === 'note_attachments') { | ||||
|             return this.getNoteAttachment(entityId); | ||||
|         } | ||||
|  | ||||
|         const camelCaseEntityName = entityName.toLowerCase().replace(/(_[a-z])/g, | ||||
|   | ||||
| @@ -198,8 +198,8 @@ class BBranch extends AbstractBeccaEntity { | ||||
|                 relation.markAsDeleted(deleteId); | ||||
|             } | ||||
|  | ||||
|             for (const noteAncillary of note.getNoteAncillaries()) { | ||||
|                 noteAncillary.markAsDeleted(deleteId); | ||||
|             for (const noteAttachment of note.getNoteAttachments()) { | ||||
|                 noteAttachment.markAsDeleted(deleteId); | ||||
|             } | ||||
|  | ||||
|             note.markAsDeleted(deleteId); | ||||
|   | ||||
| @@ -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 BNoteAncillary = require("./bnote_attachment.js"); | ||||
| const BNoteAttachment = require("./bnote_attachment.js"); | ||||
| const TaskContext = require("../../services/task_context"); | ||||
| const dayjs = require("dayjs"); | ||||
| const utc = require('dayjs/plugin/utc'); | ||||
| @@ -1161,16 +1161,16 @@ class BNote extends AbstractBeccaEntity { | ||||
|             .map(row => new BNoteRevision(row)); | ||||
|     } | ||||
|  | ||||
|     /** @returns {BNoteAncillary[]} */ | ||||
|     getNoteAncillaries() { | ||||
|         return sql.getRows("SELECT * FROM note_ancillaries WHERE noteId = ? AND isDeleted = 0", [this.noteId]) | ||||
|             .map(row => new BNoteAncillary(row)); | ||||
|     /** @returns {BNoteAttachment[]} */ | ||||
|     getNoteAttachments() { | ||||
|         return sql.getRows("SELECT * FROM note_attachments WHERE noteId = ? AND isDeleted = 0", [this.noteId]) | ||||
|             .map(row => new BNoteAttachment(row)); | ||||
|     } | ||||
|  | ||||
|     /** @returns {BNoteAncillary|undefined} */ | ||||
|     getNoteAncillaryByName(name) { | ||||
|         return sql.getRows("SELECT * FROM note_ancillaries WHERE noteId = ? AND name = ? AND isDeleted = 0", [this.noteId, name]) | ||||
|             .map(row => new BNoteAncillary(row)) | ||||
|     /** @returns {BNoteAttachment|undefined} */ | ||||
|     getNoteAttachmentByName(name) { | ||||
|         return sql.getRows("SELECT * FROM note_attachments WHERE noteId = ? AND name = ? AND isDeleted = 0", [this.noteId, name]) | ||||
|             .map(row => new BNoteAttachment(row)) | ||||
|             [0]; | ||||
|     } | ||||
|  | ||||
| @@ -1502,21 +1502,21 @@ class BNote extends AbstractBeccaEntity { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * @returns {BNoteAncillary} | ||||
|      * @returns {BNoteAttachment} | ||||
|      */ | ||||
|     saveNoteAncillary(name, mime, content) { | ||||
|         let noteAncillary = this.getNoteAncillaryByName(name); | ||||
|     saveNoteAttachment(name, mime, content) { | ||||
|         let noteAttachment = this.getNoteAttachmentByName(name); | ||||
|  | ||||
|         noteAncillary = new BNoteAncillary({ | ||||
|         noteAttachment = new BNoteAttachment({ | ||||
|             noteId: this.noteId, | ||||
|             name, | ||||
|             mime, | ||||
|             isProtected: this.isProtected | ||||
|         }); | ||||
|  | ||||
|         noteAncillary.setContent(content); | ||||
|         noteAttachment.setContent(content); | ||||
|  | ||||
|         return noteAncillary; | ||||
|         return noteAttachment; | ||||
|     } | ||||
|  | ||||
|     beforeSaving() { | ||||
|   | ||||
| @@ -9,29 +9,29 @@ const entityChangesService = require('../../services/entity_changes'); | ||||
| const AbstractBeccaEntity = require("./abstract_becca_entity"); | ||||
|  | ||||
| /** | ||||
|  * NoteAncillary represent data related/attached to the note. Conceptually similar to attributes, but intended for | ||||
|  * NoteAttachment represent data related/attached to the note. Conceptually similar to attributes, but intended for | ||||
|  * larger amounts of data and generally not accessible to the user. | ||||
|  * | ||||
|  * @extends AbstractBeccaEntity | ||||
|  */ | ||||
| class BNoteAncillary extends AbstractBeccaEntity { | ||||
|     static get entityName() { return "note_ancillaries"; } | ||||
|     static get primaryKeyName() { return "noteAncillaryId"; } | ||||
|     static get hashedProperties() { return ["noteAncillaryId", "noteId", "name", "content", "utcDateModified"]; } | ||||
| class BNoteAttachment extends AbstractBeccaEntity { | ||||
|     static get entityName() { return "note_attachments"; } | ||||
|     static get primaryKeyName() { return "noteAttachmentId"; } | ||||
|     static get hashedProperties() { return ["noteAttachmentId", "noteId", "name", "content", "utcDateModified"]; } | ||||
|  | ||||
|     constructor(row) { | ||||
|         super(); | ||||
|  | ||||
|         if (!row.noteId) { | ||||
|             throw new Error("'noteId' must be given to initialize a NoteAncillary entity"); | ||||
|             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 NoteAncillary entity"); | ||||
|             throw new Error("'name' 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.noteAncillaryId = row.noteAncillaryId || `${this.noteId}_${this.name}`; | ||||
|         this.noteAttachmentId = row.noteAttachmentId || `${this.noteId}_${this.name}`; | ||||
|         /** @type {string} */ | ||||
|         this.noteId = row.noteId; | ||||
|         /** @type {string} */ | ||||
| @@ -55,14 +55,14 @@ class BNoteAncillary extends AbstractBeccaEntity { | ||||
|  | ||||
|     /** @returns {*} */ | ||||
|     getContent(silentNotFoundError = false) { | ||||
|         const res = sql.getRow(`SELECT content FROM note_ancillary_contents WHERE noteAncillaryId = ?`, [this.noteAncillaryId]); | ||||
|         const res = sql.getRow(`SELECT content FROM note_attachment_contents WHERE noteAttachmentId = ?`, [this.noteAttachmentId]); | ||||
|  | ||||
|         if (!res) { | ||||
|             if (silentNotFoundError) { | ||||
|                 return undefined; | ||||
|             } | ||||
|             else { | ||||
|                 throw new Error(`Cannot find note ancillary content for noteAncillaryId=${this.noteAncillaryId}`); | ||||
|                 throw new Error(`Cannot find note attachment content for noteAttachmentId=${this.noteAttachmentId}`); | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -89,10 +89,10 @@ class BNoteAncillary extends AbstractBeccaEntity { | ||||
|  | ||||
|     setContent(content) { | ||||
|         sql.transactional(() => { | ||||
|             this.save(); // also explicitly save note_ancillary to update contentCheckSum | ||||
|             this.save(); // also explicitly save note_attachment to update contentCheckSum | ||||
|  | ||||
|             const pojo = { | ||||
|                 noteAncillaryId: this.noteAncillaryId, | ||||
|                 noteAttachmentId: this.noteAttachmentId, | ||||
|                 content: content, | ||||
|                 utcDateModified: dateUtils.utcNowDateTime() | ||||
|             }; | ||||
| @@ -101,15 +101,15 @@ class BNoteAncillary extends AbstractBeccaEntity { | ||||
|                 if (protectedSessionService.isProtectedSessionAvailable()) { | ||||
|                     pojo.content = protectedSessionService.encrypt(pojo.content); | ||||
|                 } else { | ||||
|                     throw new Error(`Cannot update content of noteAncillaryId=${this.noteAncillaryId} since we're out of protected session.`); | ||||
|                     throw new Error(`Cannot update content of noteAttachmentId=${this.noteAttachmentId} since we're out of protected session.`); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             sql.upsert("note_ancillary_contents", "noteAncillaryId", pojo); | ||||
|             sql.upsert("note_attachment_contents", "noteAttachmentId", pojo); | ||||
|  | ||||
|             entityChangesService.addEntityChange({ | ||||
|                 entityName: 'note_ancillary_contents', | ||||
|                 entityId: this.noteAncillaryId, | ||||
|                 entityName: 'note_attachment_contents', | ||||
|                 entityId: this.noteAttachmentId, | ||||
|                 hash: this.contentCheckSum, // FIXME | ||||
|                 isErased: false, | ||||
|                 utcDateChanged: pojo.utcDateModified, | ||||
| @@ -119,7 +119,7 @@ class BNoteAncillary extends AbstractBeccaEntity { | ||||
|     } | ||||
|  | ||||
|     calculateCheckSum(content) { | ||||
|         return utils.hash(`${this.noteAncillaryId}|${content.toString()}`); | ||||
|         return utils.hash(`${this.noteAttachmentId}|${content.toString()}`); | ||||
|     } | ||||
|  | ||||
|     beforeSaving() { | ||||
| @@ -127,7 +127,7 @@ class BNoteAncillary extends AbstractBeccaEntity { | ||||
|             throw new Error(`Name must be alphanumerical, "${this.name}" given.`); | ||||
|         } | ||||
|  | ||||
|         this.noteAncillaryId = `${this.noteId}_${this.name}`; | ||||
|         this.noteAttachmentId = `${this.noteId}_${this.name}`; | ||||
|  | ||||
|         super.beforeSaving(); | ||||
|  | ||||
| @@ -136,7 +136,7 @@ class BNoteAncillary extends AbstractBeccaEntity { | ||||
|  | ||||
|     getPojo() { | ||||
|         return { | ||||
|             noteAncillaryId: this.noteAncillaryId, | ||||
|             noteAttachmentId: this.noteAttachmentId, | ||||
|             noteId: this.noteId, | ||||
|             name: this.name, | ||||
|             mime: this.mime, | ||||
| @@ -155,4 +155,4 @@ class BNoteAncillary extends AbstractBeccaEntity { | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = BNoteAncillary; | ||||
| module.exports = BNoteAttachment; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| const BNote = require('./entities/bnote'); | ||||
| const BNoteRevision = require('./entities/bnote_revision'); | ||||
| const BNoteAncillary = require("./entities/bnote_attachment.js"); | ||||
| const BNoteAttachment = require("./entities/bnote_attachment.js"); | ||||
| const BBranch = require('./entities/bbranch'); | ||||
| const BAttribute = require('./entities/battribute'); | ||||
| const BRecentNote = require('./entities/brecent_note'); | ||||
| @@ -12,7 +12,7 @@ const ENTITY_NAME_TO_ENTITY = { | ||||
|     "branches": BBranch, | ||||
|     "notes": BNote, | ||||
|     "note_revisions": BNoteRevision, | ||||
|     "note_ancillaries": BNoteAncillary, | ||||
|     "note_attachments": BNoteAttachment, | ||||
|     "recent_notes": BRecentNote, | ||||
|     "etapi_tokens": BEtapiToken, | ||||
|     "options": BOption | ||||
|   | ||||
| @@ -34,7 +34,7 @@ async function processEntityChanges(entityChanges) { | ||||
|  | ||||
|                 loadResults.addOption(ec.entity.name); | ||||
|             } | ||||
|             else if (['etapi_tokens', 'note_ancillaries'].includes(ec.entityName)) { | ||||
|             else if (['etapi_tokens', 'note_attachments'].includes(ec.entityName)) { | ||||
|                 // NOOP | ||||
|             } | ||||
|             else { | ||||
|   | ||||
| @@ -28,7 +28,7 @@ const TPL = ` | ||||
|         <a data-trigger-command="renderActiveNote" class="dropdown-item render-note-button"><kbd data-command="renderActiveNote"></kbd> Re-render note</a> | ||||
|         <a data-trigger-command="findInText" class="dropdown-item find-in-text-button">Search in note <kbd data-command="findInText"></a> | ||||
|         <a data-trigger-command="showNoteSource" class="dropdown-item show-source-button"><kbd data-command="showNoteSource"></kbd> Note source</a> | ||||
|         <a data-trigger-command="showNoteAncillaries" class="dropdown-item"><kbd data-command="showNoteAncillaries"></kbd> Note ancillaries</a> | ||||
|         <a data-trigger-command="showNoteAttachments" class="dropdown-item"><kbd data-command="showNoteAttachments"></kbd> Note attachments</a> | ||||
|         <a data-trigger-command="openNoteExternally" class="dropdown-item open-note-externally-button"><kbd data-command="openNoteExternally"></kbd> Open note externally</a> | ||||
|         <a class="dropdown-item import-files-button">Import files</a> | ||||
|         <a class="dropdown-item export-note-button">Export note</a> | ||||
|   | ||||
| @@ -27,7 +27,7 @@ import NoteMapTypeWidget from "./type_widgets/note_map.js"; | ||||
| import WebViewTypeWidget from "./type_widgets/web_view.js"; | ||||
| import DocTypeWidget from "./type_widgets/doc.js"; | ||||
| import ContentWidgetTypeWidget from "./type_widgets/content_widget.js"; | ||||
| import AncillariesTypeWidget from "./type_widgets/attachments.js"; | ||||
| import AttachmentsTypeWidget from "./type_widgets/attachments.js"; | ||||
|  | ||||
| const TPL = ` | ||||
| <div class="note-detail"> | ||||
| @@ -63,7 +63,7 @@ const typeWidgetClasses = { | ||||
|     'webView': WebViewTypeWidget, | ||||
|     'doc': DocTypeWidget, | ||||
|     'contentWidget': ContentWidgetTypeWidget, | ||||
|     'ancillaries': AncillariesTypeWidget | ||||
|     'attachments': AttachmentsTypeWidget | ||||
| }; | ||||
|  | ||||
| export default class NoteDetailWidget extends NoteContextAwareWidget { | ||||
| @@ -191,8 +191,8 @@ export default class NoteDetailWidget extends NoteContextAwareWidget { | ||||
|  | ||||
|         if (type === 'text' && this.noteContext.viewScope.viewMode === 'source') { | ||||
|             type = 'readOnlyCode'; | ||||
|         } else if (this.noteContext.viewScope.viewMode === 'ancillaries') { | ||||
|             type = 'ancillaries'; | ||||
|         } else if (this.noteContext.viewScope.viewMode === 'attachments') { | ||||
|             type = 'attachments'; | ||||
|         } else if (type === 'text' && await this.noteContext.isReadOnly()) { | ||||
|             type = 'readOnlyText'; | ||||
|         } else if ((type === 'code' || type === 'mermaid') && await this.noteContext.isReadOnly()) { | ||||
|   | ||||
| @@ -2,13 +2,13 @@ import TypeWidget from "./type_widget.js"; | ||||
| import server from "../../services/server.js"; | ||||
|  | ||||
| const TPL = ` | ||||
| <div class="note-ancillaries note-detail-printable"> | ||||
| <div class="note-attachments note-detail-printable"> | ||||
|     <style> | ||||
|         .note-ancillaries { | ||||
|         .note-attachments { | ||||
|             padding: 15px; | ||||
|         } | ||||
|          | ||||
|         .ancillary-content { | ||||
|         .attachment-content { | ||||
|             max-height: 400px; | ||||
|             background: var(--accented-background-color); | ||||
|             padding: 10px; | ||||
| @@ -16,26 +16,26 @@ const TPL = ` | ||||
|             margin-bottom: 10px; | ||||
|         } | ||||
|          | ||||
|         .ancillary-details th { | ||||
|         .attachment-details th { | ||||
|             padding-left: 10px; | ||||
|             padding-right: 10px; | ||||
|         } | ||||
|     </style> | ||||
|  | ||||
|     <div class="alert alert-info" style="margin: 10px 0 10px 0; padding: 20px;"> | ||||
|         Note ancillaries are pieces of data attached to a given note, providing ancillary support.  | ||||
|         Note attachments are pieces of data attached to a given note, providing attachment support.  | ||||
|         This view is useful for diagnostics. | ||||
|     </div> | ||||
|      | ||||
|     <div class="note-ancillary-list"></div> | ||||
|     <div class="note-attachment-list"></div> | ||||
| </div>`; | ||||
|  | ||||
| export default class AncillariesTypeWidget extends TypeWidget { | ||||
|     static getType() { return "ancillaries"; } | ||||
| export default class AttachmentsTypeWidget extends TypeWidget { | ||||
|     static getType() { return "attachments"; } | ||||
|  | ||||
|     doRender() { | ||||
|         this.$widget = $(TPL); | ||||
|         this.$list = this.$widget.find('.note-ancillary-list'); | ||||
|         this.$list = this.$widget.find('.note-attachment-list'); | ||||
|  | ||||
|         super.doRender(); | ||||
|     } | ||||
| @@ -43,35 +43,35 @@ export default class AncillariesTypeWidget extends TypeWidget { | ||||
|     async doRefresh(note) { | ||||
|         this.$list.empty(); | ||||
|  | ||||
|         const ancillaries = await server.get(`notes/${this.noteId}/ancillaries?includeContent=true`); | ||||
|         const attachments = await server.get(`notes/${this.noteId}/attachments?includeContent=true`); | ||||
|  | ||||
|         if (ancillaries.length === 0) { | ||||
|             this.$list.html("<strong>This note has no ancillaries.</strong>"); | ||||
|         if (attachments.length === 0) { | ||||
|             this.$list.html("<strong>This note has no attachments.</strong>"); | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         for (const ancillary of ancillaries) { | ||||
|         for (const attachment of attachments) { | ||||
|             this.$list.append( | ||||
|                 $('<div class="note-ancillary-wrapper">') | ||||
|                 $('<div class="note-attachment-wrapper">') | ||||
|                     .append( | ||||
|                         $('<h4>').append($('<span class="ancillary-name">').text(ancillary.name)) | ||||
|                         $('<h4>').append($('<span class="attachment-name">').text(attachment.name)) | ||||
|                     ) | ||||
|                     .append( | ||||
|                         $('<table class="ancillary-details">') | ||||
|                         $('<table class="attachment-details">') | ||||
|                             .append( | ||||
|                                 $('<tr>') | ||||
|                                     .append($('<th>').text('Length:')) | ||||
|                                     .append($('<td>').text(ancillary.contentLength)) | ||||
|                                     .append($('<td>').text(attachment.contentLength)) | ||||
|                                     .append($('<th>').text('MIME:')) | ||||
|                                     .append($('<td>').text(ancillary.mime)) | ||||
|                                     .append($('<td>').text(attachment.mime)) | ||||
|                                     .append($('<th>').text('Date modified:')) | ||||
|                                     .append($('<td>').text(ancillary.utcDateModified)) | ||||
|                                     .append($('<td>').text(attachment.utcDateModified)) | ||||
|                             ) | ||||
|                     ) | ||||
|                     .append( | ||||
|                         $('<pre class="ancillary-content">') | ||||
|                             .text(ancillary.content) | ||||
|                         $('<pre class="attachment-content">') | ||||
|                             .text(attachment.content) | ||||
|                     ) | ||||
|             ); | ||||
|         } | ||||
|   | ||||
| @@ -54,10 +54,10 @@ function createNote(req) { | ||||
| } | ||||
|  | ||||
| function updateNoteData(req) { | ||||
|     const {content, ancillaries} = req.body; | ||||
|     const {content, attachments} = req.body; | ||||
|     const {noteId} = req.params; | ||||
|  | ||||
|     return noteService.updateNoteData(noteId, content, ancillaries); | ||||
|     return noteService.updateNoteData(noteId, content, attachments); | ||||
| } | ||||
|  | ||||
| function deleteNote(req) { | ||||
| @@ -127,7 +127,7 @@ function setNoteTypeMime(req) { | ||||
|     note.save(); | ||||
| } | ||||
|  | ||||
| function getNoteAncillaries(req) { | ||||
| function getNoteAttachments(req) { | ||||
|     const includeContent = req.query.includeContent === 'true'; | ||||
|     const {noteId} = req.params; | ||||
|  | ||||
| @@ -137,19 +137,19 @@ function getNoteAncillaries(req) { | ||||
|         throw new NotFoundError(`Note '${noteId}' doesn't exist.`); | ||||
|     } | ||||
|  | ||||
|     const noteAncillaries = note.getNoteAncillaries(); | ||||
|     const noteAttachments = note.getNoteAttachments(); | ||||
|  | ||||
|     return noteAncillaries.map(ancillary => { | ||||
|        const pojo = ancillary.getPojo(); | ||||
|     return noteAttachments.map(attachment => { | ||||
|        const pojo = attachment.getPojo(); | ||||
|  | ||||
|        if (includeContent && utils.isStringNote(null, ancillary.mime)) { | ||||
|            pojo.content = ancillary.getContent()?.toString(); | ||||
|        if (includeContent && utils.isStringNote(null, attachment.mime)) { | ||||
|            pojo.content = attachment.getContent()?.toString(); | ||||
|            pojo.contentLength = pojo.content.length; | ||||
|  | ||||
|            const MAX_ANCILLARY_LENGTH = 1_000_000; | ||||
|            const MAX_ATTACHMENT_LENGTH = 1_000_000; | ||||
|  | ||||
|            if (pojo.content.length > MAX_ANCILLARY_LENGTH) { | ||||
|                pojo.content = pojo.content.substring(0, MAX_ANCILLARY_LENGTH); | ||||
|            if (pojo.content.length > MAX_ATTACHMENT_LENGTH) { | ||||
|                pojo.content = pojo.content.substring(0, MAX_ATTACHMENT_LENGTH); | ||||
|            } | ||||
|        } | ||||
|  | ||||
| @@ -157,7 +157,7 @@ function getNoteAncillaries(req) { | ||||
|     }); | ||||
| } | ||||
|  | ||||
| function saveNoteAncillary(req) { | ||||
| function saveNoteAttachment(req) { | ||||
|     const {noteId, name} = req.params; | ||||
|     const {mime, content} = req.body; | ||||
|  | ||||
| @@ -167,7 +167,7 @@ function saveNoteAncillary(req) { | ||||
|         throw new NotFoundError(`Note '${noteId}' doesn't exist.`); | ||||
|     } | ||||
|  | ||||
|     note.saveNoteAncillary(name, mime, content); | ||||
|     note.saveNoteAttachment(name, mime, content); | ||||
| } | ||||
|  | ||||
| function getRelationMap(req) { | ||||
| @@ -384,6 +384,6 @@ module.exports = { | ||||
|     getDeleteNotesPreview, | ||||
|     uploadModifiedFile, | ||||
|     forceSaveNoteRevision, | ||||
|     getNoteAncillaries, | ||||
|     saveNoteAncillary | ||||
|     getNoteAttachments, | ||||
|     saveNoteAttachment | ||||
| }; | ||||
|   | ||||
| @@ -113,9 +113,9 @@ function forceNoteSync(req) { | ||||
|         entityChangesService.moveEntityChangeToTop('note_revisions', noteRevisionId); | ||||
|     } | ||||
|  | ||||
|     for (const noteAncillaryId of sql.getColumn("SELECT noteAncillaryId FROM note_ancillaries WHERE noteId = ?", [noteId])) { | ||||
|         sql.execute(`UPDATE note_ancillaries SET utcDateModified = ? WHERE noteAncillaryId = ?`, [now, noteAncillaryId]); | ||||
|         entityChangesService.moveEntityChangeToTop('note_ancillaries', noteAncillaryId); | ||||
|     for (const noteAttachmentId of sql.getColumn("SELECT noteAttachmentId FROM note_attachments WHERE noteId = ?", [noteId])) { | ||||
|         sql.execute(`UPDATE note_attachments SET utcDateModified = ? WHERE noteAttachmentId = ?`, [now, noteAttachmentId]); | ||||
|         entityChangesService.moveEntityChangeToTop('note_attachments', noteAttachmentId); | ||||
|     } | ||||
|  | ||||
|     log.info(`Forcing note sync for ${noteId}`); | ||||
|   | ||||
| @@ -126,8 +126,8 @@ function register(app) { | ||||
|     apiRoute(PUT, '/api/notes/:noteId/sort-children', notesApiRoute.sortChildNotes); | ||||
|     apiRoute(PUT, '/api/notes/:noteId/protect/:isProtected', notesApiRoute.protectNote); | ||||
|     apiRoute(PUT, '/api/notes/:noteId/type', notesApiRoute.setNoteTypeMime); | ||||
|     apiRoute(GET, '/api/notes/:noteId/ancillaries', notesApiRoute.getNoteAncillaries); | ||||
|     apiRoute(PUT, '/api/notes/:noteId/ancillaries/:name', notesApiRoute.saveNoteAncillary); | ||||
|     apiRoute(GET, '/api/notes/:noteId/attachments', notesApiRoute.getNoteAttachments); | ||||
|     apiRoute(PUT, '/api/notes/:noteId/attachments/:name', notesApiRoute.saveNoteAttachment); | ||||
|     apiRoute(GET, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.getNoteRevisions); | ||||
|     apiRoute(DELETE, '/api/notes/:noteId/revisions', noteRevisionsApiRoute.eraseAllNoteRevisions); | ||||
|     apiRoute(GET, '/api/notes/:noteId/revisions/:noteRevisionId', noteRevisionsApiRoute.getNoteRevision); | ||||
|   | ||||
| @@ -215,21 +215,21 @@ class ConsistencyChecks { | ||||
|             }); | ||||
|  | ||||
|         this.findAndFixIssues(` | ||||
|                     SELECT noteAncillaryId, note_ancillaries.noteId AS noteId | ||||
|                     FROM note_ancillaries | ||||
|                     SELECT noteAttachmentId, note_attachments.noteId AS noteId | ||||
|                     FROM note_attachments | ||||
|                       LEFT JOIN notes USING (noteId) | ||||
|                     WHERE notes.noteId IS NULL | ||||
|                       AND note_ancillaries.isDeleted = 0`, | ||||
|             ({noteAncillaryId, noteId}) => { | ||||
|                       AND note_attachments.isDeleted = 0`, | ||||
|             ({noteAttachmentId, noteId}) => { | ||||
|                 if (this.autoFix) { | ||||
|                     const noteAncillary = becca.getNoteAncillary(noteAncillaryId); | ||||
|                     noteAncillary.markAsDeleted(); | ||||
|                     const noteAttachment = becca.getNoteAttachment(noteAttachmentId); | ||||
|                     noteAttachment.markAsDeleted(); | ||||
|  | ||||
|                     this.reloadNeeded = false; | ||||
|  | ||||
|                     logFix(`Note ancillary '${noteAncillaryId}' has been deleted since it references missing note '${noteId}'`); | ||||
|                     logFix(`Note attachment '${noteAttachmentId}' has been deleted since it references missing note '${noteId}'`); | ||||
|                 } else { | ||||
|                     logError(`Note ancillary '${noteAncillaryId}' references missing note '${noteId}'`); | ||||
|                     logError(`Note attachment '${noteAttachmentId}' references missing note '${noteId}'`); | ||||
|                 } | ||||
|             }); | ||||
|     } | ||||
| @@ -341,22 +341,22 @@ class ConsistencyChecks { | ||||
|             }); | ||||
|  | ||||
|         this.findAndFixIssues(` | ||||
|                     SELECT noteAncillaryId, | ||||
|                            note_ancillaries.noteId AS noteId | ||||
|                     FROM note_ancillaries | ||||
|                     SELECT noteAttachmentId, | ||||
|                            note_attachments.noteId AS noteId | ||||
|                     FROM note_attachments | ||||
|                       JOIN notes USING (noteId) | ||||
|                     WHERE notes.isDeleted = 1 | ||||
|                       AND note_ancillaries.isDeleted = 0`, | ||||
|             ({noteAncillaryId, noteId}) => { | ||||
|                       AND note_attachments.isDeleted = 0`, | ||||
|             ({noteAttachmentId, noteId}) => { | ||||
|                 if (this.autoFix) { | ||||
|                     const noteAncillary = becca.getNoteAncillary(noteAncillaryId); | ||||
|                     noteAncillary.markAsDeleted(); | ||||
|                     const noteAttachment = becca.getNoteAttachment(noteAttachmentId); | ||||
|                     noteAttachment.markAsDeleted(); | ||||
|  | ||||
|                     this.reloadNeeded = false; | ||||
|  | ||||
|                     logFix(`Note ancillary '${noteAncillaryId}' has been deleted since associated note '${noteId}' is deleted.`); | ||||
|                     logFix(`Note attachment '${noteAttachmentId}' has been deleted since associated note '${noteId}' is deleted.`); | ||||
|                 } else { | ||||
|                     logError(`Note ancillary '${noteAncillaryId}' is not deleted even though associated note '${noteId}' is deleted.`) | ||||
|                     logError(`Note attachment '${noteAttachmentId}' is not deleted even though associated note '${noteId}' is deleted.`) | ||||
|                 } | ||||
|             }); | ||||
|     } | ||||
| @@ -657,7 +657,7 @@ class ConsistencyChecks { | ||||
|     findEntityChangeIssues() { | ||||
|         this.runEntityChangeChecks("notes", "noteId"); | ||||
|         this.runEntityChangeChecks("note_revisions", "noteRevisionId"); | ||||
|         this.runEntityChangeChecks("note_ancillaries", "noteAncillaryId"); | ||||
|         this.runEntityChangeChecks("note_attachments", "noteAttachmentId"); | ||||
|         this.runEntityChangeChecks("blobs", "blobId"); | ||||
|         this.runEntityChangeChecks("branches", "branchId"); | ||||
|         this.runEntityChangeChecks("attributes", "attributeId"); | ||||
| @@ -754,7 +754,7 @@ class ConsistencyChecks { | ||||
|             return `${tableName}: ${count}`; | ||||
|         } | ||||
|  | ||||
|         const tables = [ "notes", "note_revisions", "note_ancillaries", "branches", "attributes", "etapi_tokens" ]; | ||||
|         const tables = [ "notes", "note_revisions", "note_attachments", "branches", "attributes", "etapi_tokens" ]; | ||||
|  | ||||
|         log.info(`Table counts: ${tables.map(tableName => getTableRowCount(tableName)).join(", ")}`); | ||||
|     } | ||||
|   | ||||
| @@ -149,7 +149,7 @@ function fillAllEntityChanges() { | ||||
|         fillEntityChanges("notes", "noteId"); | ||||
|         fillEntityChanges("branches", "branchId"); | ||||
|         fillEntityChanges("note_revisions", "noteRevisionId"); | ||||
|         fillEntityChanges("note_ancillaries", "noteAncillaryId"); | ||||
|         fillEntityChanges("note_attachments", "noteAttachmentId"); | ||||
|         fillEntityChanges("blobs", "blobId"); | ||||
|         fillEntityChanges("attributes", "attributeId"); | ||||
|         fillEntityChanges("etapi_tokens", "etapiTokenId"); | ||||
|   | ||||
| @@ -170,19 +170,19 @@ async function exportToZip(taskContext, branch, format, res, setHeaders = true) | ||||
|             meta.dataFileName = getDataFileName(note.type, note.mime, baseFileName, existingFileNames); | ||||
|         } | ||||
|  | ||||
|         const ancillaries = note.getNoteAncillaries(); | ||||
|         const attachments = note.getNoteAttachments(); | ||||
|  | ||||
|         if (ancillaries.length > 0) { | ||||
|             meta.ancillaries = ancillaries | ||||
|                 .filter(ancillary => ["canvasSvg", "mermaidSvg"].includes(ancillary.name)) | ||||
|                 .map(ancillary => ({ | ||||
|         if (attachments.length > 0) { | ||||
|             meta.attachments = attachments | ||||
|                 .filter(attachment => ["canvasSvg", "mermaidSvg"].includes(attachment.name)) | ||||
|                 .map(attachment => ({ | ||||
|  | ||||
|                 name: ancillary.name, | ||||
|                 mime: ancillary.mime, | ||||
|                 name: attachment.name, | ||||
|                 mime: attachment.mime, | ||||
|                 dataFileName: getDataFileName( | ||||
|                     null, | ||||
|                     ancillary.mime, | ||||
|                     baseFileName + "_" + ancillary.name, | ||||
|                     attachment.mime, | ||||
|                     baseFileName + "_" + attachment.name, | ||||
|                     existingFileNames | ||||
|                 ) | ||||
|             })); | ||||
| @@ -337,12 +337,12 @@ ${markdownContent}`; | ||||
|  | ||||
|         taskContext.increaseProgressCount(); | ||||
|  | ||||
|         for (const ancillaryMeta of noteMeta.ancillaries || []) { | ||||
|             const noteAncillary = note.getNoteAncillaryByName(ancillaryMeta.name); | ||||
|             const content = noteAncillary.getContent(); | ||||
|         for (const attachmentMeta of noteMeta.attachments || []) { | ||||
|             const noteAttachment = note.getNoteAttachmentByName(attachmentMeta.name); | ||||
|             const content = noteAttachment.getContent(); | ||||
|  | ||||
|             archive.append(content, { | ||||
|                 name: filePathPrefix + ancillaryMeta.dataFileName, | ||||
|                 name: filePathPrefix + attachmentMeta.dataFileName, | ||||
|                 date: dateUtils.parseDateTime(note.utcDateModified) | ||||
|             }); | ||||
|         } | ||||
|   | ||||
| @@ -14,7 +14,7 @@ const treeService = require("../tree"); | ||||
| const yauzl = require("yauzl"); | ||||
| const htmlSanitizer = require('../html_sanitizer'); | ||||
| const becca = require("../../becca/becca"); | ||||
| const BNoteAncillary = require("../../becca/entities/bnote_attachment.js"); | ||||
| const BNoteAttachment = require("../../becca/entities/bnote_attachment.js"); | ||||
|  | ||||
| /** | ||||
|  * @param {TaskContext} taskContext | ||||
| @@ -65,7 +65,7 @@ async function importZip(taskContext, fileBuffer, importRootNote) { | ||||
|         }; | ||||
|  | ||||
|         let parent; | ||||
|         let ancillaryMeta = false; | ||||
|         let attachmentMeta = false; | ||||
|  | ||||
|         for (const segment of pathSegments) { | ||||
|             if (!cursor || !cursor.children || cursor.children.length === 0) { | ||||
| @@ -77,10 +77,10 @@ async function importZip(taskContext, fileBuffer, importRootNote) { | ||||
|  | ||||
|             if (!cursor) { | ||||
|                 for (const file of parent.children) { | ||||
|                     for (const ancillary of file.ancillaries || []) { | ||||
|                         if (ancillary.dataFileName === segment) { | ||||
|                     for (const attachment of file.attachments || []) { | ||||
|                         if (attachment.dataFileName === segment) { | ||||
|                             cursor = file; | ||||
|                             ancillaryMeta = ancillary; | ||||
|                             attachmentMeta = attachment; | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
| @@ -95,7 +95,7 @@ async function importZip(taskContext, fileBuffer, importRootNote) { | ||||
|         return { | ||||
|             parentNoteMeta: parent, | ||||
|             noteMeta: cursor, | ||||
|             ancillaryMeta | ||||
|             attachmentMeta | ||||
|         }; | ||||
|     } | ||||
|  | ||||
| @@ -370,7 +370,7 @@ async function importZip(taskContext, fileBuffer, importRootNote) { | ||||
|     } | ||||
|  | ||||
|     function saveNote(filePath, content) { | ||||
|         const {parentNoteMeta, noteMeta, ancillaryMeta} = getMeta(filePath); | ||||
|         const {parentNoteMeta, noteMeta, attachmentMeta} = getMeta(filePath); | ||||
|  | ||||
|         if (noteMeta?.noImport) { | ||||
|             return; | ||||
| @@ -378,14 +378,14 @@ async function importZip(taskContext, fileBuffer, importRootNote) { | ||||
|  | ||||
|         const noteId = getNoteId(noteMeta, filePath); | ||||
|  | ||||
|         if (ancillaryMeta) { | ||||
|             const noteAncillary = new BNoteAncillary({ | ||||
|         if (attachmentMeta) { | ||||
|             const noteAttachment = new BNoteAttachment({ | ||||
|                 noteId, | ||||
|                 name: ancillaryMeta.name, | ||||
|                 mime: ancillaryMeta.mime | ||||
|                 name: attachmentMeta.name, | ||||
|                 mime: attachmentMeta.mime | ||||
|             }); | ||||
|  | ||||
|             noteAncillary.setContent(content); | ||||
|             noteAttachment.setContent(content); | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|   | ||||
| @@ -4,27 +4,27 @@ const log = require("./log"); | ||||
| /** | ||||
|  * @param {BNote} note | ||||
|  */ | ||||
| function protectNoteAncillaries(note) { | ||||
|     for (const noteAncillary of note.getNoteAncillaries()) { | ||||
|         if (note.isProtected !== noteAncillary.isProtected) { | ||||
| function protectNoteAttachments(note) { | ||||
|     for (const noteAttachment of note.getNoteAttachments()) { | ||||
|         if (note.isProtected !== noteAttachment.isProtected) { | ||||
|             if (!protectedSession.isProtectedSessionAvailable()) { | ||||
|                 log.error("Protected session is not available to fix note ancillaries."); | ||||
|                 log.error("Protected session is not available to fix note attachments."); | ||||
|  | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             try { | ||||
|                 const content = noteAncillary.getContent(); | ||||
|                 const content = noteAttachment.getContent(); | ||||
|  | ||||
|                 noteAncillary.isProtected = note.isProtected; | ||||
|                 noteAttachment.isProtected = note.isProtected; | ||||
|  | ||||
|                 // this will force de/encryption | ||||
|                 noteAncillary.setContent(content); | ||||
|                 noteAttachment.setContent(content); | ||||
|  | ||||
|                 noteAncillary.save(); | ||||
|                 noteAttachment.save(); | ||||
|             } | ||||
|             catch (e) { | ||||
|                 log.error(`Could not un/protect note ancillary ID = ${noteAncillary.noteAncillaryId}`); | ||||
|                 log.error(`Could not un/protect note attachment ID = ${noteAttachment.noteAttachmentId}`); | ||||
|  | ||||
|                 throw e; | ||||
|             } | ||||
| @@ -33,5 +33,5 @@ function protectNoteAncillaries(note) { | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
|     protectNoteAncillaries | ||||
|     protectNoteAttachments | ||||
| } | ||||
|   | ||||
| @@ -114,7 +114,7 @@ function eraseEntity(entityChange, instanceId) { | ||||
|         "branches", | ||||
|         "attributes", | ||||
|         "note_revisions", | ||||
|         "note_ancillaries", | ||||
|         "note_attachments", | ||||
|         "blobs", | ||||
|     ]; | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user