feat: 🎸 add basic abilities modeling for read/update/delete
This commit is contained in:
5 files changed
+1338
-820
No files matched your search
@@ -0,0 +1,59 @@
|
||||
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 canRead() {
|
||||
return this.hasAuthorizedAction('read');
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canUpdate() {
|
||||
return this.hasAuthorizedAction('update');
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canDelete() {
|
||||
return this.hasAuthorizedAction('delete');
|
||||
}
|
||||
|
||||
/**
|
||||
* To save an existing model (already persisted to the API), it must contain
|
||||
* the the `update` authorized action.
|
||||
*
|
||||
* For now, new models _always_ have this ability. The reason is because the
|
||||
* `create` action is authorized on collections, not individual records. So
|
||||
* this function can't actually tell from a model instance if create
|
||||
* is allowed.
|
||||
*
|
||||
* @type {boolean}
|
||||
*/
|
||||
get canSave() {
|
||||
if (this.model.isNew || (!this.model.isNew && this.canUpdate)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// =methods
|
||||
|
||||
/**
|
||||
* Returns true if the given action is contained in the ability model's
|
||||
* `authorized_actions` array.
|
||||
* @param {string} action
|
||||
* @return {boolean}
|
||||
*/
|
||||
hasAuthorizedAction(action) {
|
||||
return this.model.authorized_actions?.includes(action);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default } from 'api/abilities/model';
|
||||
@@ -24,6 +24,7 @@
|
||||
"doc:toc": "doctoc README.md"
|
||||
},
|
||||
"dependencies": {
|
||||
"ember-can": "^3.1.0",
|
||||
"ember-cli-babel": "^7.23.0",
|
||||
"ember-cli-htmlbars": "^5.3.1",
|
||||
"ember-cli-mirage": "^1.1.8",
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
import { module, test } from 'qunit';
|
||||
import { setupTest } from 'ember-qunit';
|
||||
|
||||
module('Unit | Abilities | Model', function (hooks) {
|
||||
setupTest(hooks);
|
||||
|
||||
test('it reflects when a given model may be read based on authorized_actions', function (assert) {
|
||||
assert.expect(2);
|
||||
const service = this.owner.lookup('service:can');
|
||||
const store = this.owner.lookup('service:store');
|
||||
const model = store.createRecord('account', {
|
||||
authorized_actions: ['read'],
|
||||
});
|
||||
assert.ok(service.can('read model', model));
|
||||
model.authorized_actions = [];
|
||||
assert.notOk(service.can('read model', model));
|
||||
});
|
||||
|
||||
test('it reflects when a given model may be updated based on authorized_actions', function (assert) {
|
||||
assert.expect(2);
|
||||
const service = this.owner.lookup('service:can');
|
||||
const store = this.owner.lookup('service:store');
|
||||
const model = store.createRecord('account', {
|
||||
authorized_actions: ['update'],
|
||||
});
|
||||
assert.ok(service.can('update model', model));
|
||||
model.authorized_actions = [];
|
||||
assert.notOk(service.can('update model', model));
|
||||
});
|
||||
|
||||
test('it reflects when a given model may be deleted based on authorized_actions', function (assert) {
|
||||
assert.expect(2);
|
||||
const service = this.owner.lookup('service:can');
|
||||
const store = this.owner.lookup('service:store');
|
||||
const model = store.createRecord('account', {
|
||||
authorized_actions: ['delete'],
|
||||
});
|
||||
assert.ok(service.can('delete model', model));
|
||||
model.authorized_actions = [];
|
||||
assert.notOk(service.can('delete model', model));
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user