From 5df3b78abce2a40998cc28807e855e4f3ef98c83 Mon Sep 17 00:00:00 2001 From: azivner Date: Tue, 24 Oct 2017 22:58:59 -0400 Subject: [PATCH] notes_tree is now soft deleted as well --- app.js | 3 +++ .../0010__add_is_deleted_to_notes_tree.sql | 5 +++++ routes/api/notes.js | 15 ++++++++----- routes/api/notes_move.js | 4 ++-- routes/api/settings.js | 2 +- routes/api/sync.js | 22 +++++++++++++++++++ routes/api/tree.js | 2 +- services/migration.js | 2 +- 8 files changed, 44 insertions(+), 11 deletions(-) create mode 100644 migrations/0010__add_is_deleted_to_notes_tree.sql create mode 100644 routes/api/sync.js diff --git a/app.js b/app.js index e15965d1d..7cfb930fe 100644 --- a/app.js +++ b/app.js @@ -24,6 +24,8 @@ const recentChangesApiRoute = require('./routes/api/recent_changes'); const settingsApiRoute = require('./routes/api/settings'); const passwordApiRoute = require('./routes/api/password'); const migrationApiRoute = require('./routes/api/migration'); +const syncApiRoute = require('./routes/api/sync'); + const dataDir = require('./services/data_dir'); const sessionSecret = require('./services/session_secret'); @@ -81,6 +83,7 @@ app.use('/api/recent-changes', recentChangesApiRoute); app.use('/api/settings', settingsApiRoute); app.use('/api/password', passwordApiRoute); app.use('/api/migration', migrationApiRoute); +app.use('/api/sync', syncApiRoute); // catch 404 and forward to error handler app.use((req, res, next) => { diff --git a/migrations/0010__add_is_deleted_to_notes_tree.sql b/migrations/0010__add_is_deleted_to_notes_tree.sql new file mode 100644 index 000000000..53d7040ee --- /dev/null +++ b/migrations/0010__add_is_deleted_to_notes_tree.sql @@ -0,0 +1,5 @@ +ALTER TABLE notes_tree ADD COLUMN is_deleted INTEGER NOT NULL DEFAULT 0; + +CREATE INDEX `IDX_notes_tree_is_deleted` ON `notes_tree` ( + `is_deleted` +); \ No newline at end of file diff --git a/routes/api/notes.js b/routes/api/notes.js index a530c9bac..72de979cd 100644 --- a/routes/api/notes.js +++ b/routes/api/notes.js @@ -116,14 +116,16 @@ router.delete('/:noteId', async (req, res, next) => { }); async function deleteNote(noteId, req) { - const children = await sql.getResults("select note_id from notes_tree where note_pid = ?", [noteId]); + const now = utils.nowTimestamp(); + + const children = await sql.getResults("select note_id from notes_tree where note_pid = ? and is_deleted = 0", [noteId]); for (const child of children) { await deleteNote(child['note_id']); } - await sql.remove("notes_tree", noteId); - await sql.execute("update notes set is_deleted = 1 where note_id = ?", [noteId]); + await sql.execute("update notes_tree set is_deleted = 1, date_modified = ? where note_id = ?", [now, noteId]); + await sql.execute("update notes set is_deleted = 1, date_modified = ? where note_id = ?", [now, noteId]); await sql.addAudit(audit_category.DELETE_NOTE, req, noteId); } @@ -142,7 +144,7 @@ router.post('/:parentNoteId/children', async (req, res, next) => { let newNotePos = 0; if (note['target'] === 'into') { - const res = await sql.getSingleResult('select max(note_pos) as max_note_pos from notes_tree where note_pid = ?', [parentNoteId]); + const res = await sql.getSingleResult('select max(note_pos) as max_note_pos from notes_tree where note_pid = ? and is_deleted = 0', [parentNoteId]); const maxNotePos = res['max_note_pos']; if (maxNotePos === null) // no children yet @@ -157,7 +159,7 @@ router.post('/:parentNoteId/children', async (req, res, next) => { const now = utils.nowTimestamp(); - await sql.execute('update notes_tree set note_pos = note_pos + 1, date_modified = ? where note_pid = ? and note_pos > ?', [now, parentNoteId, afterNote['note_pos']]); + await sql.execute('update notes_tree set note_pos = note_pos + 1, date_modified = ? where note_pid = ? and note_pos > ? and is_deleted = 0', [now, parentNoteId, afterNote['note_pos']]); } else { throw new ('Unknown target: ' + note['target']); @@ -184,7 +186,8 @@ router.post('/:parentNoteId/children', async (req, res, next) => { 'note_pid': parentNoteId, 'note_pos': newNotePos, 'is_expanded': 0, - 'date_modified': utils.nowTimestamp() + 'date_modified': utils.nowTimestamp(), + 'is_deleted': 0 }); await sql.commit(); diff --git a/routes/api/notes_move.js b/routes/api/notes_move.js index 8cc4ed0bb..e3205a344 100644 --- a/routes/api/notes_move.js +++ b/routes/api/notes_move.js @@ -11,7 +11,7 @@ router.put('/:noteId/moveTo/:parentId', auth.checkApiAuth, async (req, res, next let noteId = req.params.noteId; let parentId = req.params.parentId; - const row = await sql.getSingleResult('select max(note_pos) as max_note_pos from notes_tree where note_pid = ?', [parentId]); + const row = await sql.getSingleResult('select max(note_pos) as max_note_pos from notes_tree where note_pid = ? and is_deleted = 0', [parentId]); const maxNotePos = row['max_note_pos']; let newNotePos = 0; @@ -69,7 +69,7 @@ router.put('/:noteId/moveAfter/:afterNoteId', async (req, res, next) => { await sql.beginTransaction(); - await sql.execute("update notes_tree set note_pos = note_pos + 1, date_modified = ? where note_pid = ? and note_pos > ?", + await sql.execute("update notes_tree set note_pos = note_pos + 1, date_modified = ? where note_pid = ? and note_pos > ? and is_deleted = 0", [now, afterNote['note_pid'], afterNote['note_pos']]); await sql.execute("update notes_tree set note_pid = ?, note_pos = ?, date_modified = ? where note_id = ?", diff --git a/routes/api/settings.js b/routes/api/settings.js index 2c9af0654..fd1ff8051 100644 --- a/routes/api/settings.js +++ b/routes/api/settings.js @@ -22,7 +22,7 @@ router.get('/', auth.checkApiAuth, async (req, res, next) => { }); router.post('/', async (req, res, next) => { - body = req.body; + const body = req.body; if (ALLOWED_OPTIONS.includes(body['name'])) { const optionName = await sql.getOption(body['name']); diff --git a/routes/api/sync.js b/routes/api/sync.js new file mode 100644 index 000000000..96bc4673e --- /dev/null +++ b/routes/api/sync.js @@ -0,0 +1,22 @@ +"use strict"; + +const express = require('express'); +const router = express.Router(); +const sql = require('../../services/sql'); +const audit_category = require('../../services/audit_category'); +const auth = require('../../services/auth'); + +router.get('/', auth.checkApiAuth, async (req, res, next) => { + const dict = {}; + + const settings = await sql.getResults("SELECT opt_name, opt_value FROM options WHERE opt_name IN (" + + ALLOWED_OPTIONS.map(x => '?').join(",") + ")", ALLOWED_OPTIONS); + + for (const set of settings) { + dict[set['opt_name']] = set['opt_value']; + } + + res.send(dict); +}); + +module.exports = router; \ No newline at end of file diff --git a/routes/api/tree.js b/routes/api/tree.js index ddcaa17af..914a3749e 100644 --- a/routes/api/tree.js +++ b/routes/api/tree.js @@ -19,7 +19,7 @@ router.get('/', auth.checkApiAuth, async (req, res, next) => { + "from notes_tree " + "join notes on notes.note_id = notes_tree.note_id " + "left join notes as clone on notes.note_clone_id = clone.note_id " - + "where notes.is_deleted = 0 " + + "where notes.is_deleted = 0 and notes_tree.is_deleted = 0 " + "order by note_pid, note_pos"); const root_notes = []; diff --git a/services/migration.js b/services/migration.js index b0a31d26d..585f90d9b 100644 --- a/services/migration.js +++ b/services/migration.js @@ -3,7 +3,7 @@ const sql = require('./sql'); const fs = require('fs-extra'); const log = require('./log'); -const APP_DB_VERSION = 9; +const APP_DB_VERSION = 10; const MIGRATIONS_DIR = "./migrations"; async function migrate() {