@via-profit/ability 3.4.1 → 3.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -11
- package/dist/index.d.ts +574 -19
- package/dist/index.js +38 -123
- package/package.json +19 -18
- package/dist/cache/AbilityCacheAdapter.d.ts +0 -8
- package/dist/cache/AbilityInMemoryCache.d.ts +0 -12
- package/dist/core/AbilityCode.d.ts +0 -8
- package/dist/core/AbilityCompare.d.ts +0 -7
- package/dist/core/AbilityCondition.d.ts +0 -23
- package/dist/core/AbilityError.d.ts +0 -6
- package/dist/core/AbilityExplain.d.ts +0 -27
- package/dist/core/AbilityMatch.d.ts +0 -8
- package/dist/core/AbilityPolicy.d.ts +0 -79
- package/dist/core/AbilityPolicyEffect.d.ts +0 -7
- package/dist/core/AbilityResolver.d.ts +0 -35
- package/dist/core/AbilityResult.d.ts +0 -27
- package/dist/core/AbilityRule.d.ts +0 -88
- package/dist/core/AbilityRuleSet.d.ts +0 -51
- package/dist/core/AbilityTypeGenerator.d.ts +0 -55
- package/dist/parsers/dsl/AbilityDSLLexer.d.ts +0 -24
- package/dist/parsers/dsl/AbilityDSLParser.d.ts +0 -85
- package/dist/parsers/dsl/AbilityDSLSyntaxError.d.ts +0 -13
- package/dist/parsers/dsl/AbilityDSLToken.d.ts +0 -57
- package/dist/parsers/json/AbilityJSONParser.d.ts +0 -22
package/dist/index.js
CHANGED
|
@@ -130,7 +130,7 @@ class AbilityCondition extends AbilityCode {
|
|
|
130
130
|
case 'never':
|
|
131
131
|
return 'never';
|
|
132
132
|
default:
|
|
133
|
-
throw new Error(`Unknown condition code: ${this.code}`);
|
|
133
|
+
throw new Error(`Unknown condition code: ${String(this.code)}`);
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
}
|
|
@@ -167,8 +167,11 @@ class AbilityTypeGenerator {
|
|
|
167
167
|
const subjectPath = rule.subject;
|
|
168
168
|
const existingType = typeStructure[action][subjectPath];
|
|
169
169
|
const ruleType = this.determineTypeFromRule(rule);
|
|
170
|
-
|
|
170
|
+
if (!ruleType) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
171
173
|
if (existingType && existingType !== ruleType) {
|
|
174
|
+
// If a type already exists for this path, create a union
|
|
172
175
|
typeStructure[action][subjectPath] = `${existingType} | ${ruleType}`;
|
|
173
176
|
}
|
|
174
177
|
else {
|
|
@@ -187,6 +190,10 @@ class AbilityTypeGenerator {
|
|
|
187
190
|
* @returns TypeScript type as string
|
|
188
191
|
*/
|
|
189
192
|
determineTypeFromRule(rule) {
|
|
193
|
+
if (rule.condition.isEqual(AbilityCondition.never) ||
|
|
194
|
+
rule.condition.isEqual(AbilityCondition.always)) {
|
|
195
|
+
return null;
|
|
196
|
+
}
|
|
190
197
|
// Numeric comparisons - always number
|
|
191
198
|
if (rule.condition.isEqual(AbilityCondition.greater_than) ||
|
|
192
199
|
rule.condition.isEqual(AbilityCondition.less_than) ||
|
|
@@ -213,8 +220,9 @@ class AbilityTypeGenerator {
|
|
|
213
220
|
*/
|
|
214
221
|
getArrayType(resource) {
|
|
215
222
|
if (Array.isArray(resource)) {
|
|
216
|
-
if (resource.length === 0)
|
|
223
|
+
if (resource.length === 0) {
|
|
217
224
|
return 'any[]';
|
|
225
|
+
}
|
|
218
226
|
// Determine types of array elements
|
|
219
227
|
const elementTypes = new Set(resource.map(item => this.getPrimitiveType(item)));
|
|
220
228
|
const elementType = elementTypes.size === 1
|
|
@@ -232,10 +240,12 @@ class AbilityTypeGenerator {
|
|
|
232
240
|
* @returns TypeScript primitive type as string
|
|
233
241
|
*/
|
|
234
242
|
getPrimitiveType(value) {
|
|
235
|
-
if (value === null)
|
|
243
|
+
if (value === null) {
|
|
236
244
|
return 'null';
|
|
237
|
-
|
|
245
|
+
}
|
|
246
|
+
if (value === undefined) {
|
|
238
247
|
return 'undefined';
|
|
248
|
+
}
|
|
239
249
|
switch (typeof value) {
|
|
240
250
|
case 'string':
|
|
241
251
|
return 'string';
|
|
@@ -294,12 +304,20 @@ class AbilityTypeGenerator {
|
|
|
294
304
|
let output = '// Automatically generated by via-profit/ability\n';
|
|
295
305
|
output += '// Do not edit manually\n';
|
|
296
306
|
output += 'export type Resources = {\n';
|
|
297
|
-
// Sort actions for stable output
|
|
298
307
|
const sortedActions = Object.keys(structure).sort();
|
|
299
308
|
sortedActions.forEach(action => {
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
309
|
+
const actionObj = structure[action];
|
|
310
|
+
const isEmpty = Object.keys(actionObj).length === 0;
|
|
311
|
+
if (isEmpty) {
|
|
312
|
+
// Пустой объект → undefined
|
|
313
|
+
output += ` ['${action}']: undefined;\n`;
|
|
314
|
+
}
|
|
315
|
+
else {
|
|
316
|
+
// Непустой объект → как раньше
|
|
317
|
+
output += ` ['${action}']: {\n`;
|
|
318
|
+
output += this.formatNestedObject(actionObj, 4);
|
|
319
|
+
output += ' };\n';
|
|
320
|
+
}
|
|
303
321
|
});
|
|
304
322
|
output += '}\n';
|
|
305
323
|
return output;
|
|
@@ -444,14 +462,14 @@ class AbilityPolicy {
|
|
|
444
462
|
* @param resource - The resource to check
|
|
445
463
|
* @param environment - The user environment object
|
|
446
464
|
*/
|
|
447
|
-
|
|
465
|
+
check(resource, environment) {
|
|
448
466
|
this.matchState = AbilityMatch.mismatch;
|
|
449
467
|
if (!this.ruleSet.length) {
|
|
450
468
|
return this.matchState;
|
|
451
469
|
}
|
|
452
470
|
const rulesetCheckStates = [];
|
|
453
471
|
for (const ruleSet of this.ruleSet) {
|
|
454
|
-
const state =
|
|
472
|
+
const state = ruleSet.check(resource, environment);
|
|
455
473
|
rulesetCheckStates.push(state);
|
|
456
474
|
if (AbilityCompare.and.isEqual(this.compareMethod) && AbilityMatch.mismatch.isEqual(state)) {
|
|
457
475
|
return this.matchState; // mismatch
|
|
@@ -553,14 +571,11 @@ class AbilityResult {
|
|
|
553
571
|
|
|
554
572
|
class AbilityResolver {
|
|
555
573
|
policies;
|
|
556
|
-
cache;
|
|
557
574
|
constructor(
|
|
558
575
|
/**
|
|
559
576
|
* `Important!` The incorrect Resources type was intentionally passed to AbilityPolicy so that TypeScript could suggest the name of the permission and the structure of its resource in the parse method.
|
|
560
577
|
*/
|
|
561
|
-
policyOrListOfPolicies
|
|
562
|
-
const { cache } = options || {};
|
|
563
|
-
this.cache = cache;
|
|
578
|
+
policyOrListOfPolicies) {
|
|
564
579
|
this.policies = Array.isArray(policyOrListOfPolicies)
|
|
565
580
|
? policyOrListOfPolicies
|
|
566
581
|
: [policyOrListOfPolicies];
|
|
@@ -572,30 +587,18 @@ class AbilityResolver {
|
|
|
572
587
|
* @param resource - Resource
|
|
573
588
|
* @param environment
|
|
574
589
|
*/
|
|
575
|
-
|
|
590
|
+
resolve(permission, resource, environment) {
|
|
576
591
|
const filteredPolicies = this.policies.filter(policy => AbilityResolver.isInPermissionContain(policy.permission, String(permission).replace(/^permission\./, '')));
|
|
577
592
|
for (const policy of filteredPolicies) {
|
|
578
|
-
const
|
|
579
|
-
// cache
|
|
580
|
-
if (this.cache) {
|
|
581
|
-
const cached = await this.cache.get(cacheKey);
|
|
582
|
-
if (cached !== undefined) {
|
|
583
|
-
policy.matchState = cached;
|
|
584
|
-
continue;
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
const policyMatchState = await policy.check(resource, environment);
|
|
593
|
+
const policyMatchState = policy.check(resource, environment);
|
|
588
594
|
if (policyMatchState === AbilityMatch.pending) {
|
|
589
595
|
throw new AbilityError(`The policy "${policy.name}" is still in a pending state. Make sure to call "check" to evaluate the policy before resolving permissions.`);
|
|
590
596
|
}
|
|
591
|
-
if (this.cache) {
|
|
592
|
-
await this.cache.set(cacheKey, policyMatchState);
|
|
593
|
-
}
|
|
594
597
|
}
|
|
595
598
|
return new AbilityResult(filteredPolicies);
|
|
596
599
|
}
|
|
597
|
-
|
|
598
|
-
const result =
|
|
600
|
+
enforce(permission, resource, environment) {
|
|
601
|
+
const result = this.resolve(permission, resource, environment);
|
|
599
602
|
if (result.isDenied()) {
|
|
600
603
|
const lastPolicy = result.getLastMatchedPolicy();
|
|
601
604
|
if (lastPolicy) {
|
|
@@ -618,18 +621,6 @@ class AbilityResolver {
|
|
|
618
621
|
return chunk === '*' || longer[i] === '*' || chunk === longer[i];
|
|
619
622
|
});
|
|
620
623
|
}
|
|
621
|
-
makeCacheKey(policyId, resource, environment) {
|
|
622
|
-
if (!this.cache) {
|
|
623
|
-
return '';
|
|
624
|
-
}
|
|
625
|
-
return `policy:${policyId}:res:${this.cache.serialize(resource)}:env:${this.cache.serialize(environment)}`;
|
|
626
|
-
}
|
|
627
|
-
async invalidatePolicy(policyId) {
|
|
628
|
-
await this.cache?.deleteByPrefix(policyId);
|
|
629
|
-
}
|
|
630
|
-
async invalidateCache() {
|
|
631
|
-
await this.cache?.clear();
|
|
632
|
-
}
|
|
633
624
|
}
|
|
634
625
|
|
|
635
626
|
/**
|
|
@@ -776,7 +767,7 @@ class AbilityRule {
|
|
|
776
767
|
* @param resource - The resource to check
|
|
777
768
|
* @param environment
|
|
778
769
|
*/
|
|
779
|
-
|
|
770
|
+
check(resource, environment) {
|
|
780
771
|
const [subjectValue, resourceValue] = this.extractValues(resource, environment);
|
|
781
772
|
const handler = this.operatorHandlers[this.condition.literal];
|
|
782
773
|
const result = handler(subjectValue, resourceValue);
|
|
@@ -979,14 +970,14 @@ class AbilityRuleSet {
|
|
|
979
970
|
rules.forEach(rule => this.addRule(rule));
|
|
980
971
|
return this;
|
|
981
972
|
}
|
|
982
|
-
|
|
973
|
+
check(resources, environment) {
|
|
983
974
|
this.state = AbilityMatch.mismatch;
|
|
984
975
|
if (!this.rules.length) {
|
|
985
976
|
return this.state;
|
|
986
977
|
}
|
|
987
978
|
const ruleCheckStates = [];
|
|
988
979
|
for (const rule of this.rules) {
|
|
989
|
-
const state =
|
|
980
|
+
const state = rule.check(resources, environment);
|
|
990
981
|
ruleCheckStates.push(state);
|
|
991
982
|
if (AbilityCompare.and.isEqual(this.compareMethod) && AbilityMatch.mismatch.isEqual(state)) {
|
|
992
983
|
return this.state; // mismatch
|
|
@@ -1035,79 +1026,6 @@ class AbilityRuleSet {
|
|
|
1035
1026
|
}
|
|
1036
1027
|
}
|
|
1037
1028
|
|
|
1038
|
-
class AbilityInMemoryCache {
|
|
1039
|
-
store = new Map();
|
|
1040
|
-
async get(key) {
|
|
1041
|
-
const entry = this.store.get(key);
|
|
1042
|
-
if (!entry)
|
|
1043
|
-
return undefined;
|
|
1044
|
-
if (Date.now() > entry.expires) {
|
|
1045
|
-
this.store.delete(key);
|
|
1046
|
-
return undefined;
|
|
1047
|
-
}
|
|
1048
|
-
return entry.value;
|
|
1049
|
-
}
|
|
1050
|
-
async set(key, value, ttlSeconds = 60) {
|
|
1051
|
-
this.store.set(key, {
|
|
1052
|
-
value,
|
|
1053
|
-
expires: Date.now() + ttlSeconds * 1000,
|
|
1054
|
-
});
|
|
1055
|
-
}
|
|
1056
|
-
serialize(input) {
|
|
1057
|
-
return this.fastHash(this.stableStringify(input));
|
|
1058
|
-
}
|
|
1059
|
-
async delete(key) {
|
|
1060
|
-
this.store.delete(key);
|
|
1061
|
-
}
|
|
1062
|
-
async clear() {
|
|
1063
|
-
this.store.clear();
|
|
1064
|
-
}
|
|
1065
|
-
async deleteByPrefix(prefix) {
|
|
1066
|
-
for (const key of this.store.keys()) {
|
|
1067
|
-
if (key.startsWith(prefix)) {
|
|
1068
|
-
this.store.delete(key);
|
|
1069
|
-
}
|
|
1070
|
-
}
|
|
1071
|
-
}
|
|
1072
|
-
fastHash(str) {
|
|
1073
|
-
let hash = 5381;
|
|
1074
|
-
for (let i = 0; i < str.length; i++) {
|
|
1075
|
-
hash = (hash * 33) ^ str.charCodeAt(i);
|
|
1076
|
-
}
|
|
1077
|
-
return (hash >>> 0).toString(36);
|
|
1078
|
-
}
|
|
1079
|
-
stableStringify(obj) {
|
|
1080
|
-
if (obj === null)
|
|
1081
|
-
return 'null';
|
|
1082
|
-
const type = typeof obj;
|
|
1083
|
-
if (type === 'string')
|
|
1084
|
-
return JSON.stringify(obj);
|
|
1085
|
-
if (type === 'number' || type === 'boolean')
|
|
1086
|
-
return String(obj);
|
|
1087
|
-
if (type === 'undefined')
|
|
1088
|
-
return 'undefined';
|
|
1089
|
-
if (Array.isArray(obj)) {
|
|
1090
|
-
let out = '[';
|
|
1091
|
-
for (let i = 0; i < obj.length; i++) {
|
|
1092
|
-
if (i > 0)
|
|
1093
|
-
out += ',';
|
|
1094
|
-
out += this.stableStringify(obj[i]);
|
|
1095
|
-
}
|
|
1096
|
-
return out + ']';
|
|
1097
|
-
}
|
|
1098
|
-
const keys = Object.keys(obj);
|
|
1099
|
-
keys.sort();
|
|
1100
|
-
let out = '{';
|
|
1101
|
-
for (let i = 0; i < keys.length; i++) {
|
|
1102
|
-
const k = keys[i];
|
|
1103
|
-
if (i > 0)
|
|
1104
|
-
out += ',';
|
|
1105
|
-
out += k + ':' + this.stableStringify(obj[k]);
|
|
1106
|
-
}
|
|
1107
|
-
return out + '}';
|
|
1108
|
-
}
|
|
1109
|
-
}
|
|
1110
|
-
|
|
1111
1029
|
class AbilityJSONParser {
|
|
1112
1030
|
/**
|
|
1113
1031
|
* Parses an array of policy configurations into an array of AbilityPolicy instances.
|
|
@@ -2185,9 +2103,7 @@ class AbilityDSLParser {
|
|
|
2185
2103
|
return best;
|
|
2186
2104
|
}
|
|
2187
2105
|
levenshteinDistance(a, b) {
|
|
2188
|
-
const matrix = Array(b.length + 1)
|
|
2189
|
-
.fill(null)
|
|
2190
|
-
.map(() => Array(a.length + 1).fill(null));
|
|
2106
|
+
const matrix = Array.from({ length: b.length + 1 }, () => Array.from({ length: a.length + 1 }, () => 0));
|
|
2191
2107
|
for (let i = 0; i <= a.length; i++)
|
|
2192
2108
|
matrix[0][i] = i;
|
|
2193
2109
|
for (let j = 0; j <= b.length; j++)
|
|
@@ -2262,7 +2178,6 @@ exports.AbilityExplain = AbilityExplain;
|
|
|
2262
2178
|
exports.AbilityExplainPolicy = AbilityExplainPolicy;
|
|
2263
2179
|
exports.AbilityExplainRule = AbilityExplainRule;
|
|
2264
2180
|
exports.AbilityExplainRuleSet = AbilityExplainRuleSet;
|
|
2265
|
-
exports.AbilityInMemoryCache = AbilityInMemoryCache;
|
|
2266
2181
|
exports.AbilityJSONParser = AbilityJSONParser;
|
|
2267
2182
|
exports.AbilityMatch = AbilityMatch;
|
|
2268
2183
|
exports.AbilityParserError = AbilityParserError;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@via-profit/ability",
|
|
3
3
|
"support": "https://via-profit.ru",
|
|
4
|
-
"version": "3.
|
|
4
|
+
"version": "3.5.0",
|
|
5
5
|
"description": "Via-Profit Ability service",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"ability",
|
|
@@ -43,31 +43,32 @@
|
|
|
43
43
|
],
|
|
44
44
|
"license": "MIT",
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@eslint/js": "^
|
|
46
|
+
"@eslint/js": "^10.0.1",
|
|
47
47
|
"@jagi/jest-transform-graphql": "^1.0.2",
|
|
48
|
-
"@jest/types": "^
|
|
48
|
+
"@jest/types": "^30.3.0",
|
|
49
49
|
"@rollup/plugin-alias": "^6.0.0",
|
|
50
50
|
"@rollup/plugin-commonjs": "^29.0.2",
|
|
51
51
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
52
52
|
"@rollup/plugin-typescript": "^12.3.0",
|
|
53
|
-
"@types/jest": "^
|
|
54
|
-
"@types/node": "^
|
|
55
|
-
"
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"eslint": "^
|
|
59
|
-
"globals": "^
|
|
60
|
-
"jest": "^
|
|
53
|
+
"@types/jest": "^30.0.0",
|
|
54
|
+
"@types/node": "^25.5.0",
|
|
55
|
+
"concurrently": "^9.2.1",
|
|
56
|
+
"cross-env": "^10.1.0",
|
|
57
|
+
"eslint": "^10.1.0",
|
|
58
|
+
"eslint-plugin-jest": "^29.15.1",
|
|
59
|
+
"globals": "^17.4.0",
|
|
60
|
+
"jest": "^30.3.0",
|
|
61
61
|
"jest-transform-graphql": "^2.1.0",
|
|
62
|
-
"nodemon": "^3.1.
|
|
63
|
-
"prettier": "^3.
|
|
64
|
-
"rollup": "^4.60.
|
|
62
|
+
"nodemon": "^3.1.14",
|
|
63
|
+
"prettier": "^3.8.1",
|
|
64
|
+
"rollup": "^4.60.1",
|
|
65
65
|
"rollup-plugin-copy": "^3.5.0",
|
|
66
|
+
"rollup-plugin-dts": "^6.4.1",
|
|
66
67
|
"tinybench": "^6.0.0",
|
|
67
|
-
"ts-jest": "^29.
|
|
68
|
-
"ts-loader": "^9.5.
|
|
68
|
+
"ts-jest": "^29.4.9",
|
|
69
|
+
"ts-loader": "^9.5.4",
|
|
69
70
|
"ts-node": "^10.9.2",
|
|
70
|
-
"typescript": "^
|
|
71
|
-
"typescript-eslint": "^8.
|
|
71
|
+
"typescript": "^6.0.2",
|
|
72
|
+
"typescript-eslint": "^8.58.0"
|
|
72
73
|
}
|
|
73
74
|
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export interface AbilityCacheAdapter {
|
|
2
|
-
get<T = unknown>(key: string): Promise<T | undefined>;
|
|
3
|
-
set<T = unknown>(key: string, value: T, ttlSeconds?: number): Promise<void>;
|
|
4
|
-
serialize<T = unknown>(input: T): string;
|
|
5
|
-
delete(key: string): Promise<void>;
|
|
6
|
-
clear(): Promise<void>;
|
|
7
|
-
deleteByPrefix(prefix: string): Promise<void>;
|
|
8
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { AbilityCacheAdapter } from '../cache/AbilityCacheAdapter';
|
|
2
|
-
export declare class AbilityInMemoryCache implements AbilityCacheAdapter {
|
|
3
|
-
private store;
|
|
4
|
-
get<T>(key: string): Promise<T | undefined>;
|
|
5
|
-
set<T>(key: string, value: T, ttlSeconds?: number): Promise<void>;
|
|
6
|
-
serialize(input: unknown): string;
|
|
7
|
-
delete(key: string): Promise<void>;
|
|
8
|
-
clear(): Promise<void>;
|
|
9
|
-
deleteByPrefix(prefix: string): Promise<void>;
|
|
10
|
-
private fastHash;
|
|
11
|
-
private stableStringify;
|
|
12
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
export declare class AbilityCode<Code extends string | number> {
|
|
2
|
-
_code: Code;
|
|
3
|
-
constructor(code: Code);
|
|
4
|
-
get code(): Code;
|
|
5
|
-
isEqual(compareWith: AbilityCode<Code> | null): boolean;
|
|
6
|
-
isNotEqual(compareWith: AbilityCode<Code> | null): boolean;
|
|
7
|
-
}
|
|
8
|
-
export default AbilityCode;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import AbilityCode from './AbilityCode';
|
|
2
|
-
export type AbilityCompareCodeType = 'and' | 'or';
|
|
3
|
-
export declare class AbilityCompare extends AbilityCode<AbilityCompareCodeType> {
|
|
4
|
-
static and: AbilityCompare;
|
|
5
|
-
static or: AbilityCompare;
|
|
6
|
-
}
|
|
7
|
-
export default AbilityCompare;
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import AbilityCode from './AbilityCode';
|
|
2
|
-
export type AbilityConditionCodeType = '=' | '<>' | '>' | '<' | '>=' | '<=' | 'in' | 'not in' | 'contains' | 'not contains' | 'length greater than' | 'length less than' | 'length equals' | 'always' | 'never';
|
|
3
|
-
export type AbilityConditionLiteralType = 'equals' | 'not_equals' | 'contains' | 'not_contains' | 'in' | 'not_in' | 'greater_than' | 'less_than' | 'less_or_equal' | 'greater_or_equal' | 'length_greater_than' | 'length_less_than' | 'length_equals' | 'always' | 'never';
|
|
4
|
-
export declare class AbilityCondition extends AbilityCode<AbilityConditionCodeType> {
|
|
5
|
-
static equals: AbilityCondition;
|
|
6
|
-
static not_equals: AbilityCondition;
|
|
7
|
-
static greater_than: AbilityCondition;
|
|
8
|
-
static less_than: AbilityCondition;
|
|
9
|
-
static less_or_equal: AbilityCondition;
|
|
10
|
-
static greater_or_equal: AbilityCondition;
|
|
11
|
-
static in: AbilityCondition;
|
|
12
|
-
static not_in: AbilityCondition;
|
|
13
|
-
static contains: AbilityCondition;
|
|
14
|
-
static not_contains: AbilityCondition;
|
|
15
|
-
static length_greater_than: AbilityCondition;
|
|
16
|
-
static length_less_than: AbilityCondition;
|
|
17
|
-
static length_equals: AbilityCondition;
|
|
18
|
-
static always: AbilityCondition;
|
|
19
|
-
static never: AbilityCondition;
|
|
20
|
-
static fromLiteral(literal: AbilityConditionLiteralType): AbilityCondition;
|
|
21
|
-
get literal(): AbilityConditionLiteralType;
|
|
22
|
-
}
|
|
23
|
-
export default AbilityCondition;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import AbilityRule from './AbilityRule';
|
|
2
|
-
import AbilityRuleSet from '../core/AbilityRuleSet';
|
|
3
|
-
import AbilityPolicy from '../core/AbilityPolicy';
|
|
4
|
-
import AbilityMatch from '../core/AbilityMatch';
|
|
5
|
-
export type AbilityExplainConfig = {
|
|
6
|
-
readonly type: AbilityExplainType;
|
|
7
|
-
readonly name: string;
|
|
8
|
-
readonly match: AbilityMatch;
|
|
9
|
-
};
|
|
10
|
-
export declare class AbilityExplain {
|
|
11
|
-
readonly type: AbilityExplainType;
|
|
12
|
-
readonly children: AbilityExplain[];
|
|
13
|
-
readonly name: string;
|
|
14
|
-
readonly match: AbilityMatch;
|
|
15
|
-
constructor(config: AbilityExplainConfig, children?: AbilityExplain[]);
|
|
16
|
-
toString(indent?: number): string;
|
|
17
|
-
}
|
|
18
|
-
export declare class AbilityExplainRule extends AbilityExplain {
|
|
19
|
-
constructor(rule: AbilityRule);
|
|
20
|
-
}
|
|
21
|
-
export declare class AbilityExplainRuleSet extends AbilityExplain {
|
|
22
|
-
constructor(ruleSet: AbilityRuleSet);
|
|
23
|
-
}
|
|
24
|
-
export declare class AbilityExplainPolicy extends AbilityExplain {
|
|
25
|
-
constructor(policy: AbilityPolicy);
|
|
26
|
-
}
|
|
27
|
-
export type AbilityExplainType = 'policy' | 'rule' | 'ruleSet';
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import AbilityCode from './AbilityCode';
|
|
2
|
-
export type AbilityMatchCodeType = 'pending' | 'match' | 'mismatch';
|
|
3
|
-
export declare class AbilityMatch extends AbilityCode<AbilityMatchCodeType> {
|
|
4
|
-
static pending: AbilityMatch;
|
|
5
|
-
static match: AbilityMatch;
|
|
6
|
-
static mismatch: AbilityMatch;
|
|
7
|
-
}
|
|
8
|
-
export default AbilityMatch;
|
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import AbilityRuleSet, { AbilityRuleSetConfig } from './AbilityRuleSet';
|
|
2
|
-
import AbilityMatch from './AbilityMatch';
|
|
3
|
-
import AbilityCompare, { AbilityCompareCodeType } from './AbilityCompare';
|
|
4
|
-
import AbilityPolicyEffect, { AbilityPolicyEffectCodeType } from './AbilityPolicyEffect';
|
|
5
|
-
import { AbilityExplain } from './AbilityExplain';
|
|
6
|
-
import { ResourceObject } from './AbilityTypeGenerator';
|
|
7
|
-
export type AbilityPolicyConfig = {
|
|
8
|
-
readonly permission: string;
|
|
9
|
-
readonly effect: AbilityPolicyEffectCodeType;
|
|
10
|
-
readonly compareMethod: AbilityCompareCodeType;
|
|
11
|
-
readonly ruleSet: readonly AbilityRuleSetConfig[];
|
|
12
|
-
readonly id: string;
|
|
13
|
-
readonly name: string;
|
|
14
|
-
};
|
|
15
|
-
export type AbilityPolicyConstructorProps = {
|
|
16
|
-
id: string;
|
|
17
|
-
name: string;
|
|
18
|
-
permission: string;
|
|
19
|
-
effect: AbilityPolicyEffect;
|
|
20
|
-
compareMethod?: AbilityCompare;
|
|
21
|
-
};
|
|
22
|
-
export declare class AbilityPolicy<Resource extends ResourceObject = Record<string, unknown>, Environment = unknown> {
|
|
23
|
-
matchState: AbilityMatch;
|
|
24
|
-
/**
|
|
25
|
-
* List of rules
|
|
26
|
-
*/
|
|
27
|
-
ruleSet: AbilityRuleSet<Resource, Environment>[];
|
|
28
|
-
/**
|
|
29
|
-
* Policy effect
|
|
30
|
-
*/
|
|
31
|
-
effect: AbilityPolicyEffect;
|
|
32
|
-
/**
|
|
33
|
-
* Rules compare method.\
|
|
34
|
-
* For the «and» method the rule will be permitted if all\
|
|
35
|
-
* rules will be returns «permit» status and for the «or» - if\
|
|
36
|
-
* one of the rules returns as «permit»
|
|
37
|
-
*/
|
|
38
|
-
compareMethod: AbilityCompare;
|
|
39
|
-
/**
|
|
40
|
-
* Policy name
|
|
41
|
-
*/
|
|
42
|
-
name: string;
|
|
43
|
-
/**
|
|
44
|
-
* Policy ID
|
|
45
|
-
*/
|
|
46
|
-
id: string;
|
|
47
|
-
/**
|
|
48
|
-
* Running the `enforce` or `resolve` method
|
|
49
|
-
* will select only those from all passed policies that fall under the specified permission key.
|
|
50
|
-
*/
|
|
51
|
-
permission: string;
|
|
52
|
-
constructor(params: AbilityPolicyConstructorProps);
|
|
53
|
-
/**
|
|
54
|
-
* Add rule set to the policy
|
|
55
|
-
* @param ruleSet - The rule set to add
|
|
56
|
-
*/
|
|
57
|
-
addRuleSet(ruleSet: AbilityRuleSet<Resource, Environment>): this;
|
|
58
|
-
/**
|
|
59
|
-
* Add rule set to the policy
|
|
60
|
-
* @param ruleSets - The array of rule set to add
|
|
61
|
-
*/
|
|
62
|
-
addRuleSets(ruleSets: readonly AbilityRuleSet<Resource, Environment>[]): this;
|
|
63
|
-
/**
|
|
64
|
-
* Check if the policy is matched
|
|
65
|
-
* @param resource - The resource to check
|
|
66
|
-
* @param environment - The user environment object
|
|
67
|
-
*/
|
|
68
|
-
check(resource: Resource, environment?: Environment): Promise<AbilityMatch>;
|
|
69
|
-
explain(): AbilityExplain;
|
|
70
|
-
copyWith(props: Partial<{
|
|
71
|
-
id: string;
|
|
72
|
-
name: string;
|
|
73
|
-
permission: string;
|
|
74
|
-
effect: AbilityPolicyEffect;
|
|
75
|
-
compareMethod: AbilityCompare;
|
|
76
|
-
ruleSet: AbilityRuleSet<Resource, Environment>[];
|
|
77
|
-
}>): AbilityPolicy<Resource, Environment>;
|
|
78
|
-
}
|
|
79
|
-
export default AbilityPolicy;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
import AbilityCode from './AbilityCode';
|
|
2
|
-
export type AbilityPolicyEffectCodeType = 'deny' | 'permit';
|
|
3
|
-
export declare class AbilityPolicyEffect extends AbilityCode<AbilityPolicyEffectCodeType> {
|
|
4
|
-
static deny: AbilityPolicyEffect;
|
|
5
|
-
static permit: AbilityPolicyEffect;
|
|
6
|
-
}
|
|
7
|
-
export default AbilityPolicyEffect;
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import AbilityPolicy from './AbilityPolicy';
|
|
2
|
-
import { AbilityResult } from './AbilityResult';
|
|
3
|
-
import { ResourcesMap } from './AbilityTypeGenerator';
|
|
4
|
-
import { AbilityCacheAdapter } from '../cache/AbilityCacheAdapter';
|
|
5
|
-
export type AbilityResolverOptions = {
|
|
6
|
-
readonly cache?: AbilityCacheAdapter | null;
|
|
7
|
-
};
|
|
8
|
-
export declare class AbilityResolver<Resources extends ResourcesMap, Environment = unknown> {
|
|
9
|
-
private policies;
|
|
10
|
-
private readonly cache?;
|
|
11
|
-
constructor(
|
|
12
|
-
/**
|
|
13
|
-
* `Important!` The incorrect Resources type was intentionally passed to AbilityPolicy so that TypeScript could suggest the name of the permission and the structure of its resource in the parse method.
|
|
14
|
-
*/
|
|
15
|
-
policyOrListOfPolicies: readonly AbilityPolicy<Resources>[] | AbilityPolicy<Resources>, options?: AbilityResolverOptions);
|
|
16
|
-
/**
|
|
17
|
-
* Resolve policy for the resource and permission key
|
|
18
|
-
*
|
|
19
|
-
* @param permission - Permission key
|
|
20
|
-
* @param resource - Resource
|
|
21
|
-
* @param environment
|
|
22
|
-
*/
|
|
23
|
-
resolve<Permission extends keyof Resources>(permission: Permission, resource: Resources[Permission], environment?: Environment): Promise<AbilityResult<Resources[Permission]>>;
|
|
24
|
-
enforce<Permission extends keyof Resources>(permission: Permission, resource: Resources[Permission], environment?: Environment): Promise<void | never>;
|
|
25
|
-
/**
|
|
26
|
-
* Check if the permission key is contained in another permission key
|
|
27
|
-
* @param permissionA - The first permission to check
|
|
28
|
-
* @param permissionB - The second permission to check
|
|
29
|
-
*/
|
|
30
|
-
static isInPermissionContain(permissionA: string, permissionB: string): boolean;
|
|
31
|
-
private makeCacheKey;
|
|
32
|
-
invalidatePolicy(policyId: string): Promise<void>;
|
|
33
|
-
invalidateCache(): Promise<void>;
|
|
34
|
-
}
|
|
35
|
-
export default AbilityResolver;
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { AbilityExplain } from './AbilityExplain';
|
|
2
|
-
import { ResourceObject } from './AbilityTypeGenerator';
|
|
3
|
-
import AbilityPolicy from './AbilityPolicy';
|
|
4
|
-
import AbilityPolicyEffect from './AbilityPolicyEffect';
|
|
5
|
-
export declare class AbilityResult<Resource extends ResourceObject = Record<string, unknown>> {
|
|
6
|
-
/**
|
|
7
|
-
* Already checked policies (after call the policy.check())
|
|
8
|
-
*/
|
|
9
|
-
readonly policies: readonly AbilityPolicy<Resource>[];
|
|
10
|
-
constructor(policies: readonly AbilityPolicy<Resource>[]);
|
|
11
|
-
/**
|
|
12
|
-
* Returns a list of explanations for each policy involved in the ability evaluation.
|
|
13
|
-
* Each item describes how a specific policy contributed to the final permission result.
|
|
14
|
-
*
|
|
15
|
-
* Useful for debugging, logging, or building UI tools that visualize permission logic.
|
|
16
|
-
*/
|
|
17
|
-
explain(): readonly AbilityExplain[];
|
|
18
|
-
getLastMatchedPolicy(): AbilityPolicy<Resource> | null;
|
|
19
|
-
isAllowed(): boolean;
|
|
20
|
-
isDenied(): boolean;
|
|
21
|
-
/**
|
|
22
|
-
* Get the last effect of the policy
|
|
23
|
-
*
|
|
24
|
-
* @returns {AbilityPolicyEffect | null}
|
|
25
|
-
*/
|
|
26
|
-
getLastEffectOfMatchedPolicy(): AbilityPolicyEffect | null;
|
|
27
|
-
}
|