diff --git a/framework/core/js/src/admin/components/PermissionGrid.js b/framework/core/js/src/admin/components/PermissionGrid.js index 62fa0fc1b..fb05ceb32 100644 --- a/framework/core/js/src/admin/components/PermissionGrid.js +++ b/framework/core/js/src/admin/components/PermissionGrid.js @@ -327,9 +327,29 @@ export default class PermissionGrid extends Component { ); items.add( - 'userEdit', + 'userEditCredentials', { icon: 'fas fa-user-cog', + label: app.translator.trans('core.admin.permissions.edit_users_credentials_label'), + permission: 'user.editCredentials', + }, + 60 + ); + + items.add( + 'userEditGroups', + { + icon: 'fas fa-users-cog', + label: app.translator.trans('core.admin.permissions.edit_users_groups_label'), + permission: 'user.editGroups', + }, + 60 + ); + + items.add( + 'userEdit', + { + icon: 'fas fa-address-card', label: app.translator.trans('core.admin.permissions.edit_users_label'), permission: 'user.edit', }, diff --git a/framework/core/js/src/common/models/User.js b/framework/core/js/src/common/models/User.js index 30bc0567b..42cbf673b 100644 --- a/framework/core/js/src/common/models/User.js +++ b/framework/core/js/src/common/models/User.js @@ -30,6 +30,8 @@ Object.assign(User.prototype, { commentCount: Model.attribute('commentCount'), canEdit: Model.attribute('canEdit'), + canEditCredentials: Model.attribute('canEditCredentials'), + canEditGroups: Model.attribute('canEditGroups'), canDelete: Model.attribute('canDelete'), avatarColor: null, diff --git a/framework/core/js/src/forum/components/EditUserModal.js b/framework/core/js/src/forum/components/EditUserModal.js index ad48261e4..9287f0f01 100644 --- a/framework/core/js/src/forum/components/EditUserModal.js +++ b/framework/core/js/src/forum/components/EditUserModal.js @@ -37,9 +37,10 @@ export default class EditUserModal extends Modal { } content() { + const fields = this.fields().toArray(); return (
-
{this.fields().toArray()}
+ {fields.length > 1 ?
{this.fields().toArray()}
: app.translator.trans('core.forum.edit_user.nothing_available')}
); } @@ -47,96 +48,112 @@ export default class EditUserModal extends Modal { fields() { const items = new ItemList(); - items.add( - 'username', -
- - -
, - 40 - ); - - if (app.session.user !== this.attrs.user) { + if (app.session.user.canEditCredentials()) { items.add( - 'email', + 'username',
- -
- -
- {!this.isEmailConfirmed() ? ( -
- {Button.component( - { - className: 'Button Button--block', - loading: this.loading, - onclick: this.activate.bind(this), - }, - app.translator.trans('core.forum.edit_user.activate_button') - )} -
- ) : ( - '' - )} + +
, - 30 + 40 ); - items.add( - 'password', -
- -
- - {this.setPassword() ? ( + if (app.session.user !== this.attrs.user) { + items.add( + 'email', +
+ +
+
+ {!this.isEmailConfirmed() && this.userIsAdmin(app.session.user) ? ( +
+ {Button.component( + { + className: 'Button Button--block', + loading: this.loading, + onclick: this.activate.bind(this), + }, + app.translator.trans('core.forum.edit_user.activate_button') + )} +
) : ( '' )} -
-
, - 20 - ); - } +
, + 30 + ); - items.add( - 'groups', -
- -
- {Object.keys(this.groups) - .map((id) => app.store.getById('groups', id)) - .map((group) => ( + items.add( + 'password', +
+ +
- ))} -
-
, - 10 - ); + {this.setPassword() ? ( + + ) : ( + '' + )} +
+
, + 20 + ); + } + } + + if (app.session.user.canEditGroups()) { + items.add( + 'groups', +
+ +
+ {Object.keys(this.groups) + .map((id) => app.store.getById('groups', id)) + .map((group) => ( + + ))} +
+
, + 10 + ); + } items.add( 'submit', @@ -176,21 +193,26 @@ export default class EditUserModal extends Modal { } data() { - const groups = Object.keys(this.groups) - .filter((id) => this.groups[id]()) - .map((id) => app.store.getById('groups', id)); - const data = { - username: this.username(), - relationships: { groups }, + relationships: {}, }; - if (app.session.user !== this.attrs.user) { - data.email = this.email(); + if (this.attrs.user.canEditCredentials() && !this.nonAdminEditingAdmin()) { + data.username = this.username(); + + if (app.session.user !== this.attrs.user) { + data.email = this.email(); + } + + if (this.setPassword()) { + data.password = this.password(); + } } - if (this.setPassword()) { - data.password = this.password(); + if (this.attrs.user.canEditGroups()) { + data.relationships.groups = Object.keys(this.groups) + .filter((id) => this.groups[id]()) + .map((id) => app.store.getById('groups', id)); } return data; @@ -209,4 +231,15 @@ export default class EditUserModal extends Modal { m.redraw(); }); } + + nonAdminEditingAdmin() { + return this.userIsAdmin(this.attrs.user) && !this.userIsAdmin(app.session.user); + } + + /** + * @internal @protected + */ + userIsAdmin(user) { + return user.groups().some((g) => g.id() === Group.ADMINISTRATOR_ID); + } } diff --git a/framework/core/js/src/forum/utils/UserControls.js b/framework/core/js/src/forum/utils/UserControls.js index b0aaedf41..8841df6a4 100644 --- a/framework/core/js/src/forum/utils/UserControls.js +++ b/framework/core/js/src/forum/utils/UserControls.js @@ -57,7 +57,7 @@ export default { moderationControls(user) { const items = new ItemList(); - if (user.canEdit()) { + if (user.canEdit() || user.canEditCredentials() || user.canEditGroups()) { items.add( 'edit',