diff --git a/src/js/chat.js b/src/js/chat.js index c9b6e9c..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; @@ -162,18 +167,18 @@ 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) => { + 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 782048f..58014d0 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,46 +101,78 @@ 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(); + }); + + 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); + // Check if user is here + 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 { - resolve({ - username: newUsername, - publicKey: user.publicKey - }); + 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.'); + } } + + return resolve({ + username: username, + publicKey: user.publicKey + }); } + + // User doesn't exist, create the user + return this.createUser(resolve, reject, username); }); } diff --git a/src/js/main.js b/src/js/main.js index e784695..fc7f8d0 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}); @@ -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) => { diff --git a/src/public/style.css b/src/public/style.css index d59bced..d39147e 100644 --- a/src/public/style.css +++ b/src/public/style.css @@ -317,14 +317,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 {