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