refactoring of note update

This commit is contained in:
azivner 2018-03-31 22:15:06 -04:00
parent e8a5d0ae16
commit 5f7e74e15c
7 changed files with 103 additions and 124 deletions

View File

@ -1,10 +1,15 @@
"use strict"; "use strict";
const Entity = require('./entity'); const Entity = require('./entity');
const utils = require('../services/utils');
class Branch extends Entity { class Branch extends Entity {
static get tableName() { return "branches"; } static get tableName() { return "branches"; }
static get primaryKeyName() { return "branchId"; } static get primaryKeyName() { return "branchId"; }
beforeSaving() {
this.dateModified = utils.nowDate()
}
} }
module.exports = Branch; module.exports = Branch;

View File

@ -1,5 +1,6 @@
const Note = require('../entities/note'); const Note = require('../entities/note');
const NoteRevision = require('../entities/note_revision'); const NoteRevision = require('../entities/note_revision');
const NoteImage = require('../entities/note_image');
const Branch = require('../entities/branch'); const Branch = require('../entities/branch');
const Label = require('../entities/label'); const Label = require('../entities/label');
const repository = require('../services/repository'); const repository = require('../services/repository');
@ -13,6 +14,9 @@ function createEntityFromRow(row) {
else if (row.noteRevisionId) { else if (row.noteRevisionId) {
entity = new NoteRevision(row); entity = new NoteRevision(row);
} }
else if (row.noteImageId) {
entity = new NoteImage(row);
}
else if (row.branchId) { else if (row.branchId) {
entity = new Branch(row); entity = new Branch(row);
} }

View File

@ -2,6 +2,7 @@
const Entity = require('./entity'); const Entity = require('./entity');
const repository = require('../services/repository'); const repository = require('../services/repository');
const utils = require('../services/utils');
class Label extends Entity { class Label extends Entity {
static get tableName() { return "labels"; } static get tableName() { return "labels"; }
@ -10,6 +11,14 @@ class Label extends Entity {
async getNote() { async getNote() {
return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]); return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]);
} }
beforeSaving() {
if (!this.dateCreated) {
this.dateCreated = utils.nowDate();
}
this.dateModified = utils.nowDate();
}
} }
module.exports = Label; module.exports = Label;

View File

@ -3,6 +3,7 @@
const Entity = require('./entity'); const Entity = require('./entity');
const protected_session = require('../services/protected_session'); const protected_session = require('../services/protected_session');
const repository = require('../services/repository'); const repository = require('../services/repository');
const utils = require('../services/utils');
class Note extends Entity { class Note extends Entity {
static get tableName() { return "notes"; } static get tableName() { return "notes"; }
@ -79,6 +80,10 @@ class Note extends Entity {
return await repository.getEntities("SELECT * FROM note_revisions WHERE noteId = ?", [this.noteId]); return await repository.getEntities("SELECT * FROM note_revisions WHERE noteId = ?", [this.noteId]);
} }
async getNoteImages() {
return await repository.getEntities("SELECT * FROM note_images WHERE noteId = ? AND isDeleted = 0", [this.noteId]);
}
async getTrees() { async getTrees() {
return await 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]);
} }
@ -127,11 +132,19 @@ class Note extends Entity {
} }
beforeSaving() { beforeSaving() {
if (this.isJson()) {
this.content = JSON.stringify(this.jsonContent, null, '\t'); this.content = JSON.stringify(this.jsonContent, null, '\t');
}
if (this.isProtected) { if (this.isProtected) {
protected_session.encryptNote(this); protected_session.encryptNote(this);
} }
if (!this.dateCreated) {
this.dateCreated = utils.nowDate();
}
this.dateModified = utils.nowDate();
} }
} }

View File

@ -0,0 +1,15 @@
"use strict";
const Entity = require('./entity');
const repository = require('../services/repository');
class NoteImage extends Entity {
static get tableName() { return "note_images"; }
static get primaryKeyName() { return "noteImageId"; }
async getNote() {
return await repository.getEntity("SELECT * FROM notes WHERE noteId = ?", [this.noteId]);
}
}
module.exports = NoteImage;

View File

@ -177,7 +177,7 @@ function register(app) {
apiRoute(POST, '/api/cleanup/vacuum-database', cleanupRoute.vacuumDatabase); apiRoute(POST, '/api/cleanup/vacuum-database', cleanupRoute.vacuumDatabase);
route(GET, '/api/images/:imageId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage); route(GET, '/api/images/:imageId/:filename', [auth.checkApiAuthOrElectron], imageRoute.returnImage);
route(POST, '/api/images', [auth.checkApiAuthOrElectron], imageRoute.uploadImage, apiResultHandler); route(POST, '/api/images', [auth.checkApiAuthOrElectron, uploadMiddleware], imageRoute.uploadImage, apiResultHandler);
apiRoute(POST, '/api/script/exec', scriptRoute.exec); apiRoute(POST, '/api/script/exec', scriptRoute.exec);
apiRoute(POST, '/api/script/run/:noteId', scriptRoute.run); apiRoute(POST, '/api/script/run/:noteId', scriptRoute.run);

View File

@ -5,6 +5,8 @@ const sync_table = require('./sync_table');
const labels = require('./labels'); const labels = require('./labels');
const protected_session = require('./protected_session'); const protected_session = require('./protected_session');
const repository = require('./repository'); const repository = require('./repository');
const NoteImage = require('../entities/note_image');
const NoteRevision = require('../entities/note_revision');
async function createNewNote(parentNoteId, noteOpts) { async function createNewNote(parentNoteId, noteOpts) {
const noteId = utils.newNoteId(); const noteId = utils.newNoteId();
@ -127,110 +129,46 @@ async function protectNoteRecursively(note, protect) {
} }
async function protectNote(note, protect) { async function protectNote(note, protect) {
let changed = false; if (protect !== note.isProtected) {
note.isProtected = protect;
if (protect && !note.isProtected) {
note.isProtected = true;
changed = true;
}
else if (!protect && note.isProtected) {
note.isProtected = false;
changed = true;
}
if (changed) {
await repository.updateEntity(note); await repository.updateEntity(note);
await sync_table.addNoteSync(note.noteId);
} }
await protectNoteRevisions(note, protect); await protectNoteRevisions(note);
} }
async function protectNoteRevisions(note, protect) { async function protectNoteRevisions(note) {
for (const revision of await note.getRevisions()) { for (const revision of await note.getRevisions()) {
let changed = false; if (note.isProtected !== revision.isProtected) {
revision.isProtected = note.isProtected;
if (protect && !revision.isProtected) {
revision.isProtected = true;
changed = true;
}
else if(!protect && revision.isProtected) {
revision.isProtected = false;
changed = true;
}
if (changed) {
await repository.updateEntity(revision); await repository.updateEntity(revision);
} }
await sync_table.addNoteRevisionSync(revision.noteRevisionId);
} }
} }
async function saveNoteRevision(noteId, nowStr) { async function saveNoteImages(note) {
const oldNote = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]); if (note.type !== 'text') {
if (oldNote.type === 'file') {
return; return;
} }
if (oldNote.isProtected) { const existingNoteImages = await note.getNoteImages();
protected_session.decryptNote(oldNote);
oldNote.isProtected = false;
}
const newNoteRevisionId = utils.newNoteRevisionId();
await sql.insert('note_revisions', {
noteRevisionId: newNoteRevisionId,
noteId: noteId,
// title and text should be decrypted now
title: oldNote.title,
content: oldNote.content,
isProtected: 0, // will be fixed in the protectNoteRevisions() call
dateModifiedFrom: oldNote.dateModified,
dateModifiedTo: nowStr
});
await sync_table.addNoteRevisionSync(newNoteRevisionId);
}
async function saveNoteImages(noteId, noteText) {
const existingNoteImages = await sql.getRows("SELECT * FROM note_images WHERE noteId = ?", [noteId]);
const foundImageIds = []; const foundImageIds = [];
const now = utils.nowDate();
const re = /src="\/api\/images\/([a-zA-Z0-9]+)\//g; const re = /src="\/api\/images\/([a-zA-Z0-9]+)\//g;
let match; let match;
while (match = re.exec(noteText)) { while (match = re.exec(note.content)) {
const imageId = match[1]; const imageId = match[1];
const existingNoteImage = existingNoteImages.find(ni => ni.imageId === imageId); const existingNoteImage = existingNoteImages.find(ni => ni.imageId === imageId);
if (!existingNoteImage) { if (!existingNoteImage) {
const noteImageId = utils.newNoteImageId(); await repository.updateEntity(new NoteImage({
noteImageId: utils.newNoteImageId(),
await sql.insert("note_images", { noteId: note.noteId,
noteImageId: noteImageId,
noteId: noteId,
imageId: imageId, imageId: imageId,
isDeleted: 0, isDeleted: 0
dateModified: now, }));
dateCreated: now
});
await sync_table.addNoteImageSync(noteImageId);
}
else if (existingNoteImage.isDeleted) {
await sql.execute("UPDATE note_images SET isDeleted = 0, dateModified = ? WHERE noteImageId = ?",
[now, existingNoteImage.noteImageId]);
await sync_table.addNoteImageSync(existingNoteImage.noteImageId);
} }
// else we don't need to do anything // else we don't need to do anything
@ -241,67 +179,62 @@ async function saveNoteImages(noteId, noteText) {
const unusedNoteImages = existingNoteImages.filter(ni => !foundImageIds.includes(ni.imageId)); const unusedNoteImages = existingNoteImages.filter(ni => !foundImageIds.includes(ni.imageId));
for (const unusedNoteImage of unusedNoteImages) { for (const unusedNoteImage of unusedNoteImages) {
await sql.execute("UPDATE note_images SET isDeleted = 1, dateModified = ? WHERE noteImageId = ?", unusedNoteImage.isDeleted = 1;
[now, unusedNoteImage.noteImageId]);
await sync_table.addNoteImageSync(unusedNoteImage.noteImageId); await repository.updateEntity(unusedNoteImage);
} }
} }
async function loadFile(noteId, newNote) { async function saveNoteRevision(note) {
const oldNote = await sql.getRow("SELECT * FROM notes WHERE noteId = ?", [noteId]); const labelsMap = await note.getLabelMap();
if (oldNote.isProtected) {
await protected_session.decryptNote(oldNote);
}
newNote.content = oldNote.content;
}
async function updateNote(noteId, newNote) {
if (newNote.type === 'file') {
await loadFile(noteId, newNote);
}
if (newNote.isProtected) {
await protected_session.encryptNote(newNote);
}
const labelsMap = await labels.getNoteLabelMap(noteId);
const now = new Date(); const now = new Date();
const nowStr = utils.nowDate();
const noteRevisionSnapshotTimeInterval = parseInt(await options.getOption('note_revision_snapshot_time_interval')); const noteRevisionSnapshotTimeInterval = parseInt(await options.getOption('note_revision_snapshot_time_interval'));
const revisionCutoff = utils.dateStr(new Date(now.getTime() - noteRevisionSnapshotTimeInterval * 1000)); const revisionCutoff = utils.dateStr(new Date(now.getTime() - noteRevisionSnapshotTimeInterval * 1000));
const existingnoteRevisionId = await sql.getValue( const existingnoteRevisionId = await sql.getValue(
"SELECT noteRevisionId FROM note_revisions WHERE noteId = ? AND dateModifiedTo >= ?", [noteId, revisionCutoff]); "SELECT noteRevisionId FROM note_revisions WHERE noteId = ? AND dateModifiedTo >= ?", [note.noteId, revisionCutoff]);
await sql.doInTransaction(async () => { const msSinceDateCreated = now.getTime() - utils.parseDateTime(note.dateCreated).getTime();
const msSinceDateCreated = now.getTime() - utils.parseDateTime(newNote.dateCreated).getTime();
if (labelsMap.disable_versioning !== 'true' if (note.type !== 'file'
&& labelsMap.disable_versioning !== 'true'
&& !existingnoteRevisionId && !existingnoteRevisionId
&& msSinceDateCreated >= noteRevisionSnapshotTimeInterval * 1000) { && msSinceDateCreated >= noteRevisionSnapshotTimeInterval * 1000) {
await saveNoteRevision(noteId, nowStr); await repository.updateEntity(new NoteRevision({
noteRevisionId: utils.newNoteRevisionId(),
noteId: note.noteId,
// title and text should be decrypted now
title: note.title,
content: note.content,
isProtected: 0, // will be fixed in the protectNoteRevisions() call
dateModifiedFrom: note.dateModified,
dateModifiedTo: utils.nowDate()
}));
}
} }
await saveNoteImages(noteId, newNote.content); async function updateNote(noteId, noteUpdates) {
const note = await repository.getNote(noteId);
await protectNoteRevisions(await repository.getNote(noteId), newNote.isProtected); if (note.type === 'file') {
// for update file, newNote doesn't contain file payloads
noteUpdates.content = note.content;
}
await sql.execute("UPDATE notes SET title = ?, content = ?, isProtected = ?, dateModified = ? WHERE noteId = ?", [ await saveNoteRevision(note);
newNote.title,
newNote.content,
newNote.isProtected,
nowStr,
noteId]);
await sync_table.addNoteSync(noteId); note.title = noteUpdates.title;
}); note.content = noteUpdates.content;
note.isProtected = noteUpdates.isProtected;
await repository.updateEntity(note);
await saveNoteImages(note);
await protectNoteRevisions(note);
} }
async function deleteNote(branchId) { async function deleteNote(branchId) {