mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
Merge remote-tracking branch 'origin/stable'
This commit is contained in:
commit
c71f3c35b8
@ -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": {
|
||||||
|
@ -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]";
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
};
|
};
|
||||||
|
@ -200,9 +200,7 @@ function queueSector(req) {
|
|||||||
const entityName = utils.sanitizeSqlIdentifier(req.params.entityName);
|
const entityName = utils.sanitizeSqlIdentifier(req.params.entityName);
|
||||||
const sector = utils.sanitizeSqlIdentifier(req.params.sector);
|
const sector = utils.sanitizeSqlIdentifier(req.params.sector);
|
||||||
|
|
||||||
const entityPrimaryKey = entityConstructor.getEntityFromEntityName(entityName).primaryKeyName;
|
entityChangesService.addEntityChangesForSector(entityName, sector);
|
||||||
|
|
||||||
entityChangesService.addEntityChangesForSector(entityName, entityPrimaryKey, sector);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -271,6 +271,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
|
||||||
|
@ -1 +1 @@
|
|||||||
module.exports = { buildDate:"2021-03-25T20:28:57+01:00", buildRevision: "9139c597e549add45aafdb70f461d6bc39f975d9" };
|
module.exports = { buildDate:"2021-04-03T22:37:04+02:00", buildRevision: "ef37a52a06b471e60f9c0f11da704283bbcef6ab" };
|
||||||
|
@ -53,22 +53,14 @@ function moveEntityChangeToTop(entityName, entityId) {
|
|||||||
addEntityChange(entityName, entityId, hash, null, isSynced);
|
addEntityChange(entityName, entityId, hash, null, isSynced);
|
||||||
}
|
}
|
||||||
|
|
||||||
function addEntityChangesForSector(entityName, entityPrimaryKey, sector) {
|
function addEntityChangesForSector(entityName, sector) {
|
||||||
const startTime = Date.now();
|
const startTime = Date.now();
|
||||||
const repository = require('./repository');
|
|
||||||
|
const entityChanges = sql.getRows(`SELECT * FROM entity_changes WHERE entityName = ? AND SUBSTR(entityId, 1, 1) = ?`, [entityName, sector]);
|
||||||
|
|
||||||
sql.transactional(() => {
|
sql.transactional(() => {
|
||||||
const entityIds = sql.getColumn(`SELECT ${entityPrimaryKey} FROM ${entityName} WHERE SUBSTR(${entityPrimaryKey}, 1, 1) = ?`, [sector]);
|
for (const ec of entityChanges) {
|
||||||
|
insertEntityChange(entityName, ec.entityId, ec.hash, ec.isErased, ec.utcDateChanged, ec.sourceId, ec.isSynced);
|
||||||
for (const entityId of entityIds) {
|
|
||||||
// retrieving entity one by one to avoid memory issues with note_contents
|
|
||||||
const entity = repository.getEntity(`SELECT * FROM ${entityName} WHERE ${entityPrimaryKey} = ?`, [entityId]);
|
|
||||||
|
|
||||||
if (entityName === 'options' && !entity.isSynced) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
insertEntityChange(entityName, entityId, entity.generateHash(), false, entity.getUtcDateChanged(), 'content-check', true);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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) {
|
||||||
@ -424,10 +425,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
|
||||||
|
@ -179,6 +179,10 @@ eventService.subscribe(eventService.ENTER_PROTECTED_SESSION, () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
eventService.subscribe(eventService.LEAVE_PROTECTED_SESSION, () => {
|
||||||
|
load();
|
||||||
|
});
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
load
|
load
|
||||||
};
|
};
|
||||||
|
@ -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,
|
||||||
|
@ -249,9 +249,7 @@ async function checkContentHash(syncContext) {
|
|||||||
const failedChecks = contentHashService.checkContentHashes(resp.entityHashes);
|
const failedChecks = contentHashService.checkContentHashes(resp.entityHashes);
|
||||||
|
|
||||||
for (const {entityName, sector} of failedChecks) {
|
for (const {entityName, sector} of failedChecks) {
|
||||||
const entityPrimaryKey = entityConstructor.getEntityFromEntityName(entityName).primaryKeyName;
|
entityChangesService.addEntityChangesForSector(entityName, sector);
|
||||||
|
|
||||||
entityChangesService.addEntityChangesForSector(entityName, entityPrimaryKey, sector);
|
|
||||||
|
|
||||||
await syncRequest(syncContext, 'POST', `/api/sync/queue-sector/${entityName}/${sector}`);
|
await syncRequest(syncContext, 'POST', `/api/sync/queue-sector/${entityName}/${sector}`);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user