From 3f1e73d06b81a1ca9b58612fadc370133732879a Mon Sep 17 00:00:00 2001 From: azivner Date: Sat, 27 Jan 2018 17:18:19 -0500 Subject: [PATCH] more changes for scripts - separate API etc. --- plugins/reddit.js | 10 +-- public/javascripts/server.js | 4 +- routes/api/notes.js | 11 +-- routes/api/script.js | 6 +- services/notes.js | 134 ++++++++++++++++++++++------------- services/script.js | 17 ++--- services/script_context.js | 91 ++++++++++++++++++++++++ 7 files changed, 202 insertions(+), 71 deletions(-) create mode 100644 services/script_context.js diff --git a/plugins/reddit.js b/plugins/reddit.js index 6c798251d..60bed6e55 100644 --- a/plugins/reddit.js +++ b/plugins/reddit.js @@ -84,12 +84,12 @@ karma: ${comment.score}, created at ${dateTimeStr}

` let parentNoteId = await getDateNoteIdForReddit(dateTimeStr, rootNoteId); - commentNoteId = await createNote(parentNoteId, comment.link_title, noteText); - - log.info("Reddit: Imported comment to note " + commentNoteId); - importedComments++; - await sql.doInTransaction(async () => { + commentNoteId = await createNote(parentNoteId, comment.link_title, noteText); + + log.info("Reddit: Imported comment to note " + commentNoteId); + importedComments++; + await attributes.createAttribute(commentNoteId, "reddit_kind", child.kind); await attributes.createAttribute(commentNoteId, "reddit_id", redditId(child.kind, comment.id)); await attributes.createAttribute(commentNoteId, "reddit_created_utc", comment.created_utc); diff --git a/public/javascripts/server.js b/public/javascripts/server.js index 796c21874..85199d89b 100644 --- a/public/javascripts/server.js +++ b/public/javascripts/server.js @@ -29,12 +29,12 @@ const server = (function() { return await call('DELETE', url); } - async function exec(script, params = []) { + async function exec(params, script) { if (typeof script === "function") { script = script.toString(); } - return await post('script/exec', { script: script, params: params }); + return await post('script/exec/noteId', { script: script, params: params }); } let i = 1; diff --git a/routes/api/notes.js b/routes/api/notes.js index 1ca6aa93b..623328ac5 100644 --- a/routes/api/notes.js +++ b/routes/api/notes.js @@ -8,7 +8,6 @@ const notes = require('../../services/notes'); const log = require('../../services/log'); const utils = require('../../services/utils'); const protected_session = require('../../services/protected_session'); -const data_encryption = require('../../services/data_encryption'); const tree = require('../../services/tree'); const sync_table = require('../../services/sync_table'); const wrap = require('express-promise-wrap').wrap; @@ -36,11 +35,13 @@ router.post('/:parentNoteId/children', auth.checkApiAuth, wrap(async (req, res, const parentNoteId = req.params.parentNoteId; const note = req.body; - const { noteId, noteTreeId } = await notes.createNewNote(parentNoteId, note, sourceId); + await sql.doInTransaction(async () => { + const { noteId, noteTreeId } = await notes.createNewNote(parentNoteId, note, req, sourceId); - res.send({ - 'note_id': noteId, - 'note_tree_id': noteTreeId + res.send({ + 'note_id': noteId, + 'note_tree_id': noteTreeId + }); }); })); diff --git a/routes/api/script.js b/routes/api/script.js index 920d7ed82..25ba17862 100644 --- a/routes/api/script.js +++ b/routes/api/script.js @@ -10,8 +10,10 @@ const protected_session = require('../../services/protected_session'); const attributes = require('../../services/attributes'); const script = require('../../services/script'); -router.post('/exec', auth.checkApiAuth, wrap(async (req, res, next) => { - const ret = await script.executeScript(req, req.body.script, req.body.params); +router.post('/exec/:noteId', auth.checkApiAuth, wrap(async (req, res, next) => { + const noteId = req.params.noteId; + + const ret = await script.executeScript(noteId, req, req.body.script, req.body.params); res.send(ret); })); diff --git a/services/notes.js b/services/notes.js index c90ee7c44..81c4f07d9 100644 --- a/services/notes.js +++ b/services/notes.js @@ -1,7 +1,6 @@ const sql = require('./sql'); const options = require('./options'); const utils = require('./utils'); -const notes = require('./notes'); const sync_table = require('./sync_table'); const attributes = require('./attributes'); const protected_session = require('./protected_session'); @@ -14,73 +13,110 @@ async function getNoteById(noteId, dataKey) { return note; } -async function createNewNote(parentNoteId, note, sourceId) { +async function getJsonNoteById(noteId, dataKey) { + const note = await getNoteById(noteId, dataKey); + note.data = JSON.parse(note.note_text); + + return note; +} + +async function updateJsonNote(noteId, data) { + const ret = await createNewNote(noteId, { + note_title: name, + note_text: JSON.stringify(data), + target: 'into', + is_protected: false, + type: 'code', + mime: 'application/json' + }); + + return ret.noteId; +} + +async function createNewJsonNote(parentNoteId, name, payload) { + const ret = await createNewNote(parentNoteId, { + note_title: name, + note_text: JSON.stringify(payload), + target: 'into', + is_protected: false, + type: 'code', + mime: 'application/json' + }); + + return ret.noteId; +} + +async function createNewNote(parentNoteId, noteOpts, dataKey, sourceId) { const noteId = utils.newNoteId(); const noteTreeId = utils.newNoteTreeId(); let newNotePos = 0; - await sql.doInTransaction(async () => { - if (note.target === 'into') { - const maxNotePos = await sql.getFirstValue('SELECT MAX(note_position) FROM notes_tree WHERE parent_note_id = ? AND is_deleted = 0', [parentNoteId]); + if (noteOpts.target === 'into') { + const maxNotePos = await sql.getFirstValue('SELECT MAX(note_position) FROM notes_tree WHERE parent_note_id = ? AND is_deleted = 0', [parentNoteId]); - newNotePos = maxNotePos === null ? 0 : maxNotePos + 1; - } - else if (note.target === 'after') { - const afterNote = await sql.getFirst('SELECT note_position FROM notes_tree WHERE note_tree_id = ?', [note.target_note_tree_id]); + newNotePos = maxNotePos === null ? 0 : maxNotePos + 1; + } + else if (noteOpts.target === 'after') { + const afterNote = await sql.getFirst('SELECT note_position FROM notes_tree WHERE note_tree_id = ?', [noteOpts.target_note_tree_id]); - newNotePos = afterNote.note_position + 1; + newNotePos = afterNote.note_position + 1; - // not updating date_modified to avoig having to sync whole rows - await sql.execute('UPDATE notes_tree SET note_position = note_position + 1 WHERE parent_note_id = ? AND note_position > ? AND is_deleted = 0', - [parentNoteId, afterNote.note_position]); + // not updating date_modified to avoig having to sync whole rows + await sql.execute('UPDATE notes_tree SET note_position = note_position + 1 WHERE parent_note_id = ? AND note_position > ? AND is_deleted = 0', + [parentNoteId, afterNote.note_position]); - await sync_table.addNoteReorderingSync(parentNoteId, sourceId); - } - else { - throw new Error('Unknown target: ' + note.target); + await sync_table.addNoteReorderingSync(parentNoteId, sourceId); + } + else { + throw new Error('Unknown target: ' + noteOpts.target); + } + + if (parentNoteId !== 'root') { + const parent = await sql.getFirst("SELECT * FROM notes WHERE note_id = ?", [parentNoteId]); + + if (!noteOpts.type) { + noteOpts.type = parent.type; } - if (parentNoteId !== 'root') { - const parent = await sql.getFirst("SELECT * FROM notes WHERE note_id = ?", [parentNoteId]); - - if (!note.type) { - note.type = parent.type; - } - - if (!note.mime) { - note.mime = parent.mime; - } + if (!noteOpts.mime) { + noteOpts.mime = parent.mime; } + } - const now = utils.nowDate(); + const now = utils.nowDate(); - await sql.insert("notes", { - note_id: noteId, - note_title: note.note_title, - note_text: note.note_text ? note.note_text : '', - is_protected: note.is_protected, - type: note.type ? note.type : 'text', - mime: note.mime ? note.mime : 'text/html', - date_created: now, - date_modified: now - }); + const note = { + note_id: noteId, + note_title: noteOpts.note_title, + note_text: noteOpts.note_text ? noteOpts.note_text : '', + is_protected: noteOpts.is_protected, + type: noteOpts.type ? noteOpts.type : 'text', + mime: noteOpts.mime ? noteOpts.mime : 'text/html', + date_created: now, + date_modified: now + }; - await sync_table.addNoteSync(noteId, sourceId); + if (note.is_protected) { + protected_session.encryptNote(dataKey, note); + } - await sql.insert("notes_tree", { - note_tree_id: noteTreeId, - note_id: noteId, - parent_note_id: parentNoteId, - note_position: newNotePos, - is_expanded: 0, - date_modified: now, - is_deleted: 0 - }); + await sql.insert("notes", note); - await sync_table.addNoteTreeSync(noteTreeId, sourceId); + await sync_table.addNoteSync(noteId, sourceId); + + await sql.insert("notes_tree", { + note_tree_id: noteTreeId, + note_id: noteId, + parent_note_id: parentNoteId, + note_position: newNotePos, + is_expanded: 0, + date_modified: now, + is_deleted: 0 }); + await sync_table.addNoteTreeSync(noteTreeId, sourceId); + return { noteId, noteTreeId diff --git a/services/script.js b/services/script.js index d9fa4b3f9..82cc05778 100644 --- a/services/script.js +++ b/services/script.js @@ -1,18 +1,19 @@ const log = require('./log'); -const protected_session = require('./protected_session'); +const sql = require('./sql'); +const ScriptContext = require('./script_context'); -async function executeScript(dataKey, script, params) { +async function executeScript(noteId, dataKey, script, params) { log.info('Executing script: ' + script); - const ctx = { - dataKey: protected_session.getDataKey(dataKey) - }; - - params.unshift(ctx); + const ctx = new ScriptContext(noteId, dataKey); const paramsStr = getParams(params); - const ret = await eval(`(${script})(${paramsStr})`); + let ret; + + await sql.doInTransaction(async () => { + ret = await (function() { return eval(`(${script})(${paramsStr})`); }.call(ctx)); + }); log.info('Execution result: ' + ret); diff --git a/services/script_context.js b/services/script_context.js new file mode 100644 index 000000000..da3d523c8 --- /dev/null +++ b/services/script_context.js @@ -0,0 +1,91 @@ +const log = require('./log'); +const protected_session = require('./protected_session'); +const notes = require('./notes'); +const attributes = require('./attributes'); +const date_notes = require('./date_notes'); +const sql = require('./sql'); +const sync_table = require('./sync_table'); + +function ScriptContext(noteId, dataKey) { + this.scriptNoteId = noteId; + this.dataKey = protected_session.getDataKey(dataKey); + + function deserializePayload(note) { + if (note.type === "code" && note.mime === "application/json") { + note.payload = JSON.parse(note.note_text); + } + } + + this.getNoteById = async function(noteId) { + const note = await notes.getNoteById(noteId, this.dataKey); + + deserializePayload(note); + + return note; + }; + + this.getNoteWithAttribute = async function (attrName, attrValue) { + const note = await attributes.getNoteWithAttribute(this.dataKey, attrName, attrValue); + + deserializePayload(note); + + return note; + }; + + this.createNote = async function (parentNoteId, name, payload, extraOptions = {}) { + const note = { + note_title: name, + note_text: extraOptions.json ? JSON.stringify(payload) : payload, + target: 'into', + is_protected: extraOptions.isProtected !== undefined ? extraOptions.isProtected : false, + type: extraOptions.type, + mime: extraOptions.mime + }; + + if (extraOptions.json) { + note.type = "code"; + note.mime = "application/json"; + } + + if (!note.type) { + note.type = "text"; + note.mime = ""; + } + + const noteId = (await notes.createNewNote(parentNoteId, note)).noteId; + + if (extraOptions.attributes) { + for (const attrName in extraOptions.attributes) { + await attributes.createAttribute(noteId, attrName, extraOptions.attributes[attrName]); + } + } + + return noteId; + }; + + this.updateNote = async function (note) { + if (note.type === 'code' && note.mime === 'application/json') { + note.note_text = JSON.stringify(note.payload); + } + + log.info("new note text: ", note.note_text); + + delete note.payload; + + if (note.is_protected) { + protected_session.encryptNote(this.dataKey, note); + } + + await sql.replace("notes", note); + + await sync_table.addNoteSync(note.note_id); + }; + + this.log = function(message) { + log.info(`Script ${this.scriptNoteId}: ${message}`); + }; + + this.getDateNoteId = date_notes.getDateNoteId; +} + +module.exports = ScriptContext; \ No newline at end of file