@via-profit/ability 2.1.0 → 3.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +129 -0
  2. package/CONTRIBUTING.md +14 -0
  3. package/LICENSE +21 -0
  4. package/README.md +1058 -319
  5. package/SECURITY.md +33 -0
  6. package/dist/cache/AbilityCacheAdapter.d.ts +8 -0
  7. package/dist/cache/AbilityInMemoryCache.d.ts +12 -0
  8. package/dist/core/AbilityCondition.d.ts +21 -0
  9. package/dist/core/AbilityExplain.d.ts +27 -0
  10. package/dist/core/AbilityParser.d.ts +61 -0
  11. package/dist/core/AbilityPolicy.d.ts +84 -0
  12. package/dist/core/AbilityResolver.d.ts +35 -0
  13. package/dist/core/AbilityResult.d.ts +27 -0
  14. package/dist/core/AbilityRule.d.ts +77 -0
  15. package/dist/{AbilityRuleSet.d.ts → core/AbilityRuleSet.d.ts} +14 -11
  16. package/dist/index.d.ts +19 -11
  17. package/dist/index.js +2097 -303
  18. package/dist/parsers/dsl/AbilityDSLLexer.d.ts +24 -0
  19. package/dist/parsers/dsl/AbilityDSLParser.d.ts +86 -0
  20. package/dist/parsers/dsl/AbilityDSLSyntaxError.d.ts +13 -0
  21. package/dist/parsers/dsl/AbilityDSLToken.d.ts +55 -0
  22. package/dist/parsers/json/AbilityJSONParser.d.ts +22 -0
  23. package/package.json +15 -4
  24. package/assets/ability-01.drawio.png +0 -0
  25. package/build/playground.js +0 -456
  26. package/build/playground.js.map +0 -1
  27. package/dist/AbilityCondition.d.ts +0 -16
  28. package/dist/AbilityParser.d.ts +0 -18
  29. package/dist/AbilityPolicy.d.ts +0 -65
  30. package/dist/AbilityResolver.d.ts +0 -30
  31. package/dist/AbilityRule.d.ts +0 -70
  32. /package/dist/{AbilityCode.d.ts → core/AbilityCode.d.ts} +0 -0
  33. /package/dist/{AbilityCompare.d.ts → core/AbilityCompare.d.ts} +0 -0
  34. /package/dist/{AbilityError.d.ts → core/AbilityError.d.ts} +0 -0
  35. /package/dist/{AbilityMatch.d.ts → core/AbilityMatch.d.ts} +0 -0
  36. /package/dist/{AbilityPolicyEffect.d.ts → core/AbilityPolicyEffect.d.ts} +0 -0
@@ -1,456 +0,0 @@
1
- /******/ (() => { // webpackBootstrap
2
- /******/ "use strict";
3
- /******/ var __webpack_modules__ = ({
4
-
5
- /***/ "./src/AbilityCode.ts":
6
- /*!****************************!*\
7
- !*** ./src/AbilityCode.ts ***!
8
- \****************************/
9
- /***/ ((__unused_webpack_module, exports) => {
10
-
11
-
12
- Object.defineProperty(exports, "__esModule", ({ value: true }));
13
- exports.AbilityCode = void 0;
14
- class AbilityCode {
15
- _code;
16
- constructor(code) {
17
- this._code = code;
18
- }
19
- get code() {
20
- return this._code;
21
- }
22
- isEqual(compareWith) {
23
- return compareWith !== null && this.code === compareWith.code;
24
- }
25
- isNotEqual(compareWith) {
26
- return !this.isEqual(compareWith);
27
- }
28
- }
29
- exports.AbilityCode = AbilityCode;
30
- exports["default"] = AbilityCode;
31
-
32
-
33
- /***/ }),
34
-
35
- /***/ "./src/AbilityCondition.ts":
36
- /*!*********************************!*\
37
- !*** ./src/AbilityCondition.ts ***!
38
- \*********************************/
39
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
40
-
41
-
42
- var __importDefault = (this && this.__importDefault) || function (mod) {
43
- return (mod && mod.__esModule) ? mod : { "default": mod };
44
- };
45
- Object.defineProperty(exports, "__esModule", ({ value: true }));
46
- exports.AbilityCondition = void 0;
47
- const AbilityCode_1 = __importDefault(__webpack_require__(/*! ./AbilityCode */ "./src/AbilityCode.ts"));
48
- const AbilityError_1 = __webpack_require__(/*! ~/AbilityError */ "./src/AbilityError.ts");
49
- class AbilityCondition extends AbilityCode_1.default {
50
- static equal = new AbilityCondition('=');
51
- static not_equal = new AbilityCondition('<>');
52
- static more_than = new AbilityCondition('>');
53
- static less_than = new AbilityCondition('<');
54
- static less_or_equal = new AbilityCondition('<=');
55
- static more_or_equal = new AbilityCondition('>=');
56
- static in = new AbilityCondition('in');
57
- static not_in = new AbilityCondition('not in');
58
- static fromLiteral(literal) {
59
- const code = AbilityCondition[literal]?.code || null;
60
- if (code === null) {
61
- throw new AbilityError_1.AbilityParserError(`Literal ${literal} does not found in AbilityCondition class`);
62
- }
63
- return new AbilityCondition(code);
64
- }
65
- get literal() {
66
- const literal = Object.keys(AbilityCondition).find(member => {
67
- const val = AbilityCondition[member];
68
- return val.code === this.code;
69
- });
70
- if (typeof literal === 'undefined') {
71
- throw new Error(`Literal value does not found in class AbilityCondition`);
72
- }
73
- return literal;
74
- }
75
- }
76
- exports.AbilityCondition = AbilityCondition;
77
- exports["default"] = AbilityCondition;
78
-
79
-
80
- /***/ }),
81
-
82
- /***/ "./src/AbilityError.ts":
83
- /*!*****************************!*\
84
- !*** ./src/AbilityError.ts ***!
85
- \*****************************/
86
- /***/ ((__unused_webpack_module, exports) => {
87
-
88
-
89
- Object.defineProperty(exports, "__esModule", ({ value: true }));
90
- exports.PermissionError = exports.AbilityParserError = exports.AbilityError = void 0;
91
- class AbilityError extends Error {
92
- constructor(message) {
93
- super(message);
94
- }
95
- }
96
- exports.AbilityError = AbilityError;
97
- class AbilityParserError extends Error {
98
- constructor(message) {
99
- super(message);
100
- }
101
- }
102
- exports.AbilityParserError = AbilityParserError;
103
- class PermissionError extends Error {
104
- constructor(message) {
105
- super(message);
106
- }
107
- }
108
- exports.PermissionError = PermissionError;
109
-
110
-
111
- /***/ }),
112
-
113
- /***/ "./src/AbilityMatch.ts":
114
- /*!*****************************!*\
115
- !*** ./src/AbilityMatch.ts ***!
116
- \*****************************/
117
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
118
-
119
-
120
- var __importDefault = (this && this.__importDefault) || function (mod) {
121
- return (mod && mod.__esModule) ? mod : { "default": mod };
122
- };
123
- Object.defineProperty(exports, "__esModule", ({ value: true }));
124
- exports.AbilityMatch = void 0;
125
- const AbilityCode_1 = __importDefault(__webpack_require__(/*! ./AbilityCode */ "./src/AbilityCode.ts"));
126
- class AbilityMatch extends AbilityCode_1.default {
127
- static pending = new AbilityMatch('pending');
128
- static match = new AbilityMatch('match');
129
- static mismatch = new AbilityMatch('mismatch');
130
- }
131
- exports.AbilityMatch = AbilityMatch;
132
- exports["default"] = AbilityMatch;
133
-
134
-
135
- /***/ }),
136
-
137
- /***/ "./src/AbilityRule.ts":
138
- /*!****************************!*\
139
- !*** ./src/AbilityRule.ts ***!
140
- \****************************/
141
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
142
-
143
-
144
- var __importDefault = (this && this.__importDefault) || function (mod) {
145
- return (mod && mod.__esModule) ? mod : { "default": mod };
146
- };
147
- Object.defineProperty(exports, "__esModule", ({ value: true }));
148
- exports.AbilityRule = void 0;
149
- const AbilityMatch_1 = __importDefault(__webpack_require__(/*! ./AbilityMatch */ "./src/AbilityMatch.ts"));
150
- const AbilityCondition_1 = __importDefault(__webpack_require__(/*! ./AbilityCondition */ "./src/AbilityCondition.ts"));
151
- class AbilityRule {
152
- /**
153
- * Subject key path like a 'user.name'
154
- */
155
- subject;
156
- /**
157
- * Resource key path like a 'user.name' or value
158
- */
159
- resource;
160
- condition;
161
- name;
162
- id;
163
- state = AbilityMatch_1.default.pending;
164
- constructor(params) {
165
- const { id, name, subject, resource, condition } = params;
166
- this.id = id;
167
- this.name = name;
168
- this.subject = subject;
169
- this.resource = resource;
170
- this.condition = condition;
171
- }
172
- /**
173
- * Check if the rule is matched
174
- * @param resource - The resource to check
175
- */
176
- check(resource) {
177
- let is = false;
178
- const [valueS, valueO] = this.extractValues(resource);
179
- if (AbilityCondition_1.default.less_than.isEqual(this.condition)) {
180
- is = Number(valueS) < Number(valueO);
181
- }
182
- if (AbilityCondition_1.default.less_or_equal.isEqual(this.condition)) {
183
- is = Number(valueS) <= Number(valueO);
184
- }
185
- if (AbilityCondition_1.default.more_than.isEqual(this.condition)) {
186
- is = Number(valueS) > Number(valueO);
187
- }
188
- if (AbilityCondition_1.default.more_or_equal.isEqual(this.condition)) {
189
- is = Number(valueS) >= Number(valueO);
190
- }
191
- if (AbilityCondition_1.default.equal.isEqual(this.condition)) {
192
- is = valueS === valueO;
193
- }
194
- if (AbilityCondition_1.default.not_equal.isEqual(this.condition)) {
195
- is = valueS !== valueO;
196
- }
197
- if (AbilityCondition_1.default.in.isEqual(this.condition)) {
198
- // [<some>] and [<some>]
199
- if (Array.isArray(valueS) && Array.isArray(valueO)) {
200
- is = valueS.some(v => valueO.find(v1 => v1 === v));
201
- }
202
- // <some> and [<some>]
203
- if ((typeof valueS === 'string' || typeof valueS === 'number') && Array.isArray(valueO)) {
204
- is = valueO.includes(valueS);
205
- }
206
- // [<some>] and <some>
207
- if ((typeof valueO === 'string' || typeof valueO === 'number') && Array.isArray(valueS)) {
208
- is = valueS.includes(valueO);
209
- }
210
- }
211
- if (AbilityCondition_1.default.not_in.isEqual(this.condition)) {
212
- // [<some>] and [<some>]
213
- if (Array.isArray(valueS) && Array.isArray(valueO)) {
214
- is = !valueS.some(v => valueO.find(v1 => v1 === v));
215
- }
216
- // <some> and [<some>]
217
- if ((typeof valueS === 'string' || typeof valueS === 'number') && Array.isArray(valueO)) {
218
- is = !valueO.includes(valueS);
219
- }
220
- // [<some>] and <some>
221
- if ((typeof valueO === 'string' || typeof valueO === 'number') && Array.isArray(valueS)) {
222
- is = !valueS.includes(valueO);
223
- }
224
- }
225
- this.state = is ? AbilityMatch_1.default.match : AbilityMatch_1.default.mismatch;
226
- return this.state;
227
- }
228
- /**
229
- * Extract values from the resourceData
230
- * @param resourceData - The resourceData to extract values from
231
- */
232
- extractValues(resourceData) {
233
- let leftSideValue;
234
- let rightSideValue;
235
- if (resourceData === null || typeof resourceData === 'undefined') {
236
- return [NaN, NaN];
237
- }
238
- const isPath = (str) => {
239
- return typeof str === 'string' && str.match(/\./g) !== null;
240
- };
241
- if (isPath(this.subject)) {
242
- leftSideValue = this.getDotNotationValue(resourceData, this.subject);
243
- }
244
- else {
245
- leftSideValue = this.subject;
246
- }
247
- if (isPath(this.resource)) {
248
- rightSideValue = this.getDotNotationValue(resourceData, this.resource);
249
- }
250
- else {
251
- rightSideValue = this.resource;
252
- }
253
- return [leftSideValue, rightSideValue];
254
- }
255
- /**
256
- * Get the value of the object by dot notation
257
- * @param resource - The object to get the value from
258
- * @param desc - The dot notation string
259
- */
260
- getDotNotationValue(resource, desc) {
261
- const arr = desc.split('.');
262
- while (arr.length && resource) {
263
- const comp = arr.shift() || '';
264
- const match = new RegExp('(.+)\\[([0-9]*)\\]').exec(comp);
265
- if (match !== null && match.length == 3) {
266
- const arrayData = {
267
- arrName: match[1],
268
- arrIndex: match[2],
269
- };
270
- if (resource[arrayData.arrName] !== undefined) {
271
- resource = resource[arrayData.arrName][arrayData.arrIndex];
272
- }
273
- else {
274
- resource = undefined;
275
- }
276
- }
277
- else {
278
- resource = resource[comp];
279
- }
280
- }
281
- return resource;
282
- }
283
- static parse(config) {
284
- const { id, name, subject, resource, condition } = config;
285
- return new AbilityRule({
286
- id,
287
- name,
288
- subject,
289
- resource,
290
- condition: new AbilityCondition_1.default(condition),
291
- });
292
- }
293
- /**
294
- * Export the rule to config object
295
- */
296
- export() {
297
- return {
298
- id: this.id,
299
- name: this.name,
300
- subject: this.subject,
301
- resource: this.resource,
302
- condition: this.condition.code,
303
- };
304
- }
305
- }
306
- exports.AbilityRule = AbilityRule;
307
- exports["default"] = AbilityRule;
308
-
309
-
310
- /***/ }),
311
-
312
- /***/ "./src/playground.ts":
313
- /*!***************************!*\
314
- !*** ./src/playground.ts ***!
315
- \***************************/
316
- /***/ (function(__unused_webpack_module, exports, __webpack_require__) {
317
-
318
-
319
- var __importDefault = (this && this.__importDefault) || function (mod) {
320
- return (mod && mod.__esModule) ? mod : { "default": mod };
321
- };
322
- Object.defineProperty(exports, "__esModule", ({ value: true }));
323
- const node_http_1 = __importDefault(__webpack_require__(/*! node:http */ "node:http"));
324
- const AbilityCondition_1 = __importDefault(__webpack_require__(/*! ~/AbilityCondition */ "./src/AbilityCondition.ts"));
325
- const AbilityRule_1 = __importDefault(__webpack_require__(/*! ./AbilityRule */ "./src/AbilityRule.ts"));
326
- const AbilityMatch_1 = __importDefault(__webpack_require__(/*! ./AbilityMatch */ "./src/AbilityMatch.ts"));
327
- const server = node_http_1.default.createServer();
328
- server.on('request', (_req, res) => {
329
- const config = [
330
- {
331
- id: 'bb758c1b-1015-4894-ba25-d23156e063cf',
332
- name: 'Status hui',
333
- action: 'order.status',
334
- effect: 'deny',
335
- compareMethod: 'and',
336
- ruleSet: [
337
- {
338
- id: '9cc009e5-0aa9-453a-a668-cb3f418ced92',
339
- name: 'Не администратор',
340
- compareMethod: 'and',
341
- rules: [
342
- {
343
- id: '4093cd50-e54f-4062-8053-2d3b5966fad3',
344
- name: 'Нет роли администраторв',
345
- subject: 'account.roles',
346
- resource: 'administrator',
347
- condition: '<>',
348
- },
349
- ],
350
- },
351
- ],
352
- },
353
- {
354
- id: 'bb758c1b-1015-4894-ba25-d23156e063cf',
355
- name: 'Status hui 1',
356
- action: 'order.status',
357
- effect: 'permit',
358
- compareMethod: 'and',
359
- ruleSet: [
360
- {
361
- id: '2f8f9d71-860b-4fa6-b395-9331f1f0848e',
362
- name: 'Rule set',
363
- compareMethod: 'and',
364
- rules: [
365
- {
366
- id: 'a3c7d66f-5c2d-4a24-83bc-03b0a2d9c32b',
367
- name: 'Rule 1',
368
- subject: 'order.status',
369
- resource: 'не обработан',
370
- condition: '=',
371
- },
372
- {
373
- id: 'a3c7d66f-5c2d-4a24-83bc-03b0a2d9c32b',
374
- name: 'Rule 2',
375
- subject: 'feature.status',
376
- resource: 'отменен',
377
- condition: '=',
378
- },
379
- ],
380
- },
381
- ],
382
- },
383
- ];
384
- const rule = new AbilityRule_1.default({
385
- id: '<rule-id>',
386
- name: 'Пользователь является владельцем заказа',
387
- condition: AbilityCondition_1.default.equal,
388
- subject: 'user.id',
389
- resource: 'order.owner',
390
- });
391
- const matchState = rule.check({
392
- user: { id: '1' },
393
- order: { owner: '1' },
394
- });
395
- const is = matchState.isEqual(AbilityMatch_1.default.match); // true
396
- res.statusCode = 200;
397
- res.setHeader('content-type', 'application/json');
398
- res.write(JSON.stringify({
399
- status: 'ok',
400
- }));
401
- res.end();
402
- });
403
- server.listen(8081, 'localhost', () => {
404
- console.debug('server started at http://localhost:8081');
405
- });
406
-
407
-
408
- /***/ }),
409
-
410
- /***/ "node:http":
411
- /*!****************************!*\
412
- !*** external "node:http" ***!
413
- \****************************/
414
- /***/ ((module) => {
415
-
416
- module.exports = require("node:http");
417
-
418
- /***/ })
419
-
420
- /******/ });
421
- /************************************************************************/
422
- /******/ // The module cache
423
- /******/ var __webpack_module_cache__ = {};
424
- /******/
425
- /******/ // The require function
426
- /******/ function __webpack_require__(moduleId) {
427
- /******/ // Check if module is in cache
428
- /******/ var cachedModule = __webpack_module_cache__[moduleId];
429
- /******/ if (cachedModule !== undefined) {
430
- /******/ return cachedModule.exports;
431
- /******/ }
432
- /******/ // Create a new module (and put it into the cache)
433
- /******/ var module = __webpack_module_cache__[moduleId] = {
434
- /******/ // no module.id needed
435
- /******/ // no module.loaded needed
436
- /******/ exports: {}
437
- /******/ };
438
- /******/
439
- /******/ // Execute the module function
440
- /******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
441
- /******/
442
- /******/ // Return the exports of the module
443
- /******/ return module.exports;
444
- /******/ }
445
- /******/
446
- /************************************************************************/
447
- /******/
448
- /******/ // startup
449
- /******/ // Load entry module and return exports
450
- /******/ // This entry module is referenced by other modules so it can't be inlined
451
- /******/ var __webpack_exports__ = __webpack_require__("./src/playground.ts");
452
- /******/ module.exports = __webpack_exports__;
453
- /******/
454
- /******/ })()
455
- ;
456
- //# sourceMappingURL=playground.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"playground.js","mappings":"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","sources":["webpack://@via-profit/ability/./src/AbilityCode.ts","webpack://@via-profit/ability/./src/AbilityCondition.ts","webpack://@via-profit/ability/./src/AbilityError.ts","webpack://@via-profit/ability/./src/AbilityMatch.ts","webpack://@via-profit/ability/./src/AbilityRule.ts","webpack://@via-profit/ability/./src/playground.ts","webpack://@via-profit/ability/external node-commonjs \"node:http\"","webpack://@via-profit/ability/webpack/bootstrap","webpack://@via-profit/ability/webpack/before-startup","webpack://@via-profit/ability/webpack/startup","webpack://@via-profit/ability/webpack/after-startup"],"sourcesContent":["export class AbilityCode<\n Code extends string | number,\n> {\n public _code: Code;\n\n constructor(code: Code) {\n this._code = code;\n }\n\n public get code(): Code {\n return this._code;\n }\n\n public isEqual(compareWith: AbilityCode<Code> | null): boolean {\n return compareWith !== null && this.code === compareWith.code;\n }\n\n public isNotEqual(compareWith: AbilityCode<Code> | null): boolean {\n return !this.isEqual(compareWith);\n }\n}\n\nexport default AbilityCode;\n","import AbilityCode from './AbilityCode';\nimport { AbilityParserError } from '~/AbilityError';\n\nexport type AbilityConditionCodeType = '=' | '<>' | '>' | '<' | '>=' | '<=' | 'in' | 'not in';\nexport type AbilityConditionLiteralType =\n | 'equal'\n | 'not_equal'\n | 'more_than'\n | 'less_than'\n | 'less_or_equal'\n | 'more_or_equal'\n | 'in'\n | 'not_in';\n\nexport class AbilityCondition extends AbilityCode<AbilityConditionCodeType> {\n public static equal = new AbilityCondition('=');\n public static not_equal = new AbilityCondition('<>');\n public static more_than = new AbilityCondition('>');\n public static less_than = new AbilityCondition('<');\n public static less_or_equal = new AbilityCondition('<=');\n public static more_or_equal = new AbilityCondition('>=');\n public static in = new AbilityCondition('in');\n public static not_in = new AbilityCondition('not in');\n\n public static fromLiteral(literal: AbilityConditionLiteralType): AbilityCondition {\n const code = AbilityCondition[literal]?.code || null;\n if (code === null) {\n throw new AbilityParserError(`Literal ${literal} does not found in AbilityCondition class`);\n }\n\n return new AbilityCondition(code);\n }\n\n public get literal() {\n const literal = Object.keys(AbilityCondition).find(member => {\n const val = AbilityCondition[member as keyof typeof AbilityCondition] as AbilityCondition;\n return val.code === this.code;\n }) as AbilityConditionLiteralType;\n\n if (typeof literal === 'undefined') {\n throw new Error(`Literal value does not found in class AbilityCondition`);\n }\n\n return literal;\n }\n}\n\nexport default AbilityCondition;\n","export class AbilityError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\nexport class AbilityParserError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n\nexport class PermissionError extends Error {\n constructor(message: string) {\n super(message);\n }\n}\n","import AbilityCode from './AbilityCode';\n\nexport type AbilityMatchCodeType = 'pending' | 'match' | 'mismatch';\n\nexport class AbilityMatch extends AbilityCode<AbilityMatchCodeType>{\n public static pending = new AbilityMatch('pending');\n public static match = new AbilityMatch('match');\n public static mismatch = new AbilityMatch('mismatch');\n}\n\nexport default AbilityMatch;","import AbilityMatch from './AbilityMatch';\nimport AbilityCondition, { AbilityConditionCodeType } from './AbilityCondition';\n\nexport type AbilityRuleConfig = {\n readonly id: string;\n readonly name: string;\n\n /**\n * Subject key path like a 'user.name'\n */\n readonly subject: string;\n /**\n * Resource key path like a 'user.name' or value\n */\n readonly resource: string | number | boolean | (string | number)[];\n\n readonly condition: AbilityConditionCodeType;\n};\n\nexport type AbilityRuleConstructorProps = Omit<AbilityRuleConfig, 'condition'> & {\n readonly condition: AbilityCondition;\n};\n\nexport class AbilityRule<Resources extends object = object> {\n /**\n * Subject key path like a 'user.name'\n */\n public subject: string;\n /**\n * Resource key path like a 'user.name' or value\n */\n public resource: string | number | boolean | (string | number)[];\n\n public condition: AbilityCondition;\n public name: string;\n public id: string;\n public state: AbilityMatch = AbilityMatch.pending;\n\n public constructor(params: AbilityRuleConstructorProps) {\n const { id, name, subject, resource, condition } = params;\n this.id = id;\n this.name = name;\n this.subject = subject;\n this.resource = resource;\n this.condition = condition;\n }\n\n /**\n * Check if the rule is matched\n * @param resource - The resource to check\n */\n public check(resource: Resources | null): AbilityMatch {\n let is: boolean = false;\n\n const [valueS, valueO] = this.extractValues(resource);\n\n if (AbilityCondition.less_than.isEqual(this.condition)) {\n is = Number(valueS) < Number(valueO);\n }\n\n if (AbilityCondition.less_or_equal.isEqual(this.condition)) {\n is = Number(valueS) <= Number(valueO);\n }\n\n if (AbilityCondition.more_than.isEqual(this.condition)) {\n is = Number(valueS) > Number(valueO);\n }\n\n if (AbilityCondition.more_or_equal.isEqual(this.condition)) {\n is = Number(valueS) >= Number(valueO);\n }\n\n if (AbilityCondition.equal.isEqual(this.condition)) {\n is = valueS === valueO;\n }\n\n if (AbilityCondition.not_equal.isEqual(this.condition)) {\n is = valueS !== valueO;\n }\n\n if (AbilityCondition.in.isEqual(this.condition)) {\n // [<some>] and [<some>]\n if (Array.isArray(valueS) && Array.isArray(valueO)) {\n is = valueS.some(v => valueO.find(v1 => v1 === v));\n }\n // <some> and [<some>]\n if ((typeof valueS === 'string' || typeof valueS === 'number') && Array.isArray(valueO)) {\n is = valueO.includes(valueS);\n }\n // [<some>] and <some>\n if ((typeof valueO === 'string' || typeof valueO === 'number') && Array.isArray(valueS)) {\n is = valueS.includes(valueO);\n }\n }\n\n if (AbilityCondition.not_in.isEqual(this.condition)) {\n // [<some>] and [<some>]\n if (Array.isArray(valueS) && Array.isArray(valueO)) {\n is = !valueS.some(v => valueO.find(v1 => v1 === v));\n }\n // <some> and [<some>]\n if ((typeof valueS === 'string' || typeof valueS === 'number') && Array.isArray(valueO)) {\n is = !valueO.includes(valueS);\n }\n // [<some>] and <some>\n if ((typeof valueO === 'string' || typeof valueO === 'number') && Array.isArray(valueS)) {\n is = !valueS.includes(valueO);\n }\n }\n\n this.state = is ? AbilityMatch.match : AbilityMatch.mismatch;\n\n return this.state;\n }\n\n /**\n * Extract values from the resourceData\n * @param resourceData - The resourceData to extract values from\n */\n public extractValues(\n resourceData: Resources | null,\n ): [\n string | number | boolean | (string | number)[] | null | undefined,\n string | number | boolean | (string | number)[] | null | undefined,\n ] {\n let leftSideValue;\n let rightSideValue;\n\n if (resourceData === null || typeof resourceData === 'undefined') {\n return [NaN, NaN];\n }\n\n const isPath = (str: unknown): str is string => {\n return typeof str === 'string' && str.match(/\\./g) !== null;\n };\n\n if (isPath(this.subject)) {\n leftSideValue = this.getDotNotationValue<number | boolean | string | (string | number)[]>(\n resourceData,\n this.subject,\n );\n } else {\n leftSideValue = this.subject;\n }\n if (isPath(this.resource)) {\n rightSideValue = this.getDotNotationValue<number | boolean | string | (string | number)[]>(\n resourceData,\n this.resource,\n );\n } else {\n rightSideValue = this.resource as number | boolean | string | (string | number)[];\n }\n\n return [leftSideValue, rightSideValue];\n }\n\n /**\n * Get the value of the object by dot notation\n * @param resource - The object to get the value from\n * @param desc - The dot notation string\n */\n public getDotNotationValue<T = unknown>(resource: unknown, desc: string): T | undefined {\n const arr = desc.split('.');\n\n while (arr.length && resource) {\n const comp = arr.shift() || '';\n const match = new RegExp('(.+)\\\\[([0-9]*)\\\\]').exec(comp);\n\n if (match !== null && match.length == 3) {\n const arrayData = {\n arrName: match[1],\n arrIndex: match[2],\n };\n\n if (resource[arrayData.arrName as keyof typeof resource] !== undefined) {\n resource = resource[arrayData.arrName as keyof typeof resource][arrayData.arrIndex];\n } else {\n resource = undefined;\n }\n } else {\n resource = resource[comp as keyof typeof resource];\n }\n }\n\n return resource as T;\n }\n\n public static parse<Resources extends object>(config: AbilityRuleConfig): AbilityRule<Resources> {\n const { id, name, subject, resource, condition } = config;\n\n return new AbilityRule<Resources>({\n id,\n name,\n subject,\n resource,\n condition: new AbilityCondition(condition),\n });\n }\n\n /**\n * Export the rule to config object\n */\n public export(): AbilityRuleConfig {\n return {\n id: this.id,\n name: this.name,\n subject: this.subject,\n resource: this.resource,\n condition: this.condition.code,\n };\n }\n}\n\nexport default AbilityRule;\n","import http from 'node:http';\nimport { AbilityPolicyConfig } from './AbilityPolicy';\nimport AbilityCondition from '~/AbilityCondition';\nimport AbilityRule from './AbilityRule';\nimport AbilityMatch from './AbilityMatch';\n\nconst server = http.createServer();\n\nserver.on('request', (_req, res) => {\n type Resources = {\n ['order.status']: {\n readonly account: {\n readonly roles: readonly string[];\n };\n readonly order: {\n readonly status: string;\n };\n readonly feature: {\n readonly status: string;\n };\n };\n };\n\n const config: AbilityPolicyConfig[] = [\n {\n id: 'bb758c1b-1015-4894-ba25-d23156e063cf',\n name: 'Status hui',\n action: 'order.status',\n effect: 'deny',\n compareMethod: 'and',\n ruleSet: [\n {\n id: '9cc009e5-0aa9-453a-a668-cb3f418ced92',\n name: 'Не администратор',\n compareMethod: 'and',\n rules: [\n {\n id: '4093cd50-e54f-4062-8053-2d3b5966fad3',\n name: 'Нет роли администраторв',\n subject: 'account.roles',\n resource: 'administrator',\n condition: '<>',\n },\n ],\n },\n ],\n },\n {\n id: 'bb758c1b-1015-4894-ba25-d23156e063cf',\n name: 'Status hui 1',\n action: 'order.status',\n effect: 'permit',\n compareMethod: 'and',\n ruleSet: [\n {\n id: '2f8f9d71-860b-4fa6-b395-9331f1f0848e',\n name: 'Rule set',\n compareMethod: 'and',\n rules: [\n {\n id: 'a3c7d66f-5c2d-4a24-83bc-03b0a2d9c32b',\n name: 'Rule 1',\n subject: 'order.status',\n resource: 'не обработан',\n condition: '=',\n },\n {\n id: 'a3c7d66f-5c2d-4a24-83bc-03b0a2d9c32b',\n name: 'Rule 2',\n subject: 'feature.status',\n resource: 'отменен',\n condition: '=',\n },\n ],\n },\n ],\n },\n ];\n\n const rule = new AbilityRule({\n id: '<rule-id>',\n name: 'Пользователь является владельцем заказа',\n condition: AbilityCondition.equal,\n subject: 'user.id',\n resource: 'order.owner',\n });\n\n const matchState = rule.check({\n user: { id: '1' },\n order: { owner: '1' },\n });\n\n const is = matchState.isEqual(AbilityMatch.match); // true\n\n\n\n res.statusCode = 200;\n res.setHeader('content-type', 'application/json');\n\n res.write(\n JSON.stringify({\n status: 'ok',\n }),\n );\n res.end();\n});\n\nserver.listen(8081, 'localhost', () => {\n console.debug('server started at http://localhost:8081');\n});\n\nexport type Resources = {\n readonly ['account.read']: {\n readonly account: {\n readonly id: string;\n readonly roles: readonly string[];\n } | null;\n readonly resource: {\n readonly id: string;\n };\n };\n readonly ['access.auth']: {\n readonly token: {\n readonly type: string;\n readonly id: string;\n } | null;\n };\n readonly ['order.update']: {\n readonly account: {\n readonly roles: readonly string[];\n readonly department: string;\n } | null;\n readonly order: {\n readonly status: string;\n } | null;\n };\n};\n","module.exports = require(\"node:http\");","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\t// no module.id needed\n\t\t// no module.loaded needed\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n","","// startup\n// Load entry module and return exports\n// This entry module is referenced by other modules so it can't be inlined\nvar __webpack_exports__ = __webpack_require__(\"./src/playground.ts\");\n",""],"names":[],"sourceRoot":""}
@@ -1,16 +0,0 @@
1
- import AbilityCode from './AbilityCode';
2
- export type AbilityConditionCodeType = '=' | '<>' | '>' | '<' | '>=' | '<=' | 'in' | 'not in';
3
- export type AbilityConditionLiteralType = 'equal' | 'not_equal' | 'more_than' | 'less_than' | 'less_or_equal' | 'more_or_equal' | 'in' | 'not_in';
4
- export declare class AbilityCondition extends AbilityCode<AbilityConditionCodeType> {
5
- static equal: AbilityCondition;
6
- static not_equal: AbilityCondition;
7
- static more_than: AbilityCondition;
8
- static less_than: AbilityCondition;
9
- static less_or_equal: AbilityCondition;
10
- static more_or_equal: AbilityCondition;
11
- static in: AbilityCondition;
12
- static not_in: AbilityCondition;
13
- static fromLiteral(literal: AbilityConditionLiteralType): AbilityCondition;
14
- get literal(): AbilityConditionLiteralType;
15
- }
16
- export default AbilityCondition;
@@ -1,18 +0,0 @@
1
- import AbilityPolicy from './AbilityPolicy';
2
- export declare class AbilityParser {
3
- /**
4
- * Sets a value in a nested object structure based on a dot/bracket notation path.
5
- * @param object - The target object to modify.
6
- * @param path - The path to the property in dot/bracket notation.
7
- * @param value - The value to set at the specified path.
8
- */
9
- static setValueDotValue(object: Record<string, any>, path: string, value: string | number | boolean): void;
10
- /**
11
- * Generates TypeScript type definitions based on the provided policies.
12
- * @param policies - An array of AbilityPolicy instances.
13
- * @param outPath - The output path for the generated type definitions.
14
- * @returns A record containing the generated type definitions.
15
- */
16
- static generateTypeDefs(policies: readonly AbilityPolicy[], outPath: string): Record<string, any>;
17
- }
18
- export default AbilityParser;
@@ -1,65 +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
- export type AbilityPolicyConfig = {
6
- readonly action: string;
7
- readonly effect: AbilityPolicyEffectCodeType;
8
- readonly compareMethod: AbilityCompareCodeType;
9
- readonly ruleSet: readonly AbilityRuleSetConfig[];
10
- readonly id: string;
11
- readonly name: string;
12
- };
13
- export type AbilityPolicyConstructorProps = {
14
- id: string;
15
- name: string;
16
- action: string;
17
- effect: AbilityPolicyEffect;
18
- };
19
- export declare class AbilityPolicy<Resources extends object = object> {
20
- matchState: AbilityMatch;
21
- /**
22
- * List of rules
23
- */
24
- ruleSet: AbilityRuleSet[];
25
- /**
26
- * Policy effect
27
- */
28
- effect: AbilityPolicyEffect;
29
- /**
30
- * Rules compare method.\
31
- * For the «and» method the rule will be permitted if all\
32
- * rules will be returns «permit» status and for the «or» - if\
33
- * one of the rules returns as «permit»
34
- */
35
- compareMethod: AbilityCompare;
36
- /**
37
- * Policy name
38
- */
39
- name: string;
40
- /**
41
- * Policy ID
42
- */
43
- id: string;
44
- /**
45
- * Soon
46
- */
47
- action: string;
48
- constructor(params: AbilityPolicyConstructorProps);
49
- /**
50
- * Add rule set to the policy
51
- * @param ruleSet - The rule set to add
52
- */
53
- addRuleSet(ruleSet: AbilityRuleSet): this;
54
- /**
55
- * Check if the policy is matched
56
- * @param resources - The resource to check
57
- */
58
- check(resources: Resources): AbilityMatch;
59
- /**
60
- * Parse the config JSON format to Policy class instance
61
- */
62
- static parse<Resources extends object = object>(config: AbilityPolicyConfig): AbilityPolicy<Resources>;
63
- export(): AbilityPolicyConfig;
64
- }
65
- export default AbilityPolicy;
@@ -1,30 +0,0 @@
1
- import AbilityPolicy from './AbilityPolicy';
2
- import AbilityPolicyEffect from './AbilityPolicyEffect';
3
- export declare class AbilityResolver<Resources extends object = object> {
4
- policies: readonly AbilityPolicy<Resources>[];
5
- constructor(policyOrListOfPolicies: readonly AbilityPolicy<Resources>[] | AbilityPolicy<Resources>);
6
- /**
7
- * Resolve policy for the resource and action
8
- *
9
- @param action - Action
10
- * @param resource - Resource
11
- */
12
- resolve<Action extends keyof Resources>(action: Action, resource: Resources[Action]): this;
13
- enforce<Action extends keyof Resources>(action: Action, resource: Resources[Action]): void | never;
14
- /**
15
- * Get the last effect of the policy
16
- *
17
- * @returns {AbilityPolicyEffect | null}
18
- */
19
- getEffect(): AbilityPolicyEffect | null;
20
- isPermit(): boolean;
21
- isDeny(): boolean;
22
- getMatchedPolicy(): AbilityPolicy<Resources> | null;
23
- /**
24
- * Check if the action is contained in another action
25
- * @param actionA - The first action to check
26
- * @param actionB - The second action to check
27
- */
28
- static isInActionContain(actionA: string, actionB: string): boolean;
29
- }
30
- export default AbilityResolver;