* Delete Crunch Menu Component
* 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
This commit is contained in:
1 parent
df073b0e4d
commit
67b218329b
16 files changed
+797
-603
No files matched your search
+92
-50
@@ -9,80 +9,122 @@ const Note = require('@models/Note')
|
||||
|
||||
let ShareNote = module.exports = {}
|
||||
|
||||
// Share a note with a user, given the correct username
|
||||
ShareNote.addUser = (userId, noteId, rawTextId, username) => {
|
||||
const crypto = require('crypto')
|
||||
const cs = require('@helpers/CryptoString')
|
||||
|
||||
ShareNote.migrateNoteToShared = (userId, noteId, shareUserId, masterKey) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
let shareUserId = null
|
||||
let newNoteShare = null
|
||||
const cleanUser = username.toLowerCase().trim()
|
||||
const Note = require('@models/Note')
|
||||
const User = require('@models/User')
|
||||
|
||||
//Check that user actually exists
|
||||
db.promise().query(`SELECT id FROM user WHERE LOWER(username) = ?`, [cleanUser])
|
||||
//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')
|
||||
}
|
||||
|
||||
shareUserId = rows[0][0]['id']
|
||||
return Note.get(userId, noteId, masterKey)
|
||||
|
||||
})
|
||||
.then( noteObject => {
|
||||
|
||||
if(!noteObject){
|
||||
throw new Error('Note Not Found')
|
||||
}
|
||||
|
||||
note = noteObject
|
||||
|
||||
//Check if note has already been added for user
|
||||
return db.promise()
|
||||
.query('SELECT id FROM note WHERE user_id = ? AND note_raw_text_id = ?', [shareUserId, rawTextId])
|
||||
.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) => {
|
||||
|
||||
if(rows[0].length != 0){
|
||||
throw new Error('User Already Has Note')
|
||||
}
|
||||
//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)
|
||||
|
||||
//Lookup note to share with user, clone this data to create users new note
|
||||
return db.promise()
|
||||
.query(`SELECT * FROM note WHERE id = ? LIMIT 1`, [noteId])
|
||||
})
|
||||
.then((rows, fields) => {
|
||||
//Encrypt shared password for this user
|
||||
const encryptedSharedKey = crypto.publicEncrypt(publicKey, Buffer.from(sharedNoteMasterKey, 'utf8')).toString('base64')
|
||||
|
||||
newNoteShare = rows[0][0]
|
||||
|
||||
//Modify note with the share attributes we want
|
||||
delete newNoteShare['id']
|
||||
delete newNoteShare['opened']
|
||||
newNoteShare['share_user_id'] = userId //User who shared the note
|
||||
newNoteShare['user_id'] = shareUserId //User who gets note
|
||||
|
||||
//Setup db colums, db values and number of '?' to put into prepared statement
|
||||
let dbColumns = []
|
||||
let dbValues = []
|
||||
let escapeChars = []
|
||||
|
||||
//Pull out all the data we need from object to create prepared statemnt
|
||||
Object.keys(newNoteShare).forEach( key => {
|
||||
escapeChars.push('?')
|
||||
dbColumns.push(key)
|
||||
dbValues.push(newNoteShare[key])
|
||||
})
|
||||
|
||||
//Stick all the note value back into query, insert updated note
|
||||
return db.promise()
|
||||
.query(`INSERT INTO note (${dbColumns.join()}) VALUES (${escapeChars.join()})`, dbValues)
|
||||
})
|
||||
.then((rows, fields) => {
|
||||
|
||||
//Update note share status to 2
|
||||
return db.promise()
|
||||
.query('UPDATE note SET shared = 2 WHERE id = ?', [noteId])
|
||||
//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) => {
|
||||
//Success!
|
||||
return resolve({'success':true, shareUserId})
|
||||
|
||||
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)
|
||||
resolve(false)
|
||||
})
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user