@flusys/nestjs-shared 9.1.0-rc.1 → 9.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -0
- package/constants/permissions.d.ts +0 -2
- package/fesm/270.js +659 -0
- package/fesm/470.js +5 -40
- package/fesm/681.js +78 -2
- package/fesm/948.js +0 -1
- package/fesm/constants/index.js +0 -1
- package/fesm/guards/index.js +83 -42
- package/fesm/index.js +54 -539
- package/fesm/interceptors/index.js +0 -1
- package/fesm/interfaces/index.js +21 -3
- package/fesm/utils/index.js +131 -537
- package/guards/permission.guard.d.ts +0 -1
- package/interfaces/branch-hierarchy-resolver.interface.d.ts +10 -0
- package/interfaces/company-access-resolver.interface.d.ts +19 -0
- package/interfaces/email-adapter.interface.d.ts +27 -0
- package/interfaces/index.d.ts +3 -0
- package/modules/shared-permission-cache/shared-permission-cache.service.d.ts +6 -1
- package/package.json +3 -3
- package/utils/branch-hierarchy.util.d.ts +15 -0
- package/utils/index.d.ts +1 -0
- package/utils/permission-match.util.d.ts +18 -0
- package/utils/query-helpers.util.d.ts +6 -0
package/fesm/470.js
CHANGED
|
@@ -2224,6 +2224,8 @@ OptionalJwtGuard = optional_jwt_auth_guard_ts_decorate([
|
|
|
2224
2224
|
var permission_exception = __webpack_require__(374);
|
|
2225
2225
|
// EXTERNAL MODULE: ./projects/nestjs-shared/src/modules/shared-permission-cache/shared-permission-cache.service.ts
|
|
2226
2226
|
var shared_permission_cache_service = __webpack_require__(657);
|
|
2227
|
+
// EXTERNAL MODULE: ./projects/nestjs-shared/src/utils/permission-match.util.ts
|
|
2228
|
+
var permission_match_util = __webpack_require__(788);
|
|
2227
2229
|
;// CONCATENATED MODULE: ./projects/nestjs-shared/src/guards/permission.guard.ts
|
|
2228
2230
|
function permission_guard_ts_decorate(decorators, target, key, desc) {
|
|
2229
2231
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -2253,6 +2255,7 @@ function permission_guard_ts_param(paramIndex, decorator) {
|
|
|
2253
2255
|
|
|
2254
2256
|
|
|
2255
2257
|
|
|
2258
|
+
|
|
2256
2259
|
class PermissionGuard {
|
|
2257
2260
|
reflector;
|
|
2258
2261
|
permissionCacheService;
|
|
@@ -2280,8 +2283,7 @@ class PermissionGuard {
|
|
|
2280
2283
|
if (!this.permissionCacheService?.isCacheConfigured()) {
|
|
2281
2284
|
throw new permission_exception/* .PermissionSystemUnavailableException */.GS();
|
|
2282
2285
|
}
|
|
2283
|
-
const
|
|
2284
|
-
const userPermissions = await permissionService.getPermissions({
|
|
2286
|
+
const userPermissions = await this.permissionCacheService.getPermissions({
|
|
2285
2287
|
userId: user.id,
|
|
2286
2288
|
companyId: user.companyId,
|
|
2287
2289
|
branchId: user.branchId
|
|
@@ -2291,7 +2293,7 @@ class PermissionGuard {
|
|
|
2291
2293
|
}
|
|
2292
2294
|
const logicNode = this.normalizeToLogicNode(permissionConfig);
|
|
2293
2295
|
if (!logicNode) return true;
|
|
2294
|
-
const result =
|
|
2296
|
+
const result = (0,permission_match_util/* .evaluatePermissionLogic */.Ng)(logicNode, userPermissions);
|
|
2295
2297
|
if (!result.passed) {
|
|
2296
2298
|
throw new permission_exception/* .InsufficientPermissionsException */.z8(result.missingPermissions, result.operator);
|
|
2297
2299
|
}
|
|
@@ -2341,43 +2343,6 @@ class PermissionGuard {
|
|
|
2341
2343
|
// ILogicNode
|
|
2342
2344
|
return config;
|
|
2343
2345
|
}
|
|
2344
|
-
evaluateLogicNode(node, userPermissions, permissionService) {
|
|
2345
|
-
if (node.type === 'action') {
|
|
2346
|
-
const passed = permissionService.matchPermission(userPermissions, node.actionId);
|
|
2347
|
-
return {
|
|
2348
|
-
passed,
|
|
2349
|
-
missingPermissions: passed ? [] : [
|
|
2350
|
-
node.actionId
|
|
2351
|
-
],
|
|
2352
|
-
operator: 'AND'
|
|
2353
|
-
};
|
|
2354
|
-
}
|
|
2355
|
-
// Group node
|
|
2356
|
-
const { operator, children } = node;
|
|
2357
|
-
// SECURITY: Fail-closed - deny access when no children configured
|
|
2358
|
-
if (!children || children.length === 0) {
|
|
2359
|
-
return {
|
|
2360
|
-
passed: false,
|
|
2361
|
-
missingPermissions: [],
|
|
2362
|
-
operator
|
|
2363
|
-
};
|
|
2364
|
-
}
|
|
2365
|
-
const results = [];
|
|
2366
|
-
const missingPermissions = [];
|
|
2367
|
-
for (const child of children){
|
|
2368
|
-
const childResult = this.evaluateLogicNode(child, userPermissions, permissionService);
|
|
2369
|
-
results.push(childResult.passed);
|
|
2370
|
-
if (!childResult.passed) {
|
|
2371
|
-
missingPermissions.push(...childResult.missingPermissions);
|
|
2372
|
-
}
|
|
2373
|
-
}
|
|
2374
|
-
const passed = operator === 'OR' ? results.some((r)=>r) : results.every((r)=>r);
|
|
2375
|
-
return {
|
|
2376
|
-
passed,
|
|
2377
|
-
missingPermissions: passed ? [] : missingPermissions,
|
|
2378
|
-
operator
|
|
2379
|
-
};
|
|
2380
|
-
}
|
|
2381
2346
|
}
|
|
2382
2347
|
PermissionGuard = permission_guard_ts_decorate([
|
|
2383
2348
|
(0,common_.Injectable)(),
|
package/fesm/681.js
CHANGED
|
@@ -611,11 +611,21 @@ class SharedPermissionCacheService {
|
|
|
611
611
|
requiredPermission
|
|
612
612
|
], 'AND');
|
|
613
613
|
}
|
|
614
|
+
/** Throws 403 (naming what is missing) unless `user` passes the AND / OR tree; fails closed (500) when no cache is wired up. */ async assertPermissionLogic(user, logic) {
|
|
615
|
+
if (!this.isCacheConfigured()) throw new _exceptions_permission_exception_js__rspack_import_3/* .PermissionSystemUnavailableException */.GS();
|
|
616
|
+
const granted = user?.id ? await this.getPermissions({
|
|
617
|
+
userId: user.id,
|
|
618
|
+
companyId: user.companyId,
|
|
619
|
+
branchId: user.branchId
|
|
620
|
+
}) : [];
|
|
621
|
+
const result = (0,_utils_permission_match_util_js__rspack_import_5/* .evaluatePermissionLogic */.Ng)(logic, granted);
|
|
622
|
+
if (!result.passed) throw new _exceptions_permission_exception_js__rspack_import_3/* .InsufficientPermissionsException */.z8(result.missingPermissions, result.operator);
|
|
623
|
+
}
|
|
614
624
|
/** Whether a cache instance is wired up; false means permission checks can't be served at all */ isCacheConfigured() {
|
|
615
625
|
return !!this.cache;
|
|
616
626
|
}
|
|
617
627
|
/** Match an already-fetched permission list against a required permission, honoring `*` and `prefix.*` wildcards */ matchPermission(userPermissions, requiredPermission) {
|
|
618
|
-
return (0,_utils_permission_match_util_js__rspack_import_5/* .matchesPermission */.
|
|
628
|
+
return (0,_utils_permission_match_util_js__rspack_import_5/* .matchesPermission */.xY)(userPermissions, requiredPermission);
|
|
619
629
|
}
|
|
620
630
|
}
|
|
621
631
|
SharedPermissionCacheService = _ts_decorate([
|
|
@@ -843,6 +853,8 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
843
853
|
|
|
844
854
|
},
|
|
845
855
|
788(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
856
|
+
/* import */ var _exceptions_permission_exception_js__rspack_import_0 = __webpack_require__(374);
|
|
857
|
+
|
|
846
858
|
/** Whether `granted` covers `required`, honoring `*` (everything) and `prefix.*` (everything under prefix) wildcards */ function matchesPermission(granted, required) {
|
|
847
859
|
if (granted.includes(required)) return true;
|
|
848
860
|
for (const permission of granted){
|
|
@@ -851,9 +863,73 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
851
863
|
}
|
|
852
864
|
return false;
|
|
853
865
|
}
|
|
866
|
+
/** Evaluates an AND / OR permission tree against `granted`; a group without children fails closed. */ function evaluatePermissionLogic(node, granted) {
|
|
867
|
+
if (node.type === 'action') {
|
|
868
|
+
const passed = matchesPermission(granted, node.actionId);
|
|
869
|
+
return {
|
|
870
|
+
passed,
|
|
871
|
+
missingPermissions: passed ? [] : [
|
|
872
|
+
node.actionId
|
|
873
|
+
],
|
|
874
|
+
operator: 'AND'
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
const { operator, children } = node;
|
|
878
|
+
if (!children?.length) return {
|
|
879
|
+
passed: false,
|
|
880
|
+
missingPermissions: [],
|
|
881
|
+
operator
|
|
882
|
+
};
|
|
883
|
+
const results = children.map((child)=>evaluatePermissionLogic(child, granted));
|
|
884
|
+
const passed = operator === 'OR' ? results.some((r)=>r.passed) : results.every((r)=>r.passed);
|
|
885
|
+
return {
|
|
886
|
+
passed,
|
|
887
|
+
missingPermissions: passed ? [] : results.flatMap((r)=>r.missingPermissions),
|
|
888
|
+
operator
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
/** Every permission code a tree names, each once, in order. */ function permissionLogicCodes(node) {
|
|
892
|
+
if (node.type === 'action') return node.actionId ? [
|
|
893
|
+
node.actionId
|
|
894
|
+
] : [];
|
|
895
|
+
return [
|
|
896
|
+
...new Set((node.children ?? []).flatMap(permissionLogicCodes))
|
|
897
|
+
];
|
|
898
|
+
}
|
|
899
|
+
/** Groups nested in a permission rule, the outer one included. */ const MAX_PERMISSION_LOGIC_DEPTH = 5;
|
|
900
|
+
/** Permission codes one rule may name. */ const MAX_PERMISSION_LOGIC_CODES = 50;
|
|
901
|
+
const MAX_PERMISSION_CODE_LENGTH = 255;
|
|
902
|
+
/** What is wrong with a stored permission rule: `invalid` (its shape), `empty` (it names no permission), `too_many` codes, or null. */ function permissionLogicProblem(value) {
|
|
903
|
+
let codes = 0;
|
|
904
|
+
const walk = (node, depth)=>{
|
|
905
|
+
if (!node || typeof node !== 'object' || Array.isArray(node)) return false;
|
|
906
|
+
const n = node;
|
|
907
|
+
if (n['type'] === 'action') {
|
|
908
|
+
codes++;
|
|
909
|
+
return typeof n['actionId'] === 'string' && n['actionId'].trim() !== '' && n['actionId'].length <= MAX_PERMISSION_CODE_LENGTH;
|
|
910
|
+
}
|
|
911
|
+
if (n['type'] !== 'group' || n['operator'] !== 'AND' && n['operator'] !== 'OR' || !Array.isArray(n['children'])) return false;
|
|
912
|
+
if (depth >= MAX_PERMISSION_LOGIC_DEPTH || !n['children'].length) return false;
|
|
913
|
+
return n['children'].every((child)=>walk(child, depth + 1));
|
|
914
|
+
};
|
|
915
|
+
if (!value || typeof value !== 'object') return 'invalid';
|
|
916
|
+
const node = value;
|
|
917
|
+
if (node['type'] === 'group' && (node['operator'] === 'AND' || node['operator'] === 'OR') && Array.isArray(node['children']) && !node['children'].length) return 'empty';
|
|
918
|
+
if (!walk(value, 0)) return 'invalid';
|
|
919
|
+
return codes > MAX_PERMISSION_LOGIC_CODES ? 'too_many' : null;
|
|
920
|
+
}
|
|
921
|
+
/** A user's codes in `scope`, from the resolver or else the cache; with neither, fails closed with PermissionSystemUnavailableException. */ async function loadPermissionCodes(scope, sources) {
|
|
922
|
+
if (sources.resolver) return sources.resolver.getPermissionCodes(scope);
|
|
923
|
+
if (sources.cache?.isCacheConfigured()) return sources.cache.getPermissions(scope);
|
|
924
|
+
throw new _exceptions_permission_exception_js__rspack_import_0/* .PermissionSystemUnavailableException */.GS();
|
|
925
|
+
}
|
|
854
926
|
|
|
855
927
|
__webpack_require__.d(__webpack_exports__, {
|
|
856
|
-
|
|
928
|
+
CQ: () => (loadPermissionCodes),
|
|
929
|
+
HU: () => (permissionLogicProblem),
|
|
930
|
+
MO: () => (permissionLogicCodes),
|
|
931
|
+
Ng: () => (evaluatePermissionLogic),
|
|
932
|
+
xY: () => (matchesPermission)
|
|
857
933
|
});
|
|
858
934
|
|
|
859
935
|
|
package/fesm/948.js
CHANGED
|
@@ -522,7 +522,6 @@ const FLOW_DEFINITION_PERMISSIONS = {
|
|
|
522
522
|
UPDATE: 'entity_builder.flow_definition.update',
|
|
523
523
|
DELETE: 'entity_builder.flow_definition.delete',
|
|
524
524
|
TEST: 'entity_builder.flow_definition.test',
|
|
525
|
-
/** Needed to save a flow that runs as the system (bypassing per-entity permissions). */ SYSTEM: 'entity_builder.flow_definition.system',
|
|
526
525
|
/** Needed to save a flow containing a code node (sandboxed JavaScript). */ CODE: 'entity_builder.flow_definition.code'
|
|
527
526
|
};
|
|
528
527
|
const ENTITY_BUILDER_DYNAMIC_PREFIX = 'entity_builder.entity';
|
package/fesm/constants/index.js
CHANGED
|
@@ -273,7 +273,6 @@ const FLOW_DEFINITION_PERMISSIONS = {
|
|
|
273
273
|
UPDATE: 'entity_builder.flow_definition.update',
|
|
274
274
|
DELETE: 'entity_builder.flow_definition.delete',
|
|
275
275
|
TEST: 'entity_builder.flow_definition.test',
|
|
276
|
-
/** Needed to save a flow that runs as the system (bypassing per-entity permissions). */ SYSTEM: 'entity_builder.flow_definition.system',
|
|
277
276
|
/** Needed to save a flow containing a code node (sandboxed JavaScript). */ CODE: 'entity_builder.flow_definition.code'
|
|
278
277
|
};
|
|
279
278
|
const ENTITY_BUILDER_DYNAMIC_PREFIX = 'entity_builder.entity';
|
package/fesm/guards/index.js
CHANGED
|
@@ -287,6 +287,8 @@ OptionalJwtGuard = optional_jwt_auth_guard_ts_decorate([
|
|
|
287
287
|
var permission_exception = __webpack_require__(374);
|
|
288
288
|
// EXTERNAL MODULE: ./projects/nestjs-shared/src/modules/shared-permission-cache/shared-permission-cache.service.ts
|
|
289
289
|
var shared_permission_cache_service = __webpack_require__(657);
|
|
290
|
+
// EXTERNAL MODULE: ./projects/nestjs-shared/src/utils/permission-match.util.ts
|
|
291
|
+
var permission_match_util = __webpack_require__(788);
|
|
290
292
|
;// CONCATENATED MODULE: ./projects/nestjs-shared/src/guards/permission.guard.ts
|
|
291
293
|
function permission_guard_ts_decorate(decorators, target, key, desc) {
|
|
292
294
|
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
@@ -316,6 +318,7 @@ function permission_guard_ts_param(paramIndex, decorator) {
|
|
|
316
318
|
|
|
317
319
|
|
|
318
320
|
|
|
321
|
+
|
|
319
322
|
class PermissionGuard {
|
|
320
323
|
reflector;
|
|
321
324
|
permissionCacheService;
|
|
@@ -343,8 +346,7 @@ class PermissionGuard {
|
|
|
343
346
|
if (!this.permissionCacheService?.isCacheConfigured()) {
|
|
344
347
|
throw new permission_exception/* .PermissionSystemUnavailableException */.GS();
|
|
345
348
|
}
|
|
346
|
-
const
|
|
347
|
-
const userPermissions = await permissionService.getPermissions({
|
|
349
|
+
const userPermissions = await this.permissionCacheService.getPermissions({
|
|
348
350
|
userId: user.id,
|
|
349
351
|
companyId: user.companyId,
|
|
350
352
|
branchId: user.branchId
|
|
@@ -354,7 +356,7 @@ class PermissionGuard {
|
|
|
354
356
|
}
|
|
355
357
|
const logicNode = this.normalizeToLogicNode(permissionConfig);
|
|
356
358
|
if (!logicNode) return true;
|
|
357
|
-
const result =
|
|
359
|
+
const result = (0,permission_match_util/* .evaluatePermissionLogic */.Ng)(logicNode, userPermissions);
|
|
358
360
|
if (!result.passed) {
|
|
359
361
|
throw new permission_exception/* .InsufficientPermissionsException */.z8(result.missingPermissions, result.operator);
|
|
360
362
|
}
|
|
@@ -404,43 +406,6 @@ class PermissionGuard {
|
|
|
404
406
|
// ILogicNode
|
|
405
407
|
return config;
|
|
406
408
|
}
|
|
407
|
-
evaluateLogicNode(node, userPermissions, permissionService) {
|
|
408
|
-
if (node.type === 'action') {
|
|
409
|
-
const passed = permissionService.matchPermission(userPermissions, node.actionId);
|
|
410
|
-
return {
|
|
411
|
-
passed,
|
|
412
|
-
missingPermissions: passed ? [] : [
|
|
413
|
-
node.actionId
|
|
414
|
-
],
|
|
415
|
-
operator: 'AND'
|
|
416
|
-
};
|
|
417
|
-
}
|
|
418
|
-
// Group node
|
|
419
|
-
const { operator, children } = node;
|
|
420
|
-
// SECURITY: Fail-closed - deny access when no children configured
|
|
421
|
-
if (!children || children.length === 0) {
|
|
422
|
-
return {
|
|
423
|
-
passed: false,
|
|
424
|
-
missingPermissions: [],
|
|
425
|
-
operator
|
|
426
|
-
};
|
|
427
|
-
}
|
|
428
|
-
const results = [];
|
|
429
|
-
const missingPermissions = [];
|
|
430
|
-
for (const child of children){
|
|
431
|
-
const childResult = this.evaluateLogicNode(child, userPermissions, permissionService);
|
|
432
|
-
results.push(childResult.passed);
|
|
433
|
-
if (!childResult.passed) {
|
|
434
|
-
missingPermissions.push(...childResult.missingPermissions);
|
|
435
|
-
}
|
|
436
|
-
}
|
|
437
|
-
const passed = operator === 'OR' ? results.some((r)=>r) : results.every((r)=>r);
|
|
438
|
-
return {
|
|
439
|
-
passed,
|
|
440
|
-
missingPermissions: passed ? [] : missingPermissions,
|
|
441
|
-
operator
|
|
442
|
-
};
|
|
443
|
-
}
|
|
444
409
|
}
|
|
445
410
|
PermissionGuard = permission_guard_ts_decorate([
|
|
446
411
|
(0,common_.Injectable)(),
|
|
@@ -541,11 +506,21 @@ class SharedPermissionCacheService {
|
|
|
541
506
|
requiredPermission
|
|
542
507
|
], 'AND');
|
|
543
508
|
}
|
|
509
|
+
/** Throws 403 (naming what is missing) unless `user` passes the AND / OR tree; fails closed (500) when no cache is wired up. */ async assertPermissionLogic(user, logic) {
|
|
510
|
+
if (!this.isCacheConfigured()) throw new _exceptions_permission_exception_js__rspack_import_3/* .PermissionSystemUnavailableException */.GS();
|
|
511
|
+
const granted = user?.id ? await this.getPermissions({
|
|
512
|
+
userId: user.id,
|
|
513
|
+
companyId: user.companyId,
|
|
514
|
+
branchId: user.branchId
|
|
515
|
+
}) : [];
|
|
516
|
+
const result = (0,_utils_permission_match_util_js__rspack_import_5/* .evaluatePermissionLogic */.Ng)(logic, granted);
|
|
517
|
+
if (!result.passed) throw new _exceptions_permission_exception_js__rspack_import_3/* .InsufficientPermissionsException */.z8(result.missingPermissions, result.operator);
|
|
518
|
+
}
|
|
544
519
|
/** Whether a cache instance is wired up; false means permission checks can't be served at all */ isCacheConfigured() {
|
|
545
520
|
return !!this.cache;
|
|
546
521
|
}
|
|
547
522
|
/** Match an already-fetched permission list against a required permission, honoring `*` and `prefix.*` wildcards */ matchPermission(userPermissions, requiredPermission) {
|
|
548
|
-
return (0,_utils_permission_match_util_js__rspack_import_5/* .matchesPermission */.
|
|
523
|
+
return (0,_utils_permission_match_util_js__rspack_import_5/* .matchesPermission */.xY)(userPermissions, requiredPermission);
|
|
549
524
|
}
|
|
550
525
|
}
|
|
551
526
|
SharedPermissionCacheService = _ts_decorate([
|
|
@@ -590,6 +565,8 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
590
565
|
|
|
591
566
|
},
|
|
592
567
|
788(__unused_rspack_module, __webpack_exports__, __webpack_require__) {
|
|
568
|
+
/* import */ var _exceptions_permission_exception_js__rspack_import_0 = __webpack_require__(374);
|
|
569
|
+
|
|
593
570
|
/** Whether `granted` covers `required`, honoring `*` (everything) and `prefix.*` (everything under prefix) wildcards */ function matchesPermission(granted, required) {
|
|
594
571
|
if (granted.includes(required)) return true;
|
|
595
572
|
for (const permission of granted){
|
|
@@ -598,9 +575,73 @@ __webpack_require__.d(__webpack_exports__, {
|
|
|
598
575
|
}
|
|
599
576
|
return false;
|
|
600
577
|
}
|
|
578
|
+
/** Evaluates an AND / OR permission tree against `granted`; a group without children fails closed. */ function evaluatePermissionLogic(node, granted) {
|
|
579
|
+
if (node.type === 'action') {
|
|
580
|
+
const passed = matchesPermission(granted, node.actionId);
|
|
581
|
+
return {
|
|
582
|
+
passed,
|
|
583
|
+
missingPermissions: passed ? [] : [
|
|
584
|
+
node.actionId
|
|
585
|
+
],
|
|
586
|
+
operator: 'AND'
|
|
587
|
+
};
|
|
588
|
+
}
|
|
589
|
+
const { operator, children } = node;
|
|
590
|
+
if (!children?.length) return {
|
|
591
|
+
passed: false,
|
|
592
|
+
missingPermissions: [],
|
|
593
|
+
operator
|
|
594
|
+
};
|
|
595
|
+
const results = children.map((child)=>evaluatePermissionLogic(child, granted));
|
|
596
|
+
const passed = operator === 'OR' ? results.some((r)=>r.passed) : results.every((r)=>r.passed);
|
|
597
|
+
return {
|
|
598
|
+
passed,
|
|
599
|
+
missingPermissions: passed ? [] : results.flatMap((r)=>r.missingPermissions),
|
|
600
|
+
operator
|
|
601
|
+
};
|
|
602
|
+
}
|
|
603
|
+
/** Every permission code a tree names, each once, in order. */ function permissionLogicCodes(node) {
|
|
604
|
+
if (node.type === 'action') return node.actionId ? [
|
|
605
|
+
node.actionId
|
|
606
|
+
] : [];
|
|
607
|
+
return [
|
|
608
|
+
...new Set((node.children ?? []).flatMap(permissionLogicCodes))
|
|
609
|
+
];
|
|
610
|
+
}
|
|
611
|
+
/** Groups nested in a permission rule, the outer one included. */ const MAX_PERMISSION_LOGIC_DEPTH = 5;
|
|
612
|
+
/** Permission codes one rule may name. */ const MAX_PERMISSION_LOGIC_CODES = 50;
|
|
613
|
+
const MAX_PERMISSION_CODE_LENGTH = 255;
|
|
614
|
+
/** What is wrong with a stored permission rule: `invalid` (its shape), `empty` (it names no permission), `too_many` codes, or null. */ function permissionLogicProblem(value) {
|
|
615
|
+
let codes = 0;
|
|
616
|
+
const walk = (node, depth)=>{
|
|
617
|
+
if (!node || typeof node !== 'object' || Array.isArray(node)) return false;
|
|
618
|
+
const n = node;
|
|
619
|
+
if (n['type'] === 'action') {
|
|
620
|
+
codes++;
|
|
621
|
+
return typeof n['actionId'] === 'string' && n['actionId'].trim() !== '' && n['actionId'].length <= MAX_PERMISSION_CODE_LENGTH;
|
|
622
|
+
}
|
|
623
|
+
if (n['type'] !== 'group' || n['operator'] !== 'AND' && n['operator'] !== 'OR' || !Array.isArray(n['children'])) return false;
|
|
624
|
+
if (depth >= MAX_PERMISSION_LOGIC_DEPTH || !n['children'].length) return false;
|
|
625
|
+
return n['children'].every((child)=>walk(child, depth + 1));
|
|
626
|
+
};
|
|
627
|
+
if (!value || typeof value !== 'object') return 'invalid';
|
|
628
|
+
const node = value;
|
|
629
|
+
if (node['type'] === 'group' && (node['operator'] === 'AND' || node['operator'] === 'OR') && Array.isArray(node['children']) && !node['children'].length) return 'empty';
|
|
630
|
+
if (!walk(value, 0)) return 'invalid';
|
|
631
|
+
return codes > MAX_PERMISSION_LOGIC_CODES ? 'too_many' : null;
|
|
632
|
+
}
|
|
633
|
+
/** A user's codes in `scope`, from the resolver or else the cache; with neither, fails closed with PermissionSystemUnavailableException. */ async function loadPermissionCodes(scope, sources) {
|
|
634
|
+
if (sources.resolver) return sources.resolver.getPermissionCodes(scope);
|
|
635
|
+
if (sources.cache?.isCacheConfigured()) return sources.cache.getPermissions(scope);
|
|
636
|
+
throw new _exceptions_permission_exception_js__rspack_import_0/* .PermissionSystemUnavailableException */.GS();
|
|
637
|
+
}
|
|
601
638
|
|
|
602
639
|
__webpack_require__.d(__webpack_exports__, {
|
|
603
|
-
|
|
640
|
+
CQ: () => (loadPermissionCodes),
|
|
641
|
+
HU: () => (permissionLogicProblem),
|
|
642
|
+
MO: () => (permissionLogicCodes),
|
|
643
|
+
Ng: () => (evaluatePermissionLogic),
|
|
644
|
+
xY: () => (matchesPermission)
|
|
604
645
|
});
|
|
605
646
|
|
|
606
647
|
|