// // 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) }) }) }