@via-profit/ability 1.0.3 → 2.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +155 -310
- package/assets/ability-01.drawio.png +0 -0
- package/build/playground.js +910 -0
- package/build/playground.js.map +1 -0
- package/dist/AbilityCode.d.ts +7 -0
- package/dist/AbilityCompare.d.ts +6 -0
- package/dist/AbilityCondition.d.ts +12 -0
- package/dist/AbilityError.d.ts +9 -0
- package/dist/AbilityMatch.d.ts +7 -0
- package/dist/AbilityParser.d.ts +33 -0
- package/dist/AbilityPolicy.d.ts +42 -50
- package/dist/AbilityPolicyEffect.d.ts +6 -0
- package/dist/AbilityPolicyResult.d.ts +6 -0
- package/dist/AbilityResolver.d.ts +30 -0
- package/dist/AbilityRule.d.ts +27 -94
- package/dist/AbilityRuleSet.d.ts +44 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.js +631 -356
- package/dist/playground.d.ts +26 -0
- package/package.json +4 -2
- package/dist/AbilityService.d.ts +0 -74
- package/dist/AbilityStatement.d.ts +0 -98
|
@@ -0,0 +1,910 @@
|
|
|
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
|
+
isEqual(compareWith) {
|
|
20
|
+
return compareWith !== null && this.code === compareWith.code;
|
|
21
|
+
}
|
|
22
|
+
isNotEqual(compareWith) {
|
|
23
|
+
return !this.isEqual(compareWith);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.AbilityCode = AbilityCode;
|
|
27
|
+
exports["default"] = AbilityCode;
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
/***/ }),
|
|
31
|
+
|
|
32
|
+
/***/ "./src/AbilityCompare.ts":
|
|
33
|
+
/*!*******************************!*\
|
|
34
|
+
!*** ./src/AbilityCompare.ts ***!
|
|
35
|
+
\*******************************/
|
|
36
|
+
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
40
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
41
|
+
};
|
|
42
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
43
|
+
exports.AbilityCompare = void 0;
|
|
44
|
+
const AbilityCode_1 = __importDefault(__webpack_require__(/*! ./AbilityCode */ "./src/AbilityCode.ts"));
|
|
45
|
+
class AbilityCompare extends AbilityCode_1.default {
|
|
46
|
+
static OR = new AbilityCompare(0);
|
|
47
|
+
static AND = new AbilityCompare(1);
|
|
48
|
+
}
|
|
49
|
+
exports.AbilityCompare = AbilityCompare;
|
|
50
|
+
exports["default"] = AbilityCompare;
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
/***/ }),
|
|
54
|
+
|
|
55
|
+
/***/ "./src/AbilityCondition.ts":
|
|
56
|
+
/*!*********************************!*\
|
|
57
|
+
!*** ./src/AbilityCondition.ts ***!
|
|
58
|
+
\*********************************/
|
|
59
|
+
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
63
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
64
|
+
};
|
|
65
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
66
|
+
exports.AbilityCondition = void 0;
|
|
67
|
+
const AbilityCode_1 = __importDefault(__webpack_require__(/*! ./AbilityCode */ "./src/AbilityCode.ts"));
|
|
68
|
+
class AbilityCondition extends AbilityCode_1.default {
|
|
69
|
+
static EQUAL = new AbilityCondition('=');
|
|
70
|
+
static NOT_EQUAL = new AbilityCondition('<>');
|
|
71
|
+
static MORE_THAN = new AbilityCondition('>');
|
|
72
|
+
static LESS_THAN = new AbilityCondition('<');
|
|
73
|
+
static LESS_OR_EQUAL = new AbilityCondition('<=');
|
|
74
|
+
static MORE_OR_EQUAL = new AbilityCondition('>=');
|
|
75
|
+
static IN = new AbilityCondition('in');
|
|
76
|
+
static NOT_IN = new AbilityCondition('not in');
|
|
77
|
+
}
|
|
78
|
+
exports.AbilityCondition = AbilityCondition;
|
|
79
|
+
exports["default"] = AbilityCondition;
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
/***/ }),
|
|
83
|
+
|
|
84
|
+
/***/ "./src/AbilityError.ts":
|
|
85
|
+
/*!*****************************!*\
|
|
86
|
+
!*** ./src/AbilityError.ts ***!
|
|
87
|
+
\*****************************/
|
|
88
|
+
/***/ ((__unused_webpack_module, exports) => {
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
92
|
+
exports.PermissionError = exports.AbilityParserError = exports.AbilityError = void 0;
|
|
93
|
+
class AbilityError extends Error {
|
|
94
|
+
constructor(message) {
|
|
95
|
+
super(message);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.AbilityError = AbilityError;
|
|
99
|
+
class AbilityParserError extends Error {
|
|
100
|
+
constructor(message) {
|
|
101
|
+
super(message);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
exports.AbilityParserError = AbilityParserError;
|
|
105
|
+
class PermissionError extends Error {
|
|
106
|
+
constructor(message) {
|
|
107
|
+
super(message);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
exports.PermissionError = PermissionError;
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
/***/ }),
|
|
114
|
+
|
|
115
|
+
/***/ "./src/AbilityMatch.ts":
|
|
116
|
+
/*!*****************************!*\
|
|
117
|
+
!*** ./src/AbilityMatch.ts ***!
|
|
118
|
+
\*****************************/
|
|
119
|
+
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
123
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
124
|
+
};
|
|
125
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
126
|
+
exports.AbilityMatch = void 0;
|
|
127
|
+
const AbilityCode_1 = __importDefault(__webpack_require__(/*! ./AbilityCode */ "./src/AbilityCode.ts"));
|
|
128
|
+
class AbilityMatch extends AbilityCode_1.default {
|
|
129
|
+
static PENDING = new AbilityMatch(2);
|
|
130
|
+
static MATCH = new AbilityMatch(1);
|
|
131
|
+
static MISMATCH = new AbilityMatch(0);
|
|
132
|
+
}
|
|
133
|
+
exports.AbilityMatch = AbilityMatch;
|
|
134
|
+
exports["default"] = AbilityMatch;
|
|
135
|
+
|
|
136
|
+
|
|
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
|
+
const [leftFieldPath, condition, rightFiledPath] = rule.matches;
|
|
240
|
+
let value = 'any';
|
|
241
|
+
switch (true) {
|
|
242
|
+
case condition.isEqual(AbilityCondition_1.default.NOT_EQUAL):
|
|
243
|
+
case condition.isEqual(AbilityCondition_1.default.EQUAL):
|
|
244
|
+
value = typeof rightFiledPath;
|
|
245
|
+
break;
|
|
246
|
+
case condition.isEqual(AbilityCondition_1.default.IN):
|
|
247
|
+
case condition.isEqual(AbilityCondition_1.default.NOT_IN):
|
|
248
|
+
value = `${typeof rightFiledPath}[]`;
|
|
249
|
+
break;
|
|
250
|
+
case condition.isEqual(AbilityCondition_1.default.MORE_OR_EQUAL):
|
|
251
|
+
case condition.isEqual(AbilityCondition_1.default.MORE_THAN):
|
|
252
|
+
case condition.isEqual(AbilityCondition_1.default.LESS_OR_EQUAL):
|
|
253
|
+
case condition.isEqual(AbilityCondition_1.default.LESS_THAN):
|
|
254
|
+
value = 'number';
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
AbilityParser.setValueDotValue(record, leftFieldPath, value);
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
console.log(JSON.stringify(record));
|
|
262
|
+
return record;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
exports.AbilityParser = AbilityParser;
|
|
266
|
+
exports["default"] = AbilityParser;
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
/***/ }),
|
|
270
|
+
|
|
271
|
+
/***/ "./src/AbilityPolicy.ts":
|
|
272
|
+
/*!******************************!*\
|
|
273
|
+
!*** ./src/AbilityPolicy.ts ***!
|
|
274
|
+
\******************************/
|
|
275
|
+
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
279
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
280
|
+
};
|
|
281
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
282
|
+
exports.AbilityPolicy = void 0;
|
|
283
|
+
const AbilityRule_1 = __importDefault(__webpack_require__(/*! ./AbilityRule */ "./src/AbilityRule.ts"));
|
|
284
|
+
const AbilityRuleSet_1 = __importDefault(__webpack_require__(/*! ./AbilityRuleSet */ "./src/AbilityRuleSet.ts"));
|
|
285
|
+
const AbilityMatch_1 = __importDefault(__webpack_require__(/*! ./AbilityMatch */ "./src/AbilityMatch.ts"));
|
|
286
|
+
const AbilityCompare_1 = __importDefault(__webpack_require__(/*! ./AbilityCompare */ "./src/AbilityCompare.ts"));
|
|
287
|
+
const AbilityPolicyEffect_1 = __importDefault(__webpack_require__(/*! ./AbilityPolicyEffect */ "./src/AbilityPolicyEffect.ts"));
|
|
288
|
+
const AbilityParser_1 = __importDefault(__webpack_require__(/*! ./AbilityParser */ "./src/AbilityParser.ts"));
|
|
289
|
+
class AbilityPolicy {
|
|
290
|
+
matchState = AbilityMatch_1.default.PENDING;
|
|
291
|
+
/**
|
|
292
|
+
* List of rules
|
|
293
|
+
*/
|
|
294
|
+
ruleSet = [];
|
|
295
|
+
/**
|
|
296
|
+
* Policy effect
|
|
297
|
+
*/
|
|
298
|
+
effect;
|
|
299
|
+
/**
|
|
300
|
+
* Rules compare method.\
|
|
301
|
+
* For the «and» method the rule will be permitted if all\
|
|
302
|
+
* rules will be returns «permit» status and for the «or» - if\
|
|
303
|
+
* one of the rules returns as «permit»
|
|
304
|
+
*/
|
|
305
|
+
compareMethod = AbilityCompare_1.default.AND;
|
|
306
|
+
/**
|
|
307
|
+
* Policy name
|
|
308
|
+
*/
|
|
309
|
+
name;
|
|
310
|
+
/**
|
|
311
|
+
* Policy ID
|
|
312
|
+
*/
|
|
313
|
+
id;
|
|
314
|
+
/**
|
|
315
|
+
* Soon
|
|
316
|
+
*/
|
|
317
|
+
action;
|
|
318
|
+
constructor(params) {
|
|
319
|
+
const { name, id, action, effect } = params;
|
|
320
|
+
this.name = name || Symbol('name');
|
|
321
|
+
this.id = id || Symbol('id');
|
|
322
|
+
this.action = action;
|
|
323
|
+
this.effect = effect;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Add rule set to the policy
|
|
327
|
+
* @param ruleSet - The rule set to add
|
|
328
|
+
*/
|
|
329
|
+
addRuleSet(ruleSet) {
|
|
330
|
+
this.ruleSet.push(ruleSet);
|
|
331
|
+
return this;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Add rule to the policy
|
|
335
|
+
* @param rule - The rule to add
|
|
336
|
+
*/
|
|
337
|
+
addRule(rule) {
|
|
338
|
+
this.addRuleSet(new AbilityRuleSet_1.default({
|
|
339
|
+
name: rule.name,
|
|
340
|
+
}).addRule(rule, AbilityCompare_1.default.AND));
|
|
341
|
+
return this;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Check if the policy is matched
|
|
345
|
+
* @param resource - The resource to check
|
|
346
|
+
*/
|
|
347
|
+
check(resource) {
|
|
348
|
+
this.matchState = AbilityMatch_1.default.MISMATCH;
|
|
349
|
+
/**
|
|
350
|
+
* If policy contain a rules
|
|
351
|
+
*/
|
|
352
|
+
if (this.ruleSet.length) {
|
|
353
|
+
const ruleCheckStates = [];
|
|
354
|
+
this.ruleSet.forEach(rule => {
|
|
355
|
+
const ruleCheckState = rule.check(resource);
|
|
356
|
+
ruleCheckStates.push(ruleCheckState);
|
|
357
|
+
});
|
|
358
|
+
if (AbilityCompare_1.default.AND.isEqual(this.compareMethod)) {
|
|
359
|
+
if (ruleCheckStates.every(ruleState => AbilityMatch_1.default.MATCH.isEqual(ruleState))) {
|
|
360
|
+
this.matchState = AbilityMatch_1.default.MATCH;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
if (AbilityCompare_1.default.OR.isEqual(this.compareMethod)) {
|
|
364
|
+
if (ruleCheckStates.some(ruleState => AbilityMatch_1.default.MATCH.isEqual(ruleState))) {
|
|
365
|
+
this.matchState = AbilityMatch_1.default.MATCH;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return this.matchState;
|
|
370
|
+
}
|
|
371
|
+
/**
|
|
372
|
+
* Parse the config JSON format to Policy class instance
|
|
373
|
+
*/
|
|
374
|
+
static parse(configOrJson) {
|
|
375
|
+
const config = AbilityParser_1.default.prepareAndValidateConfig(configOrJson, [
|
|
376
|
+
['id', 'string', false],
|
|
377
|
+
['name', 'string', true],
|
|
378
|
+
['action', 'string', true],
|
|
379
|
+
['effect', 'number', true],
|
|
380
|
+
['compareMethod', 'number', true],
|
|
381
|
+
['ruleSet', 'array', true],
|
|
382
|
+
]);
|
|
383
|
+
const { id, name, ruleSet, compareMethod, action, effect } = config;
|
|
384
|
+
// Create the empty policy
|
|
385
|
+
const policy = new AbilityPolicy({
|
|
386
|
+
name,
|
|
387
|
+
id,
|
|
388
|
+
action,
|
|
389
|
+
effect: new AbilityPolicyEffect_1.default(effect),
|
|
390
|
+
});
|
|
391
|
+
policy.compareMethod = new AbilityCompare_1.default(compareMethod);
|
|
392
|
+
ruleSet.forEach(ruleOrRuleSet => {
|
|
393
|
+
// is ruleset
|
|
394
|
+
if ('rules' in ruleOrRuleSet) {
|
|
395
|
+
policy.addRuleSet(AbilityRuleSet_1.default.parse(ruleOrRuleSet));
|
|
396
|
+
}
|
|
397
|
+
// is simple rule
|
|
398
|
+
if (!('rules' in ruleOrRuleSet)) {
|
|
399
|
+
policy.addRule(AbilityRule_1.default.parse(ruleOrRuleSet));
|
|
400
|
+
}
|
|
401
|
+
});
|
|
402
|
+
return policy;
|
|
403
|
+
}
|
|
404
|
+
export() {
|
|
405
|
+
return {
|
|
406
|
+
id: this.id.toString(),
|
|
407
|
+
name: this.name.toString(),
|
|
408
|
+
compareMethod: this.compareMethod.code,
|
|
409
|
+
ruleSet: this.ruleSet.map(rule => rule.export()),
|
|
410
|
+
action: this.action,
|
|
411
|
+
effect: this.effect.code,
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
exports.AbilityPolicy = AbilityPolicy;
|
|
416
|
+
exports["default"] = AbilityPolicy;
|
|
417
|
+
|
|
418
|
+
|
|
419
|
+
/***/ }),
|
|
420
|
+
|
|
421
|
+
/***/ "./src/AbilityPolicyEffect.ts":
|
|
422
|
+
/*!************************************!*\
|
|
423
|
+
!*** ./src/AbilityPolicyEffect.ts ***!
|
|
424
|
+
\************************************/
|
|
425
|
+
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
429
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
430
|
+
};
|
|
431
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
432
|
+
exports.AbilityPolicyEffect = void 0;
|
|
433
|
+
const AbilityCode_1 = __importDefault(__webpack_require__(/*! ./AbilityCode */ "./src/AbilityCode.ts"));
|
|
434
|
+
class AbilityPolicyEffect extends AbilityCode_1.default {
|
|
435
|
+
static DENY = new AbilityPolicyEffect(0);
|
|
436
|
+
static PERMIT = new AbilityPolicyEffect(1);
|
|
437
|
+
}
|
|
438
|
+
exports.AbilityPolicyEffect = AbilityPolicyEffect;
|
|
439
|
+
exports["default"] = AbilityPolicyEffect;
|
|
440
|
+
|
|
441
|
+
|
|
442
|
+
/***/ }),
|
|
443
|
+
|
|
444
|
+
/***/ "./src/AbilityResolver.ts":
|
|
445
|
+
/*!********************************!*\
|
|
446
|
+
!*** ./src/AbilityResolver.ts ***!
|
|
447
|
+
\********************************/
|
|
448
|
+
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
449
|
+
|
|
450
|
+
|
|
451
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
452
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
453
|
+
};
|
|
454
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
455
|
+
exports.AbilityResolver = void 0;
|
|
456
|
+
const AbilityPolicyEffect_1 = __importDefault(__webpack_require__(/*! ./AbilityPolicyEffect */ "./src/AbilityPolicyEffect.ts"));
|
|
457
|
+
const AbilityMatch_1 = __importDefault(__webpack_require__(/*! ./AbilityMatch */ "./src/AbilityMatch.ts"));
|
|
458
|
+
const AbilityError_1 = __webpack_require__(/*! ./AbilityError */ "./src/AbilityError.ts");
|
|
459
|
+
class AbilityResolver {
|
|
460
|
+
policies;
|
|
461
|
+
constructor(policies) {
|
|
462
|
+
this.policies = policies;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Resolve policy for the resource and action
|
|
466
|
+
*
|
|
467
|
+
@param action - Action
|
|
468
|
+
* @param resource - Resource
|
|
469
|
+
*/
|
|
470
|
+
resolve(action, resource) {
|
|
471
|
+
const filteredPolicies = this.policies.filter(policy => {
|
|
472
|
+
return AbilityResolver.isInActionContain(policy.action, String(action));
|
|
473
|
+
});
|
|
474
|
+
filteredPolicies.map(policy => policy.check(resource));
|
|
475
|
+
this.policies = filteredPolicies;
|
|
476
|
+
return this;
|
|
477
|
+
}
|
|
478
|
+
enforce(action, resource) {
|
|
479
|
+
const resolver = this.resolve(action, resource);
|
|
480
|
+
if (resolver) {
|
|
481
|
+
if (resolver.isDeny()) {
|
|
482
|
+
throw new AbilityError_1.PermissionError(['Permission denied', resolver.getPolicy()?.name?.toString()].join('. '));
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Get the last effect of the policy
|
|
488
|
+
*
|
|
489
|
+
* @returns {AbilityPolicyEffect | null}
|
|
490
|
+
*/
|
|
491
|
+
getEffect() {
|
|
492
|
+
const effects = this.policies.reduce((collect, policy, _index) => {
|
|
493
|
+
if (policy.matchState.isEqual(AbilityMatch_1.default.MATCH)) {
|
|
494
|
+
return collect.concat(policy.effect);
|
|
495
|
+
}
|
|
496
|
+
return collect;
|
|
497
|
+
}, []);
|
|
498
|
+
if (effects.length) {
|
|
499
|
+
return effects[effects.length - 1];
|
|
500
|
+
}
|
|
501
|
+
return null;
|
|
502
|
+
}
|
|
503
|
+
isPermit() {
|
|
504
|
+
const effect = this.getEffect();
|
|
505
|
+
return effect !== null && effect.isEqual(AbilityPolicyEffect_1.default.PERMIT);
|
|
506
|
+
}
|
|
507
|
+
isDeny() {
|
|
508
|
+
const effect = this.getEffect();
|
|
509
|
+
return effect !== null && effect.isEqual(AbilityPolicyEffect_1.default.DENY);
|
|
510
|
+
}
|
|
511
|
+
getPolicy() {
|
|
512
|
+
const lastPolicy = this.policies.length ? this.policies[this.policies.length - 1] : null;
|
|
513
|
+
return lastPolicy && lastPolicy.matchState.isEqual(AbilityMatch_1.default.MATCH) ? lastPolicy : null;
|
|
514
|
+
}
|
|
515
|
+
/**
|
|
516
|
+
* Check if the action is contained in another action
|
|
517
|
+
* @param actionA - The first action to check
|
|
518
|
+
* @param actionB - The second action to check
|
|
519
|
+
*/
|
|
520
|
+
static isInActionContain(actionA, actionB) {
|
|
521
|
+
const actionAArray = String(actionA).split('.');
|
|
522
|
+
const actionBArray = String(actionB).split('.');
|
|
523
|
+
const a = actionAArray.length >= actionBArray.length ? actionAArray : actionBArray;
|
|
524
|
+
const b = actionBArray.length >= actionAArray.length ? actionBArray : actionAArray;
|
|
525
|
+
return a
|
|
526
|
+
.reduce((acc, chunk, index) => {
|
|
527
|
+
const iterationRes = chunk === b[index] || b[index] === '*' || chunk === '*';
|
|
528
|
+
return acc.concat(iterationRes);
|
|
529
|
+
}, [])
|
|
530
|
+
.every(Boolean);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
exports.AbilityResolver = AbilityResolver;
|
|
534
|
+
exports["default"] = AbilityResolver;
|
|
535
|
+
|
|
536
|
+
|
|
537
|
+
/***/ }),
|
|
538
|
+
|
|
539
|
+
/***/ "./src/AbilityRule.ts":
|
|
540
|
+
/*!****************************!*\
|
|
541
|
+
!*** ./src/AbilityRule.ts ***!
|
|
542
|
+
\****************************/
|
|
543
|
+
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
544
|
+
|
|
545
|
+
|
|
546
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
547
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
548
|
+
};
|
|
549
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
550
|
+
exports.AbilityRule = void 0;
|
|
551
|
+
const AbilityMatch_1 = __importDefault(__webpack_require__(/*! ./AbilityMatch */ "./src/AbilityMatch.ts"));
|
|
552
|
+
const AbilityCondition_1 = __importDefault(__webpack_require__(/*! ./AbilityCondition */ "./src/AbilityCondition.ts"));
|
|
553
|
+
const AbilityParser_1 = __importDefault(__webpack_require__(/*! ./AbilityParser */ "./src/AbilityParser.ts"));
|
|
554
|
+
class AbilityRule {
|
|
555
|
+
matches;
|
|
556
|
+
name;
|
|
557
|
+
state = AbilityMatch_1.default.PENDING;
|
|
558
|
+
constructor(params) {
|
|
559
|
+
const { name, matches } = params;
|
|
560
|
+
this.name = name || Symbol('name');
|
|
561
|
+
this.matches = matches;
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* Check if the rule is matched
|
|
565
|
+
* @param resource - The resource to check
|
|
566
|
+
*/
|
|
567
|
+
check(resource) {
|
|
568
|
+
const [_subjectPathName, condition, _staticValueOrPathName] = this.matches;
|
|
569
|
+
let is = false;
|
|
570
|
+
const [valueS, valueO] = this.extractValues(resource);
|
|
571
|
+
if (AbilityCondition_1.default.LESS_THAN.isEqual(condition)) {
|
|
572
|
+
is = Number(valueS) < Number(valueO);
|
|
573
|
+
}
|
|
574
|
+
if (AbilityCondition_1.default.LESS_OR_EQUAL.isEqual(condition)) {
|
|
575
|
+
is = Number(valueS) <= Number(valueO);
|
|
576
|
+
}
|
|
577
|
+
if (AbilityCondition_1.default.MORE_THAN.isEqual(condition)) {
|
|
578
|
+
is = Number(valueS) > Number(valueO);
|
|
579
|
+
}
|
|
580
|
+
if (AbilityCondition_1.default.MORE_OR_EQUAL.isEqual(condition)) {
|
|
581
|
+
is = Number(valueS) >= Number(valueO);
|
|
582
|
+
}
|
|
583
|
+
if (AbilityCondition_1.default.EQUAL.isEqual(condition)) {
|
|
584
|
+
is = valueS === valueO;
|
|
585
|
+
}
|
|
586
|
+
if (AbilityCondition_1.default.NOT_EQUAL.isEqual(condition)) {
|
|
587
|
+
is = valueS !== valueO;
|
|
588
|
+
}
|
|
589
|
+
if (AbilityCondition_1.default.IN.isEqual(condition)) {
|
|
590
|
+
// [<some>] and [<some>]
|
|
591
|
+
if (Array.isArray(valueS) && Array.isArray(valueO)) {
|
|
592
|
+
is = valueS.some(v => valueO.find(v1 => v1 === v));
|
|
593
|
+
}
|
|
594
|
+
// <some> and [<some>]
|
|
595
|
+
if ((typeof valueS === 'string' || typeof valueS === 'number') && Array.isArray(valueO)) {
|
|
596
|
+
is = valueO.includes(valueS);
|
|
597
|
+
}
|
|
598
|
+
// [<some>] and <some>
|
|
599
|
+
if ((typeof valueO === 'string' || typeof valueO === 'number') && Array.isArray(valueS)) {
|
|
600
|
+
is = valueS.includes(valueO);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
if (AbilityCondition_1.default.NOT_IN.isEqual(condition)) {
|
|
604
|
+
// [<some>] and [<some>]
|
|
605
|
+
if (Array.isArray(valueS) && Array.isArray(valueO)) {
|
|
606
|
+
is = !valueS.some(v => valueO.find(v1 => v1 === v));
|
|
607
|
+
}
|
|
608
|
+
// <some> and [<some>]
|
|
609
|
+
if ((typeof valueS === 'string' || typeof valueS === 'number') && Array.isArray(valueO)) {
|
|
610
|
+
is = !valueO.includes(valueS);
|
|
611
|
+
}
|
|
612
|
+
// [<some>] and <some>
|
|
613
|
+
if ((typeof valueO === 'string' || typeof valueO === 'number') && Array.isArray(valueS)) {
|
|
614
|
+
is = !valueS.includes(valueO);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
this.state = is ? AbilityMatch_1.default.MATCH : AbilityMatch_1.default.MISMATCH;
|
|
618
|
+
return this.state;
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Extract values from the resource
|
|
622
|
+
* @param resource - The resource to extract values from
|
|
623
|
+
*/
|
|
624
|
+
extractValues(resource) {
|
|
625
|
+
const [subjectPathName, _condition, staticValueOrPathName] = this.matches;
|
|
626
|
+
let leftSideValue;
|
|
627
|
+
let rightSideValue;
|
|
628
|
+
if (resource === null || typeof resource === 'undefined') {
|
|
629
|
+
return [NaN, NaN];
|
|
630
|
+
}
|
|
631
|
+
const isPath = (str) => {
|
|
632
|
+
return typeof str === 'string' && str.match(/\./g) !== null;
|
|
633
|
+
};
|
|
634
|
+
if (isPath(subjectPathName)) {
|
|
635
|
+
leftSideValue = this.getDotNotationValue(resource, subjectPathName);
|
|
636
|
+
}
|
|
637
|
+
if (isPath(staticValueOrPathName)) {
|
|
638
|
+
rightSideValue = this.getDotNotationValue(resource, staticValueOrPathName);
|
|
639
|
+
}
|
|
640
|
+
else {
|
|
641
|
+
rightSideValue = staticValueOrPathName;
|
|
642
|
+
}
|
|
643
|
+
return [leftSideValue, rightSideValue];
|
|
644
|
+
}
|
|
645
|
+
/**
|
|
646
|
+
* Get the value of the object by dot notation
|
|
647
|
+
* @param resource - The object to get the value from
|
|
648
|
+
* @param desc - The dot notation string
|
|
649
|
+
*/
|
|
650
|
+
getDotNotationValue(resource, desc) {
|
|
651
|
+
const arr = desc.split('.');
|
|
652
|
+
while (arr.length && resource) {
|
|
653
|
+
const comp = arr.shift() || '';
|
|
654
|
+
const match = new RegExp('(.+)\\[([0-9]*)\\]').exec(comp);
|
|
655
|
+
if (match !== null && match.length == 3) {
|
|
656
|
+
const arrayData = {
|
|
657
|
+
arrName: match[1],
|
|
658
|
+
arrIndex: match[2],
|
|
659
|
+
};
|
|
660
|
+
if (resource[arrayData.arrName] !== undefined) {
|
|
661
|
+
resource = resource[arrayData.arrName][arrayData.arrIndex];
|
|
662
|
+
}
|
|
663
|
+
else {
|
|
664
|
+
resource = undefined;
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
else {
|
|
668
|
+
resource = resource[comp];
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
return resource;
|
|
672
|
+
}
|
|
673
|
+
static parse(configOrJson) {
|
|
674
|
+
const config = AbilityParser_1.default.prepareAndValidateConfig(configOrJson, [
|
|
675
|
+
['id', 'string', false],
|
|
676
|
+
['name', 'string', true],
|
|
677
|
+
['matches', 'array', true],
|
|
678
|
+
]);
|
|
679
|
+
const { name, matches } = config;
|
|
680
|
+
const [leftField, condition, rightField] = matches;
|
|
681
|
+
return new AbilityRule({
|
|
682
|
+
name,
|
|
683
|
+
matches: [leftField, new AbilityCondition_1.default(condition), rightField],
|
|
684
|
+
});
|
|
685
|
+
}
|
|
686
|
+
/**
|
|
687
|
+
* Export the rule to config object
|
|
688
|
+
*/
|
|
689
|
+
export() {
|
|
690
|
+
const [leftField, condition, rightField] = this.matches;
|
|
691
|
+
return {
|
|
692
|
+
name: this.name,
|
|
693
|
+
matches: [leftField, condition.code, rightField],
|
|
694
|
+
};
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
exports.AbilityRule = AbilityRule;
|
|
698
|
+
exports["default"] = AbilityRule;
|
|
699
|
+
|
|
700
|
+
|
|
701
|
+
/***/ }),
|
|
702
|
+
|
|
703
|
+
/***/ "./src/AbilityRuleSet.ts":
|
|
704
|
+
/*!*******************************!*\
|
|
705
|
+
!*** ./src/AbilityRuleSet.ts ***!
|
|
706
|
+
\*******************************/
|
|
707
|
+
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
708
|
+
|
|
709
|
+
|
|
710
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
711
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
712
|
+
};
|
|
713
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
714
|
+
exports.AbilityRuleSet = void 0;
|
|
715
|
+
const AbilityRule_1 = __importDefault(__webpack_require__(/*! ./AbilityRule */ "./src/AbilityRule.ts"));
|
|
716
|
+
const AbilityCompare_1 = __importDefault(__webpack_require__(/*! ./AbilityCompare */ "./src/AbilityCompare.ts"));
|
|
717
|
+
const AbilityMatch_1 = __importDefault(__webpack_require__(/*! ./AbilityMatch */ "./src/AbilityMatch.ts"));
|
|
718
|
+
const AbilityParser_1 = __importDefault(__webpack_require__(/*! ./AbilityParser */ "./src/AbilityParser.ts"));
|
|
719
|
+
class AbilityRuleSet {
|
|
720
|
+
state = AbilityMatch_1.default.PENDING;
|
|
721
|
+
/**
|
|
722
|
+
* List of rules
|
|
723
|
+
*/
|
|
724
|
+
rules = [];
|
|
725
|
+
/**
|
|
726
|
+
* Rules compare method.\
|
|
727
|
+
* For the «and» method the rule will be permitted if all\
|
|
728
|
+
* rules will be returns «permit» status and for the «or» - if\
|
|
729
|
+
* one of the rules returns as «permit»
|
|
730
|
+
*/
|
|
731
|
+
compareMethod = AbilityCompare_1.default.AND;
|
|
732
|
+
/**
|
|
733
|
+
* Group name
|
|
734
|
+
*/
|
|
735
|
+
name;
|
|
736
|
+
/**
|
|
737
|
+
* Group ID
|
|
738
|
+
*/
|
|
739
|
+
id;
|
|
740
|
+
constructor(params) {
|
|
741
|
+
const { name, id } = params || {};
|
|
742
|
+
this.name = name || Symbol('name');
|
|
743
|
+
this.id = id || Symbol('id');
|
|
744
|
+
}
|
|
745
|
+
addRule(rule, compareMethod) {
|
|
746
|
+
this.rules.push(rule);
|
|
747
|
+
this.compareMethod = compareMethod;
|
|
748
|
+
return this;
|
|
749
|
+
}
|
|
750
|
+
addRules(rules, compareMethod) {
|
|
751
|
+
rules.forEach(rule => this.addRule(rule, compareMethod));
|
|
752
|
+
return this;
|
|
753
|
+
}
|
|
754
|
+
check(resources) {
|
|
755
|
+
this.state = AbilityMatch_1.default.MISMATCH;
|
|
756
|
+
if (!this.rules.length) {
|
|
757
|
+
return this.state;
|
|
758
|
+
}
|
|
759
|
+
const ruleCheckStates = this.rules.reduce((collect, rule) => {
|
|
760
|
+
return collect.concat(rule.check(resources));
|
|
761
|
+
}, []);
|
|
762
|
+
if (AbilityCompare_1.default.AND.isEqual(this.compareMethod)) {
|
|
763
|
+
if (ruleCheckStates.every(ruleState => AbilityMatch_1.default.MATCH.isEqual(ruleState))) {
|
|
764
|
+
this.state = AbilityMatch_1.default.MATCH;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
if (AbilityCompare_1.default.OR.isEqual(this.compareMethod)) {
|
|
768
|
+
if (ruleCheckStates.some(ruleState => AbilityMatch_1.default.MATCH.isEqual(ruleState))) {
|
|
769
|
+
this.state = AbilityMatch_1.default.MATCH;
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
return this.state;
|
|
773
|
+
}
|
|
774
|
+
/**
|
|
775
|
+
* Parse the config JSON format to Group class instance
|
|
776
|
+
*/
|
|
777
|
+
static parse(configOrJson) {
|
|
778
|
+
const config = AbilityParser_1.default.prepareAndValidateConfig(configOrJson, [
|
|
779
|
+
['id', 'string', false],
|
|
780
|
+
['name', 'string', true],
|
|
781
|
+
['compareMethod', 'number', true],
|
|
782
|
+
['rules', 'array', true],
|
|
783
|
+
]);
|
|
784
|
+
const { id, name, rules, compareMethod } = config;
|
|
785
|
+
const ruleSet = new AbilityRuleSet({
|
|
786
|
+
name,
|
|
787
|
+
id,
|
|
788
|
+
});
|
|
789
|
+
ruleSet.compareMethod = new AbilityCompare_1.default(compareMethod);
|
|
790
|
+
// Adding rules if exists
|
|
791
|
+
if (rules && rules.length > 0) {
|
|
792
|
+
const abilityRules = rules.map(ruleConfig => AbilityRule_1.default.parse(ruleConfig));
|
|
793
|
+
ruleSet.addRules(abilityRules, ruleSet.compareMethod);
|
|
794
|
+
}
|
|
795
|
+
return ruleSet;
|
|
796
|
+
}
|
|
797
|
+
export() {
|
|
798
|
+
return {
|
|
799
|
+
id: this.id.toString(),
|
|
800
|
+
name: this.name.toString(),
|
|
801
|
+
compareMethod: this.compareMethod.code,
|
|
802
|
+
rules: this.rules.map(rule => rule.export()),
|
|
803
|
+
};
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
exports.AbilityRuleSet = AbilityRuleSet;
|
|
807
|
+
exports["default"] = AbilityRuleSet;
|
|
808
|
+
|
|
809
|
+
|
|
810
|
+
/***/ }),
|
|
811
|
+
|
|
812
|
+
/***/ "./src/playground.ts":
|
|
813
|
+
/*!***************************!*\
|
|
814
|
+
!*** ./src/playground.ts ***!
|
|
815
|
+
\***************************/
|
|
816
|
+
/***/ (function(__unused_webpack_module, exports, __webpack_require__) {
|
|
817
|
+
|
|
818
|
+
|
|
819
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
820
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
821
|
+
};
|
|
822
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
823
|
+
const node_http_1 = __importDefault(__webpack_require__(/*! node:http */ "node:http"));
|
|
824
|
+
const AbilityPolicy_1 = __importDefault(__webpack_require__(/*! ./AbilityPolicy */ "./src/AbilityPolicy.ts"));
|
|
825
|
+
const AbilityResolver_1 = __importDefault(__webpack_require__(/*! ~/AbilityResolver */ "./src/AbilityResolver.ts"));
|
|
826
|
+
const policies_json_1 = __importDefault(__webpack_require__(/*! ./policies.json */ "./src/policies.json"));
|
|
827
|
+
const server = node_http_1.default.createServer();
|
|
828
|
+
server.on('request', (_req, res) => {
|
|
829
|
+
new AbilityResolver_1.default(policies_json_1.default.map(p => {
|
|
830
|
+
return AbilityPolicy_1.default.parse(p);
|
|
831
|
+
})).enforce('account.read', {
|
|
832
|
+
account: {
|
|
833
|
+
id: '1',
|
|
834
|
+
roles: ['managers'],
|
|
835
|
+
},
|
|
836
|
+
resource: {
|
|
837
|
+
id: '1',
|
|
838
|
+
},
|
|
839
|
+
});
|
|
840
|
+
res.statusCode = 200;
|
|
841
|
+
res.setHeader('content-type', 'application/json');
|
|
842
|
+
res.write(JSON.stringify({
|
|
843
|
+
status: 'Done',
|
|
844
|
+
}));
|
|
845
|
+
res.end();
|
|
846
|
+
});
|
|
847
|
+
server.listen(8080, 'localhost', () => {
|
|
848
|
+
console.debug('server started at http://localhost:8080');
|
|
849
|
+
});
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
/***/ }),
|
|
853
|
+
|
|
854
|
+
/***/ "node:http":
|
|
855
|
+
/*!****************************!*\
|
|
856
|
+
!*** external "node:http" ***!
|
|
857
|
+
\****************************/
|
|
858
|
+
/***/ ((module) => {
|
|
859
|
+
|
|
860
|
+
module.exports = require("node:http");
|
|
861
|
+
|
|
862
|
+
/***/ }),
|
|
863
|
+
|
|
864
|
+
/***/ "./src/policies.json":
|
|
865
|
+
/*!***************************!*\
|
|
866
|
+
!*** ./src/policies.json ***!
|
|
867
|
+
\***************************/
|
|
868
|
+
/***/ ((module) => {
|
|
869
|
+
|
|
870
|
+
module.exports = /*#__PURE__*/JSON.parse('[{"name":"Просмотр чужого логина разрешен только владельцу аккаунта и администраторам","action":"account.read","effect":0,"compareMethod":0,"ruleSet":[{"name":"Не владелец аккаунта и не администратор","compareMethod":1,"rules":[{"name":"Владелец аккаунта","matches":["account.id","<>","resource.id"]},{"name":"Администратор","matches":["account.roles","not in","administrator"]}]}]},{"name":"Unauthorized. Access token expected","action":"access.auth","effect":0,"compareMethod":1,"ruleSet":[{"name":"Токен - AccessToken","matches":["token.type","=","access"]},{"name":"Токен не пустой","matches":["token.id","<>","ACCESS_TOKEN_EMPTY_ID"]}]},{"id":"1121","name":"Менеджеры не могут редактировать заказы, созданные более 3-х дней назад, а так же завершенные и отменённые заявки","action":"order.update","effect":0,"compareMethod":1,"ruleSet":[{"name":"Менеджеры","compareMethod":0,"rules":[{"name":"Отдел - Менеджеры","matches":["user.department","=","managers"]},{"name":"Роль - Менеджер","matches":["user.roles","in","manager"]}]},{"name":"Заказы более 3-х дней, а так же завершённые и отменённые заказы","compareMethod":0,"rules":[{"name":"заказ создан более 3-х дней назад","matches":["order.createdDaysAgo",">",3]},{"name":"заказ завершён","matches":["order.status","=","COMPLETED"]},{"name":"заказ отменён","matches":["order.status","=","CANCELLED"]}]}]},{"name":"Менеджеры не могут создавать заказы","action":"order.create","effect":0,"compareMethod":0,"ruleSet":[{"name":"Менеджеры","compareMethod":0,"rules":[{"name":"Отдел - Менеджеры","matches":["user.department","=","managers"]},{"name":"Роль - Менеджер","matches":["user.roles","in","manager"]}]}]},{"name":"Уборщицы не могут видеть стоимость заказа","action":"order.read","effect":0,"compareMethod":0,"ruleSet":[{"name":"все из отдела уборщиц","matches":["user.department","in","cleaner"]}]}]');
|
|
871
|
+
|
|
872
|
+
/***/ })
|
|
873
|
+
|
|
874
|
+
/******/ });
|
|
875
|
+
/************************************************************************/
|
|
876
|
+
/******/ // The module cache
|
|
877
|
+
/******/ var __webpack_module_cache__ = {};
|
|
878
|
+
/******/
|
|
879
|
+
/******/ // The require function
|
|
880
|
+
/******/ function __webpack_require__(moduleId) {
|
|
881
|
+
/******/ // Check if module is in cache
|
|
882
|
+
/******/ var cachedModule = __webpack_module_cache__[moduleId];
|
|
883
|
+
/******/ if (cachedModule !== undefined) {
|
|
884
|
+
/******/ return cachedModule.exports;
|
|
885
|
+
/******/ }
|
|
886
|
+
/******/ // Create a new module (and put it into the cache)
|
|
887
|
+
/******/ var module = __webpack_module_cache__[moduleId] = {
|
|
888
|
+
/******/ // no module.id needed
|
|
889
|
+
/******/ // no module.loaded needed
|
|
890
|
+
/******/ exports: {}
|
|
891
|
+
/******/ };
|
|
892
|
+
/******/
|
|
893
|
+
/******/ // Execute the module function
|
|
894
|
+
/******/ __webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
895
|
+
/******/
|
|
896
|
+
/******/ // Return the exports of the module
|
|
897
|
+
/******/ return module.exports;
|
|
898
|
+
/******/ }
|
|
899
|
+
/******/
|
|
900
|
+
/************************************************************************/
|
|
901
|
+
/******/
|
|
902
|
+
/******/ // startup
|
|
903
|
+
/******/ // Load entry module and return exports
|
|
904
|
+
/******/ // This entry module is referenced by other modules so it can't be inlined
|
|
905
|
+
/******/ var __webpack_exports__ = __webpack_require__("./src/playground.ts");
|
|
906
|
+
/******/ module.exports = __webpack_exports__;
|
|
907
|
+
/******/
|
|
908
|
+
/******/ })()
|
|
909
|
+
;
|
|
910
|
+
//# sourceMappingURL=playground.js.map
|