@via-profit/ability 2.0.0-rc.4 → 2.0.0-rc.5
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/build/playground.js +151 -244
- package/build/playground.js.map +1 -1
- package/dist/AbilityCode.d.ts +1 -0
- package/dist/AbilityCompare.d.ts +3 -2
- package/dist/AbilityMatch.d.ts +5 -4
- package/dist/AbilityParser.d.ts +0 -15
- package/dist/AbilityPolicy.d.ts +7 -7
- package/dist/AbilityPolicyEffect.d.ts +4 -3
- package/dist/AbilityResolver.d.ts +1 -1
- package/dist/AbilityRule.d.ts +1 -1
- package/dist/AbilityRuleSet.d.ts +3 -3
- package/dist/index.js +80 -129
- package/package.json +1 -1
package/build/playground.js
CHANGED
|
@@ -22,6 +22,18 @@ class AbilityCode {
|
|
|
22
22
|
isNotEqual(compareWith) {
|
|
23
23
|
return !this.isEqual(compareWith);
|
|
24
24
|
}
|
|
25
|
+
static fromLiteral(literal) {
|
|
26
|
+
let Code = null;
|
|
27
|
+
Object.keys(this).forEach(member => {
|
|
28
|
+
if (member === literal) {
|
|
29
|
+
Code = this[member];
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
if (!Code) {
|
|
33
|
+
throw new Error(`Mismatch error. The literal ${literal} can not be find as a member of this class`);
|
|
34
|
+
}
|
|
35
|
+
return new this(Code.code);
|
|
36
|
+
}
|
|
25
37
|
}
|
|
26
38
|
exports.AbilityCode = AbilityCode;
|
|
27
39
|
exports["default"] = AbilityCode;
|
|
@@ -43,8 +55,8 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
43
55
|
exports.AbilityCompare = void 0;
|
|
44
56
|
const AbilityCode_1 = __importDefault(__webpack_require__(/*! ./AbilityCode */ "./src/AbilityCode.ts"));
|
|
45
57
|
class AbilityCompare extends AbilityCode_1.default {
|
|
46
|
-
static
|
|
47
|
-
static
|
|
58
|
+
static and = new AbilityCompare(0);
|
|
59
|
+
static or = new AbilityCompare(1);
|
|
48
60
|
}
|
|
49
61
|
exports.AbilityCompare = AbilityCompare;
|
|
50
62
|
exports["default"] = AbilityCompare;
|
|
@@ -126,145 +138,14 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
126
138
|
exports.AbilityMatch = void 0;
|
|
127
139
|
const AbilityCode_1 = __importDefault(__webpack_require__(/*! ./AbilityCode */ "./src/AbilityCode.ts"));
|
|
128
140
|
class AbilityMatch extends AbilityCode_1.default {
|
|
129
|
-
static
|
|
130
|
-
static
|
|
131
|
-
static
|
|
141
|
+
static pending = new AbilityMatch('pending');
|
|
142
|
+
static match = new AbilityMatch('match');
|
|
143
|
+
static mismatch = new AbilityMatch('mismatch');
|
|
132
144
|
}
|
|
133
145
|
exports.AbilityMatch = AbilityMatch;
|
|
134
146
|
exports["default"] = AbilityMatch;
|
|
135
147
|
|
|
136
148
|
|
|
137
|
-
/***/ }),
|
|
138
|
-
|
|
139
|
-
/***/ "./src/AbilityParser.ts":
|
|
140
|
-
/*!******************************!*\
|
|
141
|
-
!*** ./src/AbilityParser.ts ***!
|
|
142
|
-
\******************************/
|
|
143
|
-
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
147
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
148
|
-
};
|
|
149
|
-
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
150
|
-
exports.AbilityParser = void 0;
|
|
151
|
-
const AbilityError_1 = __webpack_require__(/*! ./AbilityError */ "./src/AbilityError.ts");
|
|
152
|
-
const AbilityCondition_1 = __importDefault(__webpack_require__(/*! ./AbilityCondition */ "./src/AbilityCondition.ts"));
|
|
153
|
-
class AbilityParser {
|
|
154
|
-
/**
|
|
155
|
-
* Validates the configuration object based on the provided field validation configurations.
|
|
156
|
-
* @param config - The configuration object to validate.
|
|
157
|
-
* @param fields - An array of field validation configurations.
|
|
158
|
-
* @throws {AbilityParserError} If a required field is missing or if a field has an incorrect type.
|
|
159
|
-
*/
|
|
160
|
-
static validateConfig(config, fields) {
|
|
161
|
-
fields.forEach(([field, type, isRequired]) => {
|
|
162
|
-
const value = config[field];
|
|
163
|
-
if (isRequired) {
|
|
164
|
-
if (typeof value === 'undefined') {
|
|
165
|
-
throw new AbilityError_1.AbilityParserError(`Missing required field [${field}]`);
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
switch (type) {
|
|
169
|
-
case 'array':
|
|
170
|
-
if (typeof value !== 'object' || !Array.isArray(value)) {
|
|
171
|
-
throw new AbilityError_1.AbilityParserError(`Field [${field}] must be an type of [${type}], bit got [${typeof value}]`);
|
|
172
|
-
}
|
|
173
|
-
break;
|
|
174
|
-
default:
|
|
175
|
-
if (typeof value !== type && typeof value !== 'undefined') {
|
|
176
|
-
throw new AbilityError_1.AbilityParserError(`Field [${field}] must be a type of [${type}], bit got [${typeof value}]`);
|
|
177
|
-
}
|
|
178
|
-
break;
|
|
179
|
-
}
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Prepares and validates the configuration object or JSON string.
|
|
184
|
-
* @param configOrJson - The configuration object or JSON string to validate.
|
|
185
|
-
* @param fields - An array of field validation configurations.
|
|
186
|
-
* @returns The validated configuration object.
|
|
187
|
-
*/
|
|
188
|
-
static prepareAndValidateConfig(configOrJson, fields) {
|
|
189
|
-
const config = typeof configOrJson === 'string'
|
|
190
|
-
? (JSON.parse(configOrJson))
|
|
191
|
-
: configOrJson;
|
|
192
|
-
AbilityParser.validateConfig(config, fields);
|
|
193
|
-
return config;
|
|
194
|
-
}
|
|
195
|
-
/*
|
|
196
|
-
*
|
|
197
|
-
* readonly ['order.update']: {
|
|
198
|
-
* readonly user: {
|
|
199
|
-
* readonly roles: readonly string[];
|
|
200
|
-
* readonly department: string;
|
|
201
|
-
* };
|
|
202
|
-
* readonly order: {
|
|
203
|
-
* readonly estimatedArrivalAt: number;
|
|
204
|
-
* readonly status: string;
|
|
205
|
-
* }
|
|
206
|
-
* }
|
|
207
|
-
*
|
|
208
|
-
* */
|
|
209
|
-
/**
|
|
210
|
-
* Sets a value in a nested object structure based on a dot/bracket notation path.
|
|
211
|
-
* @param object - The target object to modify.
|
|
212
|
-
* @param path - The path to the property in dot/bracket notation.
|
|
213
|
-
* @param value - The value to set at the specified path.
|
|
214
|
-
*/
|
|
215
|
-
static setValueDotValue(object, path, value) {
|
|
216
|
-
const way = path.replace(/\[/g, '.').replace(/\]/g, '').split('.');
|
|
217
|
-
const last = way.pop();
|
|
218
|
-
if (!last) {
|
|
219
|
-
throw new AbilityError_1.AbilityParserError(`Invalid path provided on a [${path}]`);
|
|
220
|
-
}
|
|
221
|
-
way.reduce((o, k, i, kk) => {
|
|
222
|
-
if (!o[k]) {
|
|
223
|
-
o[k] = isFinite(Number(kk[i + 1])) ? [] : {};
|
|
224
|
-
}
|
|
225
|
-
return o[k];
|
|
226
|
-
}, object)[last] = value;
|
|
227
|
-
}
|
|
228
|
-
/**
|
|
229
|
-
* Generates TypeScript type definitions based on the provided policies.
|
|
230
|
-
* @param policies - An array of AbilityPolicy instances.
|
|
231
|
-
* @param outPath - The output path for the generated type definitions.
|
|
232
|
-
* @returns A record containing the generated type definitions.
|
|
233
|
-
*/
|
|
234
|
-
static generateTypeDefs(policies, outPath) {
|
|
235
|
-
const record = {};
|
|
236
|
-
policies.forEach(policy => {
|
|
237
|
-
policy.ruleSet.forEach(ruleSet => {
|
|
238
|
-
ruleSet.rules.forEach(rule => {
|
|
239
|
-
let value = 'any';
|
|
240
|
-
switch (true) {
|
|
241
|
-
case rule.condition.isEqual(AbilityCondition_1.default.NOT_EQUAL):
|
|
242
|
-
case rule.condition.isEqual(AbilityCondition_1.default.EQUAL):
|
|
243
|
-
value = typeof rule.staticValueOrPathName;
|
|
244
|
-
break;
|
|
245
|
-
case rule.condition.isEqual(AbilityCondition_1.default.IN):
|
|
246
|
-
case rule.condition.isEqual(AbilityCondition_1.default.NOT_IN):
|
|
247
|
-
value = `${typeof rule.staticValueOrPathName}[]`;
|
|
248
|
-
break;
|
|
249
|
-
case rule.condition.isEqual(AbilityCondition_1.default.MORE_OR_EQUAL):
|
|
250
|
-
case rule.condition.isEqual(AbilityCondition_1.default.MORE_THAN):
|
|
251
|
-
case rule.condition.isEqual(AbilityCondition_1.default.LESS_OR_EQUAL):
|
|
252
|
-
case rule.condition.isEqual(AbilityCondition_1.default.LESS_THAN):
|
|
253
|
-
value = 'number';
|
|
254
|
-
break;
|
|
255
|
-
}
|
|
256
|
-
AbilityParser.setValueDotValue(record, rule.subjectPathName, value);
|
|
257
|
-
});
|
|
258
|
-
});
|
|
259
|
-
});
|
|
260
|
-
console.log(JSON.stringify(record));
|
|
261
|
-
return record;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
exports.AbilityParser = AbilityParser;
|
|
265
|
-
exports["default"] = AbilityParser;
|
|
266
|
-
|
|
267
|
-
|
|
268
149
|
/***/ }),
|
|
269
150
|
|
|
270
151
|
/***/ "./src/AbilityPolicy.ts":
|
|
@@ -283,9 +164,8 @@ const AbilityRuleSet_1 = __importDefault(__webpack_require__(/*! ./AbilityRuleSe
|
|
|
283
164
|
const AbilityMatch_1 = __importDefault(__webpack_require__(/*! ./AbilityMatch */ "./src/AbilityMatch.ts"));
|
|
284
165
|
const AbilityCompare_1 = __importDefault(__webpack_require__(/*! ./AbilityCompare */ "./src/AbilityCompare.ts"));
|
|
285
166
|
const AbilityPolicyEffect_1 = __importDefault(__webpack_require__(/*! ./AbilityPolicyEffect */ "./src/AbilityPolicyEffect.ts"));
|
|
286
|
-
const AbilityParser_1 = __importDefault(__webpack_require__(/*! ./AbilityParser */ "./src/AbilityParser.ts"));
|
|
287
167
|
class AbilityPolicy {
|
|
288
|
-
matchState = AbilityMatch_1.default.
|
|
168
|
+
matchState = AbilityMatch_1.default.pending;
|
|
289
169
|
/**
|
|
290
170
|
* List of rules
|
|
291
171
|
*/
|
|
@@ -300,7 +180,7 @@ class AbilityPolicy {
|
|
|
300
180
|
* rules will be returns «permit» status and for the «or» - if\
|
|
301
181
|
* one of the rules returns as «permit»
|
|
302
182
|
*/
|
|
303
|
-
compareMethod = AbilityCompare_1.default.
|
|
183
|
+
compareMethod = AbilityCompare_1.default.and;
|
|
304
184
|
/**
|
|
305
185
|
* Policy name
|
|
306
186
|
*/
|
|
@@ -330,28 +210,24 @@ class AbilityPolicy {
|
|
|
330
210
|
}
|
|
331
211
|
/**
|
|
332
212
|
* Check if the policy is matched
|
|
333
|
-
* @param
|
|
213
|
+
* @param resources - The resource to check
|
|
334
214
|
*/
|
|
335
|
-
check(
|
|
336
|
-
this.matchState = AbilityMatch_1.default.
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
if (AbilityCompare_1.default.AND.isEqual(this.compareMethod)) {
|
|
347
|
-
if (ruleCheckStates.every(ruleState => AbilityMatch_1.default.MATCH.isEqual(ruleState))) {
|
|
348
|
-
this.matchState = AbilityMatch_1.default.MATCH;
|
|
349
|
-
}
|
|
215
|
+
check(resources) {
|
|
216
|
+
this.matchState = AbilityMatch_1.default.mismatch;
|
|
217
|
+
if (!this.ruleSet.length) {
|
|
218
|
+
return this.matchState;
|
|
219
|
+
}
|
|
220
|
+
const rulesetCheckStates = this.ruleSet.reduce((collect, ruleSet) => {
|
|
221
|
+
return collect.concat(ruleSet.check(resources));
|
|
222
|
+
}, []);
|
|
223
|
+
if (AbilityCompare_1.default.and.isEqual(this.compareMethod)) {
|
|
224
|
+
if (rulesetCheckStates.every(ruleState => AbilityMatch_1.default.match.isEqual(ruleState))) {
|
|
225
|
+
this.matchState = AbilityMatch_1.default.match;
|
|
350
226
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
227
|
+
}
|
|
228
|
+
if (AbilityCompare_1.default.or.isEqual(this.compareMethod)) {
|
|
229
|
+
if (rulesetCheckStates.some(ruleState => AbilityMatch_1.default.match.isEqual(ruleState))) {
|
|
230
|
+
this.matchState = AbilityMatch_1.default.match;
|
|
355
231
|
}
|
|
356
232
|
}
|
|
357
233
|
return this.matchState;
|
|
@@ -359,15 +235,7 @@ class AbilityPolicy {
|
|
|
359
235
|
/**
|
|
360
236
|
* Parse the config JSON format to Policy class instance
|
|
361
237
|
*/
|
|
362
|
-
static parse(
|
|
363
|
-
const config = AbilityParser_1.default.prepareAndValidateConfig(configOrJson, [
|
|
364
|
-
['id', 'string', true],
|
|
365
|
-
['name', 'string', true],
|
|
366
|
-
['action', 'string', true],
|
|
367
|
-
['effect', 'number', true],
|
|
368
|
-
['compareMethod', 'number', true],
|
|
369
|
-
['ruleSet', 'array', true],
|
|
370
|
-
]);
|
|
238
|
+
static parse(config) {
|
|
371
239
|
const { id, name, ruleSet, compareMethod, action, effect } = config;
|
|
372
240
|
// Create the empty policy
|
|
373
241
|
const policy = new AbilityPolicy({
|
|
@@ -376,7 +244,7 @@ class AbilityPolicy {
|
|
|
376
244
|
action,
|
|
377
245
|
effect: new AbilityPolicyEffect_1.default(effect),
|
|
378
246
|
});
|
|
379
|
-
policy.compareMethod =
|
|
247
|
+
policy.compareMethod = AbilityCompare_1.default.fromLiteral(compareMethod);
|
|
380
248
|
ruleSet.forEach(ruleSetConfig => {
|
|
381
249
|
policy.addRuleSet(AbilityRuleSet_1.default.parse(ruleSetConfig));
|
|
382
250
|
});
|
|
@@ -386,7 +254,7 @@ class AbilityPolicy {
|
|
|
386
254
|
return {
|
|
387
255
|
id: this.id.toString(),
|
|
388
256
|
name: this.name.toString(),
|
|
389
|
-
compareMethod: this.compareMethod.code,
|
|
257
|
+
compareMethod: this.compareMethod.code.toString(),
|
|
390
258
|
ruleSet: this.ruleSet.map(rule => rule.export()),
|
|
391
259
|
action: this.action,
|
|
392
260
|
effect: this.effect.code,
|
|
@@ -413,8 +281,8 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
413
281
|
exports.AbilityPolicyEffect = void 0;
|
|
414
282
|
const AbilityCode_1 = __importDefault(__webpack_require__(/*! ./AbilityCode */ "./src/AbilityCode.ts"));
|
|
415
283
|
class AbilityPolicyEffect extends AbilityCode_1.default {
|
|
416
|
-
static
|
|
417
|
-
static
|
|
284
|
+
static deny = new AbilityPolicyEffect('deny');
|
|
285
|
+
static permit = new AbilityPolicyEffect('permit');
|
|
418
286
|
}
|
|
419
287
|
exports.AbilityPolicyEffect = AbilityPolicyEffect;
|
|
420
288
|
exports["default"] = AbilityPolicyEffect;
|
|
@@ -439,8 +307,10 @@ const AbilityMatch_1 = __importDefault(__webpack_require__(/*! ./AbilityMatch */
|
|
|
439
307
|
const AbilityError_1 = __webpack_require__(/*! ./AbilityError */ "./src/AbilityError.ts");
|
|
440
308
|
class AbilityResolver {
|
|
441
309
|
policies;
|
|
442
|
-
constructor(
|
|
443
|
-
this.policies =
|
|
310
|
+
constructor(policyOrListOfPolicies) {
|
|
311
|
+
this.policies = Array.isArray(policyOrListOfPolicies)
|
|
312
|
+
? policyOrListOfPolicies
|
|
313
|
+
: [policyOrListOfPolicies];
|
|
444
314
|
}
|
|
445
315
|
/**
|
|
446
316
|
* Resolve policy for the resource and action
|
|
@@ -471,7 +341,7 @@ class AbilityResolver {
|
|
|
471
341
|
*/
|
|
472
342
|
getEffect() {
|
|
473
343
|
const effects = this.policies.reduce((collect, policy, _index) => {
|
|
474
|
-
if (policy.matchState.isEqual(AbilityMatch_1.default.
|
|
344
|
+
if (policy.matchState.isEqual(AbilityMatch_1.default.match)) {
|
|
475
345
|
return collect.concat(policy.effect);
|
|
476
346
|
}
|
|
477
347
|
return collect;
|
|
@@ -483,15 +353,15 @@ class AbilityResolver {
|
|
|
483
353
|
}
|
|
484
354
|
isPermit() {
|
|
485
355
|
const effect = this.getEffect();
|
|
486
|
-
return effect !== null && effect.isEqual(AbilityPolicyEffect_1.default.
|
|
356
|
+
return effect !== null && effect.isEqual(AbilityPolicyEffect_1.default.permit);
|
|
487
357
|
}
|
|
488
358
|
isDeny() {
|
|
489
359
|
const effect = this.getEffect();
|
|
490
|
-
return effect !== null && effect.isEqual(AbilityPolicyEffect_1.default.
|
|
360
|
+
return effect !== null && effect.isEqual(AbilityPolicyEffect_1.default.deny);
|
|
491
361
|
}
|
|
492
362
|
getPolicy() {
|
|
493
363
|
const lastPolicy = this.policies.length ? this.policies[this.policies.length - 1] : null;
|
|
494
|
-
return lastPolicy && lastPolicy.matchState.isEqual(AbilityMatch_1.default.
|
|
364
|
+
return lastPolicy && lastPolicy.matchState.isEqual(AbilityMatch_1.default.match) ? lastPolicy : null;
|
|
495
365
|
}
|
|
496
366
|
/**
|
|
497
367
|
* Check if the action is contained in another action
|
|
@@ -531,26 +401,25 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
531
401
|
exports.AbilityRule = void 0;
|
|
532
402
|
const AbilityMatch_1 = __importDefault(__webpack_require__(/*! ./AbilityMatch */ "./src/AbilityMatch.ts"));
|
|
533
403
|
const AbilityCondition_1 = __importDefault(__webpack_require__(/*! ./AbilityCondition */ "./src/AbilityCondition.ts"));
|
|
534
|
-
const AbilityParser_1 = __importDefault(__webpack_require__(/*! ./AbilityParser */ "./src/AbilityParser.ts"));
|
|
535
404
|
class AbilityRule {
|
|
536
405
|
/**
|
|
537
406
|
* Subject key path like a 'user.name'
|
|
538
407
|
*/
|
|
539
|
-
|
|
408
|
+
subject;
|
|
540
409
|
/**
|
|
541
410
|
* Resource key path like a 'user.name' or value
|
|
542
411
|
*/
|
|
543
|
-
|
|
412
|
+
resource;
|
|
544
413
|
condition;
|
|
545
414
|
name;
|
|
546
415
|
id;
|
|
547
|
-
state = AbilityMatch_1.default.
|
|
416
|
+
state = AbilityMatch_1.default.pending;
|
|
548
417
|
constructor(params) {
|
|
549
|
-
const { id, name,
|
|
418
|
+
const { id, name, subject, resource, condition } = params;
|
|
550
419
|
this.id = id;
|
|
551
420
|
this.name = name;
|
|
552
|
-
this.
|
|
553
|
-
this.
|
|
421
|
+
this.subject = subject;
|
|
422
|
+
this.resource = resource;
|
|
554
423
|
this.condition = new AbilityCondition_1.default(condition);
|
|
555
424
|
}
|
|
556
425
|
/**
|
|
@@ -606,30 +475,33 @@ class AbilityRule {
|
|
|
606
475
|
is = !valueS.includes(valueO);
|
|
607
476
|
}
|
|
608
477
|
}
|
|
609
|
-
this.state = is ? AbilityMatch_1.default.
|
|
478
|
+
this.state = is ? AbilityMatch_1.default.match : AbilityMatch_1.default.mismatch;
|
|
610
479
|
return this.state;
|
|
611
480
|
}
|
|
612
481
|
/**
|
|
613
|
-
* Extract values from the
|
|
614
|
-
* @param
|
|
482
|
+
* Extract values from the resourceData
|
|
483
|
+
* @param resourceData - The resourceData to extract values from
|
|
615
484
|
*/
|
|
616
|
-
extractValues(
|
|
485
|
+
extractValues(resourceData) {
|
|
617
486
|
let leftSideValue;
|
|
618
487
|
let rightSideValue;
|
|
619
|
-
if (
|
|
488
|
+
if (resourceData === null || typeof resourceData === 'undefined') {
|
|
620
489
|
return [NaN, NaN];
|
|
621
490
|
}
|
|
622
491
|
const isPath = (str) => {
|
|
623
492
|
return typeof str === 'string' && str.match(/\./g) !== null;
|
|
624
493
|
};
|
|
625
|
-
if (isPath(this.
|
|
626
|
-
leftSideValue = this.getDotNotationValue(
|
|
494
|
+
if (isPath(this.subject)) {
|
|
495
|
+
leftSideValue = this.getDotNotationValue(resourceData, this.subject);
|
|
496
|
+
}
|
|
497
|
+
else {
|
|
498
|
+
leftSideValue = this.subject;
|
|
627
499
|
}
|
|
628
|
-
if (isPath(this.
|
|
629
|
-
rightSideValue = this.getDotNotationValue(
|
|
500
|
+
if (isPath(this.resource)) {
|
|
501
|
+
rightSideValue = this.getDotNotationValue(resourceData, this.resource);
|
|
630
502
|
}
|
|
631
503
|
else {
|
|
632
|
-
rightSideValue = this.
|
|
504
|
+
rightSideValue = this.resource;
|
|
633
505
|
}
|
|
634
506
|
return [leftSideValue, rightSideValue];
|
|
635
507
|
}
|
|
@@ -661,18 +533,13 @@ class AbilityRule {
|
|
|
661
533
|
}
|
|
662
534
|
return resource;
|
|
663
535
|
}
|
|
664
|
-
static parse(
|
|
665
|
-
const
|
|
666
|
-
['id', 'string', true],
|
|
667
|
-
['name', 'string', true],
|
|
668
|
-
['subjectPathName', 'string', true],
|
|
669
|
-
]);
|
|
670
|
-
const { id, name, subjectPathName, staticValueOrPathName, condition } = config;
|
|
536
|
+
static parse(config) {
|
|
537
|
+
const { id, name, subject, resource, condition } = config;
|
|
671
538
|
return new AbilityRule({
|
|
672
539
|
id,
|
|
673
540
|
name,
|
|
674
|
-
|
|
675
|
-
|
|
541
|
+
subject,
|
|
542
|
+
resource,
|
|
676
543
|
condition,
|
|
677
544
|
});
|
|
678
545
|
}
|
|
@@ -683,8 +550,8 @@ class AbilityRule {
|
|
|
683
550
|
return {
|
|
684
551
|
id: this.id,
|
|
685
552
|
name: this.name,
|
|
686
|
-
|
|
687
|
-
|
|
553
|
+
subject: this.subject,
|
|
554
|
+
resource: this.resource,
|
|
688
555
|
condition: this.condition.code,
|
|
689
556
|
};
|
|
690
557
|
}
|
|
@@ -710,9 +577,8 @@ exports.AbilityRuleSet = void 0;
|
|
|
710
577
|
const AbilityRule_1 = __importDefault(__webpack_require__(/*! ./AbilityRule */ "./src/AbilityRule.ts"));
|
|
711
578
|
const AbilityCompare_1 = __importDefault(__webpack_require__(/*! ./AbilityCompare */ "./src/AbilityCompare.ts"));
|
|
712
579
|
const AbilityMatch_1 = __importDefault(__webpack_require__(/*! ./AbilityMatch */ "./src/AbilityMatch.ts"));
|
|
713
|
-
const AbilityParser_1 = __importDefault(__webpack_require__(/*! ./AbilityParser */ "./src/AbilityParser.ts"));
|
|
714
580
|
class AbilityRuleSet {
|
|
715
|
-
state = AbilityMatch_1.default.
|
|
581
|
+
state = AbilityMatch_1.default.pending;
|
|
716
582
|
/**
|
|
717
583
|
* List of rules
|
|
718
584
|
*/
|
|
@@ -723,7 +589,7 @@ class AbilityRuleSet {
|
|
|
723
589
|
* rules will be returns «permit» status and for the «or» - if\
|
|
724
590
|
* one of the rules returns as «permit»
|
|
725
591
|
*/
|
|
726
|
-
compareMethod = AbilityCompare_1.default.
|
|
592
|
+
compareMethod = AbilityCompare_1.default.and;
|
|
727
593
|
/**
|
|
728
594
|
* Group name
|
|
729
595
|
*/
|
|
@@ -736,7 +602,8 @@ class AbilityRuleSet {
|
|
|
736
602
|
const { name, id, compareMethod } = params;
|
|
737
603
|
this.name = name;
|
|
738
604
|
this.id = id;
|
|
739
|
-
this.compareMethod =
|
|
605
|
+
this.compareMethod = AbilityCompare_1.default.fromLiteral(compareMethod);
|
|
606
|
+
// this.compareMethod = new AbilityCompare(compareMethod);
|
|
740
607
|
}
|
|
741
608
|
addRule(rule, compareMethod) {
|
|
742
609
|
this.rules.push(rule);
|
|
@@ -748,21 +615,21 @@ class AbilityRuleSet {
|
|
|
748
615
|
return this;
|
|
749
616
|
}
|
|
750
617
|
check(resources) {
|
|
751
|
-
this.state = AbilityMatch_1.default.
|
|
618
|
+
this.state = AbilityMatch_1.default.mismatch;
|
|
752
619
|
if (!this.rules.length) {
|
|
753
620
|
return this.state;
|
|
754
621
|
}
|
|
755
622
|
const ruleCheckStates = this.rules.reduce((collect, rule) => {
|
|
756
623
|
return collect.concat(rule.check(resources));
|
|
757
624
|
}, []);
|
|
758
|
-
if (AbilityCompare_1.default.
|
|
759
|
-
if (ruleCheckStates.every(ruleState => AbilityMatch_1.default.
|
|
760
|
-
this.state = AbilityMatch_1.default.
|
|
625
|
+
if (AbilityCompare_1.default.and.isEqual(this.compareMethod)) {
|
|
626
|
+
if (ruleCheckStates.every(ruleState => AbilityMatch_1.default.match.isEqual(ruleState))) {
|
|
627
|
+
this.state = AbilityMatch_1.default.match;
|
|
761
628
|
}
|
|
762
629
|
}
|
|
763
|
-
if (AbilityCompare_1.default.
|
|
764
|
-
if (ruleCheckStates.some(ruleState => AbilityMatch_1.default.
|
|
765
|
-
this.state = AbilityMatch_1.default.
|
|
630
|
+
if (AbilityCompare_1.default.or.isEqual(this.compareMethod)) {
|
|
631
|
+
if (ruleCheckStates.some(ruleState => AbilityMatch_1.default.match.isEqual(ruleState))) {
|
|
632
|
+
this.state = AbilityMatch_1.default.match;
|
|
766
633
|
}
|
|
767
634
|
}
|
|
768
635
|
return this.state;
|
|
@@ -770,13 +637,7 @@ class AbilityRuleSet {
|
|
|
770
637
|
/**
|
|
771
638
|
* Parse the config JSON format to Group class instance
|
|
772
639
|
*/
|
|
773
|
-
static parse(
|
|
774
|
-
const config = AbilityParser_1.default.prepareAndValidateConfig(configOrJson, [
|
|
775
|
-
['id', 'string', true],
|
|
776
|
-
['name', 'string', true],
|
|
777
|
-
['compareMethod', 'number', true],
|
|
778
|
-
['rules', 'array', true],
|
|
779
|
-
]);
|
|
640
|
+
static parse(config) {
|
|
780
641
|
const { id, name, rules, compareMethod } = config;
|
|
781
642
|
const ruleSet = new AbilityRuleSet({
|
|
782
643
|
compareMethod,
|
|
@@ -794,7 +655,7 @@ class AbilityRuleSet {
|
|
|
794
655
|
return {
|
|
795
656
|
id: this.id.toString(),
|
|
796
657
|
name: this.name.toString(),
|
|
797
|
-
compareMethod: this.compareMethod.code,
|
|
658
|
+
compareMethod: this.compareMethod.code.toString(),
|
|
798
659
|
rules: this.rules.map(rule => rule.export()),
|
|
799
660
|
};
|
|
800
661
|
}
|
|
@@ -819,24 +680,80 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
819
680
|
const node_http_1 = __importDefault(__webpack_require__(/*! node:http */ "node:http"));
|
|
820
681
|
const AbilityPolicy_1 = __importDefault(__webpack_require__(/*! ./AbilityPolicy */ "./src/AbilityPolicy.ts"));
|
|
821
682
|
const AbilityResolver_1 = __importDefault(__webpack_require__(/*! ~/AbilityResolver */ "./src/AbilityResolver.ts"));
|
|
822
|
-
const policies_json_1 = __importDefault(__webpack_require__(/*! ./policies.json */ "./src/policies.json"));
|
|
823
683
|
const server = node_http_1.default.createServer();
|
|
824
684
|
server.on('request', (_req, res) => {
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
685
|
+
const config = [
|
|
686
|
+
{
|
|
687
|
+
id: 'bb758c1b-1015-4894-ba25-d23156e063cf',
|
|
688
|
+
name: 'Status hui',
|
|
689
|
+
action: 'order.status',
|
|
690
|
+
effect: 'deny',
|
|
691
|
+
compareMethod: 'and',
|
|
692
|
+
ruleSet: [
|
|
693
|
+
{
|
|
694
|
+
id: '9cc009e5-0aa9-453a-a668-cb3f418ced92',
|
|
695
|
+
name: 'Не администратор',
|
|
696
|
+
compareMethod: 'and',
|
|
697
|
+
rules: [
|
|
698
|
+
{
|
|
699
|
+
id: '4093cd50-e54f-4062-8053-2d3b5966fad3',
|
|
700
|
+
name: 'Нет роли администраторв',
|
|
701
|
+
subject: 'account.roles',
|
|
702
|
+
resource: 'administrator',
|
|
703
|
+
condition: '<>',
|
|
704
|
+
},
|
|
705
|
+
],
|
|
706
|
+
},
|
|
707
|
+
]
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
id: 'bb758c1b-1015-4894-ba25-d23156e063cf',
|
|
711
|
+
name: 'Status hui 1',
|
|
712
|
+
action: 'order.status',
|
|
713
|
+
effect: 'permit',
|
|
714
|
+
compareMethod: 'and',
|
|
715
|
+
ruleSet: [
|
|
716
|
+
{
|
|
717
|
+
id: '2f8f9d71-860b-4fa6-b395-9331f1f0848e',
|
|
718
|
+
name: 'Rule set',
|
|
719
|
+
compareMethod: 'and',
|
|
720
|
+
rules: [
|
|
721
|
+
{
|
|
722
|
+
id: 'a3c7d66f-5c2d-4a24-83bc-03b0a2d9c32b',
|
|
723
|
+
name: 'Rule 1',
|
|
724
|
+
subject: 'order.status',
|
|
725
|
+
resource: 'не обработан',
|
|
726
|
+
condition: '=',
|
|
727
|
+
},
|
|
728
|
+
{
|
|
729
|
+
id: 'a3c7d66f-5c2d-4a24-83bc-03b0a2d9c32b',
|
|
730
|
+
name: 'Rule 2',
|
|
731
|
+
subject: 'feature.status',
|
|
732
|
+
resource: 'отменен',
|
|
733
|
+
condition: '=',
|
|
734
|
+
},
|
|
735
|
+
],
|
|
736
|
+
},
|
|
737
|
+
],
|
|
738
|
+
},
|
|
739
|
+
];
|
|
740
|
+
const policies = config.map(cfg => AbilityPolicy_1.default.parse(cfg));
|
|
741
|
+
const result = new AbilityResolver_1.default(policies).resolve('order.status', {
|
|
828
742
|
account: {
|
|
829
|
-
|
|
830
|
-
|
|
743
|
+
roles: ['user', 'couch'],
|
|
744
|
+
},
|
|
745
|
+
order: {
|
|
746
|
+
status: 'не обработан',
|
|
831
747
|
},
|
|
832
|
-
|
|
833
|
-
|
|
748
|
+
feature: {
|
|
749
|
+
status: 'отменен',
|
|
750
|
+
// status: 'завершен'
|
|
834
751
|
},
|
|
835
752
|
});
|
|
836
753
|
res.statusCode = 200;
|
|
837
754
|
res.setHeader('content-type', 'application/json');
|
|
838
755
|
res.write(JSON.stringify({
|
|
839
|
-
status: '
|
|
756
|
+
status: result.isDeny() ? 'deny' : 'permit',
|
|
840
757
|
}));
|
|
841
758
|
res.end();
|
|
842
759
|
});
|
|
@@ -855,16 +772,6 @@ server.listen(8080, 'localhost', () => {
|
|
|
855
772
|
|
|
856
773
|
module.exports = require("node:http");
|
|
857
774
|
|
|
858
|
-
/***/ }),
|
|
859
|
-
|
|
860
|
-
/***/ "./src/policies.json":
|
|
861
|
-
/*!***************************!*\
|
|
862
|
-
!*** ./src/policies.json ***!
|
|
863
|
-
\***************************/
|
|
864
|
-
/***/ ((module) => {
|
|
865
|
-
|
|
866
|
-
module.exports = /*#__PURE__*/JSON.parse('[{"id":"d7c491d2-b937-4f75-b26a-e989fb12f051","name":"Просмотр чужого логина разрешен только владельцу аккаунта и администраторам","action":"account.read","effect":0,"compareMethod":0,"ruleSet":[{"id":"3f3e2b42-55ae-4bf9-8438-5dfa7fd4b93e","name":"Не владелец аккаунта и не администратор","compareMethod":1,"rules":[{"id":"46d9aa89-e507-455d-9e8c-7544f75bbb8b","name":"Владелец аккаунта","subjectPathName":"account.id","staticValueOrPathName":"resource.id","condition":"<>"},{"id":"8ab0075a-1670-4d44-b643-16d55ec96831","name":"Администратор","subjectPathName":"account.roles","staticValueOrPathName":"administrator","condition":"not in"}]}]}]');
|
|
867
|
-
|
|
868
775
|
/***/ })
|
|
869
776
|
|
|
870
777
|
/******/ });
|