diff --git a/addons/api/addon/abilities/group.js b/addons/api/addon/abilities/group.js
new file mode 100644
index 000000000..810cc82c2
--- /dev/null
+++ b/addons/api/addon/abilities/group.js
@@ -0,0 +1,22 @@
+import ModelAbility from './model';
+
+/**
+ * Provides abilities for groups.
+ */
+export default class GroupAbility extends ModelAbility {
+ // =permissions
+
+ /**
+ * @type {boolean}
+ */
+ get canAddMembers() {
+ return this.hasAuthorizedAction('add-members');
+ }
+
+ /**
+ * @type {boolean}
+ */
+ get canRemoveMembers() {
+ return this.hasAuthorizedAction('remove-members');
+ }
+}
diff --git a/addons/api/app/abilities/group.js b/addons/api/app/abilities/group.js
new file mode 100644
index 000000000..308aacba4
--- /dev/null
+++ b/addons/api/app/abilities/group.js
@@ -0,0 +1 @@
+export { default } from 'api/abilities/group';
diff --git a/addons/api/mirage/factories/group.js b/addons/api/mirage/factories/group.js
index 1f7256543..6a16d3fb0 100644
--- a/addons/api/mirage/factories/group.js
+++ b/addons/api/mirage/factories/group.js
@@ -9,6 +9,8 @@ export default factory.extend({
'read',
'update',
'delete',
+ 'add-members',
+ 'remove-members',
],
id: (i) => `group-${i}`,
diff --git a/addons/api/tests/unit/abilities/group-test.js b/addons/api/tests/unit/abilities/group-test.js
new file mode 100644
index 000000000..a53be03c2
--- /dev/null
+++ b/addons/api/tests/unit/abilities/group-test.js
@@ -0,0 +1,28 @@
+import { module, test } from 'qunit';
+import { setupTest } from 'ember-qunit';
+
+module('Unit | Abilities | Group', function (hooks) {
+ setupTest(hooks);
+
+ test('it reflects when a given group resource may add members based on authorized_actions', function (assert) {
+ assert.expect(2);
+ const service = this.owner.lookup('service:can');
+ const model = {
+ authorized_actions: ['add-members'],
+ };
+ assert.ok(service.can('addMembers group', model));
+ model.authorized_actions = [];
+ assert.notOk(service.can('addMembers group', model));
+ });
+
+ test('it reflects when a given group resource may remove members based on authorized_actions', function (assert) {
+ assert.expect(2);
+ const service = this.owner.lookup('service:can');
+ const model = {
+ authorized_actions: ['remove-members'],
+ };
+ assert.ok(service.can('removeMembers group', model));
+ model.authorized_actions = [];
+ assert.notOk(service.can('removeMembers group', model));
+ });
+});
diff --git a/addons/api/tests/unit/abilities/role-test.js b/addons/api/tests/unit/abilities/role-test.js
index fc927c92a..462743446 100644
--- a/addons/api/tests/unit/abilities/role-test.js
+++ b/addons/api/tests/unit/abilities/role-test.js
@@ -1,7 +1,7 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
-module('Unit | Abilities | Account', function (hooks) {
+module('Unit | Abilities | Role', function (hooks) {
setupTest(hooks);
test('it reflects when a given role may set grants based on authorized_actions', function (assert) {
diff --git a/addons/api/tests/unit/abilities/user-test.js b/addons/api/tests/unit/abilities/user-test.js
index 23c60ac82..33d8f78e7 100644
--- a/addons/api/tests/unit/abilities/user-test.js
+++ b/addons/api/tests/unit/abilities/user-test.js
@@ -1,7 +1,7 @@
import { module, test } from 'qunit';
import { setupTest } from 'ember-qunit';
-module('Unit | Abilities | Account', function (hooks) {
+module('Unit | Abilities | User', function (hooks) {
setupTest(hooks);
test('it reflects when a given user resource may add accounts based on authorized_actions', function (assert) {
diff --git a/ui/admin/app/templates/scopes/scope/groups/group/-actions.hbs b/ui/admin/app/templates/scopes/scope/groups/group/-actions.hbs
index 253b39ab0..7dbbf977b 100644
--- a/ui/admin/app/templates/scopes/scope/groups/group/-actions.hbs
+++ b/ui/admin/app/templates/scopes/scope/groups/group/-actions.hbs
@@ -3,9 +3,11 @@
@dropdownRight={{true}}
as |dropdown|
>
-
- {{t 'resources.group.actions.add-members'}}
-
+ {{#if (can 'addMembers group' @model)}}
+
+ {{t 'resources.group.actions.add-members'}}
+
+ {{/if}}
{{#if (can 'delete model' @model)}}
-
-
- {{t 'actions.remove'}}
-
-
+
+ {{t 'actions.remove'}}
+
+
+ {{/if}}
{{/each}}
diff --git a/ui/admin/tests/acceptance/groups/members-test.js b/ui/admin/tests/acceptance/groups/members-test.js
index 2d615b8ba..295db8404 100644
--- a/ui/admin/tests/acceptance/groups/members-test.js
+++ b/ui/admin/tests/acceptance/groups/members-test.js
@@ -68,6 +68,16 @@ module('Acceptance | groups | members', function (hooks) {
assert.equal(findAll('tbody tr').length, membersCount - 1);
});
+ test('cannot remove a member without proper authorization', async function (assert) {
+ assert.expect(1);
+ const authorized_actions = instances.group.authorized_actions.filter(
+ (item) => item !== 'remove-members'
+ );
+ instances.group.update({ authorized_actions });
+ await visit(urls.members);
+ assert.notOk(find('tbody tr .rose-dropdown-button-danger'));
+ });
+
test('shows error message on member remove', async function (assert) {
assert.expect(2);
this.server.post('/groups/:idMethod', () => {
@@ -95,6 +105,22 @@ module('Acceptance | groups | members', function (hooks) {
assert.equal(currentURL(), urls.addMembers);
});
+ test('can navigate to add members with proper authorization', async function (assert) {
+ assert.expect(1);
+ await visit(urls.group);
+ assert.ok(find(`[href="${urls.addMembers}"]`));
+ });
+
+ test('cannot navigate to add members without proper authorization', async function (assert) {
+ assert.expect(1);
+ const authorized_actions = instances.group.authorized_actions.filter(
+ (item) => item !== 'add-members'
+ );
+ instances.group.update({ authorized_actions });
+ await visit(urls.group);
+ assert.notOk(find(`[href="${urls.addMembers}"]`));
+ });
+
test('select and save members to add', async function (assert) {
assert.expect(3);
instances.group.update({ memberIds: [] });
diff --git a/ui/admin/tests/acceptance/users/accounts-test.js b/ui/admin/tests/acceptance/users/accounts-test.js
index 01bd014e1..fe556f84a 100644
--- a/ui/admin/tests/acceptance/users/accounts-test.js
+++ b/ui/admin/tests/acceptance/users/accounts-test.js
@@ -107,7 +107,7 @@ module('Acceptance | users | accounts', function (hooks) {
assert.equal(currentURL(), urls.addAccounts);
});
- test('can navigate to add accounts without proper authorization', async function (assert) {
+ test('can navigate to add accounts with proper authorization', async function (assert) {
assert.expect(1);
await visit(urls.accounts);
assert.ok(find(`[href="${urls.addAccounts}"]`));