2017-10-22 09:10:33 +08:00
"use strict" ;
2017-10-15 11:31:44 +08:00
const express = require ( 'express' ) ;
const router = express . Router ( ) ;
2017-10-16 07:47:05 +08:00
const sql = require ( '../../services/sql' ) ;
2017-11-03 08:48:02 +08:00
const options = require ( '../../services/options' ) ;
2017-10-16 07:47:05 +08:00
const utils = require ( '../../services/utils' ) ;
const audit _category = require ( '../../services/audit_category' ) ;
const auth = require ( '../../services/auth' ) ;
2017-10-15 11:31:44 +08:00
2017-10-16 04:32:49 +08:00
router . get ( '/:noteId' , auth . checkApiAuth , async ( req , res , next ) => {
2017-10-15 11:31:44 +08:00
let noteId = req . params . noteId ;
2017-11-04 08:50:48 +08:00
await options . setOption ( 'start_node' , noteId ) ;
2017-10-15 11:31:44 +08:00
let detail = await sql . getSingleResult ( "select * from notes where note_id = ?" , [ noteId ] ) ;
2017-10-31 12:15:49 +08:00
if ( detail . note _clone _id ) {
noteId = detail . note _clone _id ;
2017-10-15 11:31:44 +08:00
detail = sql . getSingleResult ( "select * from notes where note_id = ?" , [ noteId ] ) ;
}
res . send ( {
2017-11-05 09:02:56 +08:00
detail : detail ,
images : await sql . getResults ( "select * from images where note_id = ? order by note_offset" , [ noteId ] ) ,
loadTime : utils . nowTimestamp ( )
2017-10-15 11:31:44 +08:00
} ) ;
} ) ;
router . put ( '/:noteId' , async ( req , res , next ) => {
let noteId = req . params . noteId ;
const detail = await sql . getSingleResult ( "select * from notes where note_id = ?" , [ noteId ] ) ;
2017-10-31 12:15:49 +08:00
if ( detail . note _clone _id ) {
noteId = detail . note _clone _id ;
2017-10-15 11:31:44 +08:00
}
const note = req . body ;
const now = utils . nowTimestamp ( ) ;
2017-11-03 08:48:02 +08:00
const historySnapshotTimeInterval = parseInt ( await options . getOption ( 'history_snapshot_time_interval' ) ) ;
2017-10-15 11:31:44 +08:00
const historyCutoff = now - historySnapshotTimeInterval ;
2017-10-31 12:15:49 +08:00
let noteHistoryId = await sql . getSingleValue ( "select note_history_id from notes_history where note_id = ? and date_modified_from >= ?" , [ noteId , historyCutoff ] ) ;
2017-10-15 11:31:44 +08:00
2017-10-30 06:50:28 +08:00
await sql . doInTransaction ( async ( ) => {
2017-10-31 12:15:49 +08:00
if ( noteHistoryId ) {
await sql . execute ( "update notes_history set note_title = ?, note_text = ?, encryption = ?, date_modified_to = ? where note_history_id = ?" , [
note . detail . note _title ,
note . detail . note _text ,
note . detail . encryption ,
2017-10-30 06:50:28 +08:00
now ,
2017-10-31 12:15:49 +08:00
noteHistoryId
2017-10-30 06:50:28 +08:00
] ) ;
}
else {
2017-10-31 12:15:49 +08:00
noteHistoryId = utils . randomString ( 16 ) ;
await sql . execute ( "insert into notes_history (note_history_id, note_id, note_title, note_text, encryption, date_modified_from, date_modified_to) " +
"values (?, ?, ?, ?, ?, ?, ?)" , [
noteHistoryId ,
2017-10-30 06:50:28 +08:00
noteId ,
2017-10-31 12:15:49 +08:00
note . detail . note _title ,
note . detail . note _text ,
note . detail . encryption ,
2017-10-30 06:50:28 +08:00
now ,
now
] ) ;
}
2017-10-31 12:15:49 +08:00
await sql . addNoteHistorySync ( noteHistoryId ) ;
if ( note . detail . note _title !== detail . note _title ) {
2017-10-30 06:50:28 +08:00
await sql . deleteRecentAudits ( audit _category . UPDATE _TITLE , req , noteId ) ;
await sql . addAudit ( audit _category . UPDATE _TITLE , req , noteId ) ;
}
2017-10-31 12:15:49 +08:00
if ( note . detail . note _text !== detail . note _text ) {
2017-10-30 06:50:28 +08:00
await sql . deleteRecentAudits ( audit _category . UPDATE _CONTENT , req , noteId ) ;
await sql . addAudit ( audit _category . UPDATE _CONTENT , req , noteId ) ;
}
2017-10-31 12:15:49 +08:00
if ( note . detail . encryption !== detail . encryption ) {
await sql . addAudit ( audit _category . ENCRYPTION , req , noteId , detail . encryption , note . detail . encryption ) ;
2017-10-30 06:50:28 +08:00
}
await sql . execute ( "update notes set note_title = ?, note_text = ?, encryption = ?, date_modified = ? where note_id = ?" , [
2017-10-31 12:15:49 +08:00
note . detail . note _title ,
note . detail . note _text ,
note . detail . encryption ,
2017-10-25 07:36:37 +08:00
now ,
2017-10-30 06:50:28 +08:00
noteId ] ) ;
2017-10-15 11:31:44 +08:00
2017-10-30 06:50:28 +08:00
await sql . remove ( "images" , noteId ) ;
2017-10-15 11:31:44 +08:00
2017-10-31 12:15:49 +08:00
for ( const img of note . images ) {
img . image _data = atob ( img . image _data ) ;
2017-10-15 11:31:44 +08:00
2017-10-30 06:50:28 +08:00
await sql . insert ( "images" , img ) ;
}
2017-10-15 11:31:44 +08:00
2017-10-30 06:50:28 +08:00
await sql . remove ( "links" , noteId ) ;
2017-10-15 11:31:44 +08:00
2017-10-31 12:15:49 +08:00
for ( const link in note . links ) {
2017-10-30 06:50:28 +08:00
await sql . insert ( "links" , link ) ;
}
2017-10-31 12:15:49 +08:00
await sql . addNoteSync ( noteId ) ;
2017-10-30 06:50:28 +08:00
} ) ;
2017-10-15 11:31:44 +08:00
res . send ( { } ) ;
} ) ;
router . delete ( '/:noteId' , async ( req , res , next ) => {
2017-10-30 06:50:28 +08:00
await sql . doInTransaction ( async ( ) => {
await deleteNote ( req . params . noteId , req ) ;
} ) ;
2017-10-15 11:31:44 +08:00
res . send ( { } ) ;
} ) ;
2017-10-23 10:13:24 +08:00
async function deleteNote ( noteId , req ) {
2017-10-25 10:58:59 +08:00
const now = utils . nowTimestamp ( ) ;
const children = await sql . getResults ( "select note_id from notes_tree where note_pid = ? and is_deleted = 0" , [ noteId ] ) ;
2017-10-15 11:31:44 +08:00
for ( const child of children ) {
2017-10-31 12:15:49 +08:00
await deleteNote ( child . note _id ) ;
2017-10-15 11:31:44 +08:00
}
2017-10-25 10:58:59 +08:00
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 ] ) ;
2017-10-15 11:31:44 +08:00
await sql . addAudit ( audit _category . DELETE _NOTE , req , noteId ) ;
}
router . post ( '/:parentNoteId/children' , async ( req , res , next ) => {
let parentNoteId = req . params . parentNoteId ;
const note = req . body ;
const noteId = utils . newNoteId ( ) ;
if ( parentNoteId === "root" ) {
parentNoteId = "" ;
}
let newNotePos = 0 ;
2017-10-31 12:15:49 +08:00
if ( note . target === 'into' ) {
2017-10-25 10:58:59 +08:00
const res = await sql . getSingleResult ( 'select max(note_pos) as max_note_pos from notes_tree where note_pid = ? and is_deleted = 0' , [ parentNoteId ] ) ;
2017-10-15 11:31:44 +08:00
const maxNotePos = res [ 'max_note_pos' ] ;
if ( maxNotePos === null ) // no children yet
newNotePos = 0 ;
else
newNotePos = maxNotePos + 1
}
2017-10-31 12:15:49 +08:00
else if ( note . target === 'after' ) {
const afterNote = await sql . getSingleResult ( 'select note_pos from notes_tree where note_id = ?' , [ note . target _note _id ] ) ;
2017-10-15 11:31:44 +08:00
2017-10-31 12:15:49 +08:00
newNotePos = afterNote . note _pos + 1 ;
2017-10-15 11:31:44 +08:00
2017-10-23 10:56:42 +08:00
const now = utils . nowTimestamp ( ) ;
2017-10-25 10:58:59 +08: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' , [ now , parentNoteId , afterNote [ 'note_pos' ] ] ) ;
2017-10-15 11:31:44 +08:00
}
else {
2017-10-31 12:15:49 +08:00
throw new Error ( 'Unknown target: ' + note . target ) ;
2017-10-15 11:31:44 +08:00
}
2017-10-30 06:50:28 +08:00
await sql . doInTransaction ( async ( ) => {
await sql . addAudit ( audit _category . CREATE _NOTE , req , noteId ) ;
2017-10-24 07:01:37 +08:00
2017-10-30 06:50:28 +08:00
const now = utils . nowTimestamp ( ) ;
2017-10-15 11:31:44 +08:00
2017-10-30 06:50:28 +08:00
await sql . insert ( "notes" , {
'note_id' : noteId ,
2017-10-31 12:15:49 +08:00
'note_title' : note . note _title ,
2017-10-30 06:50:28 +08:00
'note_text' : '' ,
'note_clone_id' : '' ,
'date_created' : now ,
'date_modified' : now ,
2017-10-31 12:15:49 +08:00
'encryption' : note . encryption
2017-10-30 06:50:28 +08:00
} ) ;
await sql . insert ( "notes_tree" , {
'note_id' : noteId ,
'note_pid' : parentNoteId ,
'note_pos' : newNotePos ,
'is_expanded' : 0 ,
'date_modified' : utils . nowTimestamp ( ) ,
'is_deleted' : 0
} ) ;
2017-10-15 11:31:44 +08:00
} ) ;
res . send ( {
'note_id' : noteId
} ) ;
} ) ;
router . get ( '/' , async ( req , res , next ) => {
const search = '%' + req . query . search + '%' ;
const result = await sql . getResults ( "select note_id from notes where note_title like ? or note_text like ?" , [ search , search ] ) ;
const noteIdList = [ ] ;
for ( const res of result ) {
2017-10-31 12:15:49 +08:00
noteIdList . push ( res . note _id ) ;
2017-10-15 11:31:44 +08:00
}
res . send ( noteIdList ) ;
} ) ;
module . exports = router ;