removed dataKey where it's not necessary anymore (use of CLS instead)

This commit is contained in:
azivner
2018-03-31 08:53:52 -04:00
parent 5d203b2278
commit 05676f3459
12 changed files with 78 additions and 105 deletions

View File

@@ -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,

View File

@@ -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
};

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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);
};

View File

@@ -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);