diff --git a/app/authorization/server/startup.js b/app/authorization/server/startup.js index d79acd6d8706..0ec0476ec9de 100644 --- a/app/authorization/server/startup.js +++ b/app/authorization/server/startup.js @@ -35,6 +35,7 @@ Meteor.startup(function() { { _id: 'edit-other-user-active-status', roles : ['admin'] }, { _id: 'edit-other-user-info', roles : ['admin'] }, { _id: 'edit-other-user-password', roles : ['admin'] }, + { _id: 'edit-other-user-avatar', roles : ['admin'] }, { _id: 'edit-privileged-setting', roles : ['admin'] }, { _id: 'edit-room', roles : ['admin', 'owner', 'moderator'] }, { _id: 'edit-room-retention-policy', roles : ['admin'] }, diff --git a/app/ui-flextab/client/tabs/userEdit.js b/app/ui-flextab/client/tabs/userEdit.js index 8d2104ac2c03..597f7599e251 100644 --- a/app/ui-flextab/client/tabs/userEdit.js +++ b/app/ui-flextab/client/tabs/userEdit.js @@ -67,7 +67,7 @@ Template.userEdit.helpers({ Template.userEdit.events({ 'click .js-select-avatar-initials'() { - Meteor.call('resetAvatarAdmin', Template.instance().user, function(err) { + Meteor.call('resetAvatar', Template.instance().user._id, function(err) { if (err && err.details) { toastr.error(t(err.message)); } else { @@ -254,13 +254,7 @@ Template.userEdit.onCreated(function() { } if (avatar) { - const params = [avatar.blob]; - - params.push(avatar.contentType); - - params.push(avatar.service); - params.push(Template.instance().user); - Meteor.call('setAvatarFromServiceAdmin', ...params, function(err) { + Meteor.call('setAvatarFromService', avatar.blob, avatar.contentType, avatar.service, Template.instance().user._id, function(err) { if (err && err.details) { toastr.error(t(err.message)); } else { diff --git a/packages/rocketchat-i18n/i18n/en.i18n.json b/packages/rocketchat-i18n/i18n/en.i18n.json index 6a8c2027ec50..d33628376c3f 100644 --- a/packages/rocketchat-i18n/i18n/en.i18n.json +++ b/packages/rocketchat-i18n/i18n/en.i18n.json @@ -1089,6 +1089,8 @@ "edit-message_description": "Permission to edit a message within a room", "edit-other-user-active-status": "Edit Other User Active Status", "edit-other-user-active-status_description": "Permission to enable or disable other accounts", + "edit-other-user-avatar": "Edit Other User Avatar", + "edit-other-user-avatar_description": "Permission to change other user's avatar.", "edit-other-user-info": "Edit Other User Information", "edit-other-user-info_description": "Permission to change other user's name, username or email address.", "edit-other-user-password": "Edit Other User Password", diff --git a/server/methods/resetAvatar.js b/server/methods/resetAvatar.js index 2adf488810f4..b56b26f21537 100644 --- a/server/methods/resetAvatar.js +++ b/server/methods/resetAvatar.js @@ -1,12 +1,13 @@ import { Meteor } from 'meteor/meteor'; import { DDPRateLimiter } from 'meteor/ddp-rate-limiter'; import { FileUpload } from '../../app/file-upload'; -import { Users } from '../../app/models'; +import { Users } from '../../app/models/server'; import { settings } from '../../app/settings'; import { Notifications } from '../../app/notifications'; +import { hasPermission } from '../../app/authorization/server'; Meteor.methods({ - resetAvatar() { + resetAvatar({ userId }) { if (!Meteor.userId()) { throw new Meteor.Error('error-invalid-user', 'Invalid user', { method: 'resetAvatar', @@ -19,30 +20,30 @@ Meteor.methods({ }); } - const user = Meteor.user(); - FileUpload.getStore('Avatars').deleteByName(user.username); - Users.unsetAvatarOrigin(user._id); - Notifications.notifyLogged('updateAvatar', { - username: user.username, - }); - }, - resetAvatarAdmin(args) { - if (!args) { - throw new Meteor.Error('error-invalid-user', 'Invalid user', { - method: 'resetAvatarAdmin', - }); + let user; + + if (userId) { + if (!hasPermission(userId, 'edit-other-user-avatar')) { + throw new Meteor.Error('error-unauthorized', 'Unauthorized', { + method: 'resetAvatar', + }); + } + + user = Users.findOneById(userId, { fields: { _id: 1, username: 1 } }); + } else { + user = Meteor.user(); } - if (!settings.get('Accounts_AllowUserAvatarChange')) { - throw new Meteor.Error('error-not-allowed', 'Not allowed', { - method: 'resetAvatarAdmin', + if (user == null) { + throw new Meteor.Error('error-invalid-desired-user', 'Invalid desired user', { + method: 'resetAvatar', }); } - FileUpload.getStore('Avatars').deleteByName(args.username); - Users.unsetAvatarOrigin(args._id); + FileUpload.getStore('Avatars').deleteByName(user.username); + Users.unsetAvatarOrigin(user._id); Notifications.notifyLogged('updateAvatar', { - username: args.username, + username: user.username, }); }, }); diff --git a/server/methods/setAvatarFromService.js b/server/methods/setAvatarFromService.js index 1066667fe580..8195af6fd557 100644 --- a/server/methods/setAvatarFromService.js +++ b/server/methods/setAvatarFromService.js @@ -3,12 +3,15 @@ import { Match, check } from 'meteor/check'; import { DDPRateLimiter } from 'meteor/ddp-rate-limiter'; import { settings } from '../../app/settings'; import { setUserAvatar } from '../../app/lib'; +import { Users } from '../../app/models/server'; +import { hasPermission } from '../../app/authorization/server'; Meteor.methods({ - setAvatarFromService(dataURI, contentType, service) { + setAvatarFromService(dataURI, contentType, service, userId) { check(dataURI, String); check(contentType, Match.Optional(String)); check(service, Match.Optional(String)); + check(userId, Match.Optional(String)); if (!Meteor.userId()) { throw new Meteor.Error('error-invalid-user', 'Invalid user', { @@ -22,29 +25,27 @@ Meteor.methods({ }); } - const user = Meteor.user(); + let user; - return setUserAvatar(user, dataURI, contentType, service); - }, - setAvatarFromServiceAdmin(dataURI, contentType, service, userData) { - check(dataURI, String); - check(contentType, Match.Optional(String)); - check(service, Match.Optional(String)); - check(userData, Match.Optional(Object)); + if (userId) { + if (!hasPermission(userId, 'edit-other-user-avatar')) { + throw new Meteor.Error('error-unauthorized', 'Unauthorized', { + method: 'setAvatarFromService', + }); + } - if (!userData) { - throw new Meteor.Error('error-invalid-user', 'Invalid user', { - method: 'setAvatarFromServiceAdmin', - }); + user = Users.findOneById(userId, { fields: { _id: 1, username: 1 } }); + } else { + user = Meteor.user(); } - if (!settings.get('Accounts_AllowUserAvatarChange')) { - throw new Meteor.Error('error-not-allowed', 'Not allowed', { - method: 'setAvatarFromServiceAdmin', + if (user == null) { + throw new Meteor.Error('error-invalid-desired-user', 'Invalid desired user', { + method: 'setAvatarFromService', }); } - return setUserAvatar(userData, dataURI, contentType, service); + return setUserAvatar(user, dataURI, contentType, service); }, });