mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
protect/unprotect subtree
This commit is contained in:
parent
c2ad14ba18
commit
9cf935efd1
@ -31,8 +31,8 @@ const contextMenu = (function() {
|
|||||||
{title: "Insert child note", cmd: "insertChildNote", uiIcon: "ui-icon-pencil"},
|
{title: "Insert child note", cmd: "insertChildNote", uiIcon: "ui-icon-pencil"},
|
||||||
{title: "Delete", cmd: "delete", uiIcon: "ui-icon-trash"},
|
{title: "Delete", cmd: "delete", uiIcon: "ui-icon-trash"},
|
||||||
{title: "----"},
|
{title: "----"},
|
||||||
{title: "Encrypt sub-tree", cmd: "encryptSubTree", uiIcon: "ui-icon-locked"},
|
{title: "Protect sub-tree", cmd: "protectSubTree", uiIcon: "ui-icon-locked"},
|
||||||
{title: "Decrypt sub-tree", cmd: "decryptSubTree", uiIcon: "ui-icon-unlocked"},
|
{title: "Unprotect sub-tree", cmd: "unprotectSubTree", uiIcon: "ui-icon-unlocked"},
|
||||||
{title: "----"},
|
{title: "----"},
|
||||||
{title: "Cut", cmd: "cut", uiIcon: "ui-icon-scissors"},
|
{title: "Cut", cmd: "cut", uiIcon: "ui-icon-scissors"},
|
||||||
{title: "Copy / clone", cmd: "copy", uiIcon: "ui-icon-copy"},
|
{title: "Copy / clone", cmd: "copy", uiIcon: "ui-icon-copy"},
|
||||||
@ -45,6 +45,9 @@ const contextMenu = (function() {
|
|||||||
treeEl.contextmenu("enableEntry", "pasteAfter", noteTree.getClipboardNoteId() !== null);
|
treeEl.contextmenu("enableEntry", "pasteAfter", noteTree.getClipboardNoteId() !== null);
|
||||||
treeEl.contextmenu("enableEntry", "pasteInto", noteTree.getClipboardNoteId() !== null);
|
treeEl.contextmenu("enableEntry", "pasteInto", noteTree.getClipboardNoteId() !== null);
|
||||||
|
|
||||||
|
treeEl.contextmenu("enableEntry", "protectSubTree", protected_session.isProtectedSessionAvailable());
|
||||||
|
treeEl.contextmenu("enableEntry", "unprotectSubTree", protected_session.isProtectedSessionAvailable());
|
||||||
|
|
||||||
// Activate node on right-click
|
// Activate node on right-click
|
||||||
node.setActive();
|
node.setActive();
|
||||||
// Disable tree keyboard handling
|
// Disable tree keyboard handling
|
||||||
@ -64,11 +67,11 @@ const contextMenu = (function() {
|
|||||||
else if (ui.cmd === "insertChildNote") {
|
else if (ui.cmd === "insertChildNote") {
|
||||||
noteEditor.createNote(node, node.key, 'into');
|
noteEditor.createNote(node, node.key, 'into');
|
||||||
}
|
}
|
||||||
else if (ui.cmd === "encryptSubTree") {
|
else if (ui.cmd === "protectSubTree") {
|
||||||
protected_session.encryptSubTree(node.key);
|
protected_session.protectSubTree(node.key, true);
|
||||||
}
|
}
|
||||||
else if (ui.cmd === "decryptSubTree") {
|
else if (ui.cmd === "unprotectSubTree") {
|
||||||
protected_session.decryptSubTree(node.key);
|
protected_session.protectSubTree(node.key, false);
|
||||||
}
|
}
|
||||||
else if (ui.cmd === "cut") {
|
else if (ui.cmd === "cut") {
|
||||||
cut(node);
|
cut(node);
|
||||||
|
@ -147,6 +147,20 @@ const protected_session = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function protectSubTree(noteId, protect) {
|
||||||
|
await $.ajax({
|
||||||
|
url: baseApiUrl + 'tree/' + noteId + "/protectSubTree/" + (protect ? 1 : 0),
|
||||||
|
type: 'PUT',
|
||||||
|
contentType: 'application/json',
|
||||||
|
error: () => showError("Request to un/protect sub tree has failed.")
|
||||||
|
});
|
||||||
|
|
||||||
|
showMessage("Request to un/protect sub tree has finished successfully");
|
||||||
|
|
||||||
|
noteTree.reload();
|
||||||
|
noteEditor.reload();
|
||||||
|
}
|
||||||
|
|
||||||
passwordFormEl.submit(() => {
|
passwordFormEl.submit(() => {
|
||||||
setupProtectedSession();
|
setupProtectedSession();
|
||||||
|
|
||||||
@ -167,6 +181,7 @@ const protected_session = (function() {
|
|||||||
protectNoteAndSendToServer,
|
protectNoteAndSendToServer,
|
||||||
unprotectNoteAndSendToServer,
|
unprotectNoteAndSendToServer,
|
||||||
getProtectedSessionId,
|
getProtectedSessionId,
|
||||||
touchProtectedSession
|
touchProtectedSession,
|
||||||
|
protectSubTree
|
||||||
};
|
};
|
||||||
})();
|
})();
|
@ -12,11 +12,11 @@ const data_encryption = require('../../services/data_encryption');
|
|||||||
const RequestContext = require('../../services/request_context');
|
const RequestContext = require('../../services/request_context');
|
||||||
|
|
||||||
router.get('/:noteId', auth.checkApiAuth, async (req, res, next) => {
|
router.get('/:noteId', auth.checkApiAuth, async (req, res, next) => {
|
||||||
let noteId = req.params.noteId;
|
const noteId = req.params.noteId;
|
||||||
|
|
||||||
await options.setOption('start_node', noteId);
|
await options.setOption('start_node', noteId);
|
||||||
|
|
||||||
let detail = await sql.getSingleResult("select * from notes where note_id = ?", [noteId]);
|
const detail = await sql.getSingleResult("select * from notes where note_id = ?", [noteId]);
|
||||||
|
|
||||||
if (detail.is_protected) {
|
if (detail.is_protected) {
|
||||||
const dataKey = protected_session.getDataKey(req);
|
const dataKey = protected_session.getDataKey(req);
|
||||||
@ -33,7 +33,7 @@ router.get('/:noteId', auth.checkApiAuth, async (req, res, next) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.post('/:parentNoteId/children', async (req, res, next) => {
|
router.post('/:parentNoteId/children', async (req, res, next) => {
|
||||||
let parentNoteId = req.params.parentNoteId;
|
const parentNoteId = req.params.parentNoteId;
|
||||||
const browserId = utils.browserId(req);
|
const browserId = utils.browserId(req);
|
||||||
const note = req.body;
|
const note = req.body;
|
||||||
|
|
||||||
@ -46,7 +46,7 @@ router.post('/:parentNoteId/children', async (req, res, next) => {
|
|||||||
|
|
||||||
router.put('/:noteId', async (req, res, next) => {
|
router.put('/:noteId', async (req, res, next) => {
|
||||||
const note = req.body;
|
const note = req.body;
|
||||||
let noteId = req.params.noteId;
|
const noteId = req.params.noteId;
|
||||||
const reqCtx = new RequestContext(req);
|
const reqCtx = new RequestContext(req);
|
||||||
|
|
||||||
await notes.updateNote(noteId, note, reqCtx);
|
await notes.updateNote(noteId, note, reqCtx);
|
||||||
|
@ -9,6 +9,7 @@ const auth = require('../../services/auth');
|
|||||||
const log = require('../../services/log');
|
const log = require('../../services/log');
|
||||||
const protected_session = require('../../services/protected_session');
|
const protected_session = require('../../services/protected_session');
|
||||||
const data_encryption = require('../../services/data_encryption');
|
const data_encryption = require('../../services/data_encryption');
|
||||||
|
const notes = require('../../services/notes');
|
||||||
|
|
||||||
router.get('/', auth.checkApiAuth, async (req, res, next) => {
|
router.get('/', auth.checkApiAuth, async (req, res, next) => {
|
||||||
const notes = await sql.getResults("select "
|
const notes = await sql.getResults("select "
|
||||||
@ -59,4 +60,16 @@ router.get('/', auth.checkApiAuth, async (req, res, next) => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
router.put('/:noteId/protectSubTree/:isProtected', auth.checkApiAuth, async (req, res, next) => {
|
||||||
|
const noteId = req.params.noteId;
|
||||||
|
const isProtected = !!parseInt(req.params.isProtected);
|
||||||
|
const dataKey = protected_session.getDataKey(req);
|
||||||
|
|
||||||
|
await sql.doInTransaction(async () => {
|
||||||
|
await notes.protectNoteRecursively(noteId, dataKey, isProtected);
|
||||||
|
});
|
||||||
|
|
||||||
|
res.send({});
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
@ -69,6 +69,70 @@ async function encryptNote(note, ctx) {
|
|||||||
note.detail.note_text = data_encryption.encrypt(ctx.getDataKey(), note.detail.note_text);
|
note.detail.note_text = data_encryption.encrypt(ctx.getDataKey(), note.detail.note_text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function protectNoteRecursively(noteId, dataKey, protect) {
|
||||||
|
const note = await sql.getSingleResult("SELECT * FROM notes WHERE note_id = ?", [noteId]);
|
||||||
|
|
||||||
|
await protectNote(note, dataKey, protect);
|
||||||
|
|
||||||
|
const children = await sql.getFlattenedResults("note_id", "SELECT note_id FROM notes_tree WHERE note_pid = ?", [noteId]);
|
||||||
|
|
||||||
|
for (const childNoteId of children) {
|
||||||
|
await protectNoteRecursively(childNoteId, dataKey, protect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function protectNote(note, dataKey, protect) {
|
||||||
|
let changed = false;
|
||||||
|
|
||||||
|
if (protect && !note.is_protected) {
|
||||||
|
note.note_title = data_encryption.encrypt(dataKey, note.note_title);
|
||||||
|
note.note_text = data_encryption.encrypt(dataKey, note.note_text);
|
||||||
|
note.is_protected = true;
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
else if (!protect && note.is_protected) {
|
||||||
|
note.note_title = data_encryption.decrypt(dataKey, note.note_title);
|
||||||
|
note.note_text = data_encryption.decrypt(dataKey, note.note_text);
|
||||||
|
note.is_protected = false;
|
||||||
|
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
console.log("Updating...");
|
||||||
|
|
||||||
|
await sql.execute("UPDATE notes SET note_title = ?, note_text = ?, is_protected = ? WHERE note_id = ?",
|
||||||
|
[note.note_title, note.note_text, note.is_protected, note.note_id]);
|
||||||
|
|
||||||
|
await sql.addNoteSync(note.note_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
await protectNoteHistory(note.note_id, dataKey, protect);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function protectNoteHistory(noteId, dataKey, protect) {
|
||||||
|
const historyToChange = await sql.getResults("SELECT * FROM notes_history WHERE note_id = ? AND is_protected != ?", [noteId, protect]);
|
||||||
|
|
||||||
|
for (const history of historyToChange) {
|
||||||
|
if (protect) {
|
||||||
|
history.note_title = data_encryption.encrypt(dataKey, history.note_title);
|
||||||
|
history.note_text = data_encryption.encrypt(dataKey, history.note_text);
|
||||||
|
history.is_protected = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
history.note_title = data_encryption.decrypt(dataKey, history.note_title);
|
||||||
|
history.note_text = data_encryption.decrypt(dataKey, history.note_text);
|
||||||
|
history.is_protected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
await sql.execute("UPDATE notes_history SET note_title = ?, note_text = ?, is_protected = ? WHERE note_history_id = ?",
|
||||||
|
[history.note_title, history.note_text, history.is_protected, history.note_history_id]);
|
||||||
|
|
||||||
|
await sql.addNoteHistorySync(history.note_history_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function updateNote(noteId, newNote, ctx) {
|
async function updateNote(noteId, newNote, ctx) {
|
||||||
if (newNote.detail.is_protected) {
|
if (newNote.detail.is_protected) {
|
||||||
await encryptNote(newNote, ctx);
|
await encryptNote(newNote, ctx);
|
||||||
@ -109,23 +173,7 @@ async function updateNote(noteId, newNote, ctx) {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const historyToChange = await sql.getResults("SELECT * FROM notes_history WHERE note_id = ? AND is_protected != ?", [noteId, newNote.detail.is_protected]);
|
await protectNoteHistory(noteId, ctx.getDataKey(), newNote.detail.is_protected);
|
||||||
|
|
||||||
for (const history of historyToChange) {
|
|
||||||
if (newNote.detail.is_protected) {
|
|
||||||
history.note_title = data_encryption.encrypt(history.note_title);
|
|
||||||
history.note_text = data_encryption.encrypt(history.note_text);
|
|
||||||
history.is_protected = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
history.note_title = data_encryption.decrypt(history.note_title);
|
|
||||||
history.note_text = data_encryption.decrypt(history.note_text);
|
|
||||||
history.is_protected = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
await sql.execute("UPDATE notes_history SET note_title = ?, note_text = ?, is_protected = ? WHERE note_history_id = ?",
|
|
||||||
[history.note_title, history.note_text, history.is_protected, history.note_history_id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
await sql.addNoteHistorySync(noteHistoryId);
|
await sql.addNoteHistorySync(noteHistoryId);
|
||||||
await addNoteAudits(origNoteDetail, newNote.detail, ctx.browserId);
|
await addNoteAudits(origNoteDetail, newNote.detail, ctx.browserId);
|
||||||
@ -199,5 +247,6 @@ module.exports = {
|
|||||||
createNewNote,
|
createNewNote,
|
||||||
updateNote,
|
updateNote,
|
||||||
addNoteAudits,
|
addNoteAudits,
|
||||||
deleteNote
|
deleteNote,
|
||||||
|
protectNoteRecursively
|
||||||
};
|
};
|
Loading…
x
Reference in New Issue
Block a user