From 78790eacec298ed5d63296b4393117de44034321 Mon Sep 17 00:00:00 2001 From: Dan Seripap Date: Thu, 25 Feb 2016 11:15:26 -0500 Subject: [PATCH 1/4] Parsing new usernames as string, requiring letter as starting name --- src/js/chat.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/js/chat.js b/src/js/chat.js index c9b6e9c..7d1e7f7 100644 --- a/src/js/chat.js +++ b/src/js/chat.js @@ -162,15 +162,15 @@ export default class Chat { action: () => { let newUsername = trigger.params[0] || false; - if (newUsername > 16) { + if (newUsername.toString().length > 16) { return this.log('Username cannot be greater than 16 characters.', {error: true}); } // Remove things that arent digits or chars newUsername = newUsername.replace(/[^A-Za-z0-9]/g, '-'); - if (!newUsername.match(/^[A-Z0-9]/i)) { - return this.log('Username must start with a letter or number.', {error: true}); + if (!newUsername.match(/^[A-Z]/i)) { + return this.log('Username must start with a letter.', {error: true}); } this.darkwire.updateUsername(window.username, newUsername).then((socketData) => { From d0d47c098af221725ec20926504ee5eba7e2ad5f Mon Sep 17 00:00:00 2001 From: Dan Seripap Date: Thu, 25 Feb 2016 12:44:36 -0500 Subject: [PATCH 2/4] Fixing colors, allowing only unique usernames per chat session --- src/js/chat.js | 21 ++++++++----- src/js/darkwire.js | 75 ++++++++++++++++++++++++++------------------ src/js/main.js | 2 +- src/public/style.css | 14 ++++++--- 4 files changed, 69 insertions(+), 43 deletions(-) diff --git a/src/js/chat.js b/src/js/chat.js index 7d1e7f7..4b6881a 100644 --- a/src/js/chat.js +++ b/src/js/chat.js @@ -34,8 +34,12 @@ export default class Chat { } if (options && options.error) { - $el = $('
  • ').addClass('log').html(message); - } else if (options && options.info) { + $el = $('
  • ').addClass('log').html('ERROR: ' + message); + } else if (options && options.warning) { + $el = $('
  • ').addClass('log').html('WARNING: ' + message); + } else if (options && options.notice) { + $el = $('
  • ').addClass('log').html('NOTICE: ' + message); + } else if (options && options.info) { $el = $('
  • ').addClass('log').html(message); } else { $el = $('
  • ').addClass('log').html(message); @@ -68,9 +72,10 @@ export default class Chat { const COLORS = [ '#e21400', '#ffe400', '#ff8f00', '#58dc00', '#dd9cff', '#4ae8c4', - '#3b88eb', '#f47777', '#d300e7', - '#99FF33', '#99CC33', '#999933', - '#996633', '#993333', '#990033', + '#3b88eb', '#f47777', '#EEACB7', + '#D3FF3E', '#99CC33', '#999933', + '#996633', '#B8D5B8', '#7FFF38', + '#FADBBC', '#FAE2B7', '#EBE8AF', ]; // Compute hash code let hash = 7; @@ -173,7 +178,7 @@ export default class Chat { return this.log('Username must start with a letter.', {error: true}); } - this.darkwire.updateUsername(window.username, newUsername).then((socketData) => { + this.darkwire.updateUsername(newUsername).then((socketData) => { let modifiedSocketData = { username: window.username, newUsername: socketData.username @@ -181,6 +186,8 @@ export default class Chat { this.socket.emit('update user', modifiedSocketData); window.username = username = socketData.username; + }).catch((err) => { + return this.log(err, {error: true}); }); } }, { @@ -194,7 +201,7 @@ export default class Chat { return '/' + command; }); - this.log('Valid commands: ' + validCommands.sort().join(', '), {info: true}); + this.log('Valid commands: ' + validCommands.sort().join(', '), {notice: true}); } }, { command: 'me', diff --git a/src/js/darkwire.js b/src/js/darkwire.js index e344391..6daec6e 100644 --- a/src/js/darkwire.js +++ b/src/js/darkwire.js @@ -53,16 +53,12 @@ export default class Darkwire { return _.findWhere(this._users, {id: id}); } - getUserByName(username) { - return _.findWhere(this._users, {username: username}); - } - updateUser(data) { return new Promise((resolve, reject) => { let user = this.getUserById(data.id); if (!user) { - return reject(); + return reject('User cannot be found'); } let oldUsername = user.username; @@ -105,45 +101,62 @@ export default class Darkwire { return importKeysPromises; } + checkSessionUsernames(username) { + let matches = _.find(this._users, (users) => { + return username.toLowerCase() === users.username.toLowerCase(); + }); + + if (matches && matches.username) { + return matches; + } + + return false; + } + removeUser(data) { this._users = _.without(this._users, _.findWhere(this._users, {id: data.id})); return this._users; } - updateUsername(username, newUsername) { + updateUsername(username) { let user = null; return new Promise((resolve, reject) => { - if (newUsername) { - user = this.getUserByName(username); + if (username) { + user = this.getUserById(this._myUserId); } - if (username) { - if (!user) { - Promise.all([ - this._cryptoUtil.createPrimaryKeys() - ]) - .then((data) => { - this._keys = { - public: data[0].publicKey, - private: data[0].privateKey - }; - return Promise.all([ - this._cryptoUtil.exportKey(data[0].publicKey, 'spki') - ]); - }) - .then((exportedKeys) => { - resolve({ - username: username, - publicKey: exportedKeys[0] - }); - }); - } else { + if (!user) { + Promise.all([ + this._cryptoUtil.createPrimaryKeys() + ]) + .then((data) => { + this._keys = { + public: data[0].publicKey, + private: data[0].privateKey + }; + return Promise.all([ + this._cryptoUtil.exportKey(data[0].publicKey, 'spki') + ]); + }) + .then((exportedKeys) => { resolve({ - username: newUsername, - publicKey: user.publicKey + username: username, + publicKey: exportedKeys[0] }); + }); + } else { + let userExists = this.checkSessionUsernames(username); + if (userExists) { + if (userExists.id !== this._myUserId) { + return reject(username + ' is being used by someone else in this chat session.'); + } } + + return resolve({ + username: username, + publicKey: user.publicKey + }); } }); } diff --git a/src/js/main.js b/src/js/main.js index 9c4ff0b..a5738b3 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -48,7 +48,7 @@ $(function() { fs(window.TEMPORARY, 100, () => { - chat.log('WARNING: Your browser is not in incognito mode!', {error: true}); + chat.log('Your browser is not in incognito mode!', {warning: true}); }); } chat.log(moment().format('MMMM Do YYYY, h:mm:ss a'), {info: true}); diff --git a/src/public/style.css b/src/public/style.css index 606e38b..de53408 100644 --- a/src/public/style.css +++ b/src/public/style.css @@ -313,14 +313,20 @@ html.no-touchevents .chat #input-icons { line-height: 10px; } -.log-info { - color: #FFF; +.log-error, .log-info, .log-warning { font-weight: bold; } .log-error { - color: yellow; - font-weight: bold; + color: #D8D638; +} + +.log-info { + color: #FFF; +} + +.log-warning { + color: #E0873E; } .action { From fc63e1b2b9e54f825c238399cb4c20230333e8db Mon Sep 17 00:00:00 2001 From: Dan Seripap Date: Thu, 25 Feb 2016 12:55:02 -0500 Subject: [PATCH 3/4] Abstracted creating user versus updating user --- src/js/darkwire.js | 55 +++++++++++++++++++++++++++++----------------- 1 file changed, 35 insertions(+), 20 deletions(-) diff --git a/src/js/darkwire.js b/src/js/darkwire.js index 6daec6e..011bbad 100644 --- a/src/js/darkwire.js +++ b/src/js/darkwire.js @@ -101,6 +101,31 @@ export default class Darkwire { return importKeysPromises; } + createUser(resolve, reject, username) { + Promise.all([ + this._cryptoUtil.createPrimaryKeys() + ]) + .then((data) => { + this._keys = { + public: data[0].publicKey, + private: data[0].privateKey + }; + return Promise.all([ + this._cryptoUtil.exportKey(data[0].publicKey, 'spki') + ]); + }) + .then((exportedKeys) => { + if (!exportedKeys) { + return reject('Could not create a user session'); + } + + return resolve({ + username: username, + publicKey: exportedKeys[0] + }); + }); + } + checkSessionUsernames(username) { let matches = _.find(this._users, (users) => { return username.toLowerCase() === users.username.toLowerCase(); @@ -122,32 +147,19 @@ export default class Darkwire { let user = null; return new Promise((resolve, reject) => { + // Check if user is here if (username) { user = this.getUserById(this._myUserId); } - if (!user) { - Promise.all([ - this._cryptoUtil.createPrimaryKeys() - ]) - .then((data) => { - this._keys = { - public: data[0].publicKey, - private: data[0].privateKey - }; - return Promise.all([ - this._cryptoUtil.exportKey(data[0].publicKey, 'spki') - ]); - }) - .then((exportedKeys) => { - resolve({ - username: username, - publicKey: exportedKeys[0] - }); - }); - } else { + if (user) { + // User exists and is attempting to change username + // Check if anyone else is using the requested username let userExists = this.checkSessionUsernames(username); + if (userExists) { + // Someone else is using the username requested, allow reformatting + // if it is owned by the user, else reject the promise if (userExists.id !== this._myUserId) { return reject(username + ' is being used by someone else in this chat session.'); } @@ -158,6 +170,9 @@ export default class Darkwire { publicKey: user.publicKey }); } + + // User doesn't exist, create the user + return this.createUser(resolve, reject, username); }); } From 0f4fff2d6f3ef95bc383493665c20b185f5caa9b Mon Sep 17 00:00:00 2001 From: Dan Seripap Date: Thu, 25 Feb 2016 16:43:53 -0500 Subject: [PATCH 4/4] Escaping characters before embed --- src/js/main.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/js/main.js b/src/js/main.js index a5738b3..e0f1d02 100644 --- a/src/js/main.js +++ b/src/js/main.js @@ -211,9 +211,10 @@ $(function() { darkwire.encodeMessage(cleanedMessage, 'text').then((socketData) => { message.val(''); $('#send-message-btn').removeClass('active'); + // Add escaped message since message did not come from the server chat.addChatMessage({ username: username, - message: cleanedMessage + message: escape(cleanedMessage) }); socket.emit('new message', socketData); }).catch((err) => {