diff --git a/addons/api/addon/abilities/collection.js b/addons/api/addon/abilities/collection.js new file mode 100644 index 000000000..8cb3ca2d7 --- /dev/null +++ b/addons/api/addon/abilities/collection.js @@ -0,0 +1,36 @@ +import { Ability } from 'ember-can'; + +/** + * Generic ability provides abilities common to all models in the API. + */ +export default class ModelAbility 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; + const collection = this.collection || {}; + return authorized_collection_actions[collection]?.includes(action); + } +} diff --git a/addons/api/app/abilities/collection.js b/addons/api/app/abilities/collection.js new file mode 100644 index 000000000..041825d2d --- /dev/null +++ b/addons/api/app/abilities/collection.js @@ -0,0 +1 @@ +export { default } from 'api/abilities/collection'; diff --git a/addons/api/tests/unit/abilities/collection-test.js b/addons/api/tests/unit/abilities/collection-test.js new file mode 100644 index 000000000..dd9037ee6 --- /dev/null +++ b/addons/api/tests/unit/abilities/collection-test.js @@ -0,0 +1,38 @@ +import { module, test } from 'qunit'; +import { setupTest } from 'ember-qunit'; + +module('Unit | Abilities | Model', 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 = []; + 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 = []; + assert.notOk( + service.can('create collection', model, { collection: 'foobars' }) + ); + }); +});