2017-11-05 10:41:54 -05:00
const sql = require ( './sql' ) ;
const options = require ( './options' ) ;
const utils = require ( './utils' ) ;
const notes = require ( './notes' ) ;
2017-11-14 21:54:12 -05:00
const data _encryption = require ( './data_encryption' ) ;
2017-11-16 21:50:00 -05:00
const sync _table = require ( './sync_table' ) ;
2017-11-05 10:41:54 -05:00
2017-11-24 20:51:44 -05:00
async function createNewNote ( parentNoteId , note ) {
2017-11-05 10:41:54 -05:00
const noteId = utils . newNoteId ( ) ;
2017-11-19 08:47:22 -05:00
const noteTreeId = utils . newNoteTreeId ( ) ;
2017-11-05 10:41:54 -05:00
let newNotePos = 0 ;
2017-11-28 17:24:08 -05:00
await sql . doInTransaction ( async ( ) => {
2017-11-26 23:10:23 -05:00
if ( note . target === 'into' ) {
const maxNotePos = await sql . getSingleValue ( 'SELECT MAX(note_pos) FROM notes_tree WHERE note_pid = ? AND is_deleted = 0' , [ parentNoteId ] ) ;
2017-11-05 10:41:54 -05:00
2017-11-26 23:10:23 -05:00
newNotePos = maxNotePos === null ? 0 : maxNotePos + 1 ;
}
else if ( note . target === 'after' ) {
const afterNote = await sql . getSingleResult ( 'SELECT note_pos FROM notes_tree WHERE note_tree_id = ?' , [ note . target _note _tree _id ] ) ;
2017-11-05 10:41:54 -05:00
2017-11-26 23:10:23 -05:00
newNotePos = afterNote . note _pos + 1 ;
2017-11-05 10:41:54 -05:00
2017-11-28 17:24:08 -05:00
await sql . execute ( 'UPDATE notes_tree SET note_pos = note_pos + 1, date_modified = ? WHERE note_pid = ? AND note_pos > ? AND is_deleted = 0' ,
2017-11-26 23:10:23 -05:00
[ utils . nowTimestamp ( ) , parentNoteId , afterNote . note _pos ] ) ;
2017-11-29 21:04:30 -05:00
await sync _table . addNoteReorderingSync ( parentNoteId ) ;
2017-11-26 23:10:23 -05:00
}
else {
2017-12-06 20:58:59 -05:00
throw new Error ( 'Unknown target: ' + note . target ) ;
2017-11-26 23:10:23 -05:00
}
2017-11-05 10:41:54 -05:00
const now = utils . nowTimestamp ( ) ;
2017-11-28 17:24:08 -05:00
await sql . insert ( "notes" , {
2017-11-05 10:41:54 -05:00
'note_id' : noteId ,
'note_title' : note . note _title ,
'note_text' : '' ,
'date_created' : now ,
'date_modified' : now ,
2017-11-14 21:54:12 -05:00
'is_protected' : note . is _protected
2017-11-05 10:41:54 -05:00
} ) ;
2017-11-29 21:04:30 -05:00
await sync _table . addNoteSync ( noteId ) ;
2017-11-28 17:24:08 -05:00
await sql . insert ( "notes_tree" , {
2017-11-18 17:05:50 -05:00
'note_tree_id' : noteTreeId ,
2017-11-05 10:41:54 -05:00
'note_id' : noteId ,
'note_pid' : parentNoteId ,
'note_pos' : newNotePos ,
'is_expanded' : 0 ,
2017-11-19 16:35:35 -05:00
'date_modified' : now ,
2017-11-05 10:41:54 -05:00
'is_deleted' : 0
} ) ;
2017-11-29 21:04:30 -05:00
await sync _table . addNoteTreeSync ( noteTreeId ) ;
2017-11-05 10:41:54 -05:00
} ) ;
2017-11-18 17:05:50 -05:00
return {
noteId ,
noteTreeId
} ;
2017-11-05 10:41:54 -05:00
}
2017-11-14 21:54:12 -05:00
async function encryptNote ( note , ctx ) {
2017-11-18 12:53:17 -05:00
note . detail . note _title = data _encryption . encrypt ( ctx . getDataKey ( ) , data _encryption . noteTitleIv ( note . detail . note _id ) , note . detail . note _title ) ;
note . detail . note _text = data _encryption . encrypt ( ctx . getDataKey ( ) , data _encryption . noteTextIv ( note . detail . note _id ) , note . detail . note _text ) ;
2017-11-14 21:54:12 -05:00
}
2017-11-05 10:41:54 -05:00
2017-11-28 17:24:08 -05:00
async function protectNoteRecursively ( noteId , dataKey , protect ) {
2017-11-15 00:04:26 -05:00
const note = await sql . getSingleResult ( "SELECT * FROM notes WHERE note_id = ?" , [ noteId ] ) ;
2017-11-28 17:24:08 -05:00
await protectNote ( note , dataKey , protect ) ;
2017-11-15 00:04:26 -05:00
const children = await sql . getFlattenedResults ( "note_id" , "SELECT note_id FROM notes_tree WHERE note_pid = ?" , [ noteId ] ) ;
for ( const childNoteId of children ) {
await protectNoteRecursively ( childNoteId , dataKey , protect ) ;
}
}
2017-11-28 17:24:08 -05:00
async function protectNote ( note , dataKey , protect ) {
2017-11-15 00:04:26 -05:00
let changed = false ;
if ( protect && ! note . is _protected ) {
2017-11-18 12:53:17 -05:00
note . note _title = data _encryption . encrypt ( dataKey , data _encryption . noteTitleIv ( note . note _id ) , note . note _title ) ;
note . note _text = data _encryption . encrypt ( dataKey , data _encryption . noteTextIv ( note . note _id ) , note . note _text ) ;
2017-11-15 00:04:26 -05:00
note . is _protected = true ;
changed = true ;
}
else if ( ! protect && note . is _protected ) {
2017-11-18 12:53:17 -05:00
note . note _title = data _encryption . decryptString ( dataKey , data _encryption . noteTitleIv ( note . note _id ) , note . note _title ) ;
note . note _text = data _encryption . decryptString ( dataKey , data _encryption . noteTextIv ( note . note _id ) , note . note _text ) ;
2017-11-15 00:04:26 -05:00
note . is _protected = false ;
changed = true ;
}
if ( changed ) {
console . log ( "Updating..." ) ;
2017-11-28 17:24:08 -05:00
await sql . execute ( "UPDATE notes SET note_title = ?, note_text = ?, is_protected = ? WHERE note_id = ?" ,
2017-11-15 00:04:26 -05:00
[ note . note _title , note . note _text , note . is _protected , note . note _id ] ) ;
2017-11-28 17:24:08 -05:00
await sync _table . addNoteSync ( note . note _id ) ;
2017-11-15 00:04:26 -05:00
}
2017-11-28 17:24:08 -05:00
await protectNoteHistory ( note . note _id , dataKey , protect ) ;
2017-11-15 00:04:26 -05:00
}
2017-11-28 17:24:08 -05:00
async function protectNoteHistory ( noteId , dataKey , protect ) {
2017-11-15 00:04:26 -05:00
const historyToChange = await sql . getResults ( "SELECT * FROM notes_history WHERE note_id = ? AND is_protected != ?" , [ noteId , protect ] ) ;
for ( const history of historyToChange ) {
if ( protect ) {
2017-11-18 12:53:17 -05:00
history . note _title = data _encryption . encrypt ( dataKey , data _encryption . noteTitleIv ( history . note _history _id ) , history . note _title ) ;
history . note _text = data _encryption . encrypt ( dataKey , data _encryption . noteTextIv ( history . note _history _id ) , history . note _text ) ;
2017-11-15 00:04:26 -05:00
history . is _protected = true ;
}
else {
2017-11-18 12:53:17 -05:00
history . note _title = data _encryption . decryptString ( dataKey , data _encryption . noteTitleIv ( history . note _history _id ) , history . note _title ) ;
history . note _text = data _encryption . decryptString ( dataKey , data _encryption . noteTextIv ( history . note _history _id ) , history . note _text ) ;
2017-11-15 00:04:26 -05:00
history . is _protected = false ;
}
2017-11-28 17:24:08 -05:00
await sql . execute ( "UPDATE notes_history SET note_title = ?, note_text = ?, is_protected = ? WHERE note_history_id = ?" ,
2017-11-15 00:04:26 -05:00
[ history . note _title , history . note _text , history . is _protected , history . note _history _id ] ) ;
2017-11-28 17:24:08 -05:00
await sync _table . addNoteHistorySync ( history . note _history _id ) ;
2017-11-15 00:04:26 -05:00
}
}
2017-11-14 21:54:12 -05:00
async function updateNote ( noteId , newNote , ctx ) {
if ( newNote . detail . is _protected ) {
await encryptNote ( newNote , ctx ) ;
2017-11-05 10:41:54 -05:00
}
const now = utils . nowTimestamp ( ) ;
const historySnapshotTimeInterval = parseInt ( await options . getOption ( 'history_snapshot_time_interval' ) ) ;
const historyCutoff = now - historySnapshotTimeInterval ;
2017-12-06 22:31:28 -05:00
const existingNoteHistoryId = await sql . getSingleValue ( "SELECT note_history_id FROM notes_history WHERE note_id = ? AND date_modified_to >= ?" , [ noteId , historyCutoff ] ) ;
2017-11-05 10:41:54 -05:00
2017-11-28 17:24:08 -05:00
await sql . doInTransaction ( async ( ) => {
2017-11-30 22:49:40 -05:00
if ( ! existingNoteHistoryId && ( now - newNote . detail . date _created ) >= historySnapshotTimeInterval ) {
2017-12-06 22:31:28 -05:00
const oldNote = await sql . getSingleResult ( "SELECT * FROM notes WHERE note_id = ?" , [ noteId ] ) ;
2017-11-19 08:47:22 -05:00
const newNoteHistoryId = utils . newNoteHistoryId ( ) ;
2017-11-05 10:41:54 -05:00
2017-11-28 17:24:08 -05:00
await sql . insert ( 'notes_history' , {
2017-11-20 23:51:28 -05:00
note _history _id : newNoteHistoryId ,
note _id : noteId ,
2017-12-06 22:31:28 -05:00
note _title : oldNote . note _title ,
note _text : oldNote . note _text ,
is _protected : oldNote . is _protected ,
date _modified _from : oldNote . date _modified ,
2017-11-20 23:51:28 -05:00
date _modified _to : now
} ) ;
2017-11-16 00:22:00 -05:00
2017-11-28 17:24:08 -05:00
await sync _table . addNoteHistorySync ( newNoteHistoryId ) ;
2017-11-05 10:41:54 -05:00
}
2017-11-28 17:24:08 -05:00
await protectNoteHistory ( noteId , ctx . getDataKeyOrNull ( ) , newNote . detail . is _protected ) ;
2017-11-14 22:21:56 -05:00
2017-11-28 17:24:08 -05:00
await sql . execute ( "UPDATE notes SET note_title = ?, note_text = ?, is_protected = ?, date_modified = ? WHERE note_id = ?" , [
2017-11-05 10:41:54 -05:00
newNote . detail . note _title ,
newNote . detail . note _text ,
2017-11-14 21:54:12 -05:00
newNote . detail . is _protected ,
2017-11-05 10:41:54 -05:00
now ,
noteId ] ) ;
2017-11-28 17:24:08 -05:00
await sync _table . addNoteSync ( noteId ) ;
2017-11-05 10:41:54 -05:00
} ) ;
}
2017-11-28 17:24:08 -05:00
async function deleteNote ( noteTreeId ) {
2017-11-05 10:41:54 -05:00
const now = utils . nowTimestamp ( ) ;
2017-11-29 21:04:30 -05:00
2017-11-28 17:24:08 -05:00
await sql . execute ( "UPDATE notes_tree SET is_deleted = 1, date_modified = ? WHERE note_tree_id = ?" , [ now , noteTreeId ] ) ;
await sync _table . addNoteTreeSync ( noteTreeId ) ;
2017-11-05 10:41:54 -05:00
2017-11-19 23:12:39 -05:00
const noteId = await sql . getSingleValue ( "SELECT note_id FROM notes_tree WHERE note_tree_id = ?" , [ noteTreeId ] ) ;
2017-11-05 10:41:54 -05:00
2017-11-23 23:54:54 -05:00
const notDeletedNoteTreesCount = await sql . getSingleValue ( "SELECT COUNT(*) FROM notes_tree WHERE note_id = ? AND is_deleted = 0" , [ noteId ] ) ;
2017-11-19 23:12:39 -05:00
if ( ! notDeletedNoteTreesCount ) {
2017-11-28 17:24:08 -05:00
await sql . execute ( "UPDATE notes SET is_deleted = 1, date_modified = ? WHERE note_id = ?" , [ now , noteId ] ) ;
await sync _table . addNoteSync ( noteId ) ;
2017-11-05 10:41:54 -05:00
2017-11-23 23:54:54 -05:00
const children = await sql . getResults ( "SELECT note_tree_id FROM notes_tree WHERE note_pid = ? AND is_deleted = 0" , [ noteId ] ) ;
2017-11-05 10:41:54 -05:00
2017-11-19 23:12:39 -05:00
for ( const child of children ) {
2017-11-28 17:24:08 -05:00
await deleteNote ( child . note _tree _id ) ;
2017-11-19 23:12:39 -05:00
}
}
2017-11-05 10:41:54 -05:00
}
module . exports = {
createNewNote ,
updateNote ,
2017-11-15 00:04:26 -05:00
deleteNote ,
protectNoteRecursively
2017-11-05 17:58:55 -05:00
} ;