Compare commits

...

7 Commits

13 changed files with 53 additions and 11 deletions

View File

@@ -2,7 +2,7 @@
"name": "trilium", "name": "trilium",
"productName": "Trilium Notes", "productName": "Trilium Notes",
"description": "Trilium Notes", "description": "Trilium Notes",
"version": "0.46.6", "version": "0.46.7",
"license": "AGPL-3.0-only", "license": "AGPL-3.0-only",
"main": "electron.js", "main": "electron.js",
"bin": { "bin": {

View File

@@ -49,8 +49,13 @@ class Note extends Entity {
this.isContentAvailable = protectedSessionService.isProtectedSessionAvailable(); this.isContentAvailable = protectedSessionService.isProtectedSessionAvailable();
if (this.isContentAvailable) { if (this.isContentAvailable) {
try {
this.title = protectedSessionService.decryptString(this.title); this.title = protectedSessionService.decryptString(this.title);
} }
catch (e) {
throw new Error(`Could not decrypt title of note ${this.noteId}: ${e.message} ${e.stack}`)
}
}
else { else {
this.title = "[protected]"; this.title = "[protected]";
} }

View File

@@ -359,7 +359,7 @@ class NoteShort {
const workspaceIconClass = this.getWorkspaceIconClass(); const workspaceIconClass = this.getWorkspaceIconClass();
if (iconClassLabels.length > 0) { if (iconClassLabels.length > 0) {
return iconClassLabels.map(l => l.value).join(' '); return iconClassLabels[0].value;
} }
else if (workspaceIconClass) { else if (workspaceIconClass) {
return workspaceIconClass; return workspaceIconClass;

View File

@@ -1,5 +1,6 @@
import utils from "./utils.js"; import utils from "./utils.js";
import options from './options.js'; import options from './options.js';
import server from "./server.js";
const PROTECTED_SESSION_ID_KEY = 'protectedSessionId'; const PROTECTED_SESSION_ID_KEY = 'protectedSessionId';
@@ -23,11 +24,11 @@ function resetSessionCookie() {
utils.setSessionCookie(PROTECTED_SESSION_ID_KEY, null); utils.setSessionCookie(PROTECTED_SESSION_ID_KEY, null);
} }
function resetProtectedSession() { async function resetProtectedSession() {
resetSessionCookie(); resetSessionCookie();
// most secure solution - guarantees nothing remained in memory await server.post("logout/protected");
// since this expires because user doesn't use the app, it shouldn't be disruptive
utils.reloadApp(); utils.reloadApp();
} }

View File

@@ -14,6 +14,10 @@ const TPL = `
height: 35px; height: 35px;
} }
.standard-top-widget > div {
flex-shrink: 0; /* fixes https://github.com/zadam/trilium/issues/1745 */
}
.standard-top-widget button.noborder { .standard-top-widget button.noborder {
padding: 1px 5px 1px 5px; padding: 1px 5px 1px 5px;
font-size: 90%; font-size: 90%;

View File

@@ -78,6 +78,12 @@ function loginToProtectedSession(req) {
}; };
} }
function logoutFromProtectedSession() {
protectedSessionService.resetDataKey();
eventService.emit(eventService.LEAVE_PROTECTED_SESSION);
}
function token(req) { function token(req) {
const username = req.body.username; const username = req.body.username;
const password = req.body.password; const password = req.body.password;
@@ -101,5 +107,6 @@ function token(req) {
module.exports = { module.exports = {
loginSync, loginSync,
loginToProtectedSession, loginToProtectedSession,
logoutFromProtectedSession,
token token
}; };

View File

@@ -270,6 +270,8 @@ function register(app) {
route(POST, '/api/login/sync', [], loginApiRoute.loginSync, apiResultHandler); route(POST, '/api/login/sync', [], loginApiRoute.loginSync, apiResultHandler);
// this is for entering protected mode so user has to be already logged-in (that's the reason we don't require username) // this is for entering protected mode so user has to be already logged-in (that's the reason we don't require username)
apiRoute(POST, '/api/login/protected', loginApiRoute.loginToProtectedSession); apiRoute(POST, '/api/login/protected', loginApiRoute.loginToProtectedSession);
apiRoute(POST, '/api/logout/protected', loginApiRoute.logoutFromProtectedSession);
route(POST, '/api/login/token', [], loginApiRoute.token, apiResultHandler); route(POST, '/api/login/token', [], loginApiRoute.token, apiResultHandler);
// in case of local electron, local calls are allowed unauthenticated, for server they need auth // in case of local electron, local calls are allowed unauthenticated, for server they need auth

View File

@@ -1 +1 @@
module.exports = { buildDate:"2021-03-23T23:57:48+01:00", buildRevision: "1862acd1ff9261536ebc7118d35bbbd8449ba94d" }; module.exports = { buildDate:"2021-04-03T22:37:04+02:00", buildRevision: "ef37a52a06b471e60f9c0f11da704283bbcef6ab" };

View File

@@ -2,6 +2,7 @@ const log = require('./log');
const NOTE_TITLE_CHANGED = "NOTE_TITLE_CHANGED"; const NOTE_TITLE_CHANGED = "NOTE_TITLE_CHANGED";
const ENTER_PROTECTED_SESSION = "ENTER_PROTECTED_SESSION"; const ENTER_PROTECTED_SESSION = "ENTER_PROTECTED_SESSION";
const LEAVE_PROTECTED_SESSION = "LEAVE_PROTECTED_SESSION";
const ENTITY_CREATED = "ENTITY_CREATED"; const ENTITY_CREATED = "ENTITY_CREATED";
const ENTITY_CHANGED = "ENTITY_CHANGED"; const ENTITY_CHANGED = "ENTITY_CHANGED";
const ENTITY_DELETED = "ENTITY_DELETED"; const ENTITY_DELETED = "ENTITY_DELETED";
@@ -47,6 +48,7 @@ module.exports = {
// event types: // event types:
NOTE_TITLE_CHANGED, NOTE_TITLE_CHANGED,
ENTER_PROTECTED_SESSION, ENTER_PROTECTED_SESSION,
LEAVE_PROTECTED_SESSION,
ENTITY_CREATED, ENTITY_CREATED,
ENTITY_CHANGED, ENTITY_CHANGED,
ENTITY_DELETED, ENTITY_DELETED,

View File

@@ -1,6 +1,7 @@
"use strict"; "use strict";
const protectedSessionService = require('../../protected_session'); const protectedSessionService = require('../../protected_session');
const log = require('../../log');
class Note { class Note {
constructor(noteCache, row) { constructor(noteCache, row) {
@@ -416,10 +417,15 @@ class Note {
decrypt() { decrypt() {
if (this.isProtected && !this.isDecrypted && protectedSessionService.isProtectedSessionAvailable()) { if (this.isProtected && !this.isDecrypted && protectedSessionService.isProtectedSessionAvailable()) {
try {
this.title = protectedSessionService.decryptString(this.title); this.title = protectedSessionService.decryptString(this.title);
this.isDecrypted = true; this.isDecrypted = true;
} }
catch (e) {
log.error(`Could not decrypt note ${this.noteId}: ${e.message} ${e.stack}`);
}
}
} }
// for logging etc // for logging etc

View File

@@ -177,6 +177,10 @@ eventService.subscribe(eventService.ENTER_PROTECTED_SESSION, () => {
} }
}); });
eventService.subscribe(eventService.LEAVE_PROTECTED_SESSION, () => {
load();
});
module.exports = { module.exports = {
load load
}; };

View File

@@ -5,7 +5,7 @@ const log = require('./log');
const dataEncryptionService = require('./data_encryption'); const dataEncryptionService = require('./data_encryption');
const cls = require('./cls'); const cls = require('./cls');
const dataKeyMap = {}; let dataKeyMap = {};
function setDataKey(decryptedDataKey) { function setDataKey(decryptedDataKey) {
const protectedSessionId = utils.randomSecureToken(32); const protectedSessionId = utils.randomSecureToken(32);
@@ -29,6 +29,10 @@ function getDataKey() {
return dataKeyMap[protectedSessionId]; return dataKeyMap[protectedSessionId];
} }
function resetDataKey() {
dataKeyMap = {};
}
function isProtectedSessionAvailable() { function isProtectedSessionAvailable() {
const protectedSessionId = getProtectedSessionId(); const protectedSessionId = getProtectedSessionId();
@@ -71,6 +75,7 @@ function decryptString(cipherText) {
module.exports = { module.exports = {
setDataKey, setDataKey,
getDataKey, getDataKey,
resetDataKey,
isProtectedSessionAvailable, isProtectedSessionAvailable,
encrypt, encrypt,
decrypt, decrypt,

View File

@@ -1,6 +1,7 @@
"use strict"; "use strict";
const sql = require('./sql'); const sql = require('./sql');
const log = require('./log');
const repository = require('./repository'); const repository = require('./repository');
const Branch = require('../entities/branch'); const Branch = require('../entities/branch');
const entityChangesService = require('./entity_changes.js'); const entityChangesService = require('./entity_changes.js');
@@ -139,7 +140,12 @@ function sortNotesByTitle(parentNoteId, foldersFirst = false, reverse = false) {
sql.execute("UPDATE branches SET notePosition = ? WHERE branchId = ?", sql.execute("UPDATE branches SET notePosition = ? WHERE branchId = ?",
[position, note.branchId]); [position, note.branchId]);
if (note.branchId in noteCache.branches) {
noteCache.branches[note.branchId].notePosition = position; noteCache.branches[note.branchId].notePosition = position;
}
else {
log.info(`Branch "${note.branchId}" was not found in note cache.`);
}
position += 10; position += 10;
} }