diff --git a/ui/admin/app/components/auth-methods/auth-method/actions/index.hbs b/ui/admin/app/components/auth-methods/auth-method/actions/index.hbs
index 60203da29..848f582c5 100644
--- a/ui/admin/app/components/auth-methods/auth-method/actions/index.hbs
+++ b/ui/admin/app/components/auth-methods/auth-method/actions/index.hbs
@@ -26,39 +26,54 @@
{{/each}}
{{/if}}
-
-
- {{#if @model.isPrimary}}
-
- {{t 'resources.auth-method.actions.remove-as-primary'}}
-
- {{else}}
-
- {{t 'resources.auth-method.actions.make-primary'}}
-
+{{#let
+ (hash
+ canCreateAccount=(can 'create model' @model collection='accounts')
+ canCreateManagedGroup=(can
+ 'create model' @model collection='managed-groups'
+ )
+ canDelete=(can 'delete auth-method' @model)
+ )
+ as |perms|
+}}
+ {{#if
+ (or perms.canCreateAccount perms.canCreateManagedGroup perms.canDelete)
+ }}
+
+
+ {{#if @model.isPrimary}}
+
+ {{t 'resources.auth-method.actions.remove-as-primary'}}
+
+ {{else}}
+
+ {{t 'resources.auth-method.actions.make-primary'}}
+
+ {{/if}}
+ {{#if perms.canCreateAccount}}
+
+ {{t 'resources.account.actions.create'}}
+
+ {{/if}}
+ {{#if perms.canCreateManagedGroup}}
+ {{#if (or @model.isOIDC @model.isLDAP)}}
+
+ {{t 'resources.managed-group.actions.create'}}
+
+ {{/if}}
+ {{/if}}
+ {{#if perms.canDelete}}
+
+
+ {{t 'resources.auth-method.actions.delete'}}
+
+ {{/if}}
+
{{/if}}
- {{#if (can 'create model' @model collection='accounts')}}
-
- {{t 'resources.account.actions.create'}}
-
- {{/if}}
- {{#if (can 'create model' @model collection='managed-groups')}}
- {{#if (or @model.isOIDC @model.isLDAP)}}
-
- {{t 'resources.managed-group.actions.create'}}
-
- {{/if}}
- {{/if}}
- {{#if (can 'delete auth-method' @model)}}
-
-
- {{t 'resources.auth-method.actions.delete'}}
-
- {{/if}}
-
\ No newline at end of file
+{{/let}}
\ No newline at end of file
diff --git a/ui/admin/app/components/credential-stores/credential-store/actions/index.hbs b/ui/admin/app/components/credential-stores/credential-store/actions/index.hbs
index d5e8a613f..45dab0c85 100644
--- a/ui/admin/app/components/credential-stores/credential-store/actions/index.hbs
+++ b/ui/admin/app/components/credential-stores/credential-store/actions/index.hbs
@@ -2,33 +2,63 @@
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: BUSL-1.1
}}
-
-
- {{#if (can 'create model' @model collection='credential-libraries')}}
-
- {{t 'resources.credential-library.actions.create'}}
-
+
+{{#let
+ (hash
+ canCreateCredLibraries=(can
+ 'create model' @model collection='credential-libraries'
+ )
+ canCreateCredentials=(can 'create model' @model collection='credentials')
+ canDelete=(can 'delete model' @model)
+ canEditWorkerFilter=(and (feature-flag 'worker-filter') @model.isVault)
+ )
+ as |perms|
+}}
+ {{#if
+ (or
+ perms.canCreateCredLibraries
+ perms.canCreateCredentials
+ perms.canEditWorkerFilter
+ perms.canDelete
+ )
+ }}
+
+
+ {{#if perms.canCreateCredLibraries}}
+
+ {{t 'resources.credential-library.actions.create'}}
+
+ {{/if}}
+ {{#if perms.canCreateCredentials}}
+
+ {{t 'resources.credential.actions.create'}}
+
+ {{/if}}
+ {{#if perms.canEditWorkerFilter}}
+
+ {{t 'actions.edit-worker-filter'}}
+
+ {{/if}}
+ {{#if perms.canDelete}}
+ {{#if
+ (or
+ perms.canCreateCredLibraries
+ perms.canCreateCredentials
+ perms.canEditWorkerFilter
+ )
+ }}
+
+ {{/if}}
+
+ {{t 'resources.credential-store.actions.delete'}}
+
+ {{/if}}
+
{{/if}}
- {{#if (can 'create model' @model collection='credentials')}}
-
- {{t 'resources.credential.actions.create'}}
-
- {{/if}}
- {{#if (and (feature-flag 'worker-filter') @model.isVault)}}
-
- {{t 'actions.edit-worker-filter'}}
-
- {{/if}}
- {{#if (can 'delete model' @model)}}
-
-
- {{t 'resources.credential-store.actions.delete'}}
-
- {{/if}}
-
\ No newline at end of file
+{{/let}}
\ No newline at end of file
diff --git a/ui/admin/app/components/groups/group/actions/index.hbs b/ui/admin/app/components/groups/group/actions/index.hbs
index 813094ec1..fcf07f61a 100644
--- a/ui/admin/app/components/groups/group/actions/index.hbs
+++ b/ui/admin/app/components/groups/group/actions/index.hbs
@@ -3,21 +3,33 @@
SPDX-License-Identifier: BUSL-1.1
}}
-
-
- {{#if (can 'addMembers group' @model)}}
-
- {{t 'resources.group.actions.add-members'}}
-
+{{#let
+ (hash
+ canAddMembers=(can 'addMembers group' @model)
+ canDelete=(can 'delete model' @model)
+ )
+ as |perms|
+}}
+ {{#if (or perms.canAddMembers perms.canDelete)}}
+
+
+ {{#if perms.canAddMembers}}
+
+ {{t 'resources.group.actions.add-members'}}
+
+ {{/if}}
+ {{#if perms.canDelete}}
+ {{#if perms.canAddMembers}}
+
+ {{/if}}
+
+ {{t 'resources.group.actions.delete'}}
+
+ {{/if}}
+
{{/if}}
- {{#if (can 'delete model' @model)}}
-
-
- {{t 'resources.group.actions.delete'}}
-
- {{/if}}
-
\ No newline at end of file
+{{/let}}
\ No newline at end of file
diff --git a/ui/admin/app/components/host-catalogs/host-catalog/actions/index.hbs b/ui/admin/app/components/host-catalogs/host-catalog/actions/index.hbs
index 61d85b43d..6c3bbdb53 100644
--- a/ui/admin/app/components/host-catalogs/host-catalog/actions/index.hbs
+++ b/ui/admin/app/components/host-catalogs/host-catalog/actions/index.hbs
@@ -3,28 +3,41 @@
SPDX-License-Identifier: BUSL-1.1
}}
-
-
- {{#if (can 'create model' @model collection='hosts')}}
-
- {{t 'resources.host.actions.create'}}
-
+{{#let
+ (hash
+ canCreateHosts=(can 'create model' @model collection='hosts')
+ canCreateHostSets=(can 'create model' @model collection='host-sets')
+ canDelete=(can 'delete model' @model)
+ )
+ as |perms|
+}}
+ {{#if (or perms.canCreateHosts perms.canCreateHostSets perms.canDelete)}}
+
+
+ {{#if perms.canCreateHosts}}
+
+ {{t 'resources.host.actions.create'}}
+
+ {{/if}}
+ {{#if perms.canCreateHostSets}}
+
+ {{t 'resources.host-set.actions.create'}}
+
+ {{/if}}
+ {{#if perms.canDelete}}
+ {{#if (or perms.canCreateHosts perms.canCreateHostSets)}}
+
+ {{/if}}
+
+ {{t 'resources.host-catalog.actions.delete'}}
+
+ {{/if}}
+
{{/if}}
- {{#if (can 'create model' @model collection='host-sets')}}
-
- {{t 'resources.host-set.actions.create'}}
-
- {{/if}}
- {{#if (can 'delete model' @model)}}
-
-
- {{t 'resources.host-catalog.actions.delete'}}
-
- {{/if}}
-
\ No newline at end of file
+{{/let}}
\ No newline at end of file
diff --git a/ui/admin/app/components/host-catalogs/host-catalog/host-sets/host-set/actions/index.hbs b/ui/admin/app/components/host-catalogs/host-catalog/host-sets/host-set/actions/index.hbs
index 651db1e08..3a0e5c91b 100644
--- a/ui/admin/app/components/host-catalogs/host-catalog/host-sets/host-set/actions/index.hbs
+++ b/ui/admin/app/components/host-catalogs/host-catalog/host-sets/host-set/actions/index.hbs
@@ -3,24 +3,36 @@
SPDX-License-Identifier: BUSL-1.1
}}
-
-
- {{#if (can 'addHosts hostSet' @model)}}
-
- {{t 'resources.host-set.actions.create-and-add-host'}}
-
-
- {{t 'resources.host-set.actions.add-hosts'}}
-
-
+{{#let
+ (hash
+ canAddHosts=(can 'addHosts hostSet' @model)
+ canDelete=(can 'delete model' @model)
+ )
+ as |perms|
+}}
+ {{#if (or perms.canAddHosts perms.canDelete)}}
+
+
+ {{#if perms.canAddHosts}}
+
+ {{t 'resources.host-set.actions.create-and-add-host'}}
+
+
+ {{t 'resources.host-set.actions.add-hosts'}}
+
+ {{/if}}
+ {{#if perms.canDelete}}
+ {{#if perms.canAddHosts}}
+
+ {{/if}}
+
+ {{t 'resources.host-set.actions.delete'}}
+
+ {{/if}}
+
{{/if}}
- {{#if (can 'delete model' @model)}}
-
- {{t 'resources.host-set.actions.delete'}}
-
- {{/if}}
-
\ No newline at end of file
+{{/let}}
\ 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 4be1034a3..84df4cf38 100644
--- a/ui/admin/app/components/roles/role/actions/index.hbs
+++ b/ui/admin/app/components/roles/role/actions/index.hbs
@@ -3,32 +3,45 @@
SPDX-License-Identifier: BUSL-1.1
}}
-
-
- {{#if (can 'addPrincipals role' @model)}}
-
- {{t 'resources.role.principal.actions.add-principals'}}
-
+{{#let
+ (hash
+ canAddPrincipals=(can 'addPrincipals role' @model)
+ canSetGrantScopes=(can 'setGrantScopes role' @model)
+ canDelete=(can 'delete model' @model)
+ )
+ as |perms|
+}}
+ {{#if (or perms.canAddPrincipals perms.canSetGrantScopes perms.canDelete)}}
+
+
+ {{#if perms.canAddPrincipals}}
+
+ {{t 'resources.role.principal.actions.add-principals'}}
+
+ {{/if}}
+ {{#if perms.canSetGrantScopes}}
+
+ {{t 'resources.role.scope.actions.manage-scopes'}}
+
+ {{/if}}
+ {{#if perms.canDelete}}
+ {{#if (or perms.canAddPrincipals perms.canSetGrantScopes)}}
+
+ {{/if}}
+
+ {{t 'resources.role.actions.delete'}}
+
+ {{/if}}
+
{{/if}}
- {{#if (can 'setGrantScopes role' @model)}}
-
- {{t 'resources.role.scope.actions.manage-scopes'}}
-
- {{/if}}
- {{#if (can 'delete model' @model)}}
-
-
- {{t 'resources.role.actions.delete'}}
-
- {{/if}}
-
\ No newline at end of file
+{{/let}}
\ No newline at end of file
diff --git a/ui/admin/app/components/targets/target/actions/index.hbs b/ui/admin/app/components/targets/target/actions/index.hbs
index 35479ed89..86ffaf42d 100644
--- a/ui/admin/app/components/targets/target/actions/index.hbs
+++ b/ui/admin/app/components/targets/target/actions/index.hbs
@@ -2,38 +2,68 @@
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: BUSL-1.1
}}
-
-
- {{#if (can 'addHostSources target' @model)}}
-
- {{t 'resources.target.actions.add-host-sources'}}
-
+
+{{#let
+ (hash
+ canAddHostSources=(can 'addHostSources target' @model)
+ canAddBrokeredCredSources=(can 'addBrokeredCredentialSources target' @model)
+ canAddInjectedApplicationCredSources=(can
+ 'addInjectedApplicationCredentialSources target' @model
+ )
+ canDelete=(can 'delete model' @model)
+ )
+ as |perms|
+}}
+ {{#if
+ (or
+ perms.canAddHostSources
+ perms.canAddBrokeredCredSources
+ perms.canAddInjectedApplicationCredSources
+ perms.canDelete
+ )
+ }}
+
+
+ {{#if perms.canAddHostSources}}
+
+ {{t 'resources.target.actions.add-host-sources'}}
+
+ {{/if}}
+ {{#if perms.canAddBrokeredCredSources}}
+
+ {{t 'resources.target.actions.add-brokered-credential-sources'}}
+
+ {{/if}}
+ {{#if perms.canAddInjectedApplicationCredSources}}
+
+ {{t
+ 'resources.target.actions.add-injected-application-credential-sources'
+ }}
+
+ {{/if}}
+ {{#if perms.canDelete}}
+ {{#if
+ (or
+ perms.canAddHostSources
+ perms.canAddBrokeredCredSources
+ perms.canAddInjectedApplicationCredSources
+ )
+ }}
+
+ {{/if}}
+
+ {{t 'resources.target.actions.delete'}}
+
+ {{/if}}
+
{{/if}}
- {{#if (can 'addBrokeredCredentialSources target' @model)}}
-
- {{t 'resources.target.actions.add-brokered-credential-sources'}}
-
- {{/if}}
- {{#if (can 'addInjectedApplicationCredentialSources target' @model)}}
-
- {{t
- 'resources.target.actions.add-injected-application-credential-sources'
- }}
-
- {{/if}}
- {{#if (can 'delete model' @model)}}
-
-
- {{t 'resources.target.actions.delete'}}
-
- {{/if}}
-
\ No newline at end of file
+{{/let}}
\ No newline at end of file
diff --git a/ui/admin/app/components/users/user/actions/index.hbs b/ui/admin/app/components/users/user/actions/index.hbs
index 96ca3068f..f4ef1b123 100644
--- a/ui/admin/app/components/users/user/actions/index.hbs
+++ b/ui/admin/app/components/users/user/actions/index.hbs
@@ -2,23 +2,34 @@
Copyright (c) HashiCorp, Inc.
SPDX-License-Identifier: BUSL-1.1
}}
-
-
- {{#if (can 'addAccounts user' @model)}}
-
- {{t 'resources.user.actions.add-accounts'}}
-
+{{#let
+ (hash
+ canAddAccounts=(can 'addAccounts user' @model)
+ canDelete=(can 'delete model' @model)
+ )
+ as |perms|
+}}
+ {{#if (or perms.canAddAccounts perms.canDelete)}}
+
+
+ {{#if perms.canAddAccounts}}
+
+ {{t 'resources.user.actions.add-accounts'}}
+
+ {{/if}}
+ {{#if perms.canDelete}}
+ {{#if perms.canAddAccounts}}
+
+ {{/if}}
+
+ {{t 'resources.user.actions.delete'}}
+
+ {{/if}}
+
{{/if}}
-
- {{#if (can 'delete model' @model)}}
-
-
- {{t 'resources.user.actions.delete'}}
-
- {{/if}}
-
\ No newline at end of file
+{{/let}}
\ No newline at end of file
diff --git a/ui/admin/app/components/workers/worker/actions/index.hbs b/ui/admin/app/components/workers/worker/actions/index.hbs
index cce6048f3..0a9ebe652 100644
--- a/ui/admin/app/components/workers/worker/actions/index.hbs
+++ b/ui/admin/app/components/workers/worker/actions/index.hbs
@@ -3,20 +3,33 @@
SPDX-License-Identifier: BUSL-1.1
}}
-
-
- {{#if (can 'setWorkerTags worker' @model)}}
-
- {{t 'resources.worker.actions.create_tags'}}
-
+{{#let
+ (hash
+ canSetWorkerTags=(can 'setWorkerTags worker' @model)
+ canDelete=(can 'delete worker' @model)
+ )
+ as |perms|
+}}
+ {{#if (or perms.canSetWorkerTags perms.canDelete)}}
+
+
+ {{#if perms.canSetWorkerTags}}
+
+ {{t 'resources.worker.actions.create_tags'}}
+
+ {{/if}}
+ {{#if perms.canDelete}}
+ {{#if perms.canSetWorkerTags}}
+
+ {{/if}}
+
+ {{t 'resources.worker.actions.delete'}}
+
+ {{/if}}
+
{{/if}}
- {{#if (can 'delete worker' @model)}}
-
- {{t 'resources.worker.actions.delete'}}
-
- {{/if}}
-
\ No newline at end of file
+{{/let}}
\ No newline at end of file
diff --git a/ui/admin/tests/acceptance/credential-library/create-test.js b/ui/admin/tests/acceptance/credential-library/create-test.js
index 3604fb4f7..208143da1 100644
--- a/ui/admin/tests/acceptance/credential-library/create-test.js
+++ b/ui/admin/tests/acceptance/credential-library/create-test.js
@@ -215,6 +215,7 @@ module('Acceptance | credential-libraries | create', function (hooks) {
'credential-libraries'
] = [];
await visit(urls.credentialLibraries);
+ await click(selectors.MANAGE_DROPDOWN_CREDENTIAL_STORE);
assert.notOk(
instances.credentialStore.authorized_collection_actions[
diff --git a/ui/admin/tests/acceptance/credential-library/selectors.js b/ui/admin/tests/acceptance/credential-library/selectors.js
index 1cc6a7637..5bd415366 100644
--- a/ui/admin/tests/acceptance/credential-library/selectors.js
+++ b/ui/admin/tests/acceptance/credential-library/selectors.js
@@ -51,3 +51,6 @@ export const MANAGE_DROPDOWN_CRED_LIB =
'[data-test-manage-credential-library-dropdown] button:first-child';
export const MANAGE_DROPDOWN_CRED_LIB_DELETE =
'[data-test-manage-credential-library-dropdown] ul li button';
+
+export const MANAGE_DROPDOWN_CREDENTIAL_STORE =
+ '[data-test-manage-credential-stores-dropdown] button';
diff --git a/ui/admin/tests/acceptance/credential-store/credentials/create-test.js b/ui/admin/tests/acceptance/credential-store/credentials/create-test.js
index 67e6b9669..62dae4d43 100644
--- a/ui/admin/tests/acceptance/credential-store/credentials/create-test.js
+++ b/ui/admin/tests/acceptance/credential-store/credentials/create-test.js
@@ -344,6 +344,23 @@ module(
assert.dom(selectors.FIELD_TYPE_JSON).doesNotExist();
});
+ test('users cannot create a new credential without proper authorization', async function (assert) {
+ instances.staticCredentialStore.authorized_collection_actions.credentials =
+ instances.staticCredentialStore.authorized_collection_actions.credentials.filter(
+ (item) => item !== 'create',
+ );
+
+ await visit(urls.credentials);
+ await click(selectors.MANAGE_DROPDOWN_CREDENTIAL_STORE);
+
+ assert.false(
+ instances.staticCredentialStore.authorized_collection_actions.credentials.includes(
+ 'create',
+ ),
+ );
+ assert.dom(commonSelectors.HREF(urls.newCredential)).doesNotExist();
+ });
+
test('users cannot directly navigate to new credential route without proper authorization', async function (assert) {
instances.staticCredentialStore.authorized_collection_actions.credentials =
instances.staticCredentialStore.authorized_collection_actions.credentials.filter(
diff --git a/ui/admin/tests/acceptance/credential-store/credentials/selectors.js b/ui/admin/tests/acceptance/credential-store/credentials/selectors.js
index e3bd61414..0e34b5c24 100644
--- a/ui/admin/tests/acceptance/credential-store/credentials/selectors.js
+++ b/ui/admin/tests/acceptance/credential-store/credentials/selectors.js
@@ -21,4 +21,7 @@ export const MANAGE_DROPDOWN_DELETE =
export const MANAGE_DROPDOWN_NEW_CREDENTIAL =
'[data-test-manage-credential-stores-dropdown] a';
+export const MANAGE_DROPDOWN_CREDENTIAL_STORE =
+ '[data-test-manage-credential-stores-dropdown] button';
+
export const REPLACE_SECRET_BTN = '.secret-editor button';
diff --git a/ui/admin/tests/acceptance/groups/members-test.js b/ui/admin/tests/acceptance/groups/members-test.js
index 7c3102470..94c70eccb 100644
--- a/ui/admin/tests/acceptance/groups/members-test.js
+++ b/ui/admin/tests/acceptance/groups/members-test.js
@@ -129,6 +129,7 @@ module('Acceptance | groups | members', function (hooks) {
instances.group.update({ authorized_actions });
await visit(urls.group);
+ await click(selectors.MANAGE_DROPDOWN);
assert.dom(commonSelectors.HREF(urls.addMembers)).doesNotExist();
});
diff --git a/ui/admin/tests/acceptance/host-catalogs/host-sets/create-test.js b/ui/admin/tests/acceptance/host-catalogs/host-sets/create-test.js
index ce8529b92..0f80eb004 100644
--- a/ui/admin/tests/acceptance/host-catalogs/host-sets/create-test.js
+++ b/ui/admin/tests/acceptance/host-catalogs/host-sets/create-test.js
@@ -174,8 +174,12 @@ module('Acceptance | host-catalogs | host sets | create', function (hooks) {
});
test('Users cannot create a new host set without proper authorization', async function (assert) {
- instances.hostCatalog.authorized_collection_actions['host-sets'] = [];
+ instances.hostCatalog.authorized_collection_actions['host-sets'] =
+ instances.hostCatalog.authorized_collection_actions['host-sets'].filter(
+ (item) => item !== 'create',
+ );
await visit(urls.hostCatalog);
+ await click(selectors.MANAGE_DROPDOWN_HOST_CATALOG);
assert.notOk(
instances.hostCatalog.authorized_collection_actions['host-sets'].includes(
diff --git a/ui/admin/tests/acceptance/host-catalogs/host-sets/selectors.js b/ui/admin/tests/acceptance/host-catalogs/host-sets/selectors.js
index efc1752b7..7ca47c70d 100644
--- a/ui/admin/tests/acceptance/host-catalogs/host-sets/selectors.js
+++ b/ui/admin/tests/acceptance/host-catalogs/host-sets/selectors.js
@@ -15,6 +15,9 @@ export const FIELD_AZURE_FILTER = '[name=filter]';
export const FIELD_FILTERS_REMOVE_BTN =
'[name=filters] [data-test-remove-button]';
+export const MANAGE_DROPDOWN_HOST_CATALOG =
+ '[data-test-manage-host-catalogs-dropdown] button';
+
export const MANAGE_DROPDOWN_HOST_SETS =
'[data-test-manage-dropdown-host-sets] button:first-child';
export const MANAGE_DROPDOWN_HOST_SETS_DELETE =