mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-11-04 15:11:31 +08:00 
			
		
		
		
	server side WIP - saving encrypted note now works, changing terminology of "encrypted note" to "protected note"
This commit is contained in:
		
							parent
							
								
									c18799b938
								
							
						
					
					
						commit
						ff411f00b1
					
				
							
								
								
									
										52
									
								
								migrations/0028__rename_encryption_to_protected.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								migrations/0028__rename_encryption_to_protected.sql
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					UPDATE audit_log SET category = 'PROTECTED' WHERE category = 'ENCRYPTION';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DELETE FROM notes WHERE note_clone_id IS NOT NULL AND note_clone_id != '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE TABLE `notes_mig` (
 | 
				
			||||||
 | 
						`note_id`	TEXT NOT NULL,
 | 
				
			||||||
 | 
						`note_title`	TEXT,
 | 
				
			||||||
 | 
						`note_text`	TEXT,
 | 
				
			||||||
 | 
						`date_created`	INT,
 | 
				
			||||||
 | 
						`date_modified`	INT,
 | 
				
			||||||
 | 
						`is_protected`	INT NOT NULL DEFAULT 0,
 | 
				
			||||||
 | 
						`is_deleted`	INT NOT NULL DEFAULT 0,
 | 
				
			||||||
 | 
						PRIMARY KEY(`note_id`)
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INSERT INTO notes_mig (note_id, note_title, note_text, date_created, date_modified, is_protected, is_deleted)
 | 
				
			||||||
 | 
					    SELECT note_id, note_title, note_text, date_created, date_modified, encryption, is_deleted FROM notes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DROP TABLE notes;
 | 
				
			||||||
 | 
					ALTER TABLE notes_mig RENAME TO notes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE INDEX `IDX_notes_is_deleted` ON `notes` (
 | 
				
			||||||
 | 
						`is_deleted`
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE TABLE `notes_history_mig` (
 | 
				
			||||||
 | 
						`note_history_id`	TEXT NOT NULL PRIMARY KEY,
 | 
				
			||||||
 | 
						`note_id`	TEXT NOT NULL,
 | 
				
			||||||
 | 
						`note_title`	TEXT,
 | 
				
			||||||
 | 
						`note_text`	TEXT,
 | 
				
			||||||
 | 
						`is_protected`	INT,
 | 
				
			||||||
 | 
						`date_modified_from` INT,
 | 
				
			||||||
 | 
						`date_modified_to` INT
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					INSERT INTO notes_history_mig (note_history_id, note_id, note_title, note_text, is_protected, date_modified_from, date_modified_to)
 | 
				
			||||||
 | 
					                        SELECT note_history_id, note_id, note_title, note_text, encryption, date_modified_from, date_modified_to FROM notes_history;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DROP TABLE notes_history;
 | 
				
			||||||
 | 
					ALTER TABLE notes_history_mig RENAME TO notes_history;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE INDEX `IDX_notes_history_note_id` ON `notes_history` (
 | 
				
			||||||
 | 
						`note_id`
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE INDEX `IDX_notes_history_note_date_modified_from` ON `notes_history` (
 | 
				
			||||||
 | 
						`date_modified_from`
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					CREATE INDEX `IDX_notes_history_note_date_modified_to` ON `notes_history` (
 | 
				
			||||||
 | 
						`date_modified_to`
 | 
				
			||||||
 | 
					);
 | 
				
			||||||
@ -57,9 +57,9 @@ const contextMenu = (function() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            if (ui.cmd === "insertNoteHere") {
 | 
					            if (ui.cmd === "insertNoteHere") {
 | 
				
			||||||
                const parentKey = treeUtils.getParentKey(node);
 | 
					                const parentKey = treeUtils.getParentKey(node);
 | 
				
			||||||
                const encryption = treeUtils.getParentEncryption(node);
 | 
					                const isProtected = treeUtils.getParentEncryption(node);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                noteEditor.createNote(node, parentKey, 'after', encryption);
 | 
					                noteEditor.createNote(node, parentKey, 'after', isProtected);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else if (ui.cmd === "insertChildNote") {
 | 
					            else if (ui.cmd === "insertChildNote") {
 | 
				
			||||||
                noteEditor.createNote(node, node.key, 'into');
 | 
					                noteEditor.createNote(node, node.key, 'into');
 | 
				
			||||||
 | 
				
			|||||||
@ -58,7 +58,7 @@ const noteHistory = (function() {
 | 
				
			|||||||
        let noteTitle = historyItem.note_title;
 | 
					        let noteTitle = historyItem.note_title;
 | 
				
			||||||
        let noteText = historyItem.note_text;
 | 
					        let noteText = historyItem.note_text;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (historyItem.encryption > 0) {
 | 
					        if (historyItem.is_protected) {
 | 
				
			||||||
            noteTitle = encryption.decryptString(noteTitle);
 | 
					            noteTitle = encryption.decryptString(noteTitle);
 | 
				
			||||||
            noteText = encryption.decryptString(noteText);
 | 
					            noteText = encryption.decryptString(noteText);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -27,7 +27,7 @@ const encryption = (function() {
 | 
				
			|||||||
        encryptionSessionTimeout = encSessTimeout;
 | 
					        encryptionSessionTimeout = encSessTimeout;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function ensureEncryptionIsAvailable(requireEncryption, modal) {
 | 
					    function ensureProtectedSession(requireEncryption, modal) {
 | 
				
			||||||
        const dfd = $.Deferred();
 | 
					        const dfd = $.Deferred();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (requireEncryption && !isEncryptionAvailable()) {
 | 
					        if (requireEncryption && !isEncryptionAvailable()) {
 | 
				
			||||||
@ -116,15 +116,6 @@ const encryption = (function() {
 | 
				
			|||||||
        return new aesjs.ModeOfOperation.ctr(dataKey, new aesjs.Counter(5));
 | 
					        return new aesjs.ModeOfOperation.ctr(dataKey, new aesjs.Counter(5));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function encryptNoteIfNecessary(note) {
 | 
					 | 
				
			||||||
        if (note.detail.encryption === 0) {
 | 
					 | 
				
			||||||
            return note;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        else {
 | 
					 | 
				
			||||||
            return encryptNote(note);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    function encryptString(str) {
 | 
					    function encryptString(str) {
 | 
				
			||||||
        return encrypt(getDataAes(), str);
 | 
					        return encrypt(getDataAes(), str);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -184,36 +175,34 @@ const encryption = (function() {
 | 
				
			|||||||
        note.detail.note_title = encryptString(note.detail.note_title);
 | 
					        note.detail.note_title = encryptString(note.detail.note_title);
 | 
				
			||||||
        note.detail.note_text = encryptString(note.detail.note_text);
 | 
					        note.detail.note_text = encryptString(note.detail.note_text);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        note.detail.encryption = 1;
 | 
					        note.detail.is_protected = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return note;
 | 
					        return note;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async function encryptNoteAndSendToServer() {
 | 
					    async function protectNoteAndSendToServer() {
 | 
				
			||||||
        await ensureEncryptionIsAvailable(true, true);
 | 
					        await ensureProtectedSession(true, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const note = noteEditor.getCurrentNote();
 | 
					        const note = noteEditor.getCurrentNote();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        noteEditor.updateNoteFromInputs(note);
 | 
					        noteEditor.updateNoteFromInputs(note);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        encryptNote(note);
 | 
					        note.detail.is_protected = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await noteEditor.saveNoteToServer(note);
 | 
					        await noteEditor.saveNoteToServer(note);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await changeEncryptionOnNoteHistory(note.detail.note_id, true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        noteEditor.setNoteBackgroundIfEncrypted(note);
 | 
					        noteEditor.setNoteBackgroundIfEncrypted(note);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async function changeEncryptionOnNoteHistory(noteId, encrypt) {
 | 
					    async function changeEncryptionOnNoteHistory(noteId, protect) {
 | 
				
			||||||
        const result = await $.ajax({
 | 
					        const result = await $.ajax({
 | 
				
			||||||
            url: baseApiUrl + 'notes-history/' + noteId + "?encryption=" + (encrypt ? 0 : 1),
 | 
					            url: baseApiUrl + 'notes-history/' + noteId + "?encryption=" + (protect ? 0 : 1),
 | 
				
			||||||
            type: 'GET',
 | 
					            type: 'GET',
 | 
				
			||||||
            error: () => showError("Error getting note history.")
 | 
					            error: () => showError("Error getting note history.")
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (const row of result) {
 | 
					        for (const row of result) {
 | 
				
			||||||
            if (encrypt) {
 | 
					            if (protect) {
 | 
				
			||||||
                row.note_title = encryptString(row.note_title);
 | 
					                row.note_title = encryptString(row.note_title);
 | 
				
			||||||
                row.note_text = encryptString(row.note_text);
 | 
					                row.note_text = encryptString(row.note_text);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -222,7 +211,7 @@ const encryption = (function() {
 | 
				
			|||||||
                row.note_text = decryptString(row.note_text);
 | 
					                row.note_text = decryptString(row.note_text);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            row.encryption = encrypt ? 1 : 0;
 | 
					            row.is_protected = protect;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await $.ajax({
 | 
					            await $.ajax({
 | 
				
			||||||
                url: baseApiUrl + 'notes-history',
 | 
					                url: baseApiUrl + 'notes-history',
 | 
				
			||||||
@ -236,14 +225,14 @@ const encryption = (function() {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async function decryptNoteAndSendToServer() {
 | 
					    async function unprotectNoteAndSendToServer() {
 | 
				
			||||||
        await ensureEncryptionIsAvailable(true, true);
 | 
					        await ensureProtectedSession(true, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const note = noteEditor.getCurrentNote();
 | 
					        const note = noteEditor.getCurrentNote();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        noteEditor.updateNoteFromInputs(note);
 | 
					        noteEditor.updateNoteFromInputs(note);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        note.detail.encryption = 0;
 | 
					        note.detail.is_protected = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await noteEditor.saveNoteToServer(note);
 | 
					        await noteEditor.saveNoteToServer(note);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -253,13 +242,13 @@ const encryption = (function() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async function encryptSubTree(noteId) {
 | 
					    async function encryptSubTree(noteId) {
 | 
				
			||||||
        await ensureEncryptionIsAvailable(true, true);
 | 
					        await ensureProtectedSession(true, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        updateSubTreeRecursively(noteId, note => {
 | 
					        updateSubTreeRecursively(noteId, note => {
 | 
				
			||||||
                if (note.detail.encryption === null || note.detail.encryption === 0) {
 | 
					                if (!note.detail.is_protected) {
 | 
				
			||||||
                    encryptNote(note);
 | 
					                    encryptNote(note);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    note.detail.encryption = 1;
 | 
					                    note.detail.is_protected = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return true;
 | 
					                    return true;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -280,13 +269,13 @@ const encryption = (function() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async function decryptSubTree(noteId) {
 | 
					    async function decryptSubTree(noteId) {
 | 
				
			||||||
        await ensureEncryptionIsAvailable(true, true);
 | 
					        await ensureProtectedSession(true, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        updateSubTreeRecursively(noteId, note => {
 | 
					        updateSubTreeRecursively(noteId, note => {
 | 
				
			||||||
                if (note.detail.encryption === 1) {
 | 
					                if (note.detail.is_protected) {
 | 
				
			||||||
                    decryptNote(note);
 | 
					                    decryptNote(note);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    note.detail.encryption = 0;
 | 
					                    note.detail.is_protected = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return true;
 | 
					                    return true;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@ -368,14 +357,13 @@ const encryption = (function() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    return {
 | 
					    return {
 | 
				
			||||||
        setEncryptionSessionTimeout,
 | 
					        setEncryptionSessionTimeout,
 | 
				
			||||||
        ensureEncryptionIsAvailable,
 | 
					        ensureProtectedSession,
 | 
				
			||||||
        resetEncryptionSession,
 | 
					        resetEncryptionSession,
 | 
				
			||||||
        isEncryptionAvailable,
 | 
					        isEncryptionAvailable,
 | 
				
			||||||
        encryptNoteIfNecessary,
 | 
					 | 
				
			||||||
        encryptString,
 | 
					        encryptString,
 | 
				
			||||||
        decryptString,
 | 
					        decryptString,
 | 
				
			||||||
        encryptNoteAndSendToServer,
 | 
					        protectNoteAndSendToServer,
 | 
				
			||||||
        decryptNoteAndSendToServer,
 | 
					        unprotectNoteAndSendToServer,
 | 
				
			||||||
        encryptSubTree,
 | 
					        encryptSubTree,
 | 
				
			||||||
        decryptSubTree,
 | 
					        decryptSubTree,
 | 
				
			||||||
        getProtectedSessionId
 | 
					        getProtectedSessionId
 | 
				
			||||||
 | 
				
			|||||||
@ -59,8 +59,6 @@ const noteEditor = (function() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        updateNoteFromInputs(note);
 | 
					        updateNoteFromInputs(note);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        encryption.encryptNoteIfNecessary(note);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        await saveNoteToServer(note);
 | 
					        await saveNoteToServer(note);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -70,7 +68,7 @@ const noteEditor = (function() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        note.detail.note_text = contents;
 | 
					        note.detail.note_text = contents;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (!note.detail.encryption) {
 | 
					        if (!note.detail.is_protected) {
 | 
				
			||||||
            const linkRegexp = /<a[^>]+?href="[^"]*app#([A-Za-z0-9]{22})"[^>]*?>[^<]+?<\/a>/g;
 | 
					            const linkRegexp = /<a[^>]+?href="[^"]*app#([A-Za-z0-9]{22})"[^>]*?>[^<]+?<\/a>/g;
 | 
				
			||||||
            let match;
 | 
					            let match;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -170,11 +168,11 @@ const noteEditor = (function() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    function setTreeBasedOnEncryption(note) {
 | 
					    function setTreeBasedOnEncryption(note) {
 | 
				
			||||||
        const node = treeUtils.getNodeByKey(note.detail.note_id);
 | 
					        const node = treeUtils.getNodeByKey(note.detail.note_id);
 | 
				
			||||||
        node.toggleClass("encrypted", note.detail.encryption > 0);
 | 
					        node.toggleClass("encrypted", note.detail.is_protected);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function setNoteBackgroundIfEncrypted(note) {
 | 
					    function setNoteBackgroundIfEncrypted(note) {
 | 
				
			||||||
        if (note.detail.encryption > 0) {
 | 
					        if (note.detail.is_protected) {
 | 
				
			||||||
            $(".note-editable").addClass("encrypted");
 | 
					            $(".note-editable").addClass("encrypted");
 | 
				
			||||||
            encryptButton.hide();
 | 
					            encryptButton.hide();
 | 
				
			||||||
            decryptButton.show();
 | 
					            decryptButton.show();
 | 
				
			||||||
@ -197,7 +195,7 @@ const noteEditor = (function() {
 | 
				
			|||||||
            noteTitleEl.focus().select();
 | 
					            noteTitleEl.focus().select();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await encryption.ensureEncryptionIsAvailable(currentNote.detail.encryption > 0, false);
 | 
					        await encryption.ensureProtectedSession(currentNote.detail.is_protected, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        noteDetailWrapperEl.show();
 | 
					        noteDetailWrapperEl.show();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -25,7 +25,7 @@ const noteTree = (function() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            note.title = note.note_title;
 | 
					            note.title = note.note_title;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (note.encryption > 0) {
 | 
					            if (note.is_protected) {
 | 
				
			||||||
                note.extraClasses = "encrypted";
 | 
					                note.extraClasses = "encrypted";
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            else {
 | 
					            else {
 | 
				
			||||||
@ -63,7 +63,7 @@ const noteTree = (function() {
 | 
				
			|||||||
                noteEditor.createNote(node, parentKey, 'after', encryption);
 | 
					                noteEditor.createNote(node, parentKey, 'after', encryption);
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "ctrl+insert": node => {
 | 
					            "ctrl+insert": node => {
 | 
				
			||||||
                noteEditor.createNote(node, node.key, 'into', node.data.encryption);
 | 
					                noteEditor.createNote(node, node.key, 'into', node.data.is_protected);
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            "del": node => {
 | 
					            "del": node => {
 | 
				
			||||||
                treeChanges.deleteNode(node);
 | 
					                treeChanges.deleteNode(node);
 | 
				
			||||||
 | 
				
			|||||||
@ -8,7 +8,7 @@ const treeUtils = (function() {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function getParentEncryption(node) {
 | 
					    function getParentEncryption(node) {
 | 
				
			||||||
        return node.getParent() === null ? 0 : node.getParent().data.encryption;
 | 
					        return node.getParent() === null ? 0 : node.getParent().data.is_protected;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    function getNodeByKey(noteId) {
 | 
					    function getNodeByKey(noteId) {
 | 
				
			||||||
 | 
				
			|||||||
@ -7,15 +7,15 @@ const auth = require('../../services/auth');
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
router.get('/:noteId', auth.checkApiAuth, async (req, res, next) => {
 | 
					router.get('/:noteId', auth.checkApiAuth, async (req, res, next) => {
 | 
				
			||||||
    const noteId = req.params.noteId;
 | 
					    const noteId = req.params.noteId;
 | 
				
			||||||
    const encryption = req.query.encryption;
 | 
					    const isProtected = req.query.is_protected;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let history;
 | 
					    let history;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (encryption === undefined) {
 | 
					    if (isProtected === undefined) {
 | 
				
			||||||
        history = await sql.getResults("select * from notes_history where note_id = ? order by date_modified_to desc", [noteId]);
 | 
					        history = await sql.getResults("select * from notes_history where note_id = ? order by date_modified_to desc", [noteId]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    else {
 | 
					    else {
 | 
				
			||||||
        history = await sql.getResults("select * from notes_history where note_id = ? and encryption = ? order by date_modified_to desc", [noteId, encryption]);
 | 
					        history = await sql.getResults("select * from notes_history where note_id = ? and is_protected = ? order by date_modified_to desc", [noteId, is_protected]);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    res.send(history);
 | 
					    res.send(history);
 | 
				
			||||||
 | 
				
			|||||||
@ -9,6 +9,7 @@ const utils = require('../../services/utils');
 | 
				
			|||||||
const notes = require('../../services/notes');
 | 
					const notes = require('../../services/notes');
 | 
				
			||||||
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 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;
 | 
					    let noteId = req.params.noteId;
 | 
				
			||||||
@ -17,12 +18,7 @@ router.get('/:noteId', auth.checkApiAuth, async (req, res, next) => {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    let detail = await sql.getSingleResult("select * from notes where note_id = ?", [noteId]);
 | 
					    let detail = await sql.getSingleResult("select * from notes where note_id = ?", [noteId]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (detail.note_clone_id) {
 | 
					    if (detail.is_protected) {
 | 
				
			||||||
        noteId = detail.note_clone_id;
 | 
					 | 
				
			||||||
        detail = sql.getSingleResult("select * from notes where note_id = ?", [noteId]);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (detail.encryption > 0) {
 | 
					 | 
				
			||||||
        const dataKey = protected_session.getDataKey(req);
 | 
					        const dataKey = protected_session.getDataKey(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        detail.note_title = data_encryption.decrypt(dataKey, detail.note_title);
 | 
					        detail.note_title = data_encryption.decrypt(dataKey, detail.note_title);
 | 
				
			||||||
@ -49,11 +45,11 @@ router.post('/:parentNoteId/children', async (req, res, next) => {
 | 
				
			|||||||
});
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
router.put('/:noteId', async (req, res, next) => {
 | 
					router.put('/:noteId', async (req, res, next) => {
 | 
				
			||||||
    const newNote = req.body;
 | 
					    const note = req.body;
 | 
				
			||||||
    let noteId = req.params.noteId;
 | 
					    let noteId = req.params.noteId;
 | 
				
			||||||
    const browserId = utils.browserId(req);
 | 
					    const reqCtx = new RequestContext(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    await notes.updateNote(noteId, newNote, browserId);
 | 
					    await notes.updateNote(noteId, note, reqCtx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    res.send({});
 | 
					    res.send({});
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
 | 
				
			|||||||
@ -13,13 +13,10 @@ const data_encryption = require('../../services/data_encryption');
 | 
				
			|||||||
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 "
 | 
				
			||||||
        + "notes_tree.*, "
 | 
					        + "notes_tree.*, "
 | 
				
			||||||
        + "COALESCE(clone.note_title, notes.note_title) as note_title, "
 | 
					        + "notes.note_title, "
 | 
				
			||||||
        + "notes.note_clone_id, "
 | 
					        + "notes.is_protected "
 | 
				
			||||||
        + "notes.encryption, "
 | 
					 | 
				
			||||||
        + "case when notes.note_clone_id is null or notes.note_clone_id = '' then 0 else 1 end as is_clone "
 | 
					 | 
				
			||||||
        + "from notes_tree "
 | 
					        + "from notes_tree "
 | 
				
			||||||
        + "join notes on notes.note_id = notes_tree.note_id "
 | 
					        + "join notes on notes.note_id = notes_tree.note_id "
 | 
				
			||||||
        + "left join notes as clone on notes.note_clone_id = clone.note_id "
 | 
					 | 
				
			||||||
        + "where notes.is_deleted = 0 and notes_tree.is_deleted = 0 "
 | 
					        + "where notes.is_deleted = 0 and notes_tree.is_deleted = 0 "
 | 
				
			||||||
        + "order by note_pid, note_pos");
 | 
					        + "order by note_pid, note_pos");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -29,7 +26,7 @@ router.get('/', auth.checkApiAuth, async (req, res, next) => {
 | 
				
			|||||||
    const dataKey = protected_session.getDataKey(req);
 | 
					    const dataKey = protected_session.getDataKey(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (const note of notes) {
 | 
					    for (const note of notes) {
 | 
				
			||||||
        if (note['encryption']) {
 | 
					        if (note.is_protected) {
 | 
				
			||||||
            note.note_title = data_encryption.decrypt(dataKey, note.note_title);
 | 
					            note.note_title = data_encryption.decrypt(dataKey, note.note_title);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -9,7 +9,7 @@ module.exports = {
 | 
				
			|||||||
    CREATE_NOTE: 'CREATE',
 | 
					    CREATE_NOTE: 'CREATE',
 | 
				
			||||||
    DELETE_NOTE: 'DELETE',
 | 
					    DELETE_NOTE: 'DELETE',
 | 
				
			||||||
    CHANGE_PARENT: 'PARENT',
 | 
					    CHANGE_PARENT: 'PARENT',
 | 
				
			||||||
    ENCRYPTION: 'ENCRYPTION',
 | 
					    PROTECTED: 'PROTECTED',
 | 
				
			||||||
    CHANGE_PASSWORD: 'PASSWORD',
 | 
					    CHANGE_PASSWORD: 'PASSWORD',
 | 
				
			||||||
    SETTINGS: 'SETTINGS',
 | 
					    SETTINGS: 'SETTINGS',
 | 
				
			||||||
    SYNC: 'SYNC'
 | 
					    SYNC: 'SYNC'
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,8 @@
 | 
				
			|||||||
const protected_session = require('./protected_session');
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const utils = require('./utils');
 | 
					const utils = require('./utils');
 | 
				
			||||||
const aesjs = require('./aes');
 | 
					const aesjs = require('./aes');
 | 
				
			||||||
 | 
					const sha256 = require('./sha256');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getProtectedSessionId(req) {
 | 
					function getProtectedSessionId(req) {
 | 
				
			||||||
    return req.headers['x-protected-session-id'];
 | 
					    return req.headers['x-protected-session-id'];
 | 
				
			||||||
@ -10,6 +12,15 @@ function getDataAes(dataKey) {
 | 
				
			|||||||
    return new aesjs.ModeOfOperation.ctr(dataKey, new aesjs.Counter(5));
 | 
					    return new aesjs.ModeOfOperation.ctr(dataKey, new aesjs.Counter(5));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function arraysIdentical(a, b) {
 | 
				
			||||||
 | 
					    let i = a.length;
 | 
				
			||||||
 | 
					    if (i !== b.length) return false;
 | 
				
			||||||
 | 
					    while (i--) {
 | 
				
			||||||
 | 
					        if (a[i] !== b[i]) return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function decrypt(dataKey, encryptedBase64) {
 | 
					function decrypt(dataKey, encryptedBase64) {
 | 
				
			||||||
    if (!dataKey) {
 | 
					    if (!dataKey) {
 | 
				
			||||||
        return "[protected]";
 | 
					        return "[protected]";
 | 
				
			||||||
@ -24,10 +35,42 @@ function decrypt(dataKey, encryptedBase64) {
 | 
				
			|||||||
    const digest = decryptedBytes.slice(0, 4);
 | 
					    const digest = decryptedBytes.slice(0, 4);
 | 
				
			||||||
    const payload = decryptedBytes.slice(4);
 | 
					    const payload = decryptedBytes.slice(4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const hashArray = sha256Array(payload);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const computedDigest = hashArray.slice(0, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (!arraysIdentical(digest, computedDigest)) {
 | 
				
			||||||
 | 
					        return false;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    return aesjs.utils.utf8.fromBytes(payload);
 | 
					    return aesjs.utils.utf8.fromBytes(payload);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function encrypt(dataKey, plainText) {
 | 
				
			||||||
 | 
					    if (!dataKey) {
 | 
				
			||||||
 | 
					        throw new Error("No data key!");
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const aes = getDataAes(dataKey);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const payload = Array.from(aesjs.utils.utf8.toBytes(plainText));
 | 
				
			||||||
 | 
					    const digest = sha256Array(payload).slice(0, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const digestWithPayload = digest.concat(payload);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const encryptedBytes = aes.encrypt(digestWithPayload);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return utils.toBase64(encryptedBytes);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function sha256Array(content) {
 | 
				
			||||||
 | 
					    const hash = sha256.create();
 | 
				
			||||||
 | 
					    hash.update(content);
 | 
				
			||||||
 | 
					    return hash.array();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
    getProtectedSessionId,
 | 
					    getProtectedSessionId,
 | 
				
			||||||
    decrypt
 | 
					    decrypt,
 | 
				
			||||||
 | 
					    encrypt
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
@ -4,7 +4,7 @@ const options = require('./options');
 | 
				
			|||||||
const fs = require('fs-extra');
 | 
					const fs = require('fs-extra');
 | 
				
			||||||
const log = require('./log');
 | 
					const log = require('./log');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const APP_DB_VERSION = 27;
 | 
					const APP_DB_VERSION = 28;
 | 
				
			||||||
const MIGRATIONS_DIR = "./migrations";
 | 
					const MIGRATIONS_DIR = "./migrations";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function migrate() {
 | 
					async function migrate() {
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,7 @@ const options = require('./options');
 | 
				
			|||||||
const utils = require('./utils');
 | 
					const utils = require('./utils');
 | 
				
			||||||
const notes = require('./notes');
 | 
					const notes = require('./notes');
 | 
				
			||||||
const audit_category = require('./audit_category');
 | 
					const audit_category = require('./audit_category');
 | 
				
			||||||
 | 
					const data_encryption = require('./data_encryption');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function createNewNote(parentNoteId, note, browserId) {
 | 
					async function createNewNote(parentNoteId, note, browserId) {
 | 
				
			||||||
    const noteId = utils.newNoteId();
 | 
					    const noteId = utils.newNoteId();
 | 
				
			||||||
@ -46,10 +47,9 @@ async function createNewNote(parentNoteId, note, browserId) {
 | 
				
			|||||||
            'note_id': noteId,
 | 
					            'note_id': noteId,
 | 
				
			||||||
            'note_title': note.note_title,
 | 
					            'note_title': note.note_title,
 | 
				
			||||||
            'note_text': '',
 | 
					            'note_text': '',
 | 
				
			||||||
            'note_clone_id': '',
 | 
					 | 
				
			||||||
            'date_created': now,
 | 
					            'date_created': now,
 | 
				
			||||||
            'date_modified': now,
 | 
					            'date_modified': now,
 | 
				
			||||||
            'encryption': note.encryption
 | 
					            'is_protected': note.is_protected
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await sql.insert("notes_tree", {
 | 
					        await sql.insert("notes_tree", {
 | 
				
			||||||
@ -64,13 +64,17 @@ async function createNewNote(parentNoteId, note, browserId) {
 | 
				
			|||||||
    return noteId;
 | 
					    return noteId;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
async function updateNote(noteId, newNote, browserId) {
 | 
					async function encryptNote(note, ctx) {
 | 
				
			||||||
    const origNoteDetail = await sql.getSingleResult("select * from notes where note_id = ?", [noteId]);
 | 
					    note.detail.note_title = data_encryption.encrypt(ctx.getDataKey(), note.detail.note_title);
 | 
				
			||||||
 | 
					    note.detail.note_text = data_encryption.encrypt(ctx.getDataKey(), note.detail.note_text);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (origNoteDetail.note_clone_id) {
 | 
					async function updateNote(noteId, newNote, ctx) {
 | 
				
			||||||
        noteId = origNoteDetail.note_clone_id;
 | 
					    if (newNote.detail.is_protected) {
 | 
				
			||||||
 | 
					        await encryptNote(newNote, ctx);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const origNoteDetail = await sql.getSingleResult("select * from notes where note_id = ?", [noteId]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const now = utils.nowTimestamp();
 | 
					    const now = utils.nowTimestamp();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -82,10 +86,10 @@ async function updateNote(noteId, newNote, browserId) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    await sql.doInTransaction(async () => {
 | 
					    await sql.doInTransaction(async () => {
 | 
				
			||||||
        if (noteHistoryId) {
 | 
					        if (noteHistoryId) {
 | 
				
			||||||
            await sql.execute("update notes_history set note_title = ?, note_text = ?, encryption = ?, date_modified_to = ? where note_history_id = ?", [
 | 
					            await sql.execute("update notes_history set note_title = ?, note_text = ?, is_protected = ?, date_modified_to = ? where note_history_id = ?", [
 | 
				
			||||||
                newNote.detail.note_title,
 | 
					                newNote.detail.note_title,
 | 
				
			||||||
                newNote.detail.note_text,
 | 
					                newNote.detail.note_text,
 | 
				
			||||||
                newNote.detail.encryption,
 | 
					                newNote.detail.is_protected,
 | 
				
			||||||
                now,
 | 
					                now,
 | 
				
			||||||
                noteHistoryId
 | 
					                noteHistoryId
 | 
				
			||||||
            ]);
 | 
					            ]);
 | 
				
			||||||
@ -93,25 +97,25 @@ async function updateNote(noteId, newNote, browserId) {
 | 
				
			|||||||
        else {
 | 
					        else {
 | 
				
			||||||
            noteHistoryId = utils.randomString(16);
 | 
					            noteHistoryId = utils.randomString(16);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await sql.execute("insert into notes_history (note_history_id, note_id, note_title, note_text, encryption, date_modified_from, date_modified_to) " +
 | 
					            await sql.execute("insert into notes_history (note_history_id, note_id, note_title, note_text, is_protected, date_modified_from, date_modified_to) " +
 | 
				
			||||||
                "values (?, ?, ?, ?, ?, ?, ?)", [
 | 
					                "values (?, ?, ?, ?, ?, ?, ?)", [
 | 
				
			||||||
                noteHistoryId,
 | 
					                noteHistoryId,
 | 
				
			||||||
                noteId,
 | 
					                noteId,
 | 
				
			||||||
                newNote.detail.note_title,
 | 
					                newNote.detail.note_title,
 | 
				
			||||||
                newNote.detail.note_text,
 | 
					                newNote.detail.note_text,
 | 
				
			||||||
                newNote.detail.encryption,
 | 
					                newNote.detail.is_protected,
 | 
				
			||||||
                now,
 | 
					                now,
 | 
				
			||||||
                now
 | 
					                now
 | 
				
			||||||
            ]);
 | 
					            ]);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await sql.addNoteHistorySync(noteHistoryId);
 | 
					        await sql.addNoteHistorySync(noteHistoryId);
 | 
				
			||||||
        await addNoteAudits(origNoteDetail, newNote.detail, browserId);
 | 
					        await addNoteAudits(origNoteDetail, newNote.detail, ctx.browserId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await sql.execute("update notes set note_title = ?, note_text = ?, encryption = ?, date_modified = ? where note_id = ?", [
 | 
					        await sql.execute("update notes set note_title = ?, note_text = ?, is_protected = ?, date_modified = ? where note_id = ?", [
 | 
				
			||||||
            newNote.detail.note_title,
 | 
					            newNote.detail.note_title,
 | 
				
			||||||
            newNote.detail.note_text,
 | 
					            newNote.detail.note_text,
 | 
				
			||||||
            newNote.detail.encryption,
 | 
					            newNote.detail.is_protected,
 | 
				
			||||||
            now,
 | 
					            now,
 | 
				
			||||||
            noteId]);
 | 
					            noteId]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -147,10 +151,10 @@ async function addNoteAudits(origNote, newNote, browserId) {
 | 
				
			|||||||
        await sql.addAudit(audit_category.UPDATE_CONTENT, browserId, noteId);
 | 
					        await sql.addAudit(audit_category.UPDATE_CONTENT, browserId, noteId);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!origNote || newNote.encryption !== origNote.encryption) {
 | 
					    if (!origNote || newNote.is_protected !== origNote.is_protected) {
 | 
				
			||||||
        const origEncryption = origNote ? origNote.encryption : null;
 | 
					        const origIsProtected = origNote ? origNote.is_protected : null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await sql.addAudit(audit_category.ENCRYPTION, browserId, noteId, origEncryption, newNote.encryption);
 | 
					        await sql.addAudit(audit_category.PROTECTED, browserId, noteId, origIsProtected, newNote.is_protected);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,3 +1,5 @@
 | 
				
			|||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const utils = require('./utils');
 | 
					const utils = require('./utils');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function setDataKey(req, decryptedDataKey) {
 | 
					function setDataKey(req, decryptedDataKey) {
 | 
				
			||||||
@ -7,8 +9,12 @@ function setDataKey(req, decryptedDataKey) {
 | 
				
			|||||||
    return req.session.protectedSessionId;
 | 
					    return req.session.protectedSessionId;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function getProtectedSessionId(req) {
 | 
				
			||||||
 | 
					    return req.headers['x-protected-session-id'];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getDataKey(req) {
 | 
					function getDataKey(req) {
 | 
				
			||||||
    const protectedSessionId = req.headers['x-protected-session-id'];
 | 
					    const protectedSessionId = getProtectedSessionId(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (protectedSessionId && req.session.protectedSessionId === protectedSessionId) {
 | 
					    if (protectedSessionId && req.session.protectedSessionId === protectedSessionId) {
 | 
				
			||||||
        return req.session.decryptedDataKey;
 | 
					        return req.session.decryptedDataKey;
 | 
				
			||||||
@ -18,7 +24,14 @@ function getDataKey(req) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function isProtectedSessionAvailable(req) {
 | 
				
			||||||
 | 
					    const protectedSessionId = getProtectedSessionId(req);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return protectedSessionId && req.session.protectedSessionId === protectedSessionId;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
module.exports = {
 | 
					module.exports = {
 | 
				
			||||||
    setDataKey,
 | 
					    setDataKey,
 | 
				
			||||||
    getDataKey
 | 
					    getDataKey,
 | 
				
			||||||
 | 
					    isProtectedSessionAvailable
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
							
								
								
									
										25
									
								
								services/request_context.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								services/request_context.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,25 @@
 | 
				
			|||||||
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const protected_session = require('./protected_session');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					module.exports = function(req) {
 | 
				
			||||||
 | 
					    const browserId = req.headers['x-browser-id'];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function isProtectedSessionAvailable() {
 | 
				
			||||||
 | 
					        return protected_session.isProtectedSessionAvailable(req);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    function getDataKey() {
 | 
				
			||||||
 | 
					        if (!isProtectedSessionAvailable()) {
 | 
				
			||||||
 | 
					            throw new Error("Protected session is not available");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return protected_session.getDataKey(req);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return {
 | 
				
			||||||
 | 
					        browserId,
 | 
				
			||||||
 | 
					        isProtectedSessionAvailable,
 | 
				
			||||||
 | 
					        getDataKey
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
							
								
								
									
										1
									
								
								services/sha256.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								services/sha256.js
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@ -239,6 +239,10 @@ async function syncRequest(syncContext, method, uri, body) {
 | 
				
			|||||||
if (isSyncSetup) {
 | 
					if (isSyncSetup) {
 | 
				
			||||||
    log.info("Setting up sync to " + SYNC_SERVER + " with timeout " + SYNC_TIMEOUT);
 | 
					    log.info("Setting up sync to " + SYNC_SERVER + " with timeout " + SYNC_TIMEOUT);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (SYNC_PROXY) {
 | 
				
			||||||
 | 
					        log.info("Sync proxy: " + SYNC_PROXY);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setInterval(sync, 60000);
 | 
					    setInterval(sync, 60000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // kickoff initial sync immediately
 | 
					    // kickoff initial sync immediately
 | 
				
			||||||
 | 
				
			|||||||
@ -68,7 +68,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      <div class="hide-toggle" style="grid-area: title;">
 | 
					      <div class="hide-toggle" style="grid-area: title;">
 | 
				
			||||||
        <div style="display: flex; align-items: center;">
 | 
					        <div style="display: flex; align-items: center;">
 | 
				
			||||||
          <a onclick="encryption.encryptNoteAndSendToServer()"
 | 
					          <a onclick="encryption.protectNoteAndSendToServer()"
 | 
				
			||||||
             title="Encrypt the note so that password will be required to view the note"
 | 
					             title="Encrypt the note so that password will be required to view the note"
 | 
				
			||||||
             class="icon-action"
 | 
					             class="icon-action"
 | 
				
			||||||
             id="encrypt-button"
 | 
					             id="encrypt-button"
 | 
				
			||||||
@ -76,7 +76,7 @@
 | 
				
			|||||||
            <img src="images/icons/lock.png" alt="Encrypt note"/>
 | 
					            <img src="images/icons/lock.png" alt="Encrypt note"/>
 | 
				
			||||||
          </a>
 | 
					          </a>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          <a onclick="encryption.decryptNoteAndSendToServer()"
 | 
					          <a onclick="encryption.unprotectNoteAndSendToServer()"
 | 
				
			||||||
             title="Decrypt note permamently so that password will not be required to access this note in the future"
 | 
					             title="Decrypt note permamently so that password will not be required to access this note in the future"
 | 
				
			||||||
             class="icon-action"
 | 
					             class="icon-action"
 | 
				
			||||||
             id="decrypt-button"
 | 
					             id="decrypt-button"
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user