From e8a5d0ae16df655b857218d3dbb180428e973062 Mon Sep 17 00:00:00 2001 From: azivner Date: Sat, 31 Mar 2018 10:51:37 -0400 Subject: [PATCH] converted note revision protection to repository/entities --- package-lock.json | 5 ---- package.json | 1 - src/app.js | 1 + src/entities/branch.js | 8 ------ src/entities/entity_constructor.js | 33 ++++++++++++++++++++++ src/entities/label.js | 3 +- src/entities/note.js | 21 +++++++------- src/entities/note_revision.js | 18 +++++++++++- src/routes/api/import.js | 5 ---- src/routes/api/notes.js | 10 +++---- src/routes/api/sender.js | 4 --- src/services/notes.js | 45 +++++++++++++----------------- src/services/repository.js | 41 ++++++++------------------- src/services/script_context.js | 2 +- 14 files changed, 99 insertions(+), 98 deletions(-) create mode 100644 src/entities/entity_constructor.js diff --git a/package-lock.json b/package-lock.json index ee707d0c0..fa9c22cbd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4418,11 +4418,6 @@ } } }, - "express-promise-wrap": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/express-promise-wrap/-/express-promise-wrap-0.2.2.tgz", - "integrity": "sha1-d9lx4UDbIPsnw3zMUwmSREyKBG0=" - }, "express-session": { "version": "1.15.6", "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.15.6.tgz", diff --git a/package.json b/package.json index c165396f2..494765c8e 100644 --- a/package.json +++ b/package.json @@ -34,7 +34,6 @@ "electron-in-page-search": "^1.2.4", "electron-rebuild": "^1.7.3", "express": "~4.16.3", - "express-promise-wrap": "^0.2.2", "express-session": "^1.15.6", "fs-extra": "^4.0.3", "helmet": "^3.12.0", diff --git a/src/app.js b/src/app.js index 23ecb08bc..c8ae10769 100644 --- a/src/app.js +++ b/src/app.js @@ -10,6 +10,7 @@ const FileStore = require('session-file-store')(session); const os = require('os'); const sessionSecret = require('./services/session_secret'); const cls = require('./services/cls'); +require('./entities/entity_constructor'); const app = express(); diff --git a/src/entities/branch.js b/src/entities/branch.js index dc05bb8bd..b84c99289 100644 --- a/src/entities/branch.js +++ b/src/entities/branch.js @@ -5,14 +5,6 @@ const Entity = require('./entity'); class Branch extends Entity { static get tableName() { return "branches"; } static get primaryKeyName() { return "branchId"; } - - async getNote() { - return this.repository.getEntity("SELECT * FROM branches WHERE isDeleted = 0 AND noteId = ?", [this.noteId]); - } - - async getParentNote() { - return this.repository.getEntity("SELECT * FROM branches WHERE isDeleted = 0 AND parentNoteId = ?", [this.parentNoteId]); - } } module.exports = Branch; \ No newline at end of file diff --git a/src/entities/entity_constructor.js b/src/entities/entity_constructor.js new file mode 100644 index 000000000..93b5dfc5c --- /dev/null +++ b/src/entities/entity_constructor.js @@ -0,0 +1,33 @@ +const Note = require('../entities/note'); +const NoteRevision = require('../entities/note_revision'); +const Branch = require('../entities/branch'); +const Label = require('../entities/label'); +const repository = require('../services/repository'); + +function createEntityFromRow(row) { + let entity; + + if (row.labelId) { + entity = new Label(row); + } + else if (row.noteRevisionId) { + entity = new NoteRevision(row); + } + else if (row.branchId) { + entity = new Branch(row); + } + else if (row.noteId) { + entity = new Note(row); + } + else { + throw new Error('Unknown entity type for row: ' + JSON.stringify(row)); + } + + return entity; +} + +repository.setEntityConstructor(createEntityFromRow); + +module.exports = { + createEntityFromRow +}; \ No newline at end of file diff --git a/src/entities/label.js b/src/entities/label.js index ccfab2bd2..f9ae9cb34 100644 --- a/src/entities/label.js +++ b/src/entities/label.js @@ -1,13 +1,14 @@ "use strict"; const Entity = require('./entity'); +const repository = require('../services/repository'); class Label extends Entity { static get tableName() { return "labels"; } static get primaryKeyName() { return "labelId"; } async getNote() { - return this.repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]); + return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]); } } diff --git a/src/entities/note.js b/src/entities/note.js index 8af159663..68f9affad 100644 --- a/src/entities/note.js +++ b/src/entities/note.js @@ -2,13 +2,14 @@ const Entity = require('./entity'); const protected_session = require('../services/protected_session'); +const repository = require('../services/repository'); class Note extends Entity { static get tableName() { return "notes"; } static get primaryKeyName() { return "noteId"; } - constructor(repository, row) { - super(repository, row); + constructor(row) { + super(row); if (this.isProtected) { protected_session.decryptNote(this); @@ -49,7 +50,7 @@ class Note extends Entity { } async getLabels() { - return this.repository.getEntities("SELECT * FROM labels WHERE noteId = ? AND isDeleted = 0", [this.noteId]); + return await repository.getEntities("SELECT * FROM labels WHERE noteId = ? AND isDeleted = 0", [this.noteId]); } // WARNING: this doesn't take into account the possibility to have multi-valued labels! @@ -71,19 +72,19 @@ class Note extends Entity { // WARNING: this doesn't take into account the possibility to have multi-valued labels! async getLabel(name) { - return this.repository.getEntity("SELECT * FROM labels WHERE noteId = ? AND name = ?", [this.noteId, name]); + return await repository.getEntity("SELECT * FROM labels WHERE noteId = ? AND name = ?", [this.noteId, name]); } async getRevisions() { - return this.repository.getEntities("SELECT * FROM note_revisions WHERE noteId = ?", [this.noteId]); + return await repository.getEntities("SELECT * FROM note_revisions WHERE noteId = ?", [this.noteId]); } async getTrees() { - return this.repository.getEntities("SELECT * FROM branches WHERE isDeleted = 0 AND noteId = ?", [this.noteId]); + return await repository.getEntities("SELECT * FROM branches WHERE isDeleted = 0 AND noteId = ?", [this.noteId]); } async getChild(name) { - return this.repository.getEntity(` + return await repository.getEntity(` SELECT notes.* FROM branches JOIN notes USING(noteId) @@ -94,7 +95,7 @@ class Note extends Entity { } async getChildren() { - return this.repository.getEntities(` + return await repository.getEntities(` SELECT notes.* FROM branches JOIN notes USING(noteId) @@ -105,7 +106,7 @@ class Note extends Entity { } async getParents() { - return this.repository.getEntities(` + return await repository.getEntities(` SELECT parent_notes.* FROM branches AS child_tree @@ -116,7 +117,7 @@ class Note extends Entity { } async getBranch() { - return this.repository.getEntities(` + return await repository.getEntities(` SELECT branches.* FROM branches JOIN notes USING(noteId) diff --git a/src/entities/note_revision.js b/src/entities/note_revision.js index 1d140f593..f8207c1df 100644 --- a/src/entities/note_revision.js +++ b/src/entities/note_revision.js @@ -1,13 +1,29 @@ "use strict"; const Entity = require('./entity'); +const protected_session = require('../services/protected_session'); +const repository = require('../services/repository'); class NoteRevision extends Entity { static get tableName() { return "note_revisions"; } static get primaryKeyName() { return "noteRevisionId"; } + constructor(row) { + super(row); + + if (this.isProtected) { + protected_session.decryptNoteRevision(this); + } + } + async getNote() { - return this.repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]); + return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]); + } + + beforeSaving() { + if (this.isProtected) { + protected_session.encryptNoteRevision(this); + } } } diff --git a/src/routes/api/import.js b/src/routes/api/import.js index eff141163..01e58eecc 100644 --- a/src/routes/api/import.js +++ b/src/routes/api/import.js @@ -1,14 +1,9 @@ "use strict"; -const express = require('express'); -const router = express.Router(); const sql = require('../../services/sql'); -const auth = require('../../services/auth'); const labels = require('../../services/labels'); const notes = require('../../services/notes'); -const wrap = require('express-promise-wrap').wrap; const tar = require('tar-stream'); -const multer = require('multer')(); const stream = require('stream'); const path = require('path'); diff --git a/src/routes/api/notes.js b/src/routes/api/notes.js index 6d1dbff42..612b86f17 100644 --- a/src/routes/api/notes.js +++ b/src/routes/api/notes.js @@ -1,15 +1,12 @@ "use strict"; -const express = require('express'); -const router = express.Router(); -const auth = require('../../services/auth'); const sql = require('../../services/sql'); const notes = require('../../services/notes'); const utils = require('../../services/utils'); const protected_session = require('../../services/protected_session'); const tree = require('../../services/tree'); const sync_table = require('../../services/sync_table'); -const wrap = require('express-promise-wrap').wrap; +const repository = require('../../services/repository'); async function getNote(req) { const noteId = req.params.noteId; @@ -58,9 +55,10 @@ async function sortNotes(req) { async function protectBranch(req) { const noteId = req.params.noteId; - const isProtected = !!parseInt(req.params.isProtected); + const note = repository.getNote(noteId); + const protect = !!parseInt(req.params.isProtected); - await notes.protectNoteRecursively(noteId, isProtected); + await notes.protectNoteRecursively(note, protect); } async function setNoteTypeMime(req) { diff --git a/src/routes/api/sender.js b/src/routes/api/sender.js index f7f8ba3da..704e9ab71 100644 --- a/src/routes/api/sender.js +++ b/src/routes/api/sender.js @@ -1,14 +1,10 @@ "use strict"; -const express = require('express'); -const router = express.Router(); const image = require('../../services/image'); const utils = require('../../services/utils'); const date_notes = require('../../services/date_notes'); const sql = require('../../services/sql'); -const wrap = require('express-promise-wrap').wrap; const notes = require('../../services/notes'); -const multer = require('multer')(); const password_encryption = require('../../services/password_encryption'); const options = require('../../services/options'); const sync_table = require('../../services/sync_table'); diff --git a/src/services/notes.js b/src/services/notes.js index d7b750b2d..fdc8d35e3 100644 --- a/src/services/notes.js +++ b/src/services/notes.js @@ -4,6 +4,7 @@ const utils = require('./utils'); const sync_table = require('./sync_table'); const labels = require('./labels'); const protected_session = require('./protected_session'); +const repository = require('./repository'); async function createNewNote(parentNoteId, noteOpts) { const noteId = utils.newNoteId(); @@ -117,15 +118,11 @@ async function createNote(parentNoteId, title, content = "", extraOptions = {}) return noteId; } -async function protectNoteRecursively(noteId, protect) { - const note = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]); - +async function protectNoteRecursively(note, 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, protect); + for (const child of await note.getChildren()) { + await protectNoteRecursively(child, protect); } } @@ -133,47 +130,43 @@ async function protectNote(note, protect) { let changed = false; if (protect && !note.isProtected) { - protected_session.encryptNote(note); - note.isProtected = true; changed = true; } else if (!protect && note.isProtected) { - protected_session.decryptNote(note); - note.isProtected = false; changed = true; } if (changed) { - await sql.execute("UPDATE notes SET title = ?, content = ?, isProtected = ? WHERE noteId = ?", - [note.title, note.content, note.isProtected, note.noteId]); + await repository.updateEntity(note); await sync_table.addNoteSync(note.noteId); } - await protectNoteRevisions(note.noteId, protect); + await protectNoteRevisions(note, 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(revision); +async function protectNoteRevisions(note, protect) { + for (const revision of await note.getRevisions()) { + let changed = false; + if (protect && !revision.isProtected) { revision.isProtected = true; - } - else { - protected_session.decryptNoteRevision(revision); + changed = true; + } + else if(!protect && revision.isProtected) { revision.isProtected = false; + + changed = true; } - await sql.execute("UPDATE note_revisions SET title = ?, content = ?, isProtected = ? WHERE noteRevisionId = ?", - [revision.title, revision.content, revision.isProtected, revision.noteRevisionId]); + if (changed) { + await repository.updateEntity(revision); + } await sync_table.addNoteRevisionSync(revision.noteRevisionId); } @@ -298,7 +291,7 @@ async function updateNote(noteId, newNote) { await saveNoteImages(noteId, newNote.content); - await protectNoteRevisions(noteId, newNote.isProtected); + await protectNoteRevisions(await repository.getNote(noteId), newNote.isProtected); await sql.execute("UPDATE notes SET title = ?, content = ?, isProtected = ?, dateModified = ? WHERE noteId = ?", [ newNote.title, diff --git a/src/services/repository.js b/src/services/repository.js index b59b6b9c1..ef0bf0e19 100644 --- a/src/services/repository.js +++ b/src/services/repository.js @@ -1,16 +1,18 @@ "use strict"; const sql = require('./sql'); -const Note = require('../entities/note'); -const NoteRevision = require('../entities/note_revision'); -const Branch = require('../entities/branch'); -const Label = require('../entities/label'); const sync_table = require('../services/sync_table'); +let entityConstructor; + +async function setEntityConstructor(constructor) { + entityConstructor = constructor; +} + async function getEntities(query, params = []) { const rows = await sql.getRows(query, params); - return rows.map(row => this.createEntityFromRow(row)); + return rows.map(entityConstructor); } async function getEntity(query, params = []) { @@ -20,33 +22,11 @@ async function getEntity(query, params = []) { return null; } - return this.createEntityFromRow(row); + return entityConstructor(row); } async function getNote(noteId) { - return await this.getEntity("SELECT * FROM notes WHERE noteId = ?", [noteId]); -} - -function createEntityFromRow(row) { - let entity; - - if (row.labelId) { - entity = new Label(row); - } - else if (row.noteRevisionId) { - entity = new NoteRevision(row); - } - else if (row.branchId) { - entity = new Branch(row); - } - else if (row.noteId) { - entity = new Note(row); - } - else { - throw new Error('Unknown entity type for row: ' + JSON.stringify(row)); - } - - return entity; + return await getEntity("SELECT * FROM notes WHERE noteId = ?", [noteId]); } async function updateEntity(entity) { @@ -69,5 +49,6 @@ module.exports = { getEntities, getEntity, getNote, - updateEntity + updateEntity, + setEntityConstructor }; \ No newline at end of file diff --git a/src/services/script_context.js b/src/services/script_context.js index fce9f6369..7bd581400 100644 --- a/src/services/script_context.js +++ b/src/services/script_context.js @@ -41,7 +41,7 @@ function ScriptApi(startNote, currentNote) { this.getInstanceName = () => config.General ? config.General.instanceName : null; this.getNoteById = async function(noteId) { - return repository.getNote(noteId); + return await repository.getNote(noteId); }; this.getNotesWithLabel = async function (attrName, attrValue) {