From 5538199c56a476030059711025ad80b02cdab373 Mon Sep 17 00:00:00 2001 From: Marcelo Schmidt Date: Wed, 19 Aug 2015 18:16:27 -0300 Subject: [PATCH 1/3] set username as callable method from API --- packages/rocketchat-lib/package.js | 10 ++ .../checkUsernameAvailability.coffee | 2 + .../server/functions/setUsername.coffee | 35 ++++++ .../server/methods/setUsername.coffee | 19 +++ server/methods/setUsername.coffee | 117 +++++++++--------- 5 files changed, 123 insertions(+), 60 deletions(-) create mode 100644 packages/rocketchat-lib/server/functions/checkUsernameAvailability.coffee create mode 100644 packages/rocketchat-lib/server/functions/setUsername.coffee create mode 100644 packages/rocketchat-lib/server/methods/setUsername.coffee diff --git a/packages/rocketchat-lib/package.js b/packages/rocketchat-lib/package.js index 350ef2aa9e7..ce7e9e8588b 100644 --- a/packages/rocketchat-lib/package.js +++ b/packages/rocketchat-lib/package.js @@ -18,6 +18,16 @@ Package.onUse(function(api) { api.addFiles('lib/underscore.string.coffee', ['server', 'client']); api.addFiles('lib/core.coffee', ['server', 'client']); api.addFiles('lib/callbacks.coffee', ['server', 'client']); + + api.addFiles([ + 'server/functions/checkUsernameAvailability.coffee', + 'server/functions/setUsername.coffee' + ], ['server']); + + api.addFiles([ + 'server/methods/setUsername.coffee' + ], ['server']); + api.addFiles('server/sendMessage.coffee', ['server']); api.addFiles('server/slashCommand.coffee', ['server']); api.addFiles('client/slashCommand.coffee', ['client']); diff --git a/packages/rocketchat-lib/server/functions/checkUsernameAvailability.coffee b/packages/rocketchat-lib/server/functions/checkUsernameAvailability.coffee new file mode 100644 index 00000000000..1dd34b347b5 --- /dev/null +++ b/packages/rocketchat-lib/server/functions/checkUsernameAvailability.coffee @@ -0,0 +1,2 @@ +RocketChat.checkUsernameAvailability = (username) -> + return not Meteor.users.findOne({ username: { $regex : new RegExp("^" + _.trim(username) + "$", "i") } }) \ No newline at end of file diff --git a/packages/rocketchat-lib/server/functions/setUsername.coffee b/packages/rocketchat-lib/server/functions/setUsername.coffee new file mode 100644 index 00000000000..922337eb91c --- /dev/null +++ b/packages/rocketchat-lib/server/functions/setUsername.coffee @@ -0,0 +1,35 @@ +RocketChat.setUsername = (user, username) -> + username = _.trim username + if not user or not username + return false + + if not /^[0-9a-zA-Z-_.]+$/.test username + return false + + # User already has desired username, return + if user.username is username + return user + + # Check username availability + unless RocketChat.checkUsernameAvailability username + return false + + previousUsername = user.username + + # Username is available, set username and update all references + ChatMessage.update { "u._id": user._id }, { $set: { "u.username": username } }, { multi: true } + + # @TODO: update chatmessage mentions + ChatMessage.find({ "mentions.username": previousUsername }).forEach (msg) -> + updatedMsg = msg.msg.replace(new RegExp("@#{previousUsername}", "ig"), "@#{username}") + ChatMessage.update { _id: msg._id, "mentions.username": previousUsername }, { $set: { "mentions.$.username": username, "msg": updatedMsg } } + + ChatRoom.update { usernames: previousUsername }, { $set: { "usernames.$": username } }, { multi: true } + ChatRoom.update { "u._id": user._id }, { $set: { "u.username": username } }, { multi: true } + + ChatSubscription.update { "u._id": user._id }, { $set: { "u.username": username } }, { multi: true } + ChatSubscription.update { name: previousUsername, t: "d" }, { $set: { name: username } }, { multi: true } + + Meteor.users.update { _id: user._id }, { $set: { username: username } } + user.username = username + return user diff --git a/packages/rocketchat-lib/server/methods/setUsername.coffee b/packages/rocketchat-lib/server/methods/setUsername.coffee new file mode 100644 index 00000000000..6a7b05792aa --- /dev/null +++ b/packages/rocketchat-lib/server/methods/setUsername.coffee @@ -0,0 +1,19 @@ +Meteor.methods + setUsername: (username) -> + if not Meteor.userId() + throw new Meteor.Error('invalid-user', "[methods] setUsername -> Invalid user") + + console.log '[methods] setUsername -> '.green, 'userId:', Meteor.userId(), 'arguments:', arguments + + user = Meteor.user() + + if not /^[0-9a-zA-Z-_.]+$/.test username + throw new Meteor.Error 'username-invalid' + + if not RocketChat.checkUsernameAvailability username + throw new Meteor.Error 'username-unavailable' + + unless RocketChat.setUsername user, username + throw new Meteor.Error 'could-not-change-username', t('Could_not_change_username') + + return username \ No newline at end of file diff --git a/server/methods/setUsername.coffee b/server/methods/setUsername.coffee index 3b60a2e4bf1..6879f3bcece 100644 --- a/server/methods/setUsername.coffee +++ b/server/methods/setUsername.coffee @@ -1,60 +1,57 @@ -Meteor.methods - setUsername: (username) -> - if not Meteor.userId() - throw new Meteor.Error('invalid-user', "[methods] setUsername -> Invalid user") - - console.log '[methods] setUsername -> '.green, 'userId:', Meteor.userId(), 'arguments:', arguments - - user = Meteor.user() - - if user.username? - throw new Meteor.Error 'username-already-setted' - - if not usernameIsAvaliable username - throw new Meteor.Error 'username-unavaliable' - - if not /^[0-9a-zA-Z-_.]+$/.test username - throw new Meteor.Error 'username-invalid' - - if not user.username? - ChatRoom.find({default: true, t: {$in: ['c', 'p']}}).forEach (room) -> - # put user in default rooms - ChatRoom.update room._id, - $addToSet: - usernames: username - - if not ChatSubscription.findOne(rid: room._id, 'u._id': user._id)? - ChatSubscription.insert - rid: room._id - name: room.name - ts: new Date() - t: room.t - f: false - open: true - alert: true - unread: 1 - u: - _id: user._id - username: username - - ChatMessage.insert - rid: room._id - ts: new Date() - t: 'uj' - msg: '' - u: - _id: user._id - username: username - - Meteor.users.update({_id: user._id}, {$set: {username: username}}) - - return username - -slug = (text) -> - text = slugify text, '.' - return text.replace(/[^0-9a-z-_.]/g, '') - -usernameIsAvaliable = (username) -> - if username.length < 1 - return false - return not Meteor.users.findOne({username: {$regex : new RegExp(username, "i") }}) +# Meteor.methods +# setUsername: (username) -> +# if not Meteor.userId() +# throw new Meteor.Error('invalid-user', "[methods] setUsername -> Invalid user") + +# console.log '[methods] setUsername -> '.green, 'userId:', Meteor.userId(), 'arguments:', arguments + +# user = Meteor.user() + +# if not usernameIsAvaliable username +# throw new Meteor.Error 'username-unavailable' + +# if not /^[0-9a-zA-Z-_.]+$/.test username +# throw new Meteor.Error 'username-invalid' + +# if not user.username? +# ChatRoom.find({default: true, t: {$in: ['c', 'p']}}).forEach (room) -> +# # put user in default rooms +# ChatRoom.update room._id, +# $addToSet: +# usernames: username + +# if not ChatSubscription.findOne(rid: room._id, 'u._id': user._id)? +# ChatSubscription.insert +# rid: room._id +# name: room.name +# ts: new Date() +# t: room.t +# f: false +# open: true +# alert: true +# unread: 1 +# u: +# _id: user._id +# username: username + +# ChatMessage.insert +# rid: room._id +# ts: new Date() +# t: 'uj' +# msg: '' +# u: +# _id: user._id +# username: username + +# Meteor.users.update({_id: user._id}, {$set: {username: username}}) + +# return username + +# slug = (text) -> +# text = slugify text, '.' +# return text.replace(/[^0-9a-z-_.]/g, '') + +# usernameIsAvaliable = (username) -> +# if username.length < 1 +# return false +# return not Meteor.users.findOne({username: {$regex : new RegExp("^" + username + "$", "i") }}) From b2c71ed0255ada34c7806ddceead4db8304ea4d3 Mon Sep 17 00:00:00 2001 From: Marcelo Schmidt Date: Wed, 19 Aug 2015 20:42:03 -0300 Subject: [PATCH 2/3] Moved code to join default channels to outside setUsername method --- client/views/username/username.coffee | 6 +- packages/rocketchat-lib/package.js | 1 + .../server/methods/joinDefaultChannels.coffee | 41 +++++++++++++ .../server/methods/setUsername.coffee | 3 + server/methods/setUsername.coffee | 57 ------------------- server/restapi/restapi.coffee | 1 + 6 files changed, 50 insertions(+), 59 deletions(-) create mode 100644 packages/rocketchat-lib/server/methods/joinDefaultChannels.coffee delete mode 100644 server/methods/setUsername.coffee diff --git a/client/views/username/username.coffee b/client/views/username/username.coffee index 23f1adbc93d..9fb574720aa 100644 --- a/client/views/username/username.coffee +++ b/client/views/username/username.coffee @@ -40,5 +40,7 @@ Template.username.events else username.error = true username.username = value - RocketChat.Button.reset(button) - instance.username.set(username) + + Meteor.call 'joinDefaultChannels', -> + RocketChat.Button.reset(button) + instance.username.set(username) diff --git a/packages/rocketchat-lib/package.js b/packages/rocketchat-lib/package.js index ce7e9e8588b..36eaa205f67 100644 --- a/packages/rocketchat-lib/package.js +++ b/packages/rocketchat-lib/package.js @@ -25,6 +25,7 @@ Package.onUse(function(api) { ], ['server']); api.addFiles([ + 'server/methods/joinDefaultChannels.coffee' 'server/methods/setUsername.coffee' ], ['server']); diff --git a/packages/rocketchat-lib/server/methods/joinDefaultChannels.coffee b/packages/rocketchat-lib/server/methods/joinDefaultChannels.coffee new file mode 100644 index 00000000000..61805aa81bb --- /dev/null +++ b/packages/rocketchat-lib/server/methods/joinDefaultChannels.coffee @@ -0,0 +1,41 @@ +Meteor.methods + joinDefaultChannels: -> + if not Meteor.userId() + throw new Meteor.Error('invalid-user', "[methods] setUsername -> Invalid user") + + console.log '[methods] joinDefaultChannels -> '.green, 'userId:', Meteor.userId(), 'arguments:', arguments + + user = Meteor.user() + + ChatRoom.find({default: true, t: {$in: ['c', 'p']}}).forEach (room) -> + + # put user in default rooms + ChatRoom.update room._id, + $addToSet: + usernames: user.username + + if not ChatSubscription.findOne(rid: room._id, 'u._id': user._id)? + + # Add a subscription to this user + ChatSubscription.insert + rid: room._id + name: room.name + ts: new Date() + t: room.t + f: false + open: true + alert: true + unread: 1 + u: + _id: user._id + username: user.username + + # Insert user joined message + ChatMessage.insert + rid: room._id + ts: new Date() + t: 'uj' + msg: '' + u: + _id: user._id + username: user.username \ No newline at end of file diff --git a/packages/rocketchat-lib/server/methods/setUsername.coffee b/packages/rocketchat-lib/server/methods/setUsername.coffee index 6a7b05792aa..246722f1aea 100644 --- a/packages/rocketchat-lib/server/methods/setUsername.coffee +++ b/packages/rocketchat-lib/server/methods/setUsername.coffee @@ -7,6 +7,9 @@ Meteor.methods user = Meteor.user() + if user.username is username + return username + if not /^[0-9a-zA-Z-_.]+$/.test username throw new Meteor.Error 'username-invalid' diff --git a/server/methods/setUsername.coffee b/server/methods/setUsername.coffee deleted file mode 100644 index 6879f3bcece..00000000000 --- a/server/methods/setUsername.coffee +++ /dev/null @@ -1,57 +0,0 @@ -# Meteor.methods -# setUsername: (username) -> -# if not Meteor.userId() -# throw new Meteor.Error('invalid-user', "[methods] setUsername -> Invalid user") - -# console.log '[methods] setUsername -> '.green, 'userId:', Meteor.userId(), 'arguments:', arguments - -# user = Meteor.user() - -# if not usernameIsAvaliable username -# throw new Meteor.Error 'username-unavailable' - -# if not /^[0-9a-zA-Z-_.]+$/.test username -# throw new Meteor.Error 'username-invalid' - -# if not user.username? -# ChatRoom.find({default: true, t: {$in: ['c', 'p']}}).forEach (room) -> -# # put user in default rooms -# ChatRoom.update room._id, -# $addToSet: -# usernames: username - -# if not ChatSubscription.findOne(rid: room._id, 'u._id': user._id)? -# ChatSubscription.insert -# rid: room._id -# name: room.name -# ts: new Date() -# t: room.t -# f: false -# open: true -# alert: true -# unread: 1 -# u: -# _id: user._id -# username: username - -# ChatMessage.insert -# rid: room._id -# ts: new Date() -# t: 'uj' -# msg: '' -# u: -# _id: user._id -# username: username - -# Meteor.users.update({_id: user._id}, {$set: {username: username}}) - -# return username - -# slug = (text) -> -# text = slugify text, '.' -# return text.replace(/[^0-9a-z-_.]/g, '') - -# usernameIsAvaliable = (username) -> -# if username.length < 1 -# return false -# return not Meteor.users.findOne({username: {$regex : new RegExp("^" + username + "$", "i") }}) diff --git a/server/restapi/restapi.coffee b/server/restapi/restapi.coffee index 8d736b21fd4..60a0c02e6a1 100644 --- a/server/restapi/restapi.coffee +++ b/server/restapi/restapi.coffee @@ -110,6 +110,7 @@ Api.addRoute 'bulk/register', authRequired: true, ids[i] = Meteor.call 'registerUser', incoming Meteor.runAsUser ids[i].uid, () => Meteor.call 'setUsername', incoming.name + Meteor.call 'joinDefaultChannels' status: 'success', ids: ids catch e From ab0e7052bf1b997b43374327e973b8107a864be5 Mon Sep 17 00:00:00 2001 From: Marcelo Schmidt Date: Wed, 19 Aug 2015 21:03:29 -0300 Subject: [PATCH 3/3] Fixes updating username on rooms only if setting a new username; --- client/views/username/username.coffee | 8 ++++--- packages/rocketchat-lib/package.js | 2 +- .../server/functions/setUsername.coffee | 21 ++++++++++--------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/client/views/username/username.coffee b/client/views/username/username.coffee index 9fb574720aa..be28936e38a 100644 --- a/client/views/username/username.coffee +++ b/client/views/username/username.coffee @@ -41,6 +41,8 @@ Template.username.events username.error = true username.username = value - Meteor.call 'joinDefaultChannels', -> - RocketChat.Button.reset(button) - instance.username.set(username) + RocketChat.Button.reset(button) + instance.username.set(username) + + if not err? + Meteor.call 'joinDefaultChannels' \ No newline at end of file diff --git a/packages/rocketchat-lib/package.js b/packages/rocketchat-lib/package.js index 36eaa205f67..a5bbaf4cdd5 100644 --- a/packages/rocketchat-lib/package.js +++ b/packages/rocketchat-lib/package.js @@ -25,7 +25,7 @@ Package.onUse(function(api) { ], ['server']); api.addFiles([ - 'server/methods/joinDefaultChannels.coffee' + 'server/methods/joinDefaultChannels.coffee', 'server/methods/setUsername.coffee' ], ['server']); diff --git a/packages/rocketchat-lib/server/functions/setUsername.coffee b/packages/rocketchat-lib/server/functions/setUsername.coffee index 922337eb91c..b16764b61fa 100644 --- a/packages/rocketchat-lib/server/functions/setUsername.coffee +++ b/packages/rocketchat-lib/server/functions/setUsername.coffee @@ -16,20 +16,21 @@ RocketChat.setUsername = (user, username) -> previousUsername = user.username - # Username is available, set username and update all references - ChatMessage.update { "u._id": user._id }, { $set: { "u.username": username } }, { multi: true } + # Username is available; if coming from old username, update all references + if previousUsername + ChatMessage.update { "u._id": user._id }, { $set: { "u.username": username } }, { multi: true } - # @TODO: update chatmessage mentions - ChatMessage.find({ "mentions.username": previousUsername }).forEach (msg) -> - updatedMsg = msg.msg.replace(new RegExp("@#{previousUsername}", "ig"), "@#{username}") - ChatMessage.update { _id: msg._id, "mentions.username": previousUsername }, { $set: { "mentions.$.username": username, "msg": updatedMsg } } + ChatMessage.find({ "mentions.username": previousUsername }).forEach (msg) -> + updatedMsg = msg.msg.replace(new RegExp("@#{previousUsername}", "ig"), "@#{username}") + ChatMessage.update { _id: msg._id, "mentions.username": previousUsername }, { $set: { "mentions.$.username": username, "msg": updatedMsg } } - ChatRoom.update { usernames: previousUsername }, { $set: { "usernames.$": username } }, { multi: true } - ChatRoom.update { "u._id": user._id }, { $set: { "u.username": username } }, { multi: true } + ChatRoom.update { usernames: previousUsername }, { $set: { "usernames.$": username } }, { multi: true } + ChatRoom.update { "u._id": user._id }, { $set: { "u.username": username } }, { multi: true } - ChatSubscription.update { "u._id": user._id }, { $set: { "u.username": username } }, { multi: true } - ChatSubscription.update { name: previousUsername, t: "d" }, { $set: { name: username } }, { multi: true } + ChatSubscription.update { "u._id": user._id }, { $set: { "u.username": username } }, { multi: true } + ChatSubscription.update { name: previousUsername, t: "d" }, { $set: { name: username } }, { multi: true } + # Set new username Meteor.users.update { _id: user._id }, { $set: { username: username } } user.username = username return user