UNPKG

1.87 kBJavaScriptView Raw
1const ACLInterface = require('./base')
2const objectDeepKeys = require('../utils/object-deep-keys')
3const { permittedFieldsOf } = require('@casl/ability/extra')
4
5class CASL extends ACLInterface {
6 _checkIndividualAccess(item, inputItem) {
7 // Check whether the user can perform a particular action
8 // NOTE: body is only used for BUILDING the rules, not CHECKING it!
9 const ability = this.acl(
10 this.user,
11 item,
12 this.action,
13 inputItem,
14 this.opts,
15 this.relation
16 )
17
18 // Now that we don't need to "filter out" wrong inputs,
19 // we can simply check all of the attributes it's trying to change.
20 // Note that we're passing ALL the fields, including the embedded ones,
21 // as dot notation for the ability checker;
22 // normally this would be overkill but this covers cases where you're somehow
23 // checking ACL on deep, nested fields.
24 const fields = objectDeepKeys(inputItem)
25 const resource =
26 this.opts.casl.useInputItemAsResourceForRelation && this.relation
27 ? inputItem
28 : item
29
30 if (fields.length) {
31 for (let i = 0; i < fields.length; i++)
32 if (ability.cannot(this.action, resource, fields[i])) return false
33 return true
34 } else return ability.can(this.action, resource)
35 }
36
37 get allowedFields() {
38 const modelInstance = this.items[0]
39 const fields = objectDeepKeys(modelInstance)
40 const ability = this.acl(
41 this.user,
42 modelInstance,
43 this.action,
44 this.inputItems[0],
45 this.opts
46 )
47
48 // casl on its own does not have any idea what all of the fields available are.
49 // Therefore, we must inject them directly by reading them from the actual model instance
50 return permittedFieldsOf(ability, this.action, modelInstance, {
51 fieldsFrom: rule => rule.fields || fields
52 })
53 }
54}
55
56module.exports = CASL