diff --git a/HISTORY.md b/HISTORY.md index d47b699a3ce4..1d3d8139d3d1 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -8,6 +8,7 @@ - [FIX] Incoming integrations would break when trying to use the `Store` feature. - [FIX] Outgoing webhooks which have an error and they're retrying would still retry even if the integration was disabled. (#4835) - [FIX] Removed Deprecated Package rocketchat:sharedsecret. +- [BREAK] `getUsersOfRoom` API to return array of objects with user and username, instead of array of strings ## 0.54.2 - 2017-Mar-24 diff --git a/packages/rocketchat-cas/cas_server.js b/packages/rocketchat-cas/cas_server.js index 6a8516cd1809..77c5bab6e9b2 100644 --- a/packages/rocketchat-cas/cas_server.js +++ b/packages/rocketchat-cas/cas_server.js @@ -188,7 +188,7 @@ Accounts.registerLoginHandler(function(options) { logger.debug('Syncing user attributes'); // Update name if (int_attrs.name) { - Meteor.users.update(user, { $set: { name: int_attrs.name }}); + RocketChat._setRealName(user._id, int_attrs.name); } // Update email diff --git a/packages/rocketchat-crowd/server/crowd.js b/packages/rocketchat-crowd/server/crowd.js index 0ca60d4548a4..234fd09eca39 100644 --- a/packages/rocketchat-crowd/server/crowd.js +++ b/packages/rocketchat-crowd/server/crowd.js @@ -85,7 +85,6 @@ const CROWD = class CROWD { syncDataToUser(crowdUser, id) { const user = { - name: crowdUser.displayname, username: crowdUser.username, emails: [{ address : crowdUser.email, @@ -95,6 +94,10 @@ const CROWD = class CROWD { active: crowdUser.active }; + if (crowdUser.displayname) { + RocketChat._setRealName(id, crowdUser.displayname); + } + Meteor.users.update(id, { $set: user }); diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 6057e02758c1..3df551cb89d8 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1522,6 +1522,7 @@ "UI_DisplayRoles": "Display Roles", "UI_Merge_Channels_Groups": "Merge private groups with channels", "UI_Use_Name_Avatar": "Use full name initials to generate default avatar", + "UI_Use_Real_Name" : "Use Real Name", "Unarchive": "Unarchive", "Unblock_User": "Unblock User", "Unmute_someone_in_room": "Unmute someone in the room", diff --git a/packages/rocketchat-importer-hipchat/server.coffee b/packages/rocketchat-importer-hipchat/server.coffee index c84a6413b8f1..19a4cbced951 100644 --- a/packages/rocketchat-importer-hipchat/server.coffee +++ b/packages/rocketchat-importer-hipchat/server.coffee @@ -221,7 +221,7 @@ Importer.HipChat = class Importer.HipChat extends Importer.Base getRocketUser: (hipchatId) => for user in @users.users when user.user_id is hipchatId - return RocketChat.models.Users.findOneById user.rocketId, { fields: { username: 1 }} + return RocketChat.models.Users.findOneById user.rocketId, { fields: { username: 1, name: 1 }} convertHipChatMessageToRocketChat: (message) => if message? diff --git a/packages/rocketchat-importer-slack/server.coffee b/packages/rocketchat-importer-slack/server.coffee index 04ca574ac1a1..bbfa2a050474 100644 --- a/packages/rocketchat-importer-slack/server.coffee +++ b/packages/rocketchat-importer-slack/server.coffee @@ -342,7 +342,7 @@ Importer.Slack = class Importer.Slack extends Importer.Base getRocketUser: (slackId) => for user in @users.users when user.id is slackId - return RocketChat.models.Users.findOneById user.rocketId, { fields: { username: 1 }} + return RocketChat.models.Users.findOneById user.rocketId, { fields: { username: 1, name: 1 }} convertSlackMessageToRocketChat: (message) => if message? diff --git a/packages/rocketchat-ldap/server/sync.js b/packages/rocketchat-ldap/server/sync.js index 0b0b218d24eb..df3ec4bf828b 100644 --- a/packages/rocketchat-ldap/server/sync.js +++ b/packages/rocketchat-ldap/server/sync.js @@ -122,9 +122,13 @@ syncUserData = function syncUserData(user, ldapUser) { const userData = getDataToSyncUserData(ldapUser, user); if (user && user._id && userData) { + logger.debug('setting', JSON.stringify(userData, null, 2)); + if (userData.name) { + RocketChat._setRealName(user._id, userData.name); + delete userData.name; + } Meteor.users.update(user._id, { $set: userData }); user = Meteor.users.findOne({_id: user._id}); - logger.debug('setting', JSON.stringify(userData, null, 2)); } if (RocketChat.settings.get('LDAP_Username_Field') !== '') { diff --git a/packages/rocketchat-lib/package.js b/packages/rocketchat-lib/package.js index 03e88cded081..dbb17c2bda9b 100644 --- a/packages/rocketchat-lib/package.js +++ b/packages/rocketchat-lib/package.js @@ -87,6 +87,7 @@ Package.onUse(function(api) { api.addFiles('server/functions/settings.coffee', 'server'); api.addFiles('server/functions/setUserAvatar.js', 'server'); api.addFiles('server/functions/setUsername.coffee', 'server'); + api.addFiles('server/functions/setRealName.js', 'server'); api.addFiles('server/functions/setEmail.js', 'server'); api.addFiles('server/functions/unarchiveRoom.js', 'server'); api.addFiles('server/functions/updateMessage.js', 'server'); diff --git a/packages/rocketchat-lib/server/functions/addUserToRoom.js b/packages/rocketchat-lib/server/functions/addUserToRoom.js index 47ae76aeaabe..b27acb1f6791 100644 --- a/packages/rocketchat-lib/server/functions/addUserToRoom.js +++ b/packages/rocketchat-lib/server/functions/addUserToRoom.js @@ -27,7 +27,8 @@ RocketChat.addUserToRoom = function(rid, user, inviter, silenced) { ts: now, u: { _id: inviter._id, - username: inviter.username + username: inviter.username, + name: inviter.name } }); } else { diff --git a/packages/rocketchat-lib/server/functions/saveUser.js b/packages/rocketchat-lib/server/functions/saveUser.js index ac9c31abc142..540479df0afb 100644 --- a/packages/rocketchat-lib/server/functions/saveUser.js +++ b/packages/rocketchat-lib/server/functions/saveUser.js @@ -140,6 +140,10 @@ RocketChat.saveUser = function(userId, userData) { RocketChat.setUsername(userData._id, userData.username); } + if (userData.name) { + RocketChat.setRealName(userData._id, userData.name); + } + if (userData.email) { RocketChat.setEmail(userData._id, userData.email); } @@ -152,10 +156,6 @@ RocketChat.saveUser = function(userId, userData) { $set: {} }; - if (userData.name) { - updateUser.$set.name = userData.name; - } - if (userData.roles) { updateUser.$set.roles = userData.roles; } diff --git a/packages/rocketchat-lib/server/functions/sendMessage.coffee b/packages/rocketchat-lib/server/functions/sendMessage.coffee index bdce87faba4d..e25bf08cb8dc 100644 --- a/packages/rocketchat-lib/server/functions/sendMessage.coffee +++ b/packages/rocketchat-lib/server/functions/sendMessage.coffee @@ -5,7 +5,7 @@ RocketChat.sendMessage = (user, message, room, upsert = false) -> unless message.ts? message.ts = new Date() - message.u = _.pick user, ['_id','username'] + message.u = _.pick user, ['_id','username', 'name'] if not Match.test(message.msg, String) message.msg = '' diff --git a/packages/rocketchat-lib/server/functions/setRealName.js b/packages/rocketchat-lib/server/functions/setRealName.js new file mode 100644 index 000000000000..93d7545e7796 --- /dev/null +++ b/packages/rocketchat-lib/server/functions/setRealName.js @@ -0,0 +1,29 @@ +RocketChat._setRealName = function(userId, name) { + name = s.trim(name); + if (!userId || !name) { + return false; + } + + const user = RocketChat.models.Users.findOneById(userId); + + // User already has desired name, return + if (user.name === name) { + return user; + } + + const previousName = user.name; + + if (previousName) { + RocketChat.models.Messages.updateAllNamesByUserId(user._id, name); + RocketChat.models.Subscriptions.setRealNameForDirectRoomsWithUsername(user.username, name); + } + + // Set new name + RocketChat.models.Users.setName(user._id, name); + user.name = name; + return user; +}; + +RocketChat.setRealName = RocketChat.RateLimiter.limitFunction(RocketChat._setRealName, 1, 60000, { + 0() { return !Meteor.userId() || !RocketChat.authz.hasPermission(Meteor.userId(), 'edit-other-user-info'); } // Administrators have permission to change others names, so don't limit those +}); diff --git a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js index 735ac1340dea..85ab61fb1119 100644 --- a/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js +++ b/packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js @@ -128,7 +128,7 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) { } if ((userOfMention != null) && canBeNotified(userOfMentionId, 'mobile')) { RocketChat.Notifications.notifyUser(userOfMention._id, 'notification', { - title: `@${ user.username }`, + title: RocketChat.settings.get('UI_Use_Real_Name') ? user.name : `@${ user.username }`, text: message.msg, duration: settings.desktopNotificationDurations[userOfMention._id], payload: { diff --git a/packages/rocketchat-lib/server/methods/setRealName.js b/packages/rocketchat-lib/server/methods/setRealName.js index 16f7068f9ea6..467bb979822e 100644 --- a/packages/rocketchat-lib/server/methods/setRealName.js +++ b/packages/rocketchat-lib/server/methods/setRealName.js @@ -17,10 +17,14 @@ Meteor.methods({ name = _.trim(name); } - if (!RocketChat.models.Users.setName(Meteor.userId(), name)) { + if (!RocketChat.setRealName(Meteor.userId(), name)) { throw new Meteor.Error('error-could-not-change-name', 'Could not change name', { method: 'setRealName' }); } return name; } }); + +RocketChat.RateLimiter.limitMethod('setRealName', 1, 1000, { + userId: () => true +}); diff --git a/packages/rocketchat-lib/server/models/Messages.coffee b/packages/rocketchat-lib/server/models/Messages.coffee index 8ac7b4efcd7b..524133ae7b0e 100644 --- a/packages/rocketchat-lib/server/models/Messages.coffee +++ b/packages/rocketchat-lib/server/models/Messages.coffee @@ -320,6 +320,16 @@ RocketChat.models.Messages = new class extends RocketChat.models._Base return @update query, update + updateAllNamesByUserId: (userId, name) -> + query = + 'u._id': userId + + update = + $set: + "u.name": name + + return @update query, update, { multi: true } + updateUserStarById: (_id, userId, starred) -> query = _id: _id @@ -380,6 +390,7 @@ RocketChat.models.Messages = new class extends RocketChat.models._Base u: _id: user._id username: user.username + name: user.name groupable: false _.extend record, extraData diff --git a/packages/rocketchat-lib/server/models/Subscriptions.coffee b/packages/rocketchat-lib/server/models/Subscriptions.coffee index 4ae7500ffef5..7b9aa80e605a 100644 --- a/packages/rocketchat-lib/server/models/Subscriptions.coffee +++ b/packages/rocketchat-lib/server/models/Subscriptions.coffee @@ -242,6 +242,17 @@ class ModelSubscriptions extends RocketChat.models._Base return @update query, update, { multi: true } + setRealNameForDirectRoomsWithUsername: (username, name) -> + query = + name: username + t: "d" + + update = + $set: + fname: name + + return @update query, update, { multi: true } + setNameForDirectRoomsWithOldName: (oldName, name) -> query = name: oldName diff --git a/packages/rocketchat-lib/server/models/Users.coffee b/packages/rocketchat-lib/server/models/Users.coffee index f5c6a201f3c1..8eef5f4ab515 100644 --- a/packages/rocketchat-lib/server/models/Users.coffee +++ b/packages/rocketchat-lib/server/models/Users.coffee @@ -109,7 +109,7 @@ class ModelUsers extends RocketChat.models._Base return @find query, options - findByActiveUsersUsernameExcept: (searchTerm, exceptions = [], options = {}) -> + findByActiveUsersExcept: (searchTerm, exceptions = [], options = {}) -> if not _.isArray exceptions exceptions = [ exceptions ] @@ -118,7 +118,14 @@ class ModelUsers extends RocketChat.models._Base $and: [ { active: true - username: termRegex + $or: [ + { + username: termRegex + } + { + name: termRegex + } + ] } { username: { $nin: exceptions } diff --git a/packages/rocketchat-lib/server/startup/settings.coffee b/packages/rocketchat-lib/server/startup/settings.coffee index 76d858f7b4a7..4c817e5c012f 100644 --- a/packages/rocketchat-lib/server/startup/settings.coffee +++ b/packages/rocketchat-lib/server/startup/settings.coffee @@ -263,6 +263,7 @@ RocketChat.settings.addGroup 'Layout', -> @add 'UI_DisplayRoles', true, { type: 'boolean', public: true } @add 'UI_Merge_Channels_Groups', true, { type: 'boolean', public: true } @add 'UI_Use_Name_Avatar', false, { type: 'boolean', public: true } + @add 'UI_Use_Real_Name', false, { type: 'boolean', public: true } RocketChat.settings.addGroup 'Logs', -> diff --git a/packages/rocketchat-lib/startup/defaultRoomTypes.js b/packages/rocketchat-lib/startup/defaultRoomTypes.js index 2826e4a99c48..400c31fc6924 100644 --- a/packages/rocketchat-lib/startup/defaultRoomTypes.js +++ b/packages/rocketchat-lib/startup/defaultRoomTypes.js @@ -25,7 +25,7 @@ RocketChat.roomTypes.add('c', 10, { }, roomName(roomData) { - return roomData.name; + return { name: roomData.name }; }, condition() { @@ -64,8 +64,7 @@ RocketChat.roomTypes.add('d', 20, { }, roomName(roomData) { - const room = ChatSubscription.findOne({ rid: roomData._id }, { fields: { name: 1 } }); - return room && room.name; + return ChatSubscription.findOne({ rid: roomData._id }, { fields: { name: 1, fname: 1 } }); }, condition() { @@ -100,7 +99,7 @@ RocketChat.roomTypes.add('p', 30, { }, roomName(roomData) { - return roomData.name; + return { name: roomData.name }; }, condition() { diff --git a/packages/rocketchat-livechat/server/lib/Livechat.js b/packages/rocketchat-livechat/server/lib/Livechat.js index d5801811af2e..aa9200a1ac9c 100644 --- a/packages/rocketchat-livechat/server/lib/Livechat.js +++ b/packages/rocketchat-livechat/server/lib/Livechat.js @@ -116,7 +116,6 @@ RocketChat.Livechat = { userId = existingUser._id; } else { - updateUser.$set.name = name; const userData = { username, @@ -156,6 +155,10 @@ RocketChat.Livechat = { ]; } + if (name) { + RocketChat._setRealName(userId, name); + } + Meteor.users.update(userId, updateUser); return userId; diff --git a/packages/rocketchat-theme/client/imports/base.less b/packages/rocketchat-theme/client/imports/base.less index 334cd74107da..2210ab1f2102 100644 --- a/packages/rocketchat-theme/client/imports/base.less +++ b/packages/rocketchat-theme/client/imports/base.less @@ -2515,6 +2515,11 @@ label.required::after { display: inline-block; } } + + .secondary-name { + color: #666666; + font-size: 15px; + } } .message-popup-position { diff --git a/packages/rocketchat-ui-flextab/client/tabs/membersList.html b/packages/rocketchat-ui-flextab/client/tabs/membersList.html index 4f1675dead84..1c455ab3700d 100644 --- a/packages/rocketchat-ui-flextab/client/tabs/membersList.html +++ b/packages/rocketchat-ui-flextab/client/tabs/membersList.html @@ -30,9 +30,9 @@

{{_ "Members_List"}}

{{else}} {{#each users}}
  • - {{/if}} {{/if}} - {{#if alias}} - - {{else}} - - {{/if}} + {{#each roleTags}} {{description}} diff --git a/packages/rocketchat-ui-message/client/popup/messagePopupConfig.coffee b/packages/rocketchat-ui-message/client/popup/messagePopupConfig.coffee index 3cf38b4ffc67..a5bc17cc33fc 100644 --- a/packages/rocketchat-ui-message/client/popup/messagePopupConfig.coffee +++ b/packages/rocketchat-ui-message/client/popup/messagePopupConfig.coffee @@ -6,7 +6,7 @@ Meteor.startup -> return filteredUsersMemory.remove({}) - messageUsers = RocketChat.models.Messages.find({rid: Session.get('openedRoom'), 'u.username': {$ne: Meteor.user().username}}, {fields: {'u.username': 1, ts: 1}, sort: {ts: -1}}).fetch() + messageUsers = RocketChat.models.Messages.find({rid: Session.get('openedRoom'), 'u.username': {$ne: Meteor.user().username}}, {fields: {'u.username': 1, 'u.name': 1, ts: 1}, sort: {ts: -1}}).fetch() uniqueMessageUsersControl = {} messageUsers.forEach (messageUser) -> if not uniqueMessageUsersControl[messageUser.u.username]? @@ -14,6 +14,7 @@ Meteor.startup -> filteredUsersMemory.upsert messageUser.u.username, _id: messageUser.u.username username: messageUser.u.username + name: messageUser.u.name status: Session.get('user_' + messageUser.u.username + '_status') or 'offline' ts: messageUser.ts @@ -70,15 +71,16 @@ Template.messagePopupConfig.helpers exp = new RegExp("#{RegExp.escape filter}", 'i') # Get users from messages - items = filteredUsersMemory.find({ts: {$exists: true}, username: exp}, {limit: 5, sort: {ts: -1}}).fetch() + items = filteredUsersMemory.find({ts: {$exists: true}, $or: [{username: exp}, {name: exp}]}, {limit: 5, sort: {ts: -1}}).fetch() # Get online users if items.length < 5 and filter?.trim() isnt '' messageUsers = _.pluck(items, 'username') - Meteor.users.find({$and: [{username: exp}, {username: {$nin: [Meteor.user()?.username].concat(messageUsers)}}]}, {limit: 5 - messageUsers.length}).fetch().forEach (item) -> + Meteor.users.find({$and: [{$or:[{username: exp}, {name: exp}]}, {username: {$nin: [Meteor.user()?.username].concat(messageUsers)}}]}, {limit: 5 - messageUsers.length}).fetch().forEach (item) -> items.push _id: item.username username: item.username + name: item.name status: item.status sort: 1 diff --git a/packages/rocketchat-ui-sidenav/client/accountBox.html b/packages/rocketchat-ui-sidenav/client/accountBox.html index 61282239834d..f7151a3442a0 100644 --- a/packages/rocketchat-ui-sidenav/client/accountBox.html +++ b/packages/rocketchat-ui-sidenav/client/accountBox.html @@ -7,7 +7,7 @@ {{> avatar username=username}}
    -

    {{username}}

    +

    {{fname}}

    {{/if}} diff --git a/packages/rocketchat-ui-sidenav/client/accountBox.js b/packages/rocketchat-ui-sidenav/client/accountBox.js index 8ba0b4cfe51b..e5e4c2f6acf6 100644 --- a/packages/rocketchat-ui-sidenav/client/accountBox.js +++ b/packages/rocketchat-ui-sidenav/client/accountBox.js @@ -1,7 +1,8 @@ Template.accountBox.helpers({ myUserInfo() { let visualStatus = 'online'; - const username = Meteor.user() && Meteor.user().username; + const user = Meteor.user() || {}; + const { name, username } = user; switch (Session.get(`user_${ username }_status`)) { case 'away': visualStatus = t('away'); @@ -18,7 +19,8 @@ Template.accountBox.helpers({ status: Session.get(`user_${ username }_status`), visualStatus, _id: Meteor.userId(), - username + username, + fname: name }; }, diff --git a/packages/rocketchat-ui-sidenav/client/chatRoomItem.js b/packages/rocketchat-ui-sidenav/client/chatRoomItem.js index 96844128dfd7..27b481805bd9 100644 --- a/packages/rocketchat-ui-sidenav/client/chatRoomItem.js +++ b/packages/rocketchat-ui-sidenav/client/chatRoomItem.js @@ -20,6 +20,10 @@ Template.chatRoomItem.helpers({ }, name() { + if (RocketChat.settings.get('UI_Use_Real_Name') && this.fname) { + return this.fname; + } + return this.name; }, diff --git a/packages/rocketchat-ui-sidenav/client/toolbar.html b/packages/rocketchat-ui-sidenav/client/toolbar.html index 4a215c556787..2f2449517463 100644 --- a/packages/rocketchat-ui-sidenav/client/toolbar.html +++ b/packages/rocketchat-ui-sidenav/client/toolbar.html @@ -19,7 +19,7 @@