67b218329b
* Disabled Quick Note * Note crunches over when menu is open * Added a cool loader * Remomoved locked notes * Added full note encryption * Added encrypted search index * Added encrypted shared notes * Made search bar have a clear and search button * Tags only loade when clicking on the tags menu * Tweaked home page to be a little more sane * built out some gigantic test cases * simplified a lot of things to make entire app easier to maintain
189 lines
5.1 KiB
JavaScript
189 lines
5.1 KiB
JavaScript
//
|
|
// All actions in noteController.js
|
|
//
|
|
|
|
|
|
const db = require('@config/database')
|
|
|
|
const Note = require('@models/Note')
|
|
|
|
let ShareNote = module.exports = {}
|
|
|
|
const crypto = require('crypto')
|
|
const cs = require('@helpers/CryptoString')
|
|
|
|
ShareNote.migrateNoteToShared = (userId, noteId, shareUserId, masterKey) => {
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const Note = require('@models/Note')
|
|
const User = require('@models/User')
|
|
|
|
//generate new random salts and password
|
|
const sharedNoteMasterKey = cs.createSmallSalt()
|
|
|
|
let encryptedSharedKey = null //new key for note encrypted with shared users pubic key
|
|
|
|
//Current note object
|
|
let note = null
|
|
let publicKey = null
|
|
|
|
db.promise().query('SELECT id FROM user WHERE id = ?', [shareUserId])
|
|
.then((rows, fields) => {
|
|
|
|
if(rows[0].length == 0){
|
|
throw new Error('User Does Not Exist')
|
|
}
|
|
|
|
return Note.get(userId, noteId, masterKey)
|
|
|
|
})
|
|
.then( noteObject => {
|
|
|
|
if(!noteObject){
|
|
throw new Error('Note Not Found')
|
|
}
|
|
|
|
note = noteObject
|
|
|
|
return db.promise()
|
|
.query('SELECT id FROM note WHERE user_id = ? AND note_raw_text_id = ?', [shareUserId, note.rawTextId])
|
|
|
|
})
|
|
.then((rows, fields) => {
|
|
|
|
if(rows[0].length >= 1){
|
|
throw new Error('User Already has this note shared with them')
|
|
}
|
|
|
|
//All check pass, proceed with sharing note
|
|
return User.getPublicKey(userId)
|
|
})
|
|
.then( userPublicKey => {
|
|
|
|
//Get users public key
|
|
publicKey = userPublicKey
|
|
|
|
//
|
|
// Modify note to have a shared password, encrypt text with this password
|
|
//
|
|
const sharedNoteSalt = cs.createSmallSalt()
|
|
|
|
//Encrypt note text with new password
|
|
const textObject = JSON.stringify([note.title, note.text])
|
|
const encryptedText = cs.encrypt(sharedNoteMasterKey, sharedNoteSalt, textObject)
|
|
|
|
//Update note raw text with new data
|
|
return db.promise()
|
|
.query("UPDATE `application`.`note_raw_text` SET `text` = ?, `salt` = ? WHERE (`id` = ?)",
|
|
[encryptedText, sharedNoteSalt, note.rawTextId])
|
|
|
|
})
|
|
.then((rows, fields) => {
|
|
|
|
//New Encrypted snippet, using new shared password
|
|
const sharedNoteSnippetSalt = cs.createSmallSalt()
|
|
const snippet = JSON.stringify([note.title, note.text.substring(0, 500)])
|
|
const encryptedSnippet = cs.encrypt(sharedNoteMasterKey, sharedNoteSnippetSalt, snippet)
|
|
|
|
//Encrypt shared password for this user
|
|
const encryptedSharedKey = crypto.publicEncrypt(publicKey, Buffer.from(sharedNoteMasterKey, 'utf8')).toString('base64')
|
|
|
|
//Update note snippet for current user with public key encoded snippet
|
|
return db.promise().query('UPDATE note SET snippet = ?, snippet_salt = ?, encrypted_share_password_key = ? WHERE id = ? AND user_id = ?',
|
|
[encryptedSnippet, sharedNoteSnippetSalt, encryptedSharedKey, noteId, userId])
|
|
|
|
})
|
|
.then((rows, fields) => {
|
|
|
|
return User.getPublicKey(shareUserId)
|
|
|
|
})
|
|
.then(shareUserPublicKey => {
|
|
|
|
//New Encrypted snippet, using new shared password
|
|
const newSnippetSalt = cs.createSmallSalt()
|
|
const snippet = JSON.stringify([note.title, note.text.substring(0, 500)])
|
|
const encryptedSnippet = cs.encrypt(sharedNoteMasterKey, newSnippetSalt, snippet)
|
|
|
|
//Encrypt shared password for this user
|
|
const encryptedSharedKey = crypto.publicEncrypt(shareUserPublicKey, Buffer.from(sharedNoteMasterKey, 'utf8')).toString('base64')
|
|
|
|
//Insert new note for shared user
|
|
return db.promise().query(`
|
|
INSERT INTO note (user_id, note_raw_text_id, created, color, share_user_id, snippet, snippet_salt, encrypted_share_password_key) VALUES (?,?,?,?,?,?,?,?);
|
|
`, [shareUserId, note.rawTextId, note.created, note.color, userId, encryptedSnippet, newSnippetSalt, encryptedSharedKey])
|
|
|
|
})
|
|
.then((rows, fields) => {
|
|
|
|
let success = true
|
|
return resolve({success, shareUserId})
|
|
|
|
})
|
|
.catch(error => {
|
|
console.log('Shared Note Error')
|
|
console.log(error)
|
|
})
|
|
|
|
})
|
|
}
|
|
|
|
// Get users who see a shared note
|
|
ShareNote.getUsers = (userId, rawTextId) => {
|
|
return new Promise((resolve, reject) => {
|
|
db.promise()
|
|
.query(`
|
|
SELECT username, note.id as noteId
|
|
FROM note
|
|
JOIN user ON (user.id = note.user_id)
|
|
WHERE note_raw_text_id = ?
|
|
AND share_user_id = ?
|
|
AND user_id != ?
|
|
`, [rawTextId, userId, userId])
|
|
.then((rows, fields) => {
|
|
|
|
//Return a list of user names
|
|
return resolve (rows[0])
|
|
})
|
|
})
|
|
}
|
|
|
|
// Remove a user from a shared note
|
|
ShareNote.removeUser = (userId, noteId) => {
|
|
return new Promise((resolve, reject) => {
|
|
|
|
const Note = require('@models/Note')
|
|
|
|
let rawTextId = null
|
|
let removeUserId = null
|
|
|
|
//note.id = noteId, share_user_id = userId
|
|
db.promise()
|
|
.query('SELECT note_raw_text_id, user_id FROM note WHERE id = ? AND share_user_id = ?', [noteId, userId])
|
|
.then( (rows, fields) => {
|
|
|
|
rawTextId = rows[0][0]['note_raw_text_id']
|
|
removeUserId = rows[0][0]['user_id']
|
|
|
|
//Delete note entry for other user - remove users access
|
|
if(removeUserId && Number.isInteger(removeUserId)){
|
|
//Delete this users access to the note
|
|
return Note.delete(removeUserId, noteId)
|
|
|
|
} else {
|
|
|
|
return new Promise((resolve, reject) => { resolve(true) })
|
|
}
|
|
|
|
})
|
|
.then(stuff => {
|
|
resolve(true)
|
|
})
|
|
.catch(error => {
|
|
console.log(error)
|
|
resolve(false)
|
|
})
|
|
|
|
|
|
})
|
|
} |