diff --git a/addons/core/translations/actions/en-us.yaml b/addons/core/translations/actions/en-us.yaml index 97f396c438..5bd43c30d7 100644 --- a/addons/core/translations/actions/en-us.yaml +++ b/addons/core/translations/actions/en-us.yaml @@ -23,6 +23,7 @@ retry: Retry play: Play pause: Pause resume: Resume +export: Export get-topic-help: Get help for this topic copy-to-clipboard: Copy to Clipboard copy-error-detail-to-clipboard: Copy error detail to clipboard diff --git a/addons/core/translations/resources/en-us.yaml b/addons/core/translations/resources/en-us.yaml index 61043b6c8f..d7f673b19d 100644 --- a/addons/core/translations/resources/en-us.yaml +++ b/addons/core/translations/resources/en-us.yaml @@ -660,6 +660,9 @@ role: read-only-user: name: Read-Only User description: Can view but not modify any resources + edit-grants: + title: Edit Grants + description: Modify existing grant strings or add new grant strings to this role. scope: title: Scope title_plural: Scopes diff --git a/ui/admin/app/components/form/role/edit-grants/index.hbs b/ui/admin/app/components/form/role/edit-grants/index.hbs new file mode 100644 index 0000000000..809766cb09 --- /dev/null +++ b/ui/admin/app/components/form/role/edit-grants/index.hbs @@ -0,0 +1,31 @@ +{{! + Copyright IBM Corp. 2021, 2026 + SPDX-License-Identifier: BUSL-1.1 +}} + + + {{! TODO: Add responsive options to @colspan once we upgrade to HDS v6.0.0}} + + + {{! TODO: Add grants code editor. }} + + + + {{! TODO: Add string options and actions. }} + + + + + <:actions> + + + + + + + + \ No newline at end of file diff --git a/ui/admin/app/components/roles/role/actions/index.hbs b/ui/admin/app/components/roles/role/actions/index.hbs index d9323602e2..c65403ea97 100644 --- a/ui/admin/app/components/roles/role/actions/index.hbs +++ b/ui/admin/app/components/roles/role/actions/index.hbs @@ -45,6 +45,12 @@ > {{t 'resources.role.grant-templates.actions.add-grant-templates'}} + + {{t 'resources.role.edit-grants.title'}} + {{/if}} {{#if perms.canDelete}} {{#if diff --git a/ui/admin/app/router.js b/ui/admin/app/router.js index e1fd337143..ad707865cd 100644 --- a/ui/admin/app/router.js +++ b/ui/admin/app/router.js @@ -58,6 +58,7 @@ Router.map(function () { this.route('manage-custom-scopes'); this.route('manage-org-projects', { path: ':org_id' }); }); + this.route('edit-grants'); }); this.route('new'); }); diff --git a/ui/admin/app/routes/scopes/scope/roles/role/edit-grants.js b/ui/admin/app/routes/scopes/scope/roles/role/edit-grants.js new file mode 100644 index 0000000000..74dc74dcb3 --- /dev/null +++ b/ui/admin/app/routes/scopes/scope/roles/role/edit-grants.js @@ -0,0 +1,8 @@ +/** + * Copyright IBM Corp. 2021, 2026 + * SPDX-License-Identifier: BUSL-1.1 + */ + +import Route from '@ember/routing/route'; + +export default class ScopesScopeRolesRoleEditGrantsRoute extends Route {} diff --git a/ui/admin/app/templates/scopes/scope/roles/role/edit-grants.hbs b/ui/admin/app/templates/scopes/scope/roles/role/edit-grants.hbs new file mode 100644 index 0000000000..b2ff25c2ab --- /dev/null +++ b/ui/admin/app/templates/scopes/scope/roles/role/edit-grants.hbs @@ -0,0 +1,34 @@ +{{! + Copyright IBM Corp. 2021, 2026 + SPDX-License-Identifier: BUSL-1.1 +}} + +{{page-title (t 'resources.role.edit-grants.title')}} + + + + + + + + + + + {{t 'resources.role.edit-grants.title'}} + {{! TODO: Add correct doc link once it's created}} + {{! }} + + + {{t 'resources.role.edit-grants.description'}} + + + + + + + + + \ No newline at end of file diff --git a/ui/admin/tests/acceptance/roles/edit-grants-test.js b/ui/admin/tests/acceptance/roles/edit-grants-test.js new file mode 100644 index 0000000000..d625f264af --- /dev/null +++ b/ui/admin/tests/acceptance/roles/edit-grants-test.js @@ -0,0 +1,79 @@ +/** + * Copyright IBM Corp. 2021, 2026 + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { visit, click, currentURL } from '@ember/test-helpers'; +import { setupApplicationTest } from 'admin/tests/helpers'; +import * as selectors from './selectors'; +import { setRunOptions } from 'ember-a11y-testing/test-support'; + +module('Acceptance | roles/edit grants', function (hooks) { + setupApplicationTest(hooks); + + const instances = { + scopes: { + global: null, + }, + role: null, + }; + + const urls = { + role: null, + editGrants: null, + }; + + hooks.beforeEach(async function () { + instances.scopes.global = this.server.schema.scopes.find('global'); + instances.role = this.server.create('role', { + scope: instances.scopes.global, + }); + urls.role = `/scopes/global/roles/${instances.role.id}`; + urls.editGrants = `${urls.role}/edit-grants`; + }); + + test('can navigate to edit grants for roles with proper authorization', async function (assert) { + setRunOptions({ + rules: { + 'color-contrast': { + // [ember-a11y-ignore]: axe rule "color-contrast" automatically ignored on 2026-02-27 + enabled: false, + }, + }, + }); + + await visit(urls.role); + + assert.true(instances.role.authorized_actions.includes('set-grants')); + + await click(selectors.MANAGE_DROPDOWN_ROLES); + await click(selectors.MANAGE_DROPDOWN_EDIT_GRANTS); + + assert.strictEqual(currentURL(), urls.editGrants); + }); + + test('cannot navigate to edit grants for roles without proper authorization', async function (assert) { + setRunOptions({ + rules: { + 'color-contrast': { + // [ember-a11y-ignore]: axe rule "color-contrast" automatically ignored on 2026-02-27 + enabled: false, + }, + }, + }); + + instances.role.authorized_actions = + instances.role.authorized_actions.filter( + (action) => action !== 'set-grants', + ); + await visit(urls.role); + + assert.false(instances.role.authorized_actions.includes('set-grants')); + + await click(selectors.MANAGE_DROPDOWN_ROLES); + + assert.dom(selectors.MANAGE_DROPDOWN_EDIT_GRANTS).doesNotExist(); + assert.strictEqual(currentURL(), urls.role); + }); +}); diff --git a/ui/admin/tests/acceptance/roles/selectors.js b/ui/admin/tests/acceptance/roles/selectors.js index 033c34aa26..dc50628e6d 100644 --- a/ui/admin/tests/acceptance/roles/selectors.js +++ b/ui/admin/tests/acceptance/roles/selectors.js @@ -16,6 +16,7 @@ export const MANAGE_DROPDOWN_ADD_PRINCIPALS = '[data-test-manage-role-principals]'; export const MANAGE_DROPDOWN_ADD_GRANT_TEMPLATES = '[data-test-manage-role-grant-templates]'; +export const MANAGE_DROPDOWN_EDIT_GRANTS = '[data-test-manage-dropdown-grants]'; export const ROLE_BADGE = (id) => `tbody [data-test-role-row="${id}"] td:nth-child(2) .hds-badge__text`; diff --git a/ui/admin/tests/unit/routes/scopes/scope/roles/role/edit-grants-test.js b/ui/admin/tests/unit/routes/scopes/scope/roles/role/edit-grants-test.js new file mode 100644 index 0000000000..d1bb72470b --- /dev/null +++ b/ui/admin/tests/unit/routes/scopes/scope/roles/role/edit-grants-test.js @@ -0,0 +1,16 @@ +/** + * Copyright IBM Corp. 2021, 2026 + * SPDX-License-Identifier: BUSL-1.1 + */ + +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Route | scopes/scope/roles/role/edit-grants', function (hooks) { + setupTest(hooks); + + test('it exists', function (assert) { + let route = this.owner.lookup('route:scopes/scope/roles/role/edit-grants'); + assert.ok(route); + }); +});