Merge branch 'main' into fix-babel-plugin-ember-unmet-peer-dep

This commit is contained in:
Carlos Alcaide Corvo authored and GitHub committed 2022-01-31 14:13:08 -06:00
commit 99ba4f59c0
45 files changed
+154 -297

No files matched your search

-37
View File
@@ -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);
}
}
+27
View File
@@ -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
View File
@@ -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' }));
});
});
-30
View File
@@ -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);
}
}
+5 -12
View File
@@ -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',
})
) {
@@ -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',
})
) {
+1 -1
View File
@@ -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',
})
) {
+1 -1
View File
@@ -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 });
}
}
+1 -1
View File
@@ -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 });
}
}
+1 -1
View File
@@ -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 });
}
}
+8 -10
View File
@@ -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'
@@ -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
@@ -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>
@@ -27,7 +27,7 @@
<row.cell>
{{#if hostSet.isStatic}}
<Rose::Badge>
{{t (concat 'resources.host-set.types.' hostSet.type)}}
{{t (concat 'resources.host-set.types.' hostSet.compositeType)}}
</Rose::Badge>
{{else}}
<Rose::Badge
@@ -37,7 +37,7 @@
'-color-16'
}}
>
{{hostSet.compositeType}}
{{t (concat 'resources.host-set.types.' hostSet.compositeType)}}
</Rose::Badge>
{{/if}}
</row.cell>
@@ -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'
>
@@ -29,7 +29,7 @@
<row.cell>
{{#if host.isStatic}}
<Rose::Badge>
{{t (concat 'resources.host.types.' host.type)}}
{{t (concat 'resources.host.types.' host.compositeType)}}
</Rose::Badge>
{{else}}
<Rose::Badge
@@ -39,7 +39,7 @@
'-color-16'
}}
>
{{host.compositeType}}
{{t (concat 'resources.host.types.' host.compositeType)}}
</Rose::Badge>
{{/if}}
</row.cell>
@@ -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'}}
-1
View File
@@ -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' }));
});
});
-30
View File
@@ -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);
}
}
+5 -12
View File
@@ -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;
}
}
-1
View File
@@ -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' }));
});
});