@via-profit/ability 3.4.0 → 3.4.1
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/CHANGELOG.md +2 -2
- package/CONTRIBUTING.md +14 -14
- package/LICENSE +21 -21
- package/README.md +1363 -1374
- package/SECURITY.md +33 -33
- package/dist/core/AbilityCondition.d.ts +1 -1
- package/dist/core/AbilityError.d.ts +2 -2
- package/dist/core/AbilityRule.d.ts +6 -1
- package/dist/index.js +198 -184
- package/package.json +73 -73
- package/dist/core/AbilityParser.d.ts +0 -61
package/SECURITY.md
CHANGED
|
@@ -1,33 +1,33 @@
|
|
|
1
|
-
# Security Policy
|
|
2
|
-
|
|
3
|
-
## Reporting a Vulnerability
|
|
4
|
-
|
|
5
|
-
I take the security of `@via-profit/ability` seriously. If you discover a security vulnerability, please report it responsibly.
|
|
6
|
-
|
|
7
|
-
### How to Report a Vulnerability
|
|
8
|
-
|
|
9
|
-
**Please DO NOT create a public GitHub issue for security vulnerabilities.**
|
|
10
|
-
|
|
11
|
-
Instead, send the details directly to me:
|
|
12
|
-
|
|
13
|
-
- **Email**: [delhsmail@gmail.com](mailto:delhsmail@gmail.com)
|
|
14
|
-
- **Author**: Vasily Novosad
|
|
15
|
-
- **Timezone**: UTC+5 (for coordinating response time)
|
|
16
|
-
|
|
17
|
-
### What to Include
|
|
18
|
-
|
|
19
|
-
To help me address the issue quickly, please include:
|
|
20
|
-
|
|
21
|
-
- Description of the vulnerability
|
|
22
|
-
- Steps to reproduce (if applicable)
|
|
23
|
-
- Potential impact
|
|
24
|
-
- Suggestions for fixing (if any)
|
|
25
|
-
|
|
26
|
-
### Process
|
|
27
|
-
|
|
28
|
-
1. I will acknowledge your report within 48 hours
|
|
29
|
-
2. I will assess the vulnerability
|
|
30
|
-
3. Work on a fix will begin depending on severity
|
|
31
|
-
4. After the fix is released, I will notify you and acknowledge your contribution (if you agree)
|
|
32
|
-
|
|
33
|
-
Thank you for helping keep this project secure!
|
|
1
|
+
# Security Policy
|
|
2
|
+
|
|
3
|
+
## Reporting a Vulnerability
|
|
4
|
+
|
|
5
|
+
I take the security of `@via-profit/ability` seriously. If you discover a security vulnerability, please report it responsibly.
|
|
6
|
+
|
|
7
|
+
### How to Report a Vulnerability
|
|
8
|
+
|
|
9
|
+
**Please DO NOT create a public GitHub issue for security vulnerabilities.**
|
|
10
|
+
|
|
11
|
+
Instead, send the details directly to me:
|
|
12
|
+
|
|
13
|
+
- **Email**: [delhsmail@gmail.com](mailto:delhsmail@gmail.com)
|
|
14
|
+
- **Author**: Vasily Novosad
|
|
15
|
+
- **Timezone**: UTC+5 (for coordinating response time)
|
|
16
|
+
|
|
17
|
+
### What to Include
|
|
18
|
+
|
|
19
|
+
To help me address the issue quickly, please include:
|
|
20
|
+
|
|
21
|
+
- Description of the vulnerability
|
|
22
|
+
- Steps to reproduce (if applicable)
|
|
23
|
+
- Potential impact
|
|
24
|
+
- Suggestions for fixing (if any)
|
|
25
|
+
|
|
26
|
+
### Process
|
|
27
|
+
|
|
28
|
+
1. I will acknowledge your report within 48 hours
|
|
29
|
+
2. I will assess the vulnerability
|
|
30
|
+
3. Work on a fix will begin depending on severity
|
|
31
|
+
4. After the fix is released, I will notify you and acknowledge your contribution (if you agree)
|
|
32
|
+
|
|
33
|
+
Thank you for helping keep this project secure!
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import AbilityCode from './AbilityCode';
|
|
2
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' | '
|
|
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
4
|
export declare class AbilityCondition extends AbilityCode<AbilityConditionCodeType> {
|
|
5
5
|
static equals: AbilityCondition;
|
|
6
6
|
static not_equals: AbilityCondition;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare class AbilityError extends Error {
|
|
2
|
-
constructor(message: string);
|
|
2
|
+
constructor(message: string, options?: ErrorOptions);
|
|
3
3
|
}
|
|
4
4
|
export declare class AbilityParserError extends Error {
|
|
5
|
-
constructor(message: string);
|
|
5
|
+
constructor(message: string, options?: ErrorOptions);
|
|
6
6
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import AbilityMatch from './AbilityMatch';
|
|
2
|
-
import AbilityCondition,
|
|
2
|
+
import { AbilityCondition, AbilityConditionCodeType } from './AbilityCondition';
|
|
3
3
|
export type AbilityRuleConfig = {
|
|
4
4
|
readonly id?: string | null;
|
|
5
5
|
readonly name?: string | null;
|
|
@@ -42,6 +42,11 @@ export declare class AbilityRule<Resources extends object = object, Environment
|
|
|
42
42
|
* @param params
|
|
43
43
|
*/
|
|
44
44
|
constructor(params: AbilityRuleConstructorProps);
|
|
45
|
+
private isPrimitive;
|
|
46
|
+
private isNumber;
|
|
47
|
+
private isString;
|
|
48
|
+
private valueLen;
|
|
49
|
+
private operatorHandlers;
|
|
45
50
|
/**
|
|
46
51
|
* Check if the rule is matched
|
|
47
52
|
* @param resource - The resource to check
|
package/dist/index.js
CHANGED
|
@@ -22,75 +22,116 @@ class AbilityCompare extends AbilityCode {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
class AbilityError extends Error {
|
|
25
|
-
constructor(message) {
|
|
26
|
-
super(message);
|
|
25
|
+
constructor(message, options) {
|
|
26
|
+
super(message, options);
|
|
27
|
+
this.name = 'AbilityError';
|
|
28
|
+
if (Error.captureStackTrace) {
|
|
29
|
+
Error.captureStackTrace(this, this.constructor);
|
|
30
|
+
}
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
33
|
class AbilityParserError extends Error {
|
|
30
|
-
constructor(message) {
|
|
31
|
-
super(message);
|
|
34
|
+
constructor(message, options) {
|
|
35
|
+
super(message, options);
|
|
36
|
+
this.name = 'AbilityParserError';
|
|
37
|
+
if (Error.captureStackTrace) {
|
|
38
|
+
Error.captureStackTrace(this, this.constructor);
|
|
39
|
+
}
|
|
32
40
|
}
|
|
33
41
|
}
|
|
34
42
|
|
|
35
43
|
class AbilityCondition extends AbilityCode {
|
|
36
|
-
static equals
|
|
37
|
-
static not_equals
|
|
38
|
-
static greater_than
|
|
39
|
-
static less_than
|
|
40
|
-
static less_or_equal
|
|
41
|
-
static greater_or_equal
|
|
42
|
-
static in
|
|
43
|
-
static not_in
|
|
44
|
-
static contains
|
|
45
|
-
static not_contains
|
|
46
|
-
static length_greater_than
|
|
47
|
-
static length_less_than
|
|
48
|
-
static length_equals
|
|
49
|
-
static always
|
|
50
|
-
static never
|
|
44
|
+
static equals;
|
|
45
|
+
static not_equals;
|
|
46
|
+
static greater_than;
|
|
47
|
+
static less_than;
|
|
48
|
+
static less_or_equal;
|
|
49
|
+
static greater_or_equal;
|
|
50
|
+
static in;
|
|
51
|
+
static not_in;
|
|
52
|
+
static contains;
|
|
53
|
+
static not_contains;
|
|
54
|
+
static length_greater_than;
|
|
55
|
+
static length_less_than;
|
|
56
|
+
static length_equals;
|
|
57
|
+
static always;
|
|
58
|
+
static never;
|
|
59
|
+
static {
|
|
60
|
+
this.equals = new AbilityCondition('=');
|
|
61
|
+
this.not_equals = new AbilityCondition('<>');
|
|
62
|
+
this.greater_than = new AbilityCondition('>');
|
|
63
|
+
this.less_than = new AbilityCondition('<');
|
|
64
|
+
this.less_or_equal = new AbilityCondition('<=');
|
|
65
|
+
this.greater_or_equal = new AbilityCondition('>=');
|
|
66
|
+
this.in = new AbilityCondition('in');
|
|
67
|
+
this.not_in = new AbilityCondition('not in');
|
|
68
|
+
this.contains = new AbilityCondition('contains');
|
|
69
|
+
this.not_contains = new AbilityCondition('not contains');
|
|
70
|
+
this.length_greater_than = new AbilityCondition('length greater than');
|
|
71
|
+
this.length_less_than = new AbilityCondition('length less than');
|
|
72
|
+
this.length_equals = new AbilityCondition('length equals');
|
|
73
|
+
this.always = new AbilityCondition('always');
|
|
74
|
+
this.never = new AbilityCondition('never');
|
|
75
|
+
}
|
|
51
76
|
static fromLiteral(literal) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
77
|
+
const map = {
|
|
78
|
+
equals: this.equals,
|
|
79
|
+
not_equals: this.not_equals,
|
|
80
|
+
greater_than: this.greater_than,
|
|
81
|
+
less_than: this.less_than,
|
|
82
|
+
less_or_equal: this.less_or_equal,
|
|
83
|
+
greater_or_equal: this.greater_or_equal,
|
|
84
|
+
in: this.in,
|
|
85
|
+
not_in: this.not_in,
|
|
86
|
+
contains: this.contains,
|
|
87
|
+
not_contains: this.not_contains,
|
|
88
|
+
length_greater_than: this.length_greater_than,
|
|
89
|
+
length_equals: this.length_equals,
|
|
90
|
+
always: this.always,
|
|
91
|
+
never: this.never,
|
|
92
|
+
length_less_than: this.length_less_than,
|
|
93
|
+
};
|
|
94
|
+
const condition = map[literal];
|
|
95
|
+
if (!condition) {
|
|
96
|
+
throw new AbilityParserError(`Literal "${literal}" does not found in AbilityCondition class`);
|
|
97
|
+
}
|
|
98
|
+
return condition;
|
|
99
|
+
}
|
|
100
|
+
get literal() {
|
|
101
|
+
switch (this.code) {
|
|
102
|
+
case '=':
|
|
103
|
+
return 'equals';
|
|
104
|
+
case '<>':
|
|
105
|
+
return 'not_equals';
|
|
106
|
+
case '>':
|
|
107
|
+
return 'greater_than';
|
|
108
|
+
case '<':
|
|
109
|
+
return 'less_than';
|
|
110
|
+
case '>=':
|
|
111
|
+
return 'greater_or_equal';
|
|
112
|
+
case '<=':
|
|
113
|
+
return 'less_or_equal';
|
|
69
114
|
case 'in':
|
|
70
|
-
return
|
|
71
|
-
case '
|
|
72
|
-
return
|
|
73
|
-
case '
|
|
74
|
-
return
|
|
75
|
-
case '
|
|
76
|
-
return
|
|
115
|
+
return 'in';
|
|
116
|
+
case 'not in':
|
|
117
|
+
return 'not_in';
|
|
118
|
+
case 'contains':
|
|
119
|
+
return 'contains';
|
|
120
|
+
case 'not contains':
|
|
121
|
+
return 'not_contains';
|
|
122
|
+
case 'length greater than':
|
|
123
|
+
return 'length_greater_than';
|
|
124
|
+
case 'length less than':
|
|
125
|
+
return 'length_less_than';
|
|
126
|
+
case 'length equals':
|
|
127
|
+
return 'length_equals';
|
|
77
128
|
case 'always':
|
|
78
|
-
return
|
|
129
|
+
return 'always';
|
|
79
130
|
case 'never':
|
|
80
|
-
return
|
|
131
|
+
return 'never';
|
|
81
132
|
default:
|
|
82
|
-
throw new
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
get literal() {
|
|
86
|
-
const literal = Object.keys(AbilityCondition).find(member => {
|
|
87
|
-
const val = AbilityCondition[member];
|
|
88
|
-
return val.code === this.code;
|
|
89
|
-
});
|
|
90
|
-
if (typeof literal === 'undefined') {
|
|
91
|
-
throw new Error(`Literal value does not found in class AbilityCondition`);
|
|
133
|
+
throw new Error(`Unknown condition code: ${this.code}`);
|
|
92
134
|
}
|
|
93
|
-
return literal;
|
|
94
135
|
}
|
|
95
136
|
}
|
|
96
137
|
|
|
@@ -624,149 +665,122 @@ class AbilityRule {
|
|
|
624
665
|
this.resource = resource;
|
|
625
666
|
this.condition = condition;
|
|
626
667
|
}
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
if (AbilityCondition.not_equals.isEqual(this.condition)) {
|
|
646
|
-
is = subjectValue !== resourceValue;
|
|
647
|
-
}
|
|
648
|
-
// less than
|
|
649
|
-
if (AbilityCondition.less_than.isEqual(this.condition)) {
|
|
650
|
-
if (typeof subjectValue === 'number' && typeof resourceValue === 'number') {
|
|
651
|
-
is = subjectValue < resourceValue;
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
// less or equal
|
|
655
|
-
if (AbilityCondition.less_or_equal.isEqual(this.condition)) {
|
|
656
|
-
if (typeof subjectValue === 'number' && typeof resourceValue === 'number') {
|
|
657
|
-
is = subjectValue <= resourceValue;
|
|
658
|
-
}
|
|
659
|
-
}
|
|
660
|
-
// more than
|
|
661
|
-
if (AbilityCondition.greater_than.isEqual(this.condition)) {
|
|
662
|
-
if (typeof subjectValue === 'number' && typeof resourceValue === 'number') {
|
|
663
|
-
is = subjectValue > resourceValue;
|
|
664
|
-
}
|
|
665
|
-
}
|
|
666
|
-
// more or equal
|
|
667
|
-
if (AbilityCondition.greater_or_equal.isEqual(this.condition)) {
|
|
668
|
-
if (typeof subjectValue === 'number' && typeof resourceValue === 'number') {
|
|
669
|
-
is = subjectValue >= resourceValue;
|
|
670
|
-
}
|
|
671
|
-
}
|
|
672
|
-
// in
|
|
673
|
-
if (AbilityCondition.in.isEqual(this.condition)) {
|
|
674
|
-
// value in array
|
|
675
|
-
if (isValue(subjectValue) && Array.isArray(resourceValue)) {
|
|
676
|
-
is = resourceValue.includes(subjectValue);
|
|
677
|
-
}
|
|
678
|
-
// array intersects array
|
|
679
|
-
else if (Array.isArray(subjectValue) && Array.isArray(resourceValue)) {
|
|
680
|
-
is = subjectValue.some(v => resourceValue.includes(v));
|
|
681
|
-
}
|
|
682
|
-
}
|
|
683
|
-
// not in
|
|
684
|
-
if (AbilityCondition.not_in.isEqual(this.condition)) {
|
|
685
|
-
if (isValue(subjectValue) && Array.isArray(resourceValue)) {
|
|
686
|
-
is = !resourceValue.includes(subjectValue);
|
|
687
|
-
}
|
|
688
|
-
else if (Array.isArray(subjectValue) && Array.isArray(resourceValue)) {
|
|
689
|
-
is = !subjectValue.some(v => resourceValue.includes(v));
|
|
690
|
-
}
|
|
691
|
-
}
|
|
692
|
-
// contains
|
|
693
|
-
if (AbilityCondition.contains.isEqual(this.condition)) {
|
|
694
|
-
// array contains value
|
|
695
|
-
if (Array.isArray(subjectValue) && isValue(resourceValue)) {
|
|
696
|
-
is = subjectValue.includes(resourceValue);
|
|
697
|
-
}
|
|
698
|
-
// array intersects array
|
|
699
|
-
else if (Array.isArray(subjectValue) && Array.isArray(resourceValue)) {
|
|
700
|
-
is = subjectValue.some(v => resourceValue.includes(v));
|
|
668
|
+
isPrimitive(v) {
|
|
669
|
+
return typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean' || v === null;
|
|
670
|
+
}
|
|
671
|
+
isNumber(v) {
|
|
672
|
+
return typeof v === 'number';
|
|
673
|
+
}
|
|
674
|
+
isString(v) {
|
|
675
|
+
return typeof v === 'string';
|
|
676
|
+
}
|
|
677
|
+
valueLen = (v) => this.isString(v) || Array.isArray(v) ? v.length : null;
|
|
678
|
+
operatorHandlers = {
|
|
679
|
+
[AbilityCondition.always.literal]: () => true,
|
|
680
|
+
[AbilityCondition.never.literal]: () => false,
|
|
681
|
+
[AbilityCondition.equals.literal]: (a, b) => a === b,
|
|
682
|
+
[AbilityCondition.not_equals.literal]: (a, b) => a !== b,
|
|
683
|
+
[AbilityCondition.contains.literal]: (a, b) => {
|
|
684
|
+
if (Array.isArray(a) && this.isPrimitive(b)) {
|
|
685
|
+
return a.includes(b);
|
|
701
686
|
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
if (AbilityCondition.not_contains.isEqual(this.condition)) {
|
|
705
|
-
if (Array.isArray(subjectValue) && isValue(resourceValue)) {
|
|
706
|
-
is = !subjectValue.includes(resourceValue);
|
|
687
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
688
|
+
return a.some(v => b.includes(v));
|
|
707
689
|
}
|
|
708
|
-
|
|
709
|
-
|
|
690
|
+
return false;
|
|
691
|
+
},
|
|
692
|
+
[AbilityCondition.not_contains.literal]: (a, b) => {
|
|
693
|
+
if (Array.isArray(a) && this.isPrimitive(b)) {
|
|
694
|
+
return !a.includes(b);
|
|
710
695
|
}
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
if (AbilityCondition.length_equals.isEqual(this.condition)) {
|
|
714
|
-
// foo.bar == n
|
|
715
|
-
if (isValue(subjectValue) && typeof resourceValue === 'number') {
|
|
716
|
-
is = String(subjectValue).length === resourceValue;
|
|
696
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
697
|
+
return !a.some(v => b.includes(v));
|
|
717
698
|
}
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
699
|
+
return false;
|
|
700
|
+
},
|
|
701
|
+
[AbilityCondition.in.literal]: (a, b) => {
|
|
702
|
+
if (this.isPrimitive(a) && Array.isArray(b)) {
|
|
703
|
+
return b.includes(a);
|
|
721
704
|
}
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
is = subjectValue.length === resourceValue.length;
|
|
705
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
706
|
+
return a.some(v => b.includes(v));
|
|
725
707
|
}
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
708
|
+
return false;
|
|
709
|
+
},
|
|
710
|
+
[AbilityCondition.not_in.literal]: (a, b) => {
|
|
711
|
+
if (this.isPrimitive(a) && Array.isArray(b)) {
|
|
712
|
+
return !b.includes(a);
|
|
729
713
|
}
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
if (AbilityCondition.length_greater_than.isEqual(this.condition)) {
|
|
733
|
-
// foo.bar > n
|
|
734
|
-
if (isValue(subjectValue) && typeof resourceValue === 'number') {
|
|
735
|
-
is = String(subjectValue).length > resourceValue;
|
|
714
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
715
|
+
return !a.some(v => b.includes(v));
|
|
736
716
|
}
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
717
|
+
return false;
|
|
718
|
+
},
|
|
719
|
+
[AbilityCondition.greater_than.literal]: (a, b) => {
|
|
720
|
+
return this.isNumber(a) && this.isNumber(b) ? a > b : false;
|
|
721
|
+
},
|
|
722
|
+
[AbilityCondition.less_than.literal]: (a, b) => {
|
|
723
|
+
return this.isNumber(a) && this.isNumber(b) ? a < b : false;
|
|
724
|
+
},
|
|
725
|
+
[AbilityCondition.greater_or_equal.literal]: (a, b) => {
|
|
726
|
+
return this.isNumber(a) && this.isNumber(b) ? a >= b : false;
|
|
727
|
+
},
|
|
728
|
+
[AbilityCondition.less_or_equal.literal]: (a, b) => {
|
|
729
|
+
return this.isNumber(a) && this.isNumber(b) ? a <= b : false;
|
|
730
|
+
},
|
|
731
|
+
[AbilityCondition.length_greater_than.literal]: (a, b) => {
|
|
732
|
+
const alen = this.valueLen(a);
|
|
733
|
+
if (alen === null) {
|
|
734
|
+
return false;
|
|
735
|
+
}
|
|
736
|
+
if (this.isNumber(b)) {
|
|
737
|
+
return alen > b;
|
|
738
|
+
}
|
|
739
|
+
const bLen = this.valueLen(b);
|
|
740
|
+
if (bLen !== null) {
|
|
741
|
+
return alen > bLen;
|
|
740
742
|
}
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
743
|
+
return false;
|
|
744
|
+
},
|
|
745
|
+
[AbilityCondition.length_less_than.literal]: (a, b) => {
|
|
746
|
+
const alen = this.valueLen(a);
|
|
747
|
+
if (alen === null) {
|
|
748
|
+
return false;
|
|
744
749
|
}
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
is = subjectValue.length > resourceValue.length;
|
|
750
|
+
if (this.isNumber(b)) {
|
|
751
|
+
return alen < b;
|
|
748
752
|
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
// foo.bar < n
|
|
753
|
-
if (isValue(subjectValue) && typeof resourceValue === 'number') {
|
|
754
|
-
is = String(subjectValue).length < resourceValue;
|
|
753
|
+
const bLen = this.valueLen(b);
|
|
754
|
+
if (bLen !== null) {
|
|
755
|
+
return alen < bLen;
|
|
755
756
|
}
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
757
|
+
return false;
|
|
758
|
+
},
|
|
759
|
+
[AbilityCondition.length_equals.literal]: (a, b) => {
|
|
760
|
+
const alen = this.valueLen(a);
|
|
761
|
+
if (alen === null) {
|
|
762
|
+
return false;
|
|
759
763
|
}
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
is = subjectValue.length < resourceValue.length;
|
|
764
|
+
if (this.isNumber(b)) {
|
|
765
|
+
return alen === b;
|
|
763
766
|
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
+
const bLen = this.valueLen(b);
|
|
768
|
+
if (bLen !== null) {
|
|
769
|
+
return alen === bLen;
|
|
767
770
|
}
|
|
768
|
-
|
|
769
|
-
|
|
771
|
+
return false;
|
|
772
|
+
},
|
|
773
|
+
};
|
|
774
|
+
/**
|
|
775
|
+
* Check if the rule is matched
|
|
776
|
+
* @param resource - The resource to check
|
|
777
|
+
* @param environment
|
|
778
|
+
*/
|
|
779
|
+
async check(resource, environment) {
|
|
780
|
+
const [subjectValue, resourceValue] = this.extractValues(resource, environment);
|
|
781
|
+
const handler = this.operatorHandlers[this.condition.literal];
|
|
782
|
+
const result = handler(subjectValue, resourceValue);
|
|
783
|
+
this.state = result ? AbilityMatch.match : AbilityMatch.mismatch;
|
|
770
784
|
return this.state;
|
|
771
785
|
}
|
|
772
786
|
/**
|