diff --git a/packages/rocketchat-authorization/server/startup.js b/packages/rocketchat-authorization/server/startup.js index d372b117ba03..bd1ea3ff6e44 100644 --- a/packages/rocketchat-authorization/server/startup.js +++ b/packages/rocketchat-authorization/server/startup.js @@ -63,7 +63,8 @@ Meteor.startup(function() { { _id: 'view-room-administration', roles : ['admin'] }, { _id: 'view-statistics', roles : ['admin'] }, { _id: 'view-user-administration', roles : ['admin'] }, - { _id: 'preview-c-room', roles : ['admin', 'user', 'anonymous'] } + { _id: 'preview-c-room', roles : ['admin', 'user', 'anonymous'] }, + { _id: 'view-outside-room', roles : ['admin', 'owner', 'moderator', 'user'] } ]; for (const permission of permissions) { diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index a4a88674a23e..1b59eed80ced 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1328,6 +1328,7 @@ "view-privileged-setting": "View Privileged Setting", "view-privileged-setting_description": "Permission to view settings", "view-other-user-channels": "View Other User Channels", + "view-outside-room": "View Outside Room", "view-other-user-channels_description": "Permission to view channels owned by other users", "view-room-administration": "View Room Administration", "view-room-administration_description": "Permission to view public, private and direct message statistics. Does not include the ability to view conversations or archives", diff --git a/packages/rocketchat-ui-flextab/client/app.js b/packages/rocketchat-ui-flextab/client/app.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/packages/rocketchat-ui-message/client/popup/messagePopupConfig.js b/packages/rocketchat-ui-message/client/popup/messagePopupConfig.js index 4293d3e1c90c..cff8543cabff 100644 --- a/packages/rocketchat-ui-message/client/popup/messagePopupConfig.js +++ b/packages/rocketchat-ui-message/client/popup/messagePopupConfig.js @@ -38,11 +38,11 @@ Meteor.startup(function() { }); }); -const getUsersFromServer = (filter, records, cb) => { +const getUsersFromServer = (filter, records, cb, rid) => { const messageUsers = _.pluck(records, 'username'); return Meteor.call('spotlight', filter, messageUsers, { users: true - }, function(err, results) { + }, rid, function(err, results) { if (err != null) { return console.error(err); } @@ -63,10 +63,13 @@ const getUsersFromServer = (filter, records, cb) => { }); }; -const getRoomsFromServer = (filter, records, cb) => { +const getRoomsFromServer = (filter, records, cb, rid) => { + if (!RocketChat.authz.hasAllPermission('view-outside-room')) { + return cb([]); + } return Meteor.call('spotlight', filter, null, { rooms: true - }, function(err, results) { + }, rid, function(err, results) { if (err != null) { return console.error(err); } @@ -120,37 +123,42 @@ Template.messagePopupConfig.helpers({ if (items.length < 5 && filter && filter.trim() !== '') { const messageUsers = _.pluck(items, 'username'); const user = Meteor.user(); - items.push(...Meteor.users.find({ - $and: [ - { - $or: [ - { - username: exp - }, { - name: exp + if (!RocketChat.authz.hasAllPermission('view-outside-room')) { + const usernames = RocketChat.models.Subscriptions.find({$or :[{'name': exp}, { fname: exp}]}).fetch().map(({name}) =>name); + items.push(... + RocketChat.models.Users.find({username:{$in:usernames}}, {fields:{ + username: 1, + name: 1, + status: 1 + }}, { + limit: 5 - messageUsers.length + }).fetch().map(({username, name, status}) => ({ _id: username, username, name, status, sort: 1 })) + ); + } else { + items.push(...Meteor.users.find({ + $and: [ + { + $or: [ + { + username: exp + }, { + name: exp + } + ] + }, { + username: { + $nin: [(user && user.username), ...messageUsers] } - ] - }, { - username: { - $nin: [(user && user.username), ...messageUsers] } - } - ] - }, { - limit: 5 - messageUsers.length - }).fetch().map(function(item) { - return { - _id: item.username, - username: item.username, - name: item.name, - status: item.status, - sort: 1 - }; - })); + ] + }, { + limit: 5 - messageUsers.length + }).fetch().map(({username, name, status}) => ({ _id: username, username, name, status, sort: 1 }))); + } } // Get users from db if (items.length < 5 && filter && filter.trim() !== '') { - getUsersFromServerDelayed(filter, items, cb); + getUsersFromServerDelayed(filter, items, cb, RocketChat.openedRoom); } const all = { _id: 'all', @@ -207,7 +215,7 @@ Template.messagePopupConfig.helpers({ }).fetch(); if (records.length < 5 && filter && filter.trim() !== '') { - getRoomsFromServerDelayed(filter, records, cb); + getRoomsFromServerDelayed(filter, records, cb, RocketChat.openedRoom); } return records; }, diff --git a/server/publications/spotlight.js b/server/publications/spotlight.js index babbe04290c0..8f5b0cfa287b 100644 --- a/server/publications/spotlight.js +++ b/server/publications/spotlight.js @@ -1,10 +1,10 @@ Meteor.methods({ - spotlight(text, usernames, type = {users: true, rooms: true}) { + spotlight(text, usernames, type = {users: true, rooms: true}, rid) { + const regex = new RegExp(s.trim(s.escapeRegExp(text)), 'i'); const result = { users: [], rooms: [] }; - const roomOptions = { limit: 5, fields: { @@ -15,43 +15,48 @@ Meteor.methods({ name: 1 } }; - - const regex = new RegExp(s.trim(s.escapeRegExp(text)), 'i'); - - if (this.userId == null) { + const userId = this.userId; + if (userId == null) { if (RocketChat.settings.get('Accounts_AllowAnonymousRead') === true) { result.rooms = RocketChat.models.Rooms.findByNameAndTypeNotDefault(regex, 'c', roomOptions).fetch(); } return result; } + const userOptions = { + limit: 5, + fields: { + username: 1, + name: 1, + status: 1 + }, + sort: {} + }; + if (RocketChat.settings.get('UI_Use_Real_Name')) { + userOptions.sort.name = 1; + } else { + userOptions.sort.username = 1; + } - if (type.users === true && RocketChat.authz.hasPermission(this.userId, 'view-d-room')) { - const userOptions = { - limit: 5, - fields: { - username: 1, - name: 1, - status: 1 - }, - sort: {} - }; - - if (RocketChat.settings.get('UI_Use_Real_Name')) { - userOptions.sort.name = 1; - } else { - userOptions.sort.username = 1; + if (RocketChat.authz.hasPermission(userId, 'view-outside-room')) { + if (type.users === true && RocketChat.authz.hasPermission(userId, 'view-d-room')) { + result.users = RocketChat.models.Users.findByActiveUsersExcept(text, usernames, userOptions).fetch(); } - result.users = RocketChat.models.Users.findByActiveUsersExcept(text, usernames, userOptions).fetch(); - } + if (type.rooms === true && RocketChat.authz.hasPermission(userId, 'view-c-room')) { + const username = RocketChat.models.Users.findOneById(userId, { + username: 1 + }).username; - if (type.rooms === true && RocketChat.authz.hasPermission(this.userId, 'view-c-room')) { - const username = RocketChat.models.Users.findOneById(this.userId, { - username: 1 - }).username; - - result.rooms = RocketChat.models.Rooms.findByNameAndTypeNotContainingUsername(regex, 'c', username, roomOptions).fetch(); + result.rooms = RocketChat.models.Rooms.findByNameAndTypeNotContainingUsername(regex, 'c', username, roomOptions).fetch(); + } + } else if (type.users === true && rid) { + const subscriptions = RocketChat.models.Subscriptions.find({rid, 'u.username':{ + $regex: regex, + $nin:[...usernames, Meteor.user().username] + }}, {limit:userOptions.limit}).fetch().map(({u}) => u._id); + result.users = RocketChat.models.Users.find({_id:{$in:subscriptions}}, {fields:userOptions.fields, sort: userOptions.sort}).fetch(); } + return result; } });