Merge branch 'main' into chore-add-translations-to-badges-type
This commit is contained in:
45 files changed
+150
-293
No files matched your search
@@ -1,37 +0,0 @@
|
||||
import { Ability } from 'ember-can';
|
||||
|
||||
/**
|
||||
* Generic ability provides abilities common to all models in the API.
|
||||
*/
|
||||
export default class CollectionAbility extends Ability {
|
||||
// =permissions
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canList() {
|
||||
return this.hasAuthorizedCollectionAction('list');
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canCreate() {
|
||||
return this.hasAuthorizedCollectionAction('create');
|
||||
}
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Returns true if the given action is contained in the ability model's
|
||||
* `authorized_collection_actions` array.
|
||||
* @param {string} action
|
||||
* @return {boolean}
|
||||
*/
|
||||
hasAuthorizedCollectionAction(action) {
|
||||
const authorized_collection_actions =
|
||||
(this.model || {}).authorized_collection_actions || {};
|
||||
const collection = this.collection || {};
|
||||
return authorized_collection_actions[collection]?.includes(action);
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,20 @@ export default class ModelAbility extends Ability {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canList() {
|
||||
return this.hasAuthorizedCollectionAction('list');
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canCreate() {
|
||||
return this.hasAuthorizedCollectionAction('create');
|
||||
}
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
@@ -56,4 +70,17 @@ export default class ModelAbility extends Ability {
|
||||
hasAuthorizedAction(action) {
|
||||
return this.model.authorized_actions?.includes(action);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given action is contained in the ability model's
|
||||
* `authorized_collection_actions` array.
|
||||
* @param {string} action
|
||||
* @return {boolean}
|
||||
*/
|
||||
hasAuthorizedCollectionAction(action) {
|
||||
const authorized_collection_actions =
|
||||
(this.model || {}).authorized_collection_actions || {};
|
||||
const collection = this.collection || {};
|
||||
return authorized_collection_actions[collection]?.includes(action);
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export { default } from 'api/abilities/collection';
|
||||
@@ -1,38 +0,0 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
|
||||
module('Unit | Abilities | Collection', function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
test('it reflects when a resource may be listed based on authorized_collection_actions', function (assert) {
|
||||
assert.expect(2);
|
||||
const service = this.owner.lookup('service:can');
|
||||
const model = {
|
||||
authorized_collection_actions: {
|
||||
foobars: ['list'],
|
||||
},
|
||||
};
|
||||
assert.ok(service.can('list collection', model, { collection: 'foobars' }));
|
||||
model.authorized_collection_actions.foobars = [];
|
||||
assert.notOk(
|
||||
service.can('list collection', model, { collection: 'foobars' })
|
||||
);
|
||||
});
|
||||
|
||||
test('it reflects when a resource may be created based on authorized_collection_actions', function (assert) {
|
||||
assert.expect(2);
|
||||
const service = this.owner.lookup('service:can');
|
||||
const model = {
|
||||
authorized_collection_actions: {
|
||||
foobars: ['create'],
|
||||
},
|
||||
};
|
||||
assert.ok(
|
||||
service.can('create collection', model, { collection: 'foobars' })
|
||||
);
|
||||
model.authorized_collection_actions.foobars = [];
|
||||
assert.notOk(
|
||||
service.can('create collection', model, { collection: 'foobars' })
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -65,4 +65,32 @@ module('Unit | Abilities | Model', function (hooks) {
|
||||
model.authorized_actions = [];
|
||||
assert.notOk(service.can('delete model', model));
|
||||
});
|
||||
|
||||
// =collections
|
||||
|
||||
test('it reflects when a resource may be listed based on authorized_collection_actions', function (assert) {
|
||||
assert.expect(2);
|
||||
const service = this.owner.lookup('service:can');
|
||||
const model = {
|
||||
authorized_collection_actions: {
|
||||
foobars: ['list'],
|
||||
},
|
||||
};
|
||||
assert.ok(service.can('list model', model, { collection: 'foobars' }));
|
||||
model.authorized_collection_actions.foobars = [];
|
||||
assert.notOk(service.can('list model', model, { collection: 'foobars' }));
|
||||
});
|
||||
|
||||
test('it reflects when a resource may be created based on authorized_collection_actions', function (assert) {
|
||||
assert.expect(2);
|
||||
const service = this.owner.lookup('service:can');
|
||||
const model = {
|
||||
authorized_collection_actions: {
|
||||
foobars: ['create'],
|
||||
},
|
||||
};
|
||||
assert.ok(service.can('create model', model, { collection: 'foobars' }));
|
||||
model.authorized_collection_actions.foobars = [];
|
||||
assert.notOk(service.can('create model', model, { collection: 'foobars' }));
|
||||
});
|
||||
});
|
||||
@@ -1,30 +0,0 @@
|
||||
import CollectionAbility from 'api/abilities/collection';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default class OverrideCollectionAbility extends CollectionAbility {
|
||||
// =services
|
||||
|
||||
@service features;
|
||||
|
||||
// =permissions
|
||||
|
||||
/**
|
||||
* Navigating to a resource is allowed if either list or create grants
|
||||
* are present.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canNavigate() {
|
||||
return this.canList || this.canCreate;
|
||||
}
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* If the capabilities feature flag is disabled, actions are always
|
||||
* authorized. This mimics pre-capabilities behavior.
|
||||
*/
|
||||
hasAuthorizedCollectionAction() {
|
||||
if (!this.features.isEnabled('capabilities')) return true;
|
||||
return super.hasAuthorizedCollectionAction(...arguments);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,12 @@
|
||||
import ModelAbility from 'api/abilities/model';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default class OverrideModelAbility extends ModelAbility {
|
||||
// =services
|
||||
|
||||
@service features;
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* If the capabilities feature flag is disabled, actions are always
|
||||
* authorized. This mimics pre-capabilities behavior.
|
||||
* Navigating to a resource is allowed if either list or create grants
|
||||
* are present.
|
||||
* @type {boolean}
|
||||
*/
|
||||
hasAuthorizedAction() {
|
||||
if (!this.features.isEnabled('capabilities')) return true;
|
||||
return super.hasAuthorizedAction(...arguments);
|
||||
get canNavigate() {
|
||||
return this.canList || this.canCreate;
|
||||
}
|
||||
}
|
||||
@@ -57,7 +57,7 @@
|
||||
</dropdown.button>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if (can 'create collection' @model collection='accounts')}}
|
||||
{{#if (can 'create model' @model collection='accounts')}}
|
||||
|
||||
<dropdown.link
|
||||
@route='scopes.scope.auth-methods.auth-method.accounts.new'
|
||||
@@ -68,7 +68,7 @@
|
||||
{{/if}}
|
||||
|
||||
{{#if (feature-flag 'managed-groups')}}
|
||||
{{#if (can 'create collection' @model collection='managed-groups')}}
|
||||
{{#if (can 'create model' @model collection='managed-groups')}}
|
||||
{{#if @model.isOIDC}}
|
||||
<dropdown.link
|
||||
@route='scopes.scope.auth-methods.auth-method.managed-groups.new'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<nav.link @route='scopes.scope.auth-methods.auth-method.index'>
|
||||
{{t 'titles.details'}}
|
||||
</nav.link>
|
||||
{{#if (can 'navigate collection' @model collection='accounts')}}
|
||||
{{#if (can 'navigate model' @model collection='accounts')}}
|
||||
|
||||
<nav.link @route='scopes.scope.auth-methods.auth-method.accounts'>
|
||||
{{t 'resources.account.title_plural'}}
|
||||
@@ -10,7 +10,7 @@
|
||||
{{/if}}
|
||||
|
||||
{{#if (feature-flag 'managed-groups')}}
|
||||
{{#if (can 'navigate collection' @model collection='managed-groups')}}
|
||||
{{#if (can 'navigate model' @model collection='managed-groups')}}
|
||||
{{#if @model.isOIDC}}
|
||||
<nav.link @route='scopes.scope.auth-methods.auth-method.managed-groups'>
|
||||
{{t 'resources.managed-group.title_plural'}}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@dropdownRight={{true}}
|
||||
as |dropdown|
|
||||
>
|
||||
{{#if (can 'create collection' @model collection='credential-libraries')}}
|
||||
{{#if (can 'create model' @model collection='credential-libraries')}}
|
||||
|
||||
<dropdown.link
|
||||
@route='scopes.scope.credential-stores.credential-store.credential-libraries.new'
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<nav.link @route='scopes.scope.credential-stores.credential-store.index'>
|
||||
{{t 'titles.details'}}
|
||||
</nav.link>
|
||||
{{#if (can 'navigate collection' @model collection='credential-libraries')}}
|
||||
{{#if (can 'navigate model' @model collection='credential-libraries')}}
|
||||
|
||||
<nav.link
|
||||
@route='scopes.scope.credential-stores.credential-store.credential-libraries'
|
||||
|
||||
@@ -36,9 +36,7 @@ export default class ScopesScopeAuthMethodsRoute extends Route {
|
||||
async model() {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
const { id: scope_id } = scope;
|
||||
if (
|
||||
this.can.can('list collection', scope, { collection: 'auth-methods' })
|
||||
) {
|
||||
if (this.can.can('list model', scope, { collection: 'auth-methods' })) {
|
||||
const { type } = this;
|
||||
return this.resourceFilterStore.queryBy(
|
||||
'auth-method',
|
||||
|
||||
@@ -25,7 +25,7 @@ export default class ScopesScopeAuthMethodsAuthMethodAccountsRoute extends Route
|
||||
let accounts;
|
||||
|
||||
if (
|
||||
this.can.can('list collection', authMethod, {
|
||||
this.can.can('list model', authMethod, {
|
||||
collection: 'accounts',
|
||||
})
|
||||
) {
|
||||
|
||||
@@ -22,7 +22,7 @@ export default class ScopesScopeAuthMethodsAuthMethodManagedGroupsRoute extends
|
||||
async model() {
|
||||
const authMethod = this.modelFor('scopes.scope.auth-methods.auth-method');
|
||||
const { id: auth_method_id } = authMethod;
|
||||
const canListManagedGroups = this.can.can('list collection', authMethod, {
|
||||
const canListManagedGroups = this.can.can('list model', authMethod, {
|
||||
collection: 'managed-groups',
|
||||
});
|
||||
let managedGroups;
|
||||
|
||||
@@ -21,7 +21,7 @@ export default class ScopesScopeCredentialStoresRoute extends Route {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
const { id: scope_id } = scope;
|
||||
if (
|
||||
this.can.can('list collection', scope, {
|
||||
this.can.can('list model', scope, {
|
||||
collection: 'credential-stores',
|
||||
})
|
||||
) {
|
||||
|
||||
+1
-1
@@ -23,7 +23,7 @@ export default class ScopesScopeCredentialStoresCredentialStoreCredentialLibrari
|
||||
);
|
||||
const { id: credential_store_id } = credentialStore;
|
||||
if (
|
||||
this.can.can('list collection', credentialStore, {
|
||||
this.can.can('list model', credentialStore, {
|
||||
collection: 'credential-libraries',
|
||||
})
|
||||
) {
|
||||
|
||||
@@ -30,7 +30,7 @@ export default class ScopesScopeGroupsRoute extends Route {
|
||||
async model() {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
const { id: scope_id } = scope;
|
||||
if (this.can.can('list collection', scope, { collection: 'groups' })) {
|
||||
if (this.can.can('list model', scope, { collection: 'groups' })) {
|
||||
return this.store.query('group', { scope_id });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,9 +30,7 @@ export default class ScopesScopeHostCatalogsRoute extends Route {
|
||||
async model() {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
const { id: scope_id } = scope;
|
||||
if (
|
||||
this.can.can('list collection', scope, { collection: 'host-catalogs' })
|
||||
) {
|
||||
if (this.can.can('list model', scope, { collection: 'host-catalogs' })) {
|
||||
return this.store.query('host-catalog', { scope_id });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ export default class ScopesScopeHostCatalogsHostCatalogHostSetsRoute extends Rou
|
||||
|
||||
const { id: host_catalog_id } = hostCatalog;
|
||||
if (
|
||||
this.can.can('list collection', hostCatalog, {
|
||||
this.can.can('list model', hostCatalog, {
|
||||
collection: 'host-sets',
|
||||
})
|
||||
) {
|
||||
|
||||
@@ -25,7 +25,7 @@ export default class ScopesScopeHostCatalogsHostCatalogHostsRoute extends Route
|
||||
);
|
||||
const { id: host_catalog_id } = hostCatalog;
|
||||
if (
|
||||
this.can.can('list collection', hostCatalog, {
|
||||
this.can.can('list model', hostCatalog, {
|
||||
collection: 'hosts',
|
||||
})
|
||||
) {
|
||||
|
||||
@@ -30,7 +30,7 @@ export default class ScopesScopeRolesRoute extends Route {
|
||||
async model() {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
const { id: scope_id } = scope;
|
||||
if (this.can.can('list collection', scope, { collection: 'roles' })) {
|
||||
if (this.can.can('list model', scope, { collection: 'roles' })) {
|
||||
return this.store.query('role', { scope_id });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ export default class ScopesScopeTargetsRoute extends Route {
|
||||
async model() {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
const { id: scope_id } = scope;
|
||||
if (this.can.can('list collection', scope, { collection: 'targets' })) {
|
||||
if (this.can.can('list model', scope, { collection: 'targets' })) {
|
||||
return this.store.query('target', { scope_id });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ export default class ScopesScopeUsersRoute extends Route {
|
||||
async model() {
|
||||
const scope = this.modelFor('scopes.scope');
|
||||
const { id: scope_id } = scope;
|
||||
if (this.can.can('list collection', scope, { collection: 'users' })) {
|
||||
if (this.can.can('list model', scope, { collection: 'users' })) {
|
||||
return this.store.query('user', { scope_id });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@
|
||||
</Rose::Nav::Sidebar>
|
||||
--}}
|
||||
<Rose::Nav::Sidebar @title={{t 'titles.resources'}} as |nav|>
|
||||
{{#if (can 'navigate collection' @model collection='sessions')}}
|
||||
{{#if (can 'navigate model' @model collection='sessions')}}
|
||||
<nav.link @route='scopes.scope.sessions'>
|
||||
<Rose::Icon
|
||||
@name='flight-icons/svg/entry-point-16'
|
||||
@@ -80,7 +80,7 @@
|
||||
{{t 'resources.session.title_plural'}}
|
||||
</nav.link>
|
||||
{{/if}}
|
||||
{{#if (can 'navigate collection' @model collection='targets')}}
|
||||
{{#if (can 'navigate model' @model collection='targets')}}
|
||||
<nav.link @route='scopes.scope.targets'>
|
||||
<Rose::Icon
|
||||
@name='flight-icons/svg/crosshair-16'
|
||||
@@ -89,7 +89,7 @@
|
||||
{{t 'resources.target.title_plural'}}
|
||||
</nav.link>
|
||||
{{/if}}
|
||||
{{#if (can 'navigate collection' @model collection='host-catalogs')}}
|
||||
{{#if (can 'navigate model' @model collection='host-catalogs')}}
|
||||
<nav.link @route='scopes.scope.host-catalogs'>
|
||||
<Rose::Icon
|
||||
@name='flight-icons/svg/collections-16'
|
||||
@@ -98,9 +98,7 @@
|
||||
{{t 'resources.host-catalog.title_plural'}}
|
||||
</nav.link>
|
||||
{{/if}}
|
||||
{{#if
|
||||
(can 'navigate collection' @model collection='credential-stores')
|
||||
}}
|
||||
{{#if (can 'navigate model' @model collection='credential-stores')}}
|
||||
{{#if (feature-flag 'credential-store')}}
|
||||
<nav.link @route='scopes.scope.credential-stores'>
|
||||
<Rose::Icon @name='flight-icons/svg/key-16' @size='medium' />
|
||||
@@ -113,13 +111,13 @@
|
||||
|
||||
{{#unless @model.isProject}}
|
||||
<Rose::Nav::Sidebar @title={{t 'titles.iam'}} as |nav|>
|
||||
{{#if (can 'navigate collection' @model collection='users')}}
|
||||
{{#if (can 'navigate model' @model collection='users')}}
|
||||
<nav.link @route='scopes.scope.users'>
|
||||
<Rose::Icon @name='flight-icons/svg/users-16' @size='medium' />
|
||||
{{t 'resources.user.title_plural'}}
|
||||
</nav.link>
|
||||
{{/if}}
|
||||
{{#if (can 'navigate collection' @model collection='groups')}}
|
||||
{{#if (can 'navigate model' @model collection='groups')}}
|
||||
<nav.link @route='scopes.scope.groups'>
|
||||
<Rose::Icon
|
||||
@name='flight-icons/svg/folder-users-16'
|
||||
@@ -128,7 +126,7 @@
|
||||
{{t 'resources.group.title_plural'}}
|
||||
</nav.link>
|
||||
{{/if}}
|
||||
{{#if (can 'navigate collection' @model collection='roles')}}
|
||||
{{#if (can 'navigate model' @model collection='roles')}}
|
||||
<nav.link @route='scopes.scope.roles'>
|
||||
<Rose::Icon
|
||||
@name='flight-icons/svg/identity-user-16'
|
||||
@@ -137,7 +135,7 @@
|
||||
{{t 'resources.role.title_plural'}}
|
||||
</nav.link>
|
||||
{{/if}}
|
||||
{{#if (can 'navigate collection' @model collection='auth-methods')}}
|
||||
{{#if (can 'navigate model' @model collection='auth-methods')}}
|
||||
<nav.link @route='scopes.scope.auth-methods'>
|
||||
<Rose::Icon @name='flight-icons/svg/lock-16' @size='medium' />
|
||||
{{t 'resources.auth-method.title_plural'}}
|
||||
|
||||
@@ -131,14 +131,12 @@
|
||||
>
|
||||
<message.description>
|
||||
|
||||
{{#if
|
||||
(can 'list collection' this.authMethod collection='accounts')
|
||||
}}
|
||||
{{#if (can 'list model' this.authMethod collection='accounts')}}
|
||||
{{! can list (at least): show default welcome message}}
|
||||
{{t 'resources.account.description'}}
|
||||
|
||||
{{else if (can
|
||||
'create collection' this.authMethod collection='accounts'
|
||||
'create model' this.authMethod collection='accounts'
|
||||
)}}
|
||||
{{! can create (only): show create-but-not-list welcome message}}
|
||||
{{t
|
||||
@@ -155,9 +153,7 @@
|
||||
|
||||
</message.description>
|
||||
|
||||
{{#if
|
||||
(can 'create collection' this.authMethod collection='accounts')
|
||||
}}
|
||||
{{#if (can 'create model' this.authMethod collection='accounts')}}
|
||||
|
||||
<message.link
|
||||
@route='scopes.scope.auth-methods.auth-method.accounts.new'
|
||||
|
||||
+3
-7
@@ -69,14 +69,12 @@
|
||||
<message.description>
|
||||
|
||||
{{#if
|
||||
(can
|
||||
'list collection' this.authMethod collection='managed-groups'
|
||||
)
|
||||
(can 'list model' this.authMethod collection='managed-groups')
|
||||
}}
|
||||
{{! Can list (at least): show default welcome message }}
|
||||
{{t 'resources.managed-group.description'}}
|
||||
{{else if (can
|
||||
'create collection' this.authMethod collection='managed-groups'
|
||||
'create model' this.authMethod collection='managed-groups'
|
||||
)}}
|
||||
{{! Can create only: show create but not list welcome message }}
|
||||
{{t
|
||||
@@ -93,9 +91,7 @@
|
||||
</message.description>
|
||||
|
||||
{{#if
|
||||
(can
|
||||
'create collection' this.authMethod collection='managed-groups'
|
||||
)
|
||||
(can 'create model' this.authMethod collection='managed-groups')
|
||||
}}
|
||||
<message.link
|
||||
@route='scopes.scope.auth-methods.auth-method.managed-groups.new'
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
</page.breadcrumbs>
|
||||
|
||||
<page.actions>
|
||||
{{#if (can 'create collection' this.scopeModel collection='auth-methods')}}
|
||||
{{#if (can 'create model' this.scopeModel collection='auth-methods')}}
|
||||
<Rose::Dropdown
|
||||
@text={{t 'titles.new'}}
|
||||
@dropdownRight={{true}}
|
||||
@@ -227,13 +227,11 @@
|
||||
as |message|
|
||||
>
|
||||
<message.description>
|
||||
{{#if
|
||||
(can 'list collection' this.scopeModel collection='auth-methods')
|
||||
}}
|
||||
{{#if (can 'list model' this.scopeModel collection='auth-methods')}}
|
||||
{{! can list (at least): show default welcome message}}
|
||||
{{t 'resources.auth-method.messages.welcome.description'}}
|
||||
{{else if (can
|
||||
'create collection' this.scopeModel collection='auth-methods'
|
||||
'create model' this.scopeModel collection='auth-methods'
|
||||
)}}
|
||||
{{! can create (only): show create-but-not-list welcome message}}
|
||||
{{t
|
||||
|
||||
+3
-3
@@ -79,7 +79,7 @@
|
||||
<message.description>
|
||||
{{#if
|
||||
(can
|
||||
'list collection'
|
||||
'list model'
|
||||
this.credentialStore
|
||||
collection='credential-libraries'
|
||||
)
|
||||
@@ -88,7 +88,7 @@
|
||||
{{t 'resources.credential-library.description'}}
|
||||
|
||||
{{else if (can
|
||||
'create collection'
|
||||
'create model'
|
||||
this.credentialStore
|
||||
collection='credential-libraries'
|
||||
)}}
|
||||
@@ -108,7 +108,7 @@
|
||||
</message.description>
|
||||
{{#if
|
||||
(can
|
||||
'create collection'
|
||||
'create model'
|
||||
this.credentialStore
|
||||
collection='credential-libraries'
|
||||
)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
<page.actions>
|
||||
|
||||
{{#if (can 'create collection' this.scope collection='credential-stores')}}
|
||||
{{#if (can 'create model' this.scope collection='credential-stores')}}
|
||||
{{#if @model}}
|
||||
<Rose::LinkButton
|
||||
@route='scopes.scope.credential-stores.new'
|
||||
@@ -82,13 +82,11 @@
|
||||
as |message|
|
||||
>
|
||||
<message.description>
|
||||
{{#if
|
||||
(can 'list collection' this.scope collection='credential-stores')
|
||||
}}
|
||||
{{#if (can 'list model' this.scope collection='credential-stores')}}
|
||||
{{! can list (at least): show default welcome message}}
|
||||
{{t 'resources.credential-store.description'}}
|
||||
{{else if (can
|
||||
'create collection' this.scope collection='credential-stores'
|
||||
'create model' this.scope collection='credential-stores'
|
||||
)}}
|
||||
{{! can create (only): show create-but-not-list welcome message}}
|
||||
{{t
|
||||
@@ -103,9 +101,7 @@
|
||||
}}
|
||||
{{/if}}
|
||||
</message.description>
|
||||
{{#if
|
||||
(can 'create collection' this.scope collection='credential-stores')
|
||||
}}
|
||||
{{#if (can 'create model' this.scope collection='credential-stores')}}
|
||||
<message.link @route='scopes.scope.credential-stores.new'>
|
||||
<Rose::Icon @name='flight-icons/svg/plus-circle-16' />
|
||||
{{t 'titles.new'}}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
</page.header>
|
||||
|
||||
<page.actions>
|
||||
{{#if (can 'create collection' this.scope collection='groups')}}
|
||||
{{#if (can 'create model' this.scope collection='groups')}}
|
||||
{{#if @model}}
|
||||
<Rose::LinkButton @route='scopes.scope.groups.new' @style='primary'>{{t
|
||||
'titles.new'
|
||||
@@ -71,10 +71,10 @@
|
||||
as |message|
|
||||
>
|
||||
<message.description>
|
||||
{{#if (can 'list collection' this.scope collection='groups')}}
|
||||
{{#if (can 'list model' this.scope collection='groups')}}
|
||||
{{! can list (at least): show default welcome message}}
|
||||
{{t 'resources.group.description'}}
|
||||
{{else if (can 'create collection' this.scope collection='groups')}}
|
||||
{{else if (can 'create model' this.scope collection='groups')}}
|
||||
{{! can create (only): show create-but-not-list welcome message}}
|
||||
{{t
|
||||
'descriptions.create-but-not-list'
|
||||
@@ -88,7 +88,7 @@
|
||||
}}
|
||||
{{/if}}
|
||||
</message.description>
|
||||
{{#if (can 'create collection' this.scope collection='groups')}}
|
||||
{{#if (can 'create model' this.scope collection='groups')}}
|
||||
<message.link @route='scopes.scope.groups.new'>
|
||||
<Rose::Icon @name='flight-icons/svg/plus-circle-16' />
|
||||
{{t 'titles.new'}}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@dropdownRight={{true}}
|
||||
as |dropdown|
|
||||
>
|
||||
{{#if (can 'create collection' @model collection='hosts')}}
|
||||
{{#if (can 'create model' @model collection='hosts')}}
|
||||
<dropdown.link
|
||||
@route='scopes.scope.host-catalogs.host-catalog.hosts.new'
|
||||
@model={{@model}}
|
||||
@@ -11,7 +11,7 @@
|
||||
{{t 'resources.host.actions.create'}}
|
||||
</dropdown.link>
|
||||
{{/if}}
|
||||
{{#if (can 'create collection' @model collection='host-sets')}}
|
||||
{{#if (can 'create model' @model collection='host-sets')}}
|
||||
<dropdown.link
|
||||
@route='scopes.scope.host-catalogs.host-catalog.host-sets.new'
|
||||
@model={{@model}}
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
<nav.link @route='scopes.scope.host-catalogs.host-catalog.index'>
|
||||
{{t 'titles.details'}}
|
||||
</nav.link>
|
||||
{{#if (can 'navigate collection' @model collection='hosts')}}
|
||||
{{#if (can 'navigate model' @model collection='hosts')}}
|
||||
<nav.link @route='scopes.scope.host-catalogs.host-catalog.hosts'>
|
||||
{{t 'resources.host.title_plural'}}
|
||||
</nav.link>
|
||||
{{/if}}
|
||||
{{#if (can 'navigate collection' @model collection='host-sets')}}
|
||||
{{#if (can 'navigate model' @model collection='host-sets')}}
|
||||
<nav.link @route='scopes.scope.host-catalogs.host-catalog.host-sets'>
|
||||
{{t 'resources.host-set.title_plural'}}
|
||||
</nav.link>
|
||||
|
||||
@@ -64,13 +64,11 @@
|
||||
>
|
||||
<message.description>
|
||||
|
||||
{{#if (can 'list collection' this.hostCatalog collection='host-sets')}}
|
||||
{{#if (can 'list model' this.hostCatalog collection='host-sets')}}
|
||||
{{! can list (at least): show default welcome message}}
|
||||
{{t 'resources.host-set.description'}}
|
||||
|
||||
{{else if (can
|
||||
'create collection' this.hostCatalog collection='host-sets'
|
||||
)}}
|
||||
{{else if (can 'create model' this.hostCatalog collection='host-sets')}}
|
||||
{{! can create (only): show create-but-not-list welcome message}}
|
||||
{{t
|
||||
'descriptions.create-but-not-list'
|
||||
@@ -85,7 +83,7 @@
|
||||
{{/if}}
|
||||
</message.description>
|
||||
|
||||
{{#if (can 'create collection' this.hostCatalog collection='host-sets')}}
|
||||
{{#if (can 'create model' this.hostCatalog collection='host-sets')}}
|
||||
<message.link
|
||||
@route='scopes.scope.host-catalogs.host-catalog.host-sets.new'
|
||||
>
|
||||
|
||||
@@ -69,13 +69,11 @@
|
||||
>
|
||||
<message.description>
|
||||
|
||||
{{#if (can 'list collection' this.hostCatalog collection='hosts')}}
|
||||
{{#if (can 'list model' this.hostCatalog collection='hosts')}}
|
||||
{{! can list (at least): show default welcome message}}
|
||||
{{t 'resources.host.description'}}
|
||||
|
||||
{{else if (can
|
||||
'create collection' this.hostCatalog collection='hosts'
|
||||
)}}
|
||||
{{else if (can 'create model' this.hostCatalog collection='hosts')}}
|
||||
{{! can create (only): show create-but-not-list welcome message}}
|
||||
{{t
|
||||
'descriptions.create-but-not-list'
|
||||
@@ -90,7 +88,7 @@
|
||||
{{/if}}
|
||||
</message.description>
|
||||
|
||||
{{#if (can 'create collection' this.hostCatalog collection='hosts')}}
|
||||
{{#if (can 'create model' this.hostCatalog collection='hosts')}}
|
||||
|
||||
<message.link
|
||||
@route='scopes.scope.host-catalogs.host-catalog.hosts.new'
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</page.header>
|
||||
|
||||
<page.actions>
|
||||
{{#if (can 'create collection' this.scope collection='host-catalogs')}}
|
||||
{{#if (can 'create model' this.scope collection='host-catalogs')}}
|
||||
{{#if @model}}
|
||||
<Rose::LinkButton
|
||||
@route='scopes.scope.host-catalogs.new'
|
||||
@@ -113,13 +113,11 @@
|
||||
as |message|
|
||||
>
|
||||
<message.description>
|
||||
{{#if
|
||||
(can 'list collection' this.scope collection='host-catalogs')
|
||||
}}
|
||||
{{#if (can 'list model' this.scope collection='host-catalogs')}}
|
||||
{{! can list (at least): show default welcome message}}
|
||||
{{t 'resources.host-catalog.description'}}
|
||||
{{else if (can
|
||||
'create collection' this.scope collection='host-catalogs'
|
||||
'create model' this.scope collection='host-catalogs'
|
||||
)}}
|
||||
{{! can create (only): show create-but-not-list welcome message}}
|
||||
{{t
|
||||
@@ -134,9 +132,7 @@
|
||||
}}
|
||||
{{/if}}
|
||||
</message.description>
|
||||
{{#if
|
||||
(can 'create collection' this.scope collection='host-catalogs')
|
||||
}}
|
||||
{{#if (can 'create model' this.scope collection='host-catalogs')}}
|
||||
<message.link @route='scopes.scope.host-catalogs.new'>
|
||||
<Rose::Icon @name='flight-icons/svg/plus-circle-16' />
|
||||
{{t 'titles.new'}}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</page.header>
|
||||
|
||||
<page.actions>
|
||||
{{#if (can 'create collection' this.scope collection='roles')}}
|
||||
{{#if (can 'create model' this.scope collection='roles')}}
|
||||
{{#if @model}}
|
||||
<Rose::LinkButton @route='scopes.scope.roles.new' @style='primary'>{{t
|
||||
'titles.new'
|
||||
@@ -70,10 +70,10 @@
|
||||
as |message|
|
||||
>
|
||||
<message.description>
|
||||
{{#if (can 'list collection' this.scope collection='roles')}}
|
||||
{{#if (can 'list model' this.scope collection='roles')}}
|
||||
{{! can list (at least): show default welcome message}}
|
||||
{{t 'resources.roles.description'}}
|
||||
{{else if (can 'create collection' this.scope collection='roles')}}
|
||||
{{else if (can 'create model' this.scope collection='roles')}}
|
||||
{{! can create (only): show create-but-not-list welcome message}}
|
||||
{{t
|
||||
'descriptions.create-but-not-list'
|
||||
@@ -87,7 +87,7 @@
|
||||
}}
|
||||
{{/if}}
|
||||
</message.description>
|
||||
{{#if (can 'create collection' this.scope collection='roles')}}
|
||||
{{#if (can 'create model' this.scope collection='roles')}}
|
||||
<message.link @route='scopes.scope.roles.new'>
|
||||
<Rose::Icon @name='flight-icons/svg/plus-circle-16' />
|
||||
{{t 'titles.new'}}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</page.header>
|
||||
|
||||
<page.actions>
|
||||
{{#if (can 'create collection' @model.currentScope collection='scopes')}}
|
||||
{{#if (can 'create model' @model.currentScope collection='scopes')}}
|
||||
{{#if @model.subScopes}}
|
||||
<Rose::LinkButton @route='scopes.scope.new' @style='primary'>
|
||||
{{t 'titles.new'}}
|
||||
@@ -67,9 +67,7 @@
|
||||
<message.description>
|
||||
{{t 'resources.org.description'}}
|
||||
</message.description>
|
||||
{{#if
|
||||
(can 'create collection' @model.currentScope collection='scopes')
|
||||
}}
|
||||
{{#if (can 'create model' @model.currentScope collection='scopes')}}
|
||||
<message.link @route='scopes.scope.new'>
|
||||
<Rose::Icon @name='flight-icons/svg/plus-circle-16' />
|
||||
{{t 'titles.new'}}
|
||||
@@ -88,9 +86,7 @@
|
||||
<message.description>
|
||||
{{t 'resources.project.description'}}
|
||||
</message.description>
|
||||
{{#if
|
||||
(can 'create collection' @model.currentScope collection='scopes')
|
||||
}}
|
||||
{{#if (can 'create model' @model.currentScope collection='scopes')}}
|
||||
<message.link @route='scopes.scope.new'>
|
||||
<Rose::Icon @name='flight-icons/svg/plus-circle-16' />
|
||||
{{t 'titles.new'}}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</page.header>
|
||||
|
||||
<page.actions>
|
||||
{{#if (can 'create collection' this.scope collection='targets')}}
|
||||
{{#if (can 'create model' this.scope collection='targets')}}
|
||||
{{#if @model}}
|
||||
<Rose::LinkButton @route='scopes.scope.targets.new' @style='primary'>{{t
|
||||
'titles.new'
|
||||
@@ -81,12 +81,10 @@
|
||||
>
|
||||
<message.description>
|
||||
|
||||
{{#if (can 'list collection' this.scope collection='targets')}}
|
||||
{{#if (can 'list model' this.scope collection='targets')}}
|
||||
{{! can list (at least): show default welcome message}}
|
||||
{{t 'resources.target.description'}}
|
||||
{{else if (can
|
||||
'create collection' this.scope collection='targets'
|
||||
)}}
|
||||
{{else if (can 'create model' this.scope collection='targets')}}
|
||||
{{! can create (only): show create-but-not-list welcome message}}
|
||||
{{t
|
||||
'descriptions.create-but-not-list'
|
||||
@@ -102,7 +100,7 @@
|
||||
{{/if}}
|
||||
</message.description>
|
||||
|
||||
{{#if (can 'create collection' this.scope collection='targets')}}
|
||||
{{#if (can 'create model' this.scope collection='targets')}}
|
||||
<message.link @route='scopes.scope.targets.new'>
|
||||
<Rose::Icon @name='flight-icons/svg/plus-circle-16' />
|
||||
{{t 'titles.new'}}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</page.header>
|
||||
|
||||
<page.actions>
|
||||
{{#if (can 'create collection' this.scope collection='users')}}
|
||||
{{#if (can 'create model' this.scope collection='users')}}
|
||||
{{#if @model}}
|
||||
<Rose::LinkButton @route='scopes.scope.users.new' @style='primary'>{{t
|
||||
'titles.new'
|
||||
@@ -73,10 +73,10 @@
|
||||
as |message|
|
||||
>
|
||||
<message.description>
|
||||
{{#if (can 'list collection' this.scope collection='users')}}
|
||||
{{#if (can 'list model' this.scope collection='users')}}
|
||||
{{! can list (at least): show default welcome message}}
|
||||
{{t 'resources.user.description'}}
|
||||
{{else if (can 'create collection' this.scope collection='users')}}
|
||||
{{else if (can 'create model' this.scope collection='users')}}
|
||||
{{! can create (only): show create-but-not-list welcome message}}
|
||||
{{t
|
||||
'descriptions.create-but-not-list'
|
||||
@@ -90,7 +90,7 @@
|
||||
}}
|
||||
{{/if}}
|
||||
</message.description>
|
||||
{{#if (can 'create collection' this.scope collection='users')}}
|
||||
{{#if (can 'create model' this.scope collection='users')}}
|
||||
<message.link @route='scopes.scope.users.new'>
|
||||
<Rose::Icon @name='flight-icons/svg/plus-circle-16' />
|
||||
{{t 'titles.new'}}
|
||||
|
||||
@@ -95,7 +95,6 @@ module.exports = function (environment) {
|
||||
'oidc-account-crud': true,
|
||||
search: false,
|
||||
filter: true,
|
||||
capabilities: true,
|
||||
'credential-store': true,
|
||||
'managed-groups': true,
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
|
||||
module('Unit | Abilities | Collection', function (hooks) {
|
||||
module('Unit | Abilities | model', function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
test('it reflects when a resource may be navigated to based on list and create actions', function (assert) {
|
||||
@@ -11,19 +11,13 @@ module('Unit | Abilities | Collection', function (hooks) {
|
||||
authorized_collection_actions: { foobars: [] },
|
||||
};
|
||||
assert.notOk(
|
||||
service.can('navigate collection', model, { collection: 'foobars' })
|
||||
service.can('navigate model', model, { collection: 'foobars' })
|
||||
);
|
||||
model.authorized_collection_actions.foobars = ['list'];
|
||||
assert.ok(
|
||||
service.can('navigate collection', model, { collection: 'foobars' })
|
||||
);
|
||||
assert.ok(service.can('navigate model', model, { collection: 'foobars' }));
|
||||
model.authorized_collection_actions.foobars = ['create'];
|
||||
assert.ok(
|
||||
service.can('navigate collection', model, { collection: 'foobars' })
|
||||
);
|
||||
assert.ok(service.can('navigate model', model, { collection: 'foobars' }));
|
||||
model.authorized_collection_actions.foobars = ['list', 'create'];
|
||||
assert.ok(
|
||||
service.can('navigate collection', model, { collection: 'foobars' })
|
||||
);
|
||||
assert.ok(service.can('navigate model', model, { collection: 'foobars' }));
|
||||
});
|
||||
});
|
||||
@@ -1,30 +0,0 @@
|
||||
import CollectionAbility from 'api/abilities/collection';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default class OverrideCollectionAbility extends CollectionAbility {
|
||||
// =services
|
||||
|
||||
@service features;
|
||||
|
||||
// =permissions
|
||||
|
||||
/**
|
||||
* Navigating to a resource is allowed if either list or create grants
|
||||
* are present.
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canNavigate() {
|
||||
return this.canList || this.canCreate;
|
||||
}
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* If the capabilities feature flag is disabled, actions are always
|
||||
* authorized. This mimics pre-capabilities behavior.
|
||||
*/
|
||||
hasAuthorizedCollectionAction() {
|
||||
if (!this.features.isEnabled('capabilities')) return true;
|
||||
return super.hasAuthorizedCollectionAction(...arguments);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,12 @@
|
||||
import ModelAbility from 'api/abilities/model';
|
||||
import { inject as service } from '@ember/service';
|
||||
|
||||
export default class OverrideModelAbility extends ModelAbility {
|
||||
// =services
|
||||
|
||||
@service features;
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* If the capabilities feature flag is disabled, actions are always
|
||||
* authorized. This mimics pre-capabilities behavior.
|
||||
* Navigating to a resource is allowed if either list or create grants
|
||||
* are present.
|
||||
* @type {boolean}
|
||||
*/
|
||||
hasAuthorizedAction() {
|
||||
if (!this.features.isEnabled('capabilities')) return true;
|
||||
return super.hasAuthorizedAction(...arguments);
|
||||
get canNavigate() {
|
||||
return this.canList || this.canCreate;
|
||||
}
|
||||
}
|
||||
@@ -58,7 +58,6 @@ module.exports = function (environment) {
|
||||
oidc: true,
|
||||
search: false,
|
||||
filter: true,
|
||||
capabilities: true,
|
||||
'credential-store': false,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
|
||||
module('Unit | Abilities | Collection', function (hooks) {
|
||||
module('Unit | Abilities | model', function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
test('it reflects when a resource may be navigated to based on list and create actions', function (assert) {
|
||||
@@ -11,19 +11,13 @@ module('Unit | Abilities | Collection', function (hooks) {
|
||||
authorized_collection_actions: { foobars: [] },
|
||||
};
|
||||
assert.notOk(
|
||||
service.can('navigate collection', model, { collection: 'foobars' })
|
||||
service.can('navigate model', model, { collection: 'foobars' })
|
||||
);
|
||||
model.authorized_collection_actions.foobars = ['list'];
|
||||
assert.ok(
|
||||
service.can('navigate collection', model, { collection: 'foobars' })
|
||||
);
|
||||
assert.ok(service.can('navigate model', model, { collection: 'foobars' }));
|
||||
model.authorized_collection_actions.foobars = ['create'];
|
||||
assert.ok(
|
||||
service.can('navigate collection', model, { collection: 'foobars' })
|
||||
);
|
||||
assert.ok(service.can('navigate model', model, { collection: 'foobars' }));
|
||||
model.authorized_collection_actions.foobars = ['list', 'create'];
|
||||
assert.ok(
|
||||
service.can('navigate collection', model, { collection: 'foobars' })
|
||||
);
|
||||
assert.ok(service.can('navigate model', model, { collection: 'foobars' }));
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user