feat: 🎸 add basic abilities modeling for read/update/delete

This commit is contained in:
Randall Morey committed 2021-07-23 16:40:51 -04:00
1 parent c45357bf25
commit 48dc8a392d
5 files changed
+1338 -820

No files matched your search

+59
View File
@@ -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);
}
}
+1
View File
@@ -0,0 +1 @@
export { default } from 'api/abilities/model';
+1
View File
@@ -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));
});
});
+1235 -820
View File
File diff suppressed because it is too large. Load diff