mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-04 04:16:17 +01:00 
			
		
		
		
	fix undelete
This commit is contained in:
		@@ -1,7 +1,7 @@
 | 
				
			|||||||
"use strict";
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const imageService = require('../../services/image');
 | 
					const imageService = require('../../services/image');
 | 
				
			||||||
const repository = require('../../services/repository');
 | 
					const becca = require('../../services/becca/becca');
 | 
				
			||||||
const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR;
 | 
					const RESOURCE_DIR = require('../../services/resource_dir').RESOURCE_DIR;
 | 
				
			||||||
const fs = require('fs');
 | 
					const fs = require('fs');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,11 +81,9 @@ function deleteNote(req) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function undeleteNote(req) {
 | 
					function undeleteNote(req) {
 | 
				
			||||||
    const note = becca.getNote(req.params.noteId);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    const taskContext = TaskContext.getInstance(utils.randomString(10), 'undeleteNotes');
 | 
					    const taskContext = TaskContext.getInstance(utils.randomString(10), 'undeleteNotes');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    noteService.undeleteNote(note, note.deleteId, taskContext);
 | 
					    noteService.undeleteNote(req.params.noteId, taskContext);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    taskContext.taskSucceeded();
 | 
					    taskContext.taskSucceeded();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,12 +9,13 @@ const Note = require('./entities/note');
 | 
				
			|||||||
const Branch = require('./entities/branch');
 | 
					const Branch = require('./entities/branch');
 | 
				
			||||||
const Attribute = require('./entities/attribute');
 | 
					const Attribute = require('./entities/attribute');
 | 
				
			||||||
const Option = require('./entities/option');
 | 
					const Option = require('./entities/option');
 | 
				
			||||||
 | 
					const cls = require("../cls.js");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const beccaLoaded = new Promise((res, rej) => {
 | 
					const beccaLoaded = new Promise((res, rej) => {
 | 
				
			||||||
    sqlInit.dbReady.then(() => {
 | 
					    sqlInit.dbReady.then(() => {
 | 
				
			||||||
        load();
 | 
					        load();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        require('../options_init').initStartupOptions();
 | 
					        cls.init(() => require('../options_init').initStartupOptions());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        res();
 | 
					        res();
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,8 +3,9 @@
 | 
				
			|||||||
const utils = require('../../utils');
 | 
					const utils = require('../../utils');
 | 
				
			||||||
const sql = require('../../sql');
 | 
					const sql = require('../../sql');
 | 
				
			||||||
const entityChangesService = require('../../entity_changes');
 | 
					const entityChangesService = require('../../entity_changes');
 | 
				
			||||||
const eventService = require("../../events.js");
 | 
					const eventService = require("../../events");
 | 
				
			||||||
const cls = require("../../cls.js");
 | 
					const dateUtils = require("../../date_utils");
 | 
				
			||||||
 | 
					const cls = require("../../cls");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let becca = null;
 | 
					let becca = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -99,8 +100,14 @@ class AbstractEntity {
 | 
				
			|||||||
        const entityId = this[this.constructor.primaryKeyName];
 | 
					        const entityId = this[this.constructor.primaryKeyName];
 | 
				
			||||||
        const entityName = this.constructor.entityName;
 | 
					        const entityName = this.constructor.entityName;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sql.execute(`UPDATE ${entityName} SET isDeleted = 1, deleteId = ? WHERE ${this.constructor.primaryKeyName} = ?`,
 | 
					        sql.execute(`UPDATE ${entityName} SET isDeleted = 1, deleteId = ?, utcDateModified = ?
 | 
				
			||||||
            [deleteId, entityId]);
 | 
					                           WHERE ${this.constructor.primaryKeyName} = ?`,
 | 
				
			||||||
 | 
					            [deleteId, dateUtils.utcNowDateTime(), entityId]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (this.dateModified) {
 | 
				
			||||||
 | 
					            sql.execute(`UPDATE ${entityName} SET dateModified = ? WHERE ${this.constructor.primaryKeyName} = ?`,
 | 
				
			||||||
 | 
					                [dateUtils.localNowDateTime(), entityId]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.addEntityChange(true);
 | 
					        this.addEntityChange(true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -91,6 +91,7 @@ class Branch extends AbstractEntity {
 | 
				
			|||||||
            prefix: this.prefix,
 | 
					            prefix: this.prefix,
 | 
				
			||||||
            notePosition: this.notePosition,
 | 
					            notePosition: this.notePosition,
 | 
				
			||||||
            isExpanded: this.isExpanded,
 | 
					            isExpanded: this.isExpanded,
 | 
				
			||||||
 | 
					            isDeleted: false,
 | 
				
			||||||
            utcDateModified: this.utcDateModified,
 | 
					            utcDateModified: this.utcDateModified,
 | 
				
			||||||
            // not used for anything, will be later dropped
 | 
					            // not used for anything, will be later dropped
 | 
				
			||||||
            utcDateCreated: dateUtils.utcNowDateTime()
 | 
					            utcDateCreated: dateUtils.utcNowDateTime()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -79,7 +79,7 @@ class Note extends AbstractEntity {
 | 
				
			|||||||
        // ------ Derived attributes ------
 | 
					        // ------ Derived attributes ------
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        /** @param {boolean} */
 | 
					        /** @param {boolean} */
 | 
				
			||||||
        this.isDecrypted = !row.isProtected || !!row.isContentAvailable;
 | 
					        this.isDecrypted = !row.isProtected || row.isContentAvailable;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.decrypt();
 | 
					        this.decrypt();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -87,6 +87,12 @@ class Note extends AbstractEntity {
 | 
				
			|||||||
        this.flatTextCache = null;
 | 
					        this.flatTextCache = null;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    get isContentAvailable() {
 | 
				
			||||||
 | 
					        return !this.noteId // new note which was not encrypted yet
 | 
				
			||||||
 | 
					            || !this.isProtected
 | 
				
			||||||
 | 
					            || protectedSessionService.isProtectedSessionAvailable()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    getParentBranches() {
 | 
					    getParentBranches() {
 | 
				
			||||||
        return this.parentBranches;
 | 
					        return this.parentBranches;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -852,6 +858,7 @@ class Note extends AbstractEntity {
 | 
				
			|||||||
            isProtected: this.isProtected,
 | 
					            isProtected: this.isProtected,
 | 
				
			||||||
            type: this.type,
 | 
					            type: this.type,
 | 
				
			||||||
            mime: this.mime,
 | 
					            mime: this.mime,
 | 
				
			||||||
 | 
					            isDeleted: false,
 | 
				
			||||||
            dateCreated: this.dateCreated,
 | 
					            dateCreated: this.dateCreated,
 | 
				
			||||||
            dateModified: this.dateModified,
 | 
					            dateModified: this.dateModified,
 | 
				
			||||||
            utcDateCreated: this.utcDateCreated,
 | 
					            utcDateCreated: this.utcDateCreated,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,9 +5,6 @@ const dateUtils = require('./date_utils');
 | 
				
			|||||||
const entityChangesService = require('./entity_changes.js');
 | 
					const entityChangesService = require('./entity_changes.js');
 | 
				
			||||||
const eventService = require('./events');
 | 
					const eventService = require('./events');
 | 
				
			||||||
const cls = require('../services/cls');
 | 
					const cls = require('../services/cls');
 | 
				
			||||||
const BeccaNote = require('../services/becca/entities/note.js');
 | 
					 | 
				
			||||||
const BeccaBranch = require('../services/becca/entities/branch.js');
 | 
					 | 
				
			||||||
const BeccaAttribute = require('../services/becca/entities/attribute.js');
 | 
					 | 
				
			||||||
const protectedSessionService = require('../services/protected_session');
 | 
					const protectedSessionService = require('../services/protected_session');
 | 
				
			||||||
const log = require('../services/log');
 | 
					const log = require('../services/log');
 | 
				
			||||||
const utils = require('../services/utils');
 | 
					const utils = require('../services/utils');
 | 
				
			||||||
@@ -69,7 +66,7 @@ function deriveMime(type, mime) {
 | 
				
			|||||||
function copyChildAttributes(parentNote, childNote) {
 | 
					function copyChildAttributes(parentNote, childNote) {
 | 
				
			||||||
    for (const attr of parentNote.getAttributes()) {
 | 
					    for (const attr of parentNote.getAttributes()) {
 | 
				
			||||||
        if (attr.name.startsWith("child:")) {
 | 
					        if (attr.name.startsWith("child:")) {
 | 
				
			||||||
            new BeccaAttribute({
 | 
					            new Attribute({
 | 
				
			||||||
                noteId: childNote.noteId,
 | 
					                noteId: childNote.noteId,
 | 
				
			||||||
                type: attr.type,
 | 
					                type: attr.type,
 | 
				
			||||||
                name: attr.name.substr(6),
 | 
					                name: attr.name.substr(6),
 | 
				
			||||||
@@ -110,7 +107,7 @@ function createNewNote(params) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return sql.transactional(() => {
 | 
					    return sql.transactional(() => {
 | 
				
			||||||
        const note = new BeccaNote({
 | 
					        const note = new Note({
 | 
				
			||||||
            noteId: params.noteId, // optionally can force specific noteId
 | 
					            noteId: params.noteId, // optionally can force specific noteId
 | 
				
			||||||
            title: params.title,
 | 
					            title: params.title,
 | 
				
			||||||
            isProtected: !!params.isProtected,
 | 
					            isProtected: !!params.isProtected,
 | 
				
			||||||
@@ -120,7 +117,7 @@ function createNewNote(params) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        note.setContent(params.content);
 | 
					        note.setContent(params.content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const branch = new BeccaBranch({
 | 
					        const branch = new Branch({
 | 
				
			||||||
            noteId: note.noteId,
 | 
					            noteId: note.noteId,
 | 
				
			||||||
            parentNoteId: params.parentNoteId,
 | 
					            parentNoteId: params.parentNoteId,
 | 
				
			||||||
            notePosition: params.notePosition !== undefined ? params.notePosition : getNewNotePosition(params.parentNoteId),
 | 
					            notePosition: params.notePosition !== undefined ? params.notePosition : getNewNotePosition(params.parentNoteId),
 | 
				
			||||||
@@ -430,7 +427,7 @@ function saveLinks(note, content) {
 | 
				
			|||||||
            && existingLink.name === foundLink.name);
 | 
					            && existingLink.name === foundLink.name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!existingLink) {
 | 
					        if (!existingLink) {
 | 
				
			||||||
            const newLink = new BeccaAttribute({
 | 
					            const newLink = new Attribute({
 | 
				
			||||||
                noteId: note.noteId,
 | 
					                noteId: note.noteId,
 | 
				
			||||||
                type: 'relation',
 | 
					                type: 'relation',
 | 
				
			||||||
                name: foundLink.name,
 | 
					                name: foundLink.name,
 | 
				
			||||||
@@ -566,12 +563,18 @@ function deleteBranch(branch, deleteId, taskContext) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * @param {Note} note
 | 
					 * @param {string} noteId
 | 
				
			||||||
 * @param {string} deleteId
 | 
					 | 
				
			||||||
 * @param {TaskContext} taskContext
 | 
					 * @param {TaskContext} taskContext
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
function undeleteNote(note, deleteId, taskContext) {
 | 
					function undeleteNote(noteId, taskContext) {
 | 
				
			||||||
    const undeletedParentBranchIds = getUndeletedParentBranchIds(note.noteId, deleteId);
 | 
					    const note = sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!note.isDeleted) {
 | 
				
			||||||
 | 
					        log.error(`Note ${noteId} is not deleted and thus cannot be undeleted.`);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const undeletedParentBranchIds = getUndeletedParentBranchIds(noteId, note.deleteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (undeletedParentBranchIds.length === 0) {
 | 
					    if (undeletedParentBranchIds.length === 0) {
 | 
				
			||||||
        // cannot undelete if there's no undeleted parent
 | 
					        // cannot undelete if there's no undeleted parent
 | 
				
			||||||
@@ -579,7 +582,7 @@ function undeleteNote(note, deleteId, taskContext) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (const parentBranchId of undeletedParentBranchIds) {
 | 
					    for (const parentBranchId of undeletedParentBranchIds) {
 | 
				
			||||||
        undeleteBranch(parentBranchId, deleteId, taskContext);
 | 
					        undeleteBranch(parentBranchId, note.deleteId, taskContext);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -620,7 +623,7 @@ function undeleteBranch(branchId, deleteId, taskContext) {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const childBranchIds = sql.getColumn(`
 | 
					        const childBranchIds = sql.getColumn(`
 | 
				
			||||||
            SELECT branches.id
 | 
					            SELECT branches.branchId
 | 
				
			||||||
            FROM branches
 | 
					            FROM branches
 | 
				
			||||||
            WHERE branches.isDeleted = 1
 | 
					            WHERE branches.isDeleted = 1
 | 
				
			||||||
              AND branches.deleteId = ?
 | 
					              AND branches.deleteId = ?
 | 
				
			||||||
@@ -789,7 +792,7 @@ function duplicateSubtreeInner(origNote, origBranch, newParentNoteId, noteIdMapp
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    const newNoteId = noteIdMapping[origNote.noteId];
 | 
					    const newNoteId = noteIdMapping[origNote.noteId];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const newBranch = new BeccaBranch({
 | 
					    const newBranch = new Branch({
 | 
				
			||||||
        noteId: newNoteId,
 | 
					        noteId: newNoteId,
 | 
				
			||||||
        parentNoteId: newParentNoteId,
 | 
					        parentNoteId: newParentNoteId,
 | 
				
			||||||
        // here increasing just by 1 to make sure it's directly after original
 | 
					        // here increasing just by 1 to make sure it's directly after original
 | 
				
			||||||
@@ -807,7 +810,7 @@ function duplicateSubtreeInner(origNote, origBranch, newParentNoteId, noteIdMapp
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const newNote = new BeccaNote(origNote);
 | 
					    const newNote = new Note(origNote);
 | 
				
			||||||
    newNote.noteId = newNoteId;
 | 
					    newNote.noteId = newNoteId;
 | 
				
			||||||
    newNote.dateCreated = dateUtils.localNowDateTime();
 | 
					    newNote.dateCreated = dateUtils.localNowDateTime();
 | 
				
			||||||
    newNote.utcDateCreated = dateUtils.utcNowDateTime();
 | 
					    newNote.utcDateCreated = dateUtils.utcNowDateTime();
 | 
				
			||||||
@@ -823,7 +826,7 @@ function duplicateSubtreeInner(origNote, origBranch, newParentNoteId, noteIdMapp
 | 
				
			|||||||
    newNote.setContent(content);
 | 
					    newNote.setContent(content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (const attribute of origNote.getOwnedAttributes()) {
 | 
					    for (const attribute of origNote.getOwnedAttributes()) {
 | 
				
			||||||
        const attr = new BeccaAttribute(attribute);
 | 
					        const attr = new Attribute(attribute);
 | 
				
			||||||
        attr.attributeId = undefined; // force creation of new attribute
 | 
					        attr.attributeId = undefined; // force creation of new attribute
 | 
				
			||||||
        attr.noteId = newNote.noteId;
 | 
					        attr.noteId = newNote.noteId;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user