mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
removed dataKey where it's not necessary anymore (use of CLS instead)
This commit is contained in:
parent
5d203b2278
commit
05676f3459
@ -11,7 +11,7 @@ class Note extends Entity {
|
||||
super(repository, row);
|
||||
|
||||
if (this.isProtected) {
|
||||
protected_session.decryptNote(this.dataKey, this);
|
||||
protected_session.decryptNote(this);
|
||||
}
|
||||
|
||||
if (this.isJson()) {
|
||||
@ -129,7 +129,7 @@ class Note extends Entity {
|
||||
this.content = JSON.stringify(this.jsonContent, null, '\t');
|
||||
|
||||
if (this.isProtected) {
|
||||
protected_session.encryptNote(this.dataKey, this);
|
||||
protected_session.encryptNote(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -37,21 +37,18 @@ async function uploadFile(req) {
|
||||
async function downloadFile(req, res) {
|
||||
const noteId = req.params.noteId;
|
||||
const note = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]);
|
||||
const protectedSessionId = req.query.protectedSessionId;
|
||||
|
||||
if (!note) {
|
||||
return res.status(404).send(`Note ${noteId} doesn't exist.`);
|
||||
}
|
||||
|
||||
if (note.isProtected) {
|
||||
const dataKey = protected_session.getDataKeyForProtectedSessionId(protectedSessionId);
|
||||
|
||||
if (!dataKey) {
|
||||
if (!protected_session.isProtectedSessionAvailable()) {
|
||||
res.status(401).send("Protected session not available");
|
||||
return;
|
||||
}
|
||||
|
||||
protected_session.decryptNote(dataKey, note);
|
||||
protected_session.decryptNote(note);
|
||||
}
|
||||
|
||||
const labelMap = await labels.getNoteLabelMap(noteId);
|
||||
|
@ -6,7 +6,7 @@ const protected_session = require('../../services/protected_session');
|
||||
async function getNoteRevisions(req) {
|
||||
const noteId = req.params.noteId;
|
||||
const revisions = await sql.getRows("SELECT * FROM note_revisions WHERE noteId = ? order by dateModifiedTo desc", [noteId]);
|
||||
protected_session.decryptNoteRevisions(req, revisions);
|
||||
protected_session.decryptNoteRevisions(revisions);
|
||||
|
||||
return revisions;
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ async function getNote(req) {
|
||||
return [404, "Note " + noteId + " has not been found."];
|
||||
}
|
||||
|
||||
protected_session.decryptNote(req, note);
|
||||
protected_session.decryptNote(note);
|
||||
|
||||
if (note.type === 'file') {
|
||||
// no need to transfer (potentially large) file payload for this request
|
||||
@ -46,24 +46,21 @@ async function createNote(req) {
|
||||
async function updateNote(req) {
|
||||
const note = req.body;
|
||||
const noteId = req.params.noteId;
|
||||
const dataKey = protected_session.getDataKey(req);
|
||||
|
||||
await notes.updateNote(noteId, note, dataKey);
|
||||
await notes.updateNote(noteId, note);
|
||||
}
|
||||
|
||||
async function sortNotes(req) {
|
||||
const noteId = req.params.noteId;
|
||||
const dataKey = protected_session.getDataKey(req);
|
||||
|
||||
await tree.sortNotesAlphabetically(noteId, dataKey);
|
||||
await tree.sortNotesAlphabetically(noteId);
|
||||
}
|
||||
|
||||
async function protectBranch(req) {
|
||||
const noteId = req.params.noteId;
|
||||
const isProtected = !!parseInt(req.params.isProtected);
|
||||
const dataKey = protected_session.getDataKey(req);
|
||||
|
||||
await notes.protectNoteRecursively(noteId, dataKey, isProtected);
|
||||
await notes.protectNoteRecursively(noteId, isProtected);
|
||||
}
|
||||
|
||||
async function setNoteTypeMime(req) {
|
||||
|
@ -45,7 +45,7 @@ async function getTree(req) {
|
||||
WHERE
|
||||
notes.isDeleted = 0`));
|
||||
|
||||
protected_session.decryptNotes(req, notes);
|
||||
protected_session.decryptNotes(notes);
|
||||
|
||||
notes.forEach(note => {
|
||||
note.hideInAutocomplete = !!note.hideInAutocomplete;
|
||||
|
@ -38,6 +38,7 @@ const router = express.Router();
|
||||
const auth = require('../services/auth');
|
||||
const cls = require('../services/cls');
|
||||
const sql = require('../services/sql');
|
||||
const protectedSessionService = require('../services/protected_session');
|
||||
|
||||
function apiResultHandler(res, result) {
|
||||
// if it's an array and first element is integer then we consider this to be [statusCode, response] format
|
||||
@ -67,6 +68,7 @@ function route(method, path, middleware, routeHandler, resultHandler) {
|
||||
try {
|
||||
const result = await cls.init(async () => {
|
||||
cls.namespace.set('sourceId', req.headers.source_id);
|
||||
protectedSessionService.setProtectedSessionId(req);
|
||||
|
||||
return await sql.doInTransaction(async () => {
|
||||
return await routeHandler(req, res, next);
|
||||
|
@ -5,7 +5,7 @@ const sync_table = require('./sync_table');
|
||||
const labels = require('./labels');
|
||||
const protected_session = require('./protected_session');
|
||||
|
||||
async function createNewNote(parentNoteId, noteOpts, dataKey) {
|
||||
async function createNewNote(parentNoteId, noteOpts) {
|
||||
const noteId = utils.newNoteId();
|
||||
const branchId = utils.newBranchId();
|
||||
|
||||
@ -57,7 +57,7 @@ async function createNewNote(parentNoteId, noteOpts, dataKey) {
|
||||
};
|
||||
|
||||
if (note.isProtected) {
|
||||
protected_session.encryptNote(dataKey, note);
|
||||
protected_session.encryptNote(note);
|
||||
}
|
||||
|
||||
await sql.insert("notes", note);
|
||||
@ -106,7 +106,7 @@ async function createNote(parentNoteId, title, content = "", extraOptions = {})
|
||||
note.mime = "text/html";
|
||||
}
|
||||
|
||||
const {noteId} = await createNewNote(parentNoteId, note, extraOptions.dataKey);
|
||||
const {noteId} = await createNewNote(parentNoteId, note);
|
||||
|
||||
if (extraOptions.labels) {
|
||||
for (const attrName in extraOptions.labels) {
|
||||
@ -117,30 +117,30 @@ async function createNote(parentNoteId, title, content = "", extraOptions = {})
|
||||
return noteId;
|
||||
}
|
||||
|
||||
async function protectNoteRecursively(noteId, dataKey, protect) {
|
||||
async function protectNoteRecursively(noteId, protect) {
|
||||
const note = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]);
|
||||
|
||||
await protectNote(note, dataKey, protect);
|
||||
await protectNote(note, protect);
|
||||
|
||||
const children = await sql.getColumn("SELECT noteId FROM branches WHERE parentNoteId = ? AND isDeleted = 0", [noteId]);
|
||||
|
||||
for (const childNoteId of children) {
|
||||
await protectNoteRecursively(childNoteId, dataKey, protect);
|
||||
await protectNoteRecursively(childNoteId, protect);
|
||||
}
|
||||
}
|
||||
|
||||
async function protectNote(note, dataKey, protect) {
|
||||
async function protectNote(note, protect) {
|
||||
let changed = false;
|
||||
|
||||
if (protect && !note.isProtected) {
|
||||
protected_session.encryptNote(dataKey, note);
|
||||
protected_session.encryptNote(note);
|
||||
|
||||
note.isProtected = true;
|
||||
|
||||
changed = true;
|
||||
}
|
||||
else if (!protect && note.isProtected) {
|
||||
protected_session.decryptNote(dataKey, note);
|
||||
protected_session.decryptNote(note);
|
||||
|
||||
note.isProtected = false;
|
||||
|
||||
@ -154,20 +154,20 @@ async function protectNote(note, dataKey, protect) {
|
||||
await sync_table.addNoteSync(note.noteId);
|
||||
}
|
||||
|
||||
await protectNoteRevisions(note.noteId, dataKey, protect);
|
||||
await protectNoteRevisions(note.noteId, protect);
|
||||
}
|
||||
|
||||
async function protectNoteRevisions(noteId, dataKey, protect) {
|
||||
async function protectNoteRevisions(noteId, protect) {
|
||||
const revisionsToChange = await sql.getRows("SELECT * FROM note_revisions WHERE noteId = ? AND isProtected != ?", [noteId, protect]);
|
||||
|
||||
for (const revision of revisionsToChange) {
|
||||
if (protect) {
|
||||
protected_session.encryptNoteRevision(dataKey, revision);
|
||||
protected_session.encryptNoteRevision(revision);
|
||||
|
||||
revision.isProtected = true;
|
||||
}
|
||||
else {
|
||||
protected_session.decryptNoteRevision(dataKey, revision);
|
||||
protected_session.decryptNoteRevision(revision);
|
||||
|
||||
revision.isProtected = false;
|
||||
}
|
||||
@ -179,7 +179,7 @@ async function protectNoteRevisions(noteId, dataKey, protect) {
|
||||
}
|
||||
}
|
||||
|
||||
async function saveNoteRevision(noteId, dataKey, nowStr) {
|
||||
async function saveNoteRevision(noteId, nowStr) {
|
||||
const oldNote = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]);
|
||||
|
||||
if (oldNote.type === 'file') {
|
||||
@ -187,7 +187,7 @@ async function saveNoteRevision(noteId, dataKey, nowStr) {
|
||||
}
|
||||
|
||||
if (oldNote.isProtected) {
|
||||
protected_session.decryptNote(dataKey, oldNote);
|
||||
protected_session.decryptNote(oldNote);
|
||||
|
||||
oldNote.isProtected = false;
|
||||
}
|
||||
@ -255,23 +255,23 @@ async function saveNoteImages(noteId, noteText) {
|
||||
}
|
||||
}
|
||||
|
||||
async function loadFile(noteId, newNote, dataKey) {
|
||||
async function loadFile(noteId, newNote) {
|
||||
const oldNote = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]);
|
||||
|
||||
if (oldNote.isProtected) {
|
||||
await protected_session.decryptNote(dataKey, oldNote);
|
||||
await protected_session.decryptNote(oldNote);
|
||||
}
|
||||
|
||||
newNote.content = oldNote.content;
|
||||
}
|
||||
|
||||
async function updateNote(noteId, newNote, dataKey) {
|
||||
async function updateNote(noteId, newNote) {
|
||||
if (newNote.type === 'file') {
|
||||
await loadFile(noteId, newNote, dataKey);
|
||||
await loadFile(noteId, newNote);
|
||||
}
|
||||
|
||||
if (newNote.isProtected) {
|
||||
await protected_session.encryptNote(dataKey, newNote);
|
||||
await protected_session.encryptNote(newNote);
|
||||
}
|
||||
|
||||
const labelsMap = await labels.getNoteLabelMap(noteId);
|
||||
@ -293,12 +293,12 @@ async function updateNote(noteId, newNote, dataKey) {
|
||||
&& !existingnoteRevisionId
|
||||
&& msSinceDateCreated >= noteRevisionSnapshotTimeInterval * 1000) {
|
||||
|
||||
await saveNoteRevision(noteId, dataKey, nowStr);
|
||||
await saveNoteRevision(noteId, nowStr);
|
||||
}
|
||||
|
||||
await saveNoteImages(noteId, newNote.content);
|
||||
|
||||
await protectNoteRevisions(noteId, dataKey, newNote.isProtected);
|
||||
await protectNoteRevisions(noteId, newNote.isProtected);
|
||||
|
||||
await sql.execute("UPDATE notes SET title = ?, content = ?, isProtected = ?, dateModified = ? WHERE noteId = ?", [
|
||||
newNote.title,
|
||||
|
@ -2,50 +2,43 @@
|
||||
|
||||
const utils = require('./utils');
|
||||
const data_encryption = require('./data_encryption');
|
||||
const session = {};
|
||||
const dataKeyMap = {};
|
||||
const cls = require('./cls');
|
||||
|
||||
function setDataKey(req, decryptedDataKey) {
|
||||
session.decryptedDataKey = Array.from(decryptedDataKey); // can't store buffer in session
|
||||
session.protectedSessionId = utils.randomSecureToken(32);
|
||||
const protectedSessionId = utils.randomSecureToken(32);
|
||||
|
||||
return session.protectedSessionId;
|
||||
dataKeyMap[protectedSessionId] = Array.from(decryptedDataKey); // can't store buffer in session
|
||||
|
||||
return protectedSessionId;
|
||||
}
|
||||
|
||||
function getProtectedSessionId(req) {
|
||||
return req.headers.protected_session_id;
|
||||
function setProtectedSessionId(req) {
|
||||
cls.namespace.set('protectedSessionId', req.headers.protected_session_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param obj - can be either array, in that case it's considered to be already dataKey and we just return it
|
||||
* if it's not a array, we consider it a request object and try to pull dataKey based on the session id header
|
||||
*/
|
||||
function getDataKey(obj) {
|
||||
if (!obj || obj.constructor.name === 'Array') {
|
||||
return obj;
|
||||
function getProtectedSessionId() {
|
||||
return cls.namespace.get('protectedSessionId');
|
||||
}
|
||||
|
||||
const protectedSessionId = getProtectedSessionId(obj);
|
||||
function getDataKey() {
|
||||
const protectedSessionId = getProtectedSessionId();
|
||||
|
||||
return getDataKeyForProtectedSessionId(protectedSessionId);
|
||||
return dataKeyMap[protectedSessionId];
|
||||
}
|
||||
|
||||
function getDataKeyForProtectedSessionId(protectedSessionId) {
|
||||
if (protectedSessionId && session.protectedSessionId === protectedSessionId) {
|
||||
return session.decryptedDataKey;
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
return dataKeyMap[protectedSessionId];
|
||||
}
|
||||
|
||||
function isProtectedSessionAvailable(req) {
|
||||
const protectedSessionId = getProtectedSessionId(req);
|
||||
|
||||
return protectedSessionId && session.protectedSessionId === protectedSessionId;
|
||||
return !!dataKeyMap[protectedSessionId];
|
||||
}
|
||||
|
||||
function decryptNote(dataKey, note) {
|
||||
dataKey = getDataKey(dataKey);
|
||||
function decryptNote(note) {
|
||||
const dataKey = getDataKey();
|
||||
|
||||
if (!note.isProtected) {
|
||||
return;
|
||||
@ -67,16 +60,16 @@ function decryptNote(dataKey, note) {
|
||||
}
|
||||
}
|
||||
|
||||
function decryptNotes(dataKey, notes) {
|
||||
dataKey = getDataKey(dataKey);
|
||||
function decryptNotes(notes) {
|
||||
const dataKey = getDataKey();
|
||||
|
||||
for (const note of notes) {
|
||||
decryptNote(dataKey, note);
|
||||
decryptNote(note);
|
||||
}
|
||||
}
|
||||
|
||||
function decryptNoteRevision(dataKey, hist) {
|
||||
dataKey = getDataKey(dataKey);
|
||||
function decryptNoteRevision(hist) {
|
||||
const dataKey = getDataKey();
|
||||
|
||||
if (!hist.isProtected) {
|
||||
return;
|
||||
@ -91,23 +84,21 @@ function decryptNoteRevision(dataKey, hist) {
|
||||
}
|
||||
}
|
||||
|
||||
function decryptNoteRevisions(dataKey, noteRevisions) {
|
||||
dataKey = getDataKey(dataKey);
|
||||
|
||||
function decryptNoteRevisions(noteRevisions) {
|
||||
for (const revision of noteRevisions) {
|
||||
decryptNoteRevision(dataKey, revision);
|
||||
decryptNoteRevision(revision);
|
||||
}
|
||||
}
|
||||
|
||||
function encryptNote(dataKey, note) {
|
||||
dataKey = getDataKey(dataKey);
|
||||
function encryptNote(note) {
|
||||
const dataKey = getDataKey();
|
||||
|
||||
note.title = data_encryption.encrypt(dataKey, data_encryption.noteTitleIv(note.noteId), note.title);
|
||||
note.content = data_encryption.encrypt(dataKey, data_encryption.noteContentIv(note.noteId), note.content);
|
||||
}
|
||||
|
||||
function encryptNoteRevision(dataKey, revision) {
|
||||
dataKey = getDataKey(dataKey);
|
||||
function encryptNoteRevision(revision) {
|
||||
const dataKey = getDataKey();
|
||||
|
||||
revision.title = data_encryption.encrypt(dataKey, data_encryption.noteTitleIv(revision.noteRevisionId), revision.title);
|
||||
revision.content = data_encryption.encrypt(dataKey, data_encryption.noteContentIv(revision.noteRevisionId), revision.content);
|
||||
@ -123,5 +114,6 @@ module.exports = {
|
||||
decryptNoteRevision,
|
||||
decryptNoteRevisions,
|
||||
encryptNote,
|
||||
encryptNoteRevision
|
||||
encryptNoteRevision,
|
||||
setProtectedSessionId
|
||||
};
|
@ -7,17 +7,9 @@ const Label = require('../entities/label');
|
||||
const sync_table = require('../services/sync_table');
|
||||
|
||||
class Repository {
|
||||
constructor(dataKey) {
|
||||
this.dataKey = protected_session.getDataKey(dataKey);
|
||||
}
|
||||
|
||||
async getEntities(query, params = []) {
|
||||
const rows = await sql.getRows(query, params);
|
||||
|
||||
for (const row of rows) {
|
||||
row.dataKey = this.dataKey;
|
||||
}
|
||||
|
||||
return rows.map(row => this.createEntityFromRow(row));
|
||||
}
|
||||
|
||||
@ -28,8 +20,6 @@ class Repository {
|
||||
return null;
|
||||
}
|
||||
|
||||
row.dataKey = this.dataKey;
|
||||
|
||||
return this.createEntityFromRow(row);
|
||||
}
|
||||
|
||||
@ -66,7 +56,6 @@ class Repository {
|
||||
|
||||
const clone = Object.assign({}, entity);
|
||||
|
||||
delete clone.dataKey;
|
||||
delete clone.jsonContent;
|
||||
delete clone.repository;
|
||||
|
||||
|
@ -2,17 +2,17 @@ const sql = require('./sql');
|
||||
const ScriptContext = require('./script_context');
|
||||
const Repository = require('./repository');
|
||||
|
||||
async function executeNote(dataKey, note) {
|
||||
async function executeNote(note) {
|
||||
if (!note.isJavaScript()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const bundle = await getScriptBundle(note);
|
||||
|
||||
await executeBundle(dataKey, bundle);
|
||||
await executeBundle(bundle);
|
||||
}
|
||||
|
||||
async function executeBundle(dataKey, bundle, startNote) {
|
||||
async function executeBundle(bundle, startNote) {
|
||||
if (!startNote) {
|
||||
// this is the default case, the only exception is when we want to preserve frontend startNote
|
||||
startNote = bundle.note;
|
||||
@ -21,7 +21,7 @@ async function executeBundle(dataKey, bundle, startNote) {
|
||||
// last \r\n is necessary if script contains line comment on its last line
|
||||
const script = "async function() {\r\n" + bundle.script + "\r\n}";
|
||||
|
||||
const ctx = new ScriptContext(dataKey, startNote, bundle.allNotes);
|
||||
const ctx = new ScriptContext(startNote, bundle.allNotes);
|
||||
|
||||
if (await bundle.note.hasLabel('manual_transaction_handling')) {
|
||||
return await execute(ctx, script, '');
|
||||
@ -35,8 +35,8 @@ async function executeBundle(dataKey, bundle, startNote) {
|
||||
* This method preserves frontend startNode - that's why we start execution from currentNote and override
|
||||
* bundle's startNote.
|
||||
*/
|
||||
async function executeScript(dataKey, script, params, startNoteId, currentNoteId) {
|
||||
const repository = new Repository(dataKey);
|
||||
async function executeScript(script, params, startNoteId, currentNoteId) {
|
||||
const repository = new Repository();
|
||||
const startNote = await repository.getNote(startNoteId);
|
||||
const currentNote = await repository.getNote(currentNoteId);
|
||||
|
||||
@ -46,7 +46,7 @@ async function executeScript(dataKey, script, params, startNoteId, currentNoteId
|
||||
|
||||
const bundle = await getScriptBundle(currentNote);
|
||||
|
||||
return await executeBundle(dataKey, bundle, startNote);
|
||||
return await executeBundle(bundle, startNote);
|
||||
}
|
||||
|
||||
async function execute(ctx, script, paramsStr) {
|
||||
|
@ -9,12 +9,10 @@ const config = require('./config');
|
||||
const Repository = require('./repository');
|
||||
const axios = require('axios');
|
||||
|
||||
function ScriptContext(dataKey, startNote, allNotes) {
|
||||
dataKey = protected_session.getDataKey(dataKey);
|
||||
|
||||
function ScriptContext(startNote, allNotes) {
|
||||
this.modules = {};
|
||||
this.notes = utils.toObject(allNotes, note => [note.noteId, note]);
|
||||
this.apis = utils.toObject(allNotes, note => [note.noteId, new ScriptApi(dataKey, startNote, note)]);
|
||||
this.apis = utils.toObject(allNotes, note => [note.noteId, new ScriptApi(startNote, note)]);
|
||||
this.require = moduleNoteIds => {
|
||||
return moduleName => {
|
||||
const candidates = allNotes.filter(note => moduleNoteIds.includes(note.noteId));
|
||||
@ -29,8 +27,8 @@ function ScriptContext(dataKey, startNote, allNotes) {
|
||||
};
|
||||
}
|
||||
|
||||
function ScriptApi(dataKey, startNote, currentNote) {
|
||||
const repository = new Repository(dataKey);
|
||||
function ScriptApi(startNote, currentNote) {
|
||||
const repository = new Repository();
|
||||
this.startNote = startNote;
|
||||
this.currentNote = currentNote;
|
||||
|
||||
@ -59,8 +57,6 @@ function ScriptApi(dataKey, startNote, currentNote) {
|
||||
};
|
||||
|
||||
this.createNote = async function(parentNoteId, title, content = "", extraOptions = {}) {
|
||||
extraOptions.dataKey = dataKey;
|
||||
|
||||
return await notes.createNote(parentNoteId, title, content, extraOptions);
|
||||
};
|
||||
|
||||
|
@ -76,13 +76,13 @@ async function loadSubTreeNoteIds(parentNoteId, subTreeNoteIds) {
|
||||
}
|
||||
}
|
||||
|
||||
async function sortNotesAlphabetically(parentNoteId, req) {
|
||||
async function sortNotesAlphabetically(parentNoteId) {
|
||||
await sql.doInTransaction(async () => {
|
||||
const notes = await sql.getRows(`SELECT branchId, noteId, title, isProtected
|
||||
FROM notes JOIN branches USING(noteId)
|
||||
WHERE branches.isDeleted = 0 AND parentNoteId = ?`, [parentNoteId]);
|
||||
|
||||
protected_session.decryptNotes(req, notes);
|
||||
protected_session.decryptNotes(notes);
|
||||
|
||||
notes.sort((a, b) => a.title.toLowerCase() < b.title.toLowerCase() ? -1 : 1);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user