-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathability.js
More file actions
52 lines (48 loc) · 2 KB
/
ability.js
File metadata and controls
52 lines (48 loc) · 2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* CASL ability helpers.
*/
import { createMongoAbility } from '@casl/ability';
import { ref } from 'vue';
/**
* @desc Make a CASL ability reactive for Vue without Vue's `reactive()`.
* @casl/ability v7 freezes its internal rule structures, so a `reactive()`
* proxy over the frozen rules array throws a Proxy get-invariant TypeError on
* the first `.can()` call. Instead we track the ability's `updated` event with
* a ref, read inside `possibleRulesFor` (the path every can/cannot/relevantRuleFor
* call funnels through), so component computeds calling `ability.can()` re-run
* when rules change. Mirrors @casl/vue's internal reactiveAbility, which v3
* declares in its types but does not export at runtime.
* @param {import('@casl/ability').MongoAbility} ability - CASL ability instance
* @returns {import('@casl/ability').MongoAbility} the same instance, made reactive
*/
const toReactiveAbility = (ability) => {
const trigger = ref(true);
ability.on('updated', () => {
trigger.value = !trigger.value;
});
const possibleRulesFor = ability.possibleRulesFor.bind(ability);
ability.possibleRulesFor = (...args) => {
void trigger.value; // reactive read — tracks ability updates in computeds
return possibleRulesFor(...args); // forward all args (action, subject, field) unchanged
};
ability.can = ability.can.bind(ability);
ability.cannot = ability.cannot.bind(ability);
return ability;
};
/**
* @desc Reactive CASL ability instance initialised with an empty rule set.
*/
export const ability = toReactiveAbility(createMongoAbility([]));
/**
* @desc Replace the current ability rules with a new set received from the
* backend. Passing an empty array clears all permissions.
* @param {Array} rules - Array of CASL rule objects (e.g. `[{ action: 'read', subject: 'Article' }]`)
* @returns {void}
*/
export const updateAbilities = (rules) => {
ability.update(rules);
};
/**
* Exports.
*/
export default { ability, updateAbilities };