mirror of
https://github.com/zadam/trilium.git
synced 2025-11-01 19:05:59 +01:00
Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a44f43b133 | ||
|
|
69677b15fe | ||
|
|
cdb17ae937 | ||
|
|
c240fb9896 | ||
|
|
4b41eddf44 | ||
|
|
b51ac112a2 | ||
|
|
c2e3a3fe04 | ||
|
|
b2052a6ccd | ||
|
|
a07479cd5a | ||
|
|
3820384f51 | ||
|
|
0610576e5a | ||
|
|
efac7701eb | ||
|
|
27cee1cf33 | ||
|
|
b4c6d9f800 |
6
db/migrations/0127__fix_inconsistent_isProtected.sql
Normal file
6
db/migrations/0127__fix_inconsistent_isProtected.sql
Normal file
@@ -0,0 +1,6 @@
|
||||
UPDATE notes SET title = 'Recovered protected note', isProtected = 0 WHERE noteId IN (
|
||||
SELECT noteId FROM notes JOIN note_contents USING(noteId)
|
||||
WHERE notes.isProtected = 1
|
||||
AND note_contents.isProtected = 0
|
||||
AND notes.isDeleted = 0
|
||||
)
|
||||
4738
package-lock.json
generated
4738
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -2,7 +2,7 @@
|
||||
"name": "trilium",
|
||||
"productName": "Trilium Notes",
|
||||
"description": "Trilium Notes",
|
||||
"version": "0.30.5",
|
||||
"version": "0.30.8",
|
||||
"license": "AGPL-3.0-only",
|
||||
"main": "electron.js",
|
||||
"bin": {
|
||||
|
||||
@@ -17,7 +17,8 @@ import link from './services/link.js';
|
||||
import messagingService from './services/messaging.js';
|
||||
import noteDetailService from './services/note_detail.js';
|
||||
import noteType from './services/note_type.js';
|
||||
import protected_session from './services/protected_session.js';
|
||||
import protectedSessionService from './services/protected_session.js';
|
||||
import protectedSessionHolder from './services/protected_session_holder.js';
|
||||
import searchNotesService from './services/search_notes.js';
|
||||
import FrontendScriptApi from './services/frontend_script_api.js';
|
||||
import ScriptContext from './services/script_context.js';
|
||||
@@ -52,6 +53,8 @@ window.glob.getCurrentNote = noteDetailService.getCurrentNote;
|
||||
window.glob.requireLibrary = libraryLoader.requireLibrary;
|
||||
window.glob.ESLINT = libraryLoader.ESLINT;
|
||||
|
||||
protectedSessionHolder.setProtectedSessionId(null);
|
||||
|
||||
window.onerror = function (msg, url, lineNo, columnNo, error) {
|
||||
const string = msg.toLowerCase();
|
||||
|
||||
|
||||
@@ -79,7 +79,7 @@ $form.submit(() => {
|
||||
function exportBranch(branchId, type, format, version) {
|
||||
exportId = utils.randomString(10);
|
||||
|
||||
const url = utils.getHost() + `/api/notes/${branchId}/export/${type}/${format}/${version}/${exportId}?protectedSessionId=` + encodeURIComponent(protectedSessionHolder.getProtectedSessionId());
|
||||
const url = utils.getHost() + `/api/notes/${branchId}/export/${type}/${format}/${version}/${exportId}`;
|
||||
|
||||
utils.download(url);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
const $contextMenuContainer = $("#context-menu-container");
|
||||
|
||||
let dateContextMenuOpenedMs = 0;
|
||||
|
||||
function initContextMenu(event, itemContainer, selectContextMenuItem) {
|
||||
event.stopPropagation();
|
||||
|
||||
@@ -55,6 +57,8 @@ function initContextMenu(event, itemContainer, selectContextMenuItem) {
|
||||
top = event.pageY - 10;
|
||||
}
|
||||
|
||||
dateContextMenuOpenedMs = Date.now();
|
||||
|
||||
$contextMenuContainer.css({
|
||||
display: "block",
|
||||
top: top,
|
||||
@@ -62,8 +66,18 @@ function initContextMenu(event, itemContainer, selectContextMenuItem) {
|
||||
}).addClass("show");
|
||||
}
|
||||
|
||||
$(document).click(() => $contextMenuContainer.hide());
|
||||
$(document).click(() => hideContextMenu());
|
||||
|
||||
function hideContextMenu() {
|
||||
// this date checking comes from change in FF66 - https://github.com/zadam/trilium/issues/468
|
||||
// "contextmenu" event also triggers "click" event which depending on the timing can close just opened context menu
|
||||
// we might filter out right clicks, but then it's better if even right clicks close the context menu
|
||||
if (Date.now() - dateContextMenuOpenedMs > 300) {
|
||||
$contextMenuContainer.hide();
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
initContextMenu
|
||||
initContextMenu,
|
||||
hideContextMenu
|
||||
}
|
||||
@@ -34,6 +34,9 @@ async function show() {
|
||||
else {
|
||||
$previewRow.hide();
|
||||
}
|
||||
|
||||
// open doesn't work for protected notes since it works through browser which isn't in protected session
|
||||
$openButton.toggle(!currentNote.isProtected);
|
||||
}
|
||||
|
||||
$downloadButton.click(() => utils.download(getFileUrl()));
|
||||
@@ -51,8 +54,7 @@ $openButton.click(() => {
|
||||
|
||||
function getFileUrl() {
|
||||
// electron needs absolute URL so we extract current host, port, protocol
|
||||
return utils.getHost() + "/api/notes/" + noteDetailService.getCurrentNoteId()
|
||||
+ "/download?protectedSessionId=" + encodeURIComponent(protectedSessionHolder.getProtectedSessionId());
|
||||
return utils.getHost() + "/api/notes/" + noteDetailService.getCurrentNoteId() + "/download";
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -62,8 +62,7 @@ $copyToClipboardButton.click(() => {
|
||||
|
||||
function getFileUrl() {
|
||||
// electron needs absolute URL so we extract current host, port, protocol
|
||||
return utils.getHost() + "/api/notes/" + noteDetailService.getCurrentNoteId()
|
||||
+ "/download?protectedSessionId=" + encodeURIComponent(protectedSessionHolder.getProtectedSessionId());
|
||||
return utils.getHost() + "/api/notes/" + noteDetailService.getCurrentNoteId() + "/download";
|
||||
}
|
||||
|
||||
export default {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import utils from "./utils.js";
|
||||
import optionsInitService from './options_init.js';
|
||||
|
||||
const PROTECTED_SESSION_ID_KEY = 'protectedSessionId';
|
||||
|
||||
let lastProtectedSessionOperationDate = null;
|
||||
let protectedSessionTimeout = null;
|
||||
let protectedSessionId = null;
|
||||
|
||||
optionsInitService.optionsReady.then(options => protectedSessionTimeout = options.protectedSessionTimeout);
|
||||
|
||||
@@ -18,15 +19,16 @@ function setProtectedSessionTimeout(encSessTimeout) {
|
||||
}
|
||||
|
||||
function getProtectedSessionId() {
|
||||
return protectedSessionId;
|
||||
return utils.getCookie(PROTECTED_SESSION_ID_KEY);
|
||||
}
|
||||
|
||||
function setProtectedSessionId(id) {
|
||||
protectedSessionId = id;
|
||||
// using session cookie so that it disappears after browser/tab is closed
|
||||
utils.setSessionCookie(PROTECTED_SESSION_ID_KEY, id);
|
||||
}
|
||||
|
||||
function resetProtectedSession() {
|
||||
protectedSessionId = null;
|
||||
utils.setSessionCookie(PROTECTED_SESSION_ID_KEY, null);
|
||||
|
||||
// most secure solution - guarantees nothing remained in memory
|
||||
// since this expires because user doesn't use the app, it shouldn't be disruptive
|
||||
@@ -34,12 +36,12 @@ function resetProtectedSession() {
|
||||
}
|
||||
|
||||
function isProtectedSessionAvailable() {
|
||||
return protectedSessionId !== null;
|
||||
return !!utils.getCookie(PROTECTED_SESSION_ID_KEY);
|
||||
}
|
||||
|
||||
function touchProtectedSession() {
|
||||
if (isProtectedSessionAvailable()) {
|
||||
lastProtectedSessionOperationDate = new Date();
|
||||
setProtectedSessionId(utils.getCookie(PROTECTED_SESSION_ID_KEY));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ function getHeaders() {
|
||||
// so hypothetical protectedSessionId becomes protectedsessionid on the backend
|
||||
// also avoiding using underscores instead of dashes since nginx filters them out by default
|
||||
return {
|
||||
// protectedSessionId is normally carried in cookie, but for electron AJAX requests we bypass
|
||||
// HTTP so no cookies and we need to pass it here explicitly
|
||||
'trilium-protected-session-id': protectedSessionId,
|
||||
'trilium-source-id': glob.sourceId
|
||||
};
|
||||
|
||||
@@ -417,6 +417,9 @@ function initFancyTree(tree) {
|
||||
const node = data.node;
|
||||
const noteId = node.data.noteId;
|
||||
|
||||
// click event won't propagate so let's close context menu manually
|
||||
contextMenuWidget.hideContextMenu();
|
||||
|
||||
setCurrentNotePathToHash(node);
|
||||
|
||||
noteDetailService.switchToNote(noteId);
|
||||
|
||||
@@ -164,11 +164,23 @@ function isDesktop() {
|
||||
|| (!window.device && !/Mobi/.test(navigator.userAgent));
|
||||
}
|
||||
|
||||
// cookie code below works for simple use cases only - ASCII only
|
||||
// not setting path so that cookies do not leak into other websites if multiplexed with reverse proxy
|
||||
|
||||
function setCookie(name, value) {
|
||||
const date = new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1000);
|
||||
const expires = "; expires=" + date.toUTCString();
|
||||
|
||||
document.cookie = name + "=" + (value || "") + expires + "; path=/";
|
||||
document.cookie = name + "=" + (value || "") + expires + ";";
|
||||
}
|
||||
|
||||
function setSessionCookie(name, value) {
|
||||
document.cookie = name + "=" + (value || "") + ";";
|
||||
}
|
||||
|
||||
function getCookie(name) {
|
||||
const valueMatch = document.cookie.match('(^|;) ?' + name + '=([^;]*)(;|$)');
|
||||
return valueMatch ? valueMatch[2] : null;
|
||||
}
|
||||
|
||||
function getNoteTypeClass(type) {
|
||||
@@ -213,6 +225,8 @@ export default {
|
||||
isMobile,
|
||||
isDesktop,
|
||||
setCookie,
|
||||
setSessionCookie,
|
||||
getCookie,
|
||||
getNoteTypeClass,
|
||||
getMimeTypeClass
|
||||
};
|
||||
@@ -4,7 +4,7 @@ const build = require('./build');
|
||||
const packageJson = require('../../package');
|
||||
const {TRILIUM_DATA_DIR} = require('./data_dir');
|
||||
|
||||
const APP_DB_VERSION = 126;
|
||||
const APP_DB_VERSION = 127;
|
||||
const SYNC_VERSION = 6;
|
||||
|
||||
module.exports = {
|
||||
|
||||
@@ -1 +1 @@
|
||||
module.exports = { buildDate:"2019-03-12T22:21:35+01:00", buildRevision: "0144dc12dfe46fc9e5d15d64cdd8c9e3f7398637" };
|
||||
module.exports = { buildDate:"2019-04-22T15:02:39+02:00", buildRevision: "69677b15feb8852ff962116d8a2b9dfb78ad4f63" };
|
||||
|
||||
@@ -95,7 +95,8 @@ async function createNewNote(parentNoteId, noteData) {
|
||||
|
||||
note.noteContent = await new NoteContent({
|
||||
noteId: note.noteId,
|
||||
content: noteData.content
|
||||
content: noteData.content,
|
||||
isProtected: noteData.isProtected
|
||||
}).save();
|
||||
|
||||
const branch = await new Branch({
|
||||
|
||||
@@ -15,7 +15,8 @@ function setDataKey(decryptedDataKey) {
|
||||
}
|
||||
|
||||
function setProtectedSessionId(req) {
|
||||
cls.namespace.set('protectedSessionId', req.headers['trilium-protected-session-id'] || req.query.protectedSessionId);
|
||||
// cookies is the main storage but for electron header is used when bypassing HTTP
|
||||
cls.namespace.set('protectedSessionId', req.headers['trilium-protected-session-id'] || req.cookies.protectedSessionId);
|
||||
}
|
||||
|
||||
function getProtectedSessionId() {
|
||||
@@ -85,12 +86,17 @@ function decryptNoteRevision(hist) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (hist.title) {
|
||||
hist.title = dataEncryptionService.decryptString(dataKey, hist.title);
|
||||
}
|
||||
try {
|
||||
if (hist.title) {
|
||||
hist.title = dataEncryptionService.decryptString(dataKey, hist.title);
|
||||
}
|
||||
|
||||
if (hist.content) {
|
||||
hist.content = dataEncryptionService.decryptString(dataKey, hist.content);
|
||||
if (hist.content) {
|
||||
hist.content = dataEncryptionService.decryptString(dataKey, hist.content);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
throw new Error(`Decryption failed for note ${hist.noteId}: ` + e.message + " " + e.stack);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user