@via-profit/ability 2.0.0-rc.7 → 2.1.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/dist/index.js CHANGED
@@ -9,9 +9,12 @@
9
9
  Object.defineProperty(exports, "__esModule", ({ value: true }));
10
10
  exports.AbilityCode = void 0;
11
11
  class AbilityCode {
12
- code;
12
+ _code;
13
13
  constructor(code) {
14
- this.code = code;
14
+ this._code = code;
15
+ }
16
+ get code() {
17
+ return this._code;
15
18
  }
16
19
  isEqual(compareWith) {
17
20
  return compareWith !== null && this.code === compareWith.code;
@@ -19,18 +22,6 @@ class AbilityCode {
19
22
  isNotEqual(compareWith) {
20
23
  return !this.isEqual(compareWith);
21
24
  }
22
- static fromLiteral(literal) {
23
- let Code = null;
24
- Object.keys(this).forEach(member => {
25
- if (member === literal) {
26
- Code = this[member];
27
- }
28
- });
29
- if (!Code) {
30
- throw new Error(`Mismatch error. The literal ${literal} can not be find as a member of this class`);
31
- }
32
- return new this(Code.code);
33
- }
34
25
  }
35
26
  exports.AbilityCode = AbilityCode;
36
27
  exports["default"] = AbilityCode;
@@ -68,15 +59,33 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
68
59
  Object.defineProperty(exports, "__esModule", ({ value: true }));
69
60
  exports.AbilityCondition = void 0;
70
61
  const AbilityCode_1 = __importDefault(__webpack_require__(19));
62
+ const AbilityError_1 = __webpack_require__(122);
71
63
  class AbilityCondition extends AbilityCode_1.default {
72
- static EQUAL = new AbilityCondition('=');
73
- static NOT_EQUAL = new AbilityCondition('<>');
74
- static MORE_THAN = new AbilityCondition('>');
75
- static LESS_THAN = new AbilityCondition('<');
76
- static LESS_OR_EQUAL = new AbilityCondition('<=');
77
- static MORE_OR_EQUAL = new AbilityCondition('>=');
78
- static IN = new AbilityCondition('in');
79
- static NOT_IN = new AbilityCondition('not in');
64
+ static equal = new AbilityCondition('=');
65
+ static not_equal = new AbilityCondition('<>');
66
+ static more_than = new AbilityCondition('>');
67
+ static less_than = new AbilityCondition('<');
68
+ static less_or_equal = new AbilityCondition('<=');
69
+ static more_or_equal = new AbilityCondition('>=');
70
+ static in = new AbilityCondition('in');
71
+ static not_in = new AbilityCondition('not in');
72
+ static fromLiteral(literal) {
73
+ const code = AbilityCondition[literal]?.code || null;
74
+ if (code === null) {
75
+ throw new AbilityError_1.AbilityParserError(`Literal ${literal} does not found in AbilityCondition class`);
76
+ }
77
+ return new AbilityCondition(code);
78
+ }
79
+ get literal() {
80
+ const literal = Object.keys(AbilityCondition).find(member => {
81
+ const val = AbilityCondition[member];
82
+ return val.code === this.code;
83
+ });
84
+ if (typeof literal === 'undefined') {
85
+ throw new Error(`Literal value does not found in class AbilityCondition`);
86
+ }
87
+ return literal;
88
+ }
80
89
  }
81
90
  exports.AbilityCondition = AbilityCondition;
82
91
  exports["default"] = AbilityCondition;
@@ -89,7 +98,7 @@ exports["default"] = AbilityCondition;
89
98
 
90
99
 
91
100
  Object.defineProperty(exports, "__esModule", ({ value: true }));
92
- exports.PermissionError = exports.AbilityParserError = exports.AbilityError = void 0;
101
+ exports.AbilityParserError = exports.AbilityError = void 0;
93
102
  class AbilityError extends Error {
94
103
  constructor(message) {
95
104
  super(message);
@@ -102,12 +111,6 @@ class AbilityParserError extends Error {
102
111
  }
103
112
  }
104
113
  exports.AbilityParserError = AbilityParserError;
105
- class PermissionError extends Error {
106
- constructor(message) {
107
- super(message);
108
- }
109
- }
110
- exports.PermissionError = PermissionError;
111
114
 
112
115
 
113
116
  /***/ }),
@@ -191,18 +194,18 @@ class AbilityParser {
191
194
  ruleSet.rules.forEach(rule => {
192
195
  let value = 'any';
193
196
  switch (true) {
194
- case rule.condition.isEqual(AbilityCondition_1.default.NOT_EQUAL):
195
- case rule.condition.isEqual(AbilityCondition_1.default.EQUAL):
197
+ case rule.condition.isEqual(AbilityCondition_1.default.not_equal):
198
+ case rule.condition.isEqual(AbilityCondition_1.default.equal):
196
199
  value = typeof rule.resource;
197
200
  break;
198
- case rule.condition.isEqual(AbilityCondition_1.default.IN):
199
- case rule.condition.isEqual(AbilityCondition_1.default.NOT_IN):
201
+ case rule.condition.isEqual(AbilityCondition_1.default.in):
202
+ case rule.condition.isEqual(AbilityCondition_1.default.not_in):
200
203
  value = `${typeof rule.resource}[]`;
201
204
  break;
202
- case rule.condition.isEqual(AbilityCondition_1.default.MORE_OR_EQUAL):
203
- case rule.condition.isEqual(AbilityCondition_1.default.MORE_THAN):
204
- case rule.condition.isEqual(AbilityCondition_1.default.LESS_OR_EQUAL):
205
- case rule.condition.isEqual(AbilityCondition_1.default.LESS_THAN):
205
+ case rule.condition.isEqual(AbilityCondition_1.default.more_or_equal):
206
+ case rule.condition.isEqual(AbilityCondition_1.default.more_than):
207
+ case rule.condition.isEqual(AbilityCondition_1.default.less_or_equal):
208
+ case rule.condition.isEqual(AbilityCondition_1.default.less_than):
206
209
  value = 'number';
207
210
  break;
208
211
  }
@@ -313,7 +316,7 @@ class AbilityPolicy {
313
316
  action,
314
317
  effect: new AbilityPolicyEffect_1.default(effect),
315
318
  });
316
- policy.compareMethod = AbilityCompare_1.default.fromLiteral(compareMethod);
319
+ policy.compareMethod = new AbilityCompare_1.default(compareMethod);
317
320
  ruleSet.forEach(ruleSetConfig => {
318
321
  policy.addRuleSet(AbilityRuleSet_1.default.parse(ruleSetConfig));
319
322
  });
@@ -391,10 +394,8 @@ class AbilityResolver {
391
394
  }
392
395
  enforce(action, resource) {
393
396
  const resolver = this.resolve(action, resource);
394
- if (resolver) {
395
- if (resolver.isDeny()) {
396
- throw new AbilityError_1.PermissionError(resolver.getPolicy()?.name?.toString() || 'Unknown permission error');
397
- }
397
+ if (resolver.isDeny()) {
398
+ throw new AbilityError_1.AbilityError(resolver.getMatchedPolicy()?.name?.toString() || 'Unknown permission error');
398
399
  }
399
400
  }
400
401
  /**
@@ -422,9 +423,10 @@ class AbilityResolver {
422
423
  const effect = this.getEffect();
423
424
  return effect !== null && effect.isEqual(AbilityPolicyEffect_1.default.deny);
424
425
  }
425
- getPolicy() {
426
- const lastPolicy = this.policies.length ? this.policies[this.policies.length - 1] : null;
427
- return lastPolicy && lastPolicy.matchState.isEqual(AbilityMatch_1.default.match) ? lastPolicy : null;
426
+ getMatchedPolicy() {
427
+ const matchedPolicies = this.policies.filter(policy => policy.matchState.isEqual(AbilityMatch_1.default.match));
428
+ const lastPolicy = matchedPolicies.length ? matchedPolicies[matchedPolicies.length - 1] : null;
429
+ return lastPolicy || null;
428
430
  }
429
431
  /**
430
432
  * Check if the action is contained in another action
@@ -435,13 +437,12 @@ class AbilityResolver {
435
437
  const actionAArray = String(actionA).split('.');
436
438
  const actionBArray = String(actionB).split('.');
437
439
  const a = actionAArray.length >= actionBArray.length ? actionAArray : actionBArray;
438
- const b = actionBArray.length >= actionAArray.length ? actionBArray : actionAArray;
439
- return a
440
- .reduce((acc, chunk, index) => {
440
+ const b = actionBArray.length <= actionAArray.length ? actionBArray : actionAArray;
441
+ const c = a.reduce((acc, chunk, index) => {
441
442
  const iterationRes = chunk === b[index] || b[index] === '*' || chunk === '*';
442
443
  return acc.concat(iterationRes);
443
- }, [])
444
- .every(Boolean);
444
+ }, []);
445
+ return c.every(Boolean);
445
446
  }
446
447
  }
447
448
  exports.AbilityResolver = AbilityResolver;
@@ -461,6 +462,9 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
461
462
  exports.AbilityRule = void 0;
462
463
  const AbilityMatch_1 = __importDefault(__webpack_require__(909));
463
464
  const AbilityCondition_1 = __importDefault(__webpack_require__(261));
465
+ /**
466
+ * Represents a rule that defines a condition to be checked against a subject and resource.
467
+ */
464
468
  class AbilityRule {
465
469
  /**
466
470
  * Subject key path like a 'user.name'
@@ -474,13 +478,22 @@ class AbilityRule {
474
478
  name;
475
479
  id;
476
480
  state = AbilityMatch_1.default.pending;
481
+ /**
482
+ * Creates an instance of AbilityRule.
483
+ * @param {string} options.id - The unique identifier of the rule.
484
+ * @param {string} options.name - The name of the rule.
485
+ * @param {AbilityCondition} options.condition - The condition to evaluate.
486
+ * @param {string} options.subject - The subject of the rule.
487
+ * @param {string} options.resource - The resource to compare against.
488
+ * @param params
489
+ */
477
490
  constructor(params) {
478
491
  const { id, name, subject, resource, condition } = params;
479
492
  this.id = id;
480
493
  this.name = name;
481
494
  this.subject = subject;
482
495
  this.resource = resource;
483
- this.condition = new AbilityCondition_1.default(condition);
496
+ this.condition = condition;
484
497
  }
485
498
  /**
486
499
  * Check if the rule is matched
@@ -489,25 +502,25 @@ class AbilityRule {
489
502
  check(resource) {
490
503
  let is = false;
491
504
  const [valueS, valueO] = this.extractValues(resource);
492
- if (AbilityCondition_1.default.LESS_THAN.isEqual(this.condition)) {
505
+ if (AbilityCondition_1.default.less_than.isEqual(this.condition)) {
493
506
  is = Number(valueS) < Number(valueO);
494
507
  }
495
- if (AbilityCondition_1.default.LESS_OR_EQUAL.isEqual(this.condition)) {
508
+ if (AbilityCondition_1.default.less_or_equal.isEqual(this.condition)) {
496
509
  is = Number(valueS) <= Number(valueO);
497
510
  }
498
- if (AbilityCondition_1.default.MORE_THAN.isEqual(this.condition)) {
511
+ if (AbilityCondition_1.default.more_than.isEqual(this.condition)) {
499
512
  is = Number(valueS) > Number(valueO);
500
513
  }
501
- if (AbilityCondition_1.default.MORE_OR_EQUAL.isEqual(this.condition)) {
514
+ if (AbilityCondition_1.default.more_or_equal.isEqual(this.condition)) {
502
515
  is = Number(valueS) >= Number(valueO);
503
516
  }
504
- if (AbilityCondition_1.default.EQUAL.isEqual(this.condition)) {
517
+ if (AbilityCondition_1.default.equal.isEqual(this.condition)) {
505
518
  is = valueS === valueO;
506
519
  }
507
- if (AbilityCondition_1.default.NOT_EQUAL.isEqual(this.condition)) {
520
+ if (AbilityCondition_1.default.not_equal.isEqual(this.condition)) {
508
521
  is = valueS !== valueO;
509
522
  }
510
- if (AbilityCondition_1.default.IN.isEqual(this.condition)) {
523
+ if (AbilityCondition_1.default.in.isEqual(this.condition)) {
511
524
  // [<some>] and [<some>]
512
525
  if (Array.isArray(valueS) && Array.isArray(valueO)) {
513
526
  is = valueS.some(v => valueO.find(v1 => v1 === v));
@@ -521,7 +534,7 @@ class AbilityRule {
521
534
  is = valueS.includes(valueO);
522
535
  }
523
536
  }
524
- if (AbilityCondition_1.default.NOT_IN.isEqual(this.condition)) {
537
+ if (AbilityCondition_1.default.not_in.isEqual(this.condition)) {
525
538
  // [<some>] and [<some>]
526
539
  if (Array.isArray(valueS) && Array.isArray(valueO)) {
527
540
  is = !valueS.some(v => valueO.find(v1 => v1 === v));
@@ -600,7 +613,7 @@ class AbilityRule {
600
613
  name,
601
614
  subject,
602
615
  resource,
603
- condition,
616
+ condition: new AbilityCondition_1.default(condition),
604
617
  });
605
618
  }
606
619
  /**
@@ -659,16 +672,14 @@ class AbilityRuleSet {
659
672
  const { name, id, compareMethod } = params;
660
673
  this.name = name;
661
674
  this.id = id;
662
- this.compareMethod = AbilityCompare_1.default.fromLiteral(compareMethod);
663
- // this.compareMethod = new AbilityCompare(compareMethod);
675
+ this.compareMethod = compareMethod;
664
676
  }
665
- addRule(rule, compareMethod) {
677
+ addRule(rule) {
666
678
  this.rules.push(rule);
667
- this.compareMethod = compareMethod;
668
679
  return this;
669
680
  }
670
- addRules(rules, compareMethod) {
671
- rules.forEach(rule => this.addRule(rule, compareMethod));
681
+ addRules(rules) {
682
+ rules.forEach(rule => this.addRule(rule));
672
683
  return this;
673
684
  }
674
685
  check(resources) {
@@ -697,14 +708,14 @@ class AbilityRuleSet {
697
708
  static parse(config) {
698
709
  const { id, name, rules, compareMethod } = config;
699
710
  const ruleSet = new AbilityRuleSet({
700
- compareMethod,
711
+ compareMethod: new AbilityCompare_1.default(compareMethod),
701
712
  name,
702
713
  id,
703
714
  });
704
715
  // Adding rules if exists
705
716
  if (rules && rules.length > 0) {
706
717
  const abilityRules = rules.map(ruleConfig => AbilityRule_1.default.parse(ruleConfig));
707
- ruleSet.addRules(abilityRules, ruleSet.compareMethod);
718
+ ruleSet.addRules(abilityRules);
708
719
  }
709
720
  return ruleSet;
710
721
  }
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": "2.0.0-rc.7",
4
+ "version": "2.1.0",
5
5
  "description": "Via-Profit Ability service",
6
6
  "keywords": [
7
7
  "ability",
@@ -28,7 +28,6 @@
28
28
  },
29
29
  "author": {
30
30
  "name": "Via Profit",
31
- "email": "promo@via-profit.ru",
32
31
  "url": "https://dev.via-profit.ru"
33
32
  },
34
33
  "contributors": [
@@ -1,6 +0,0 @@
1
- import AbilityPolicy from './AbilityPolicy';
2
- export declare class AbilityPolicyResult {
3
- policies: readonly AbilityPolicy[];
4
- constructor(policies: readonly AbilityPolicy[]);
5
- }
6
- export default AbilityPolicyResult;
@@ -1,26 +0,0 @@
1
- export type Resources = {
2
- readonly ['account.read']: {
3
- readonly account: {
4
- readonly id: string;
5
- readonly roles: readonly string[];
6
- } | null;
7
- readonly resource: {
8
- readonly id: string;
9
- };
10
- };
11
- readonly ['access.auth']: {
12
- readonly token: {
13
- readonly type: string;
14
- readonly id: string;
15
- } | null;
16
- };
17
- readonly ['order.update']: {
18
- readonly account: {
19
- readonly roles: readonly string[];
20
- readonly department: string;
21
- } | null;
22
- readonly order: {
23
- readonly status: string;
24
- } | null;
25
- };
26
- };