casbin 5.21.0 → 5.23.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.
- package/CHANGELOG.md +14 -0
- package/examples/subject_priority_model.conf +14 -0
- package/examples/subject_priority_model_with_domain.conf +14 -0
- package/examples/subject_priority_policy.csv +16 -0
- package/examples/subject_priority_policy_with_domain.csv +7 -0
- package/lib/cjs/coreEnforcer.js +3 -0
- package/lib/cjs/effect/defaultEffectorStream.js +1 -0
- package/lib/cjs/enforcer.d.ts +4 -0
- package/lib/cjs/enforcer.js +37 -0
- package/lib/cjs/managementEnforcer.d.ts +17 -0
- package/lib/cjs/managementEnforcer.js +21 -0
- package/lib/cjs/model/model.d.ts +13 -0
- package/lib/cjs/model/model.js +78 -0
- package/lib/cjs/syncedEnforcer.d.ts +17 -0
- package/lib/cjs/syncedEnforcer.js +21 -0
- package/lib/esm/coreEnforcer.js +3 -0
- package/lib/esm/effect/defaultEffectorStream.js +1 -0
- package/lib/esm/enforcer.d.ts +4 -0
- package/lib/esm/enforcer.js +37 -0
- package/lib/esm/managementEnforcer.d.ts +17 -0
- package/lib/esm/managementEnforcer.js +21 -0
- package/lib/esm/model/model.d.ts +13 -0
- package/lib/esm/model/model.js +78 -0
- package/lib/esm/syncedEnforcer.d.ts +17 -0
- package/lib/esm/syncedEnforcer.js +21 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
# [5.23.0](https://github.com/casbin/node-casbin/compare/v5.22.0...v5.23.0) (2023-02-01)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* support `updateGroupingPolicy()`, `updateNamedGroupingPolicy()`, `getImplicitResourcesForUser()` ([#419](https://github.com/casbin/node-casbin/issues/419)) ([46c0f3a](https://github.com/casbin/node-casbin/commit/46c0f3ad09c4e8cf673d9d9b9b8fcf00251caaaf))
|
|
7
|
+
|
|
8
|
+
# [5.22.0](https://github.com/casbin/node-casbin/compare/v5.21.0...v5.22.0) (2023-01-31)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Features
|
|
12
|
+
|
|
13
|
+
* support subjectPriority ([#417](https://github.com/casbin/node-casbin/issues/417)) ([e83d505](https://github.com/casbin/node-casbin/commit/e83d5058872e65be7dc9b374ca8c6640a1f2ca9d))
|
|
14
|
+
|
|
1
15
|
# [5.21.0](https://github.com/casbin/node-casbin/compare/v5.20.4...v5.21.0) (2023-01-21)
|
|
2
16
|
|
|
3
17
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
[request_definition]
|
|
2
|
+
r = sub, obj, act
|
|
3
|
+
|
|
4
|
+
[policy_definition]
|
|
5
|
+
p = sub, obj, act, eft
|
|
6
|
+
|
|
7
|
+
[role_definition]
|
|
8
|
+
g = _, _
|
|
9
|
+
|
|
10
|
+
[policy_effect]
|
|
11
|
+
e = subjectPriority(p.eft) || deny
|
|
12
|
+
|
|
13
|
+
[matchers]
|
|
14
|
+
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
[request_definition]
|
|
2
|
+
r = sub, obj, dom, act
|
|
3
|
+
|
|
4
|
+
[policy_definition]
|
|
5
|
+
p = sub, obj, dom, act, eft
|
|
6
|
+
|
|
7
|
+
[role_definition]
|
|
8
|
+
g = _, _, _
|
|
9
|
+
|
|
10
|
+
[policy_effect]
|
|
11
|
+
e = subjectPriority(p.eft) || deny
|
|
12
|
+
|
|
13
|
+
[matchers]
|
|
14
|
+
m = g(r.sub, p.sub, r.dom) && r.dom == p.dom && r.obj == p.obj && r.act == p.act
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
p, root, data1, read, deny
|
|
2
|
+
p, admin, data1, read, deny
|
|
3
|
+
|
|
4
|
+
p, editor, data1, read, deny
|
|
5
|
+
p, subscriber, data1, deny
|
|
6
|
+
|
|
7
|
+
p, jane, data1, read, allow
|
|
8
|
+
p, alice, data1, read, allow
|
|
9
|
+
|
|
10
|
+
g, admin, root
|
|
11
|
+
|
|
12
|
+
g, editor, admin
|
|
13
|
+
g, subscriber, admin
|
|
14
|
+
|
|
15
|
+
g, jane, editor
|
|
16
|
+
g, alice, subscriber
|
package/lib/cjs/coreEnforcer.js
CHANGED
|
@@ -177,6 +177,7 @@ class CoreEnforcer {
|
|
|
177
177
|
this.model.clearPolicy();
|
|
178
178
|
await this.adapter.loadPolicy(this.model);
|
|
179
179
|
this.sortPolicies();
|
|
180
|
+
this.model.sortPoliciesBySubjectHierarchy();
|
|
180
181
|
if (this.autoBuildRoleLinks) {
|
|
181
182
|
await this.buildRoleLinksInternal();
|
|
182
183
|
}
|
|
@@ -189,6 +190,8 @@ class CoreEnforcer {
|
|
|
189
190
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
190
191
|
async loadFilteredPolicy(filter) {
|
|
191
192
|
this.model.clearPolicy();
|
|
193
|
+
this.sortPolicies();
|
|
194
|
+
this.model.sortPoliciesBySubjectHierarchy();
|
|
192
195
|
return this.loadIncrementalFilteredPolicy(filter);
|
|
193
196
|
}
|
|
194
197
|
/**
|
|
@@ -60,6 +60,7 @@ class DefaultEffectorStream {
|
|
|
60
60
|
}
|
|
61
61
|
break;
|
|
62
62
|
case "priority(p_eft) || deny" /* PRIORITY */:
|
|
63
|
+
case "subjectPriority(p_eft) || deny" /* SUBJECT_PRIORITY */:
|
|
63
64
|
if (eft !== effector_1.Effect.Indeterminate) {
|
|
64
65
|
this.res = eft === effector_1.Effect.Allow;
|
|
65
66
|
this.done = true;
|
package/lib/cjs/enforcer.d.ts
CHANGED
|
@@ -175,6 +175,10 @@ export declare class Enforcer extends ManagementEnforcer {
|
|
|
175
175
|
* But getImplicitPermissionsForUser("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]].
|
|
176
176
|
*/
|
|
177
177
|
getImplicitPermissionsForUser(user: string, ...domain: string[]): Promise<string[][]>;
|
|
178
|
+
/**
|
|
179
|
+
* getImplicitResourcesForUser returns all policies that user obtaining in domain.
|
|
180
|
+
*/
|
|
181
|
+
getImplicitResourcesForUser(user: string, ...domain: string[]): Promise<string[][]>;
|
|
178
182
|
/**
|
|
179
183
|
* getImplicitUsersForRole gets implicit users that a role has.
|
|
180
184
|
* Compared to getUsersForRole(), this function retrieves indirect users besides direct users.
|
package/lib/cjs/enforcer.js
CHANGED
|
@@ -326,6 +326,43 @@ class Enforcer extends managementEnforcer_1.ManagementEnforcer {
|
|
|
326
326
|
}
|
|
327
327
|
return res;
|
|
328
328
|
}
|
|
329
|
+
/**
|
|
330
|
+
* getImplicitResourcesForUser returns all policies that user obtaining in domain.
|
|
331
|
+
*/
|
|
332
|
+
async getImplicitResourcesForUser(user, ...domain) {
|
|
333
|
+
const permissions = await this.getImplicitPermissionsForUser(user, ...domain);
|
|
334
|
+
const res = [];
|
|
335
|
+
for (const permission of permissions) {
|
|
336
|
+
if (permission[0] === user) {
|
|
337
|
+
res.push(permission);
|
|
338
|
+
continue;
|
|
339
|
+
}
|
|
340
|
+
let resLocal = [[user]];
|
|
341
|
+
const tokensLength = permission.length;
|
|
342
|
+
const t = [];
|
|
343
|
+
for (const token of permission) {
|
|
344
|
+
if (token === permission[0]) {
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
const tokens = await this.getImplicitUsersForRole(token, ...domain);
|
|
348
|
+
tokens.push(token);
|
|
349
|
+
t.push(tokens);
|
|
350
|
+
}
|
|
351
|
+
for (let i = 0; i < tokensLength - 1; i++) {
|
|
352
|
+
const n = [];
|
|
353
|
+
for (const tokens of t[i]) {
|
|
354
|
+
for (const policy of resLocal) {
|
|
355
|
+
const t = [...policy];
|
|
356
|
+
t.push(tokens);
|
|
357
|
+
n.push(t);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
resLocal = n;
|
|
361
|
+
}
|
|
362
|
+
res.push(...resLocal);
|
|
363
|
+
}
|
|
364
|
+
return res;
|
|
365
|
+
}
|
|
329
366
|
/**
|
|
330
367
|
* getImplicitUsersForRole gets implicit users that a role has.
|
|
331
368
|
* Compared to getUsersForRole(), this function retrieves indirect users besides direct users.
|
|
@@ -367,6 +367,23 @@ export declare class ManagementEnforcer extends InternalEnforcer {
|
|
|
367
367
|
* @return succeeds or not.
|
|
368
368
|
*/
|
|
369
369
|
removeFilteredNamedGroupingPolicy(ptype: string, fieldIndex: number, ...fieldValues: string[]): Promise<boolean>;
|
|
370
|
+
/**
|
|
371
|
+
* UpdateGroupingPolicy updates an rule to the current named policy.
|
|
372
|
+
*
|
|
373
|
+
* @param oldRule the old rule.
|
|
374
|
+
* @param newRule the new rule.
|
|
375
|
+
* @return succeeds or not.
|
|
376
|
+
*/
|
|
377
|
+
updateGroupingPolicy(oldRule: string[], newRule: string[]): Promise<boolean>;
|
|
378
|
+
/**
|
|
379
|
+
* updateNamedGroupingPolicy updates an rule to the current named policy.
|
|
380
|
+
*
|
|
381
|
+
* @param ptype the policy type, can be "g", "g2", "g3", ..
|
|
382
|
+
* @param oldRule the old rule.
|
|
383
|
+
* @param newRule the new rule.
|
|
384
|
+
* @return succeeds or not.
|
|
385
|
+
*/
|
|
386
|
+
updateNamedGroupingPolicy(ptype: string, oldRule: string[], newRule: string[]): Promise<boolean>;
|
|
370
387
|
/**
|
|
371
388
|
* addFunction adds a customized function.
|
|
372
389
|
* @param name custom function name
|
|
@@ -466,6 +466,27 @@ class ManagementEnforcer extends internalEnforcer_1.InternalEnforcer {
|
|
|
466
466
|
async removeFilteredNamedGroupingPolicy(ptype, fieldIndex, ...fieldValues) {
|
|
467
467
|
return this.removeFilteredPolicyInternal('g', ptype, fieldIndex, fieldValues, true);
|
|
468
468
|
}
|
|
469
|
+
/**
|
|
470
|
+
* UpdateGroupingPolicy updates an rule to the current named policy.
|
|
471
|
+
*
|
|
472
|
+
* @param oldRule the old rule.
|
|
473
|
+
* @param newRule the new rule.
|
|
474
|
+
* @return succeeds or not.
|
|
475
|
+
*/
|
|
476
|
+
async updateGroupingPolicy(oldRule, newRule) {
|
|
477
|
+
return this.updateNamedGroupingPolicy('g', oldRule, newRule);
|
|
478
|
+
}
|
|
479
|
+
/**
|
|
480
|
+
* updateNamedGroupingPolicy updates an rule to the current named policy.
|
|
481
|
+
*
|
|
482
|
+
* @param ptype the policy type, can be "g", "g2", "g3", ..
|
|
483
|
+
* @param oldRule the old rule.
|
|
484
|
+
* @param newRule the new rule.
|
|
485
|
+
* @return succeeds or not.
|
|
486
|
+
*/
|
|
487
|
+
async updateNamedGroupingPolicy(ptype, oldRule, newRule) {
|
|
488
|
+
return this.updatePolicyInternal('g', ptype, oldRule, newRule, true);
|
|
489
|
+
}
|
|
469
490
|
/**
|
|
470
491
|
* addFunction adds a customized function.
|
|
471
492
|
* @param name custom function name
|
package/lib/cjs/model/model.d.ts
CHANGED
|
@@ -43,6 +43,19 @@ export declare class Model {
|
|
|
43
43
|
* return the field index in fieldMap, if no this field in fieldMap, add it.
|
|
44
44
|
*/
|
|
45
45
|
getFieldIndex(ptype: string, field: string): number;
|
|
46
|
+
/**
|
|
47
|
+
* sort policies by subject hieraichy
|
|
48
|
+
*/
|
|
49
|
+
sortPoliciesBySubjectHierarchy(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Calculate the priority of each policy store in Map<string, number>
|
|
52
|
+
*/
|
|
53
|
+
getSubjectHierarchyMap(groupPolicies: string[][]): Map<string, number>;
|
|
54
|
+
findHierarchy(policyMap: Map<string, string>, subjectHierarchyMap: Map<string, number>, set: Set<string>, child: string): void;
|
|
55
|
+
/**
|
|
56
|
+
* get full name with domain
|
|
57
|
+
*/
|
|
58
|
+
getNameWithDomain(domain: string, name: string): string;
|
|
46
59
|
}
|
|
47
60
|
/**
|
|
48
61
|
* newModel creates a model.
|
package/lib/cjs/model/model.js
CHANGED
|
@@ -38,6 +38,8 @@ const config_1 = require("../config");
|
|
|
38
38
|
const assertion_1 = require("./assertion");
|
|
39
39
|
const log_1 = require("../log");
|
|
40
40
|
const rbac_1 = require("../rbac");
|
|
41
|
+
const defaultDomain = '';
|
|
42
|
+
const defaultSeparator = '::';
|
|
41
43
|
exports.sectionNameMap = {
|
|
42
44
|
r: 'request_definition',
|
|
43
45
|
p: 'policy_definition',
|
|
@@ -445,6 +447,82 @@ class Model {
|
|
|
445
447
|
assertion.fieldIndexMap.set(field, index);
|
|
446
448
|
return index;
|
|
447
449
|
}
|
|
450
|
+
/**
|
|
451
|
+
* sort policies by subject hieraichy
|
|
452
|
+
*/
|
|
453
|
+
sortPoliciesBySubjectHierarchy() {
|
|
454
|
+
var _a, _b, _c;
|
|
455
|
+
if (((_b = (_a = this.model.get('e')) === null || _a === void 0 ? void 0 : _a.get('e')) === null || _b === void 0 ? void 0 : _b.value) !== "subjectPriority(p_eft) || deny" /* SUBJECT_PRIORITY */) {
|
|
456
|
+
return;
|
|
457
|
+
}
|
|
458
|
+
(_c = this.model.get('p')) === null || _c === void 0 ? void 0 : _c.forEach((assertion, ptype) => {
|
|
459
|
+
const domainIndex = this.getFieldIndex(ptype, "dom" /* Domain */);
|
|
460
|
+
const subIndex = this.getFieldIndex(ptype, "sub" /* Subject */);
|
|
461
|
+
// eslint-disable-next-line
|
|
462
|
+
const subjectHierarchyMap = this.getSubjectHierarchyMap(this.model.get('g').get('g').policy);
|
|
463
|
+
assertion.policy.sort((policyA, policyB) => {
|
|
464
|
+
const domainA = domainIndex === -1 ? defaultDomain : policyA[domainIndex];
|
|
465
|
+
const domainB = domainIndex === -1 ? defaultDomain : policyB[domainIndex];
|
|
466
|
+
// eslint-disable-next-line
|
|
467
|
+
const priorityA = subjectHierarchyMap.get(this.getNameWithDomain(domainA, policyA[subIndex]));
|
|
468
|
+
// eslint-disable-next-line
|
|
469
|
+
const priorityB = subjectHierarchyMap.get(this.getNameWithDomain(domainB, policyB[subIndex]));
|
|
470
|
+
return priorityB - priorityA;
|
|
471
|
+
});
|
|
472
|
+
});
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Calculate the priority of each policy store in Map<string, number>
|
|
476
|
+
*/
|
|
477
|
+
getSubjectHierarchyMap(groupPolicies) {
|
|
478
|
+
const subjectHierarchyMap = new Map();
|
|
479
|
+
if (!groupPolicies) {
|
|
480
|
+
return subjectHierarchyMap;
|
|
481
|
+
}
|
|
482
|
+
const policyMap = new Map();
|
|
483
|
+
let domain = defaultDomain;
|
|
484
|
+
groupPolicies.forEach((policy) => {
|
|
485
|
+
if (policy.length !== 2)
|
|
486
|
+
domain = policy[this.getFieldIndex('p', "dom" /* Domain */)];
|
|
487
|
+
const child = this.getNameWithDomain(domain, policy[this.getFieldIndex('p', "sub" /* Subject */)]);
|
|
488
|
+
const parent = this.getNameWithDomain(domain, policy[this.getFieldIndex('p', "obj" /* Object */)]);
|
|
489
|
+
policyMap.set(child, parent);
|
|
490
|
+
if (!subjectHierarchyMap.has(child)) {
|
|
491
|
+
subjectHierarchyMap.set(child, 0);
|
|
492
|
+
}
|
|
493
|
+
if (!subjectHierarchyMap.has(parent)) {
|
|
494
|
+
subjectHierarchyMap.set(parent, 0);
|
|
495
|
+
}
|
|
496
|
+
subjectHierarchyMap.set(child, 1);
|
|
497
|
+
});
|
|
498
|
+
const set = new Set();
|
|
499
|
+
subjectHierarchyMap.forEach((_, key) => {
|
|
500
|
+
if (subjectHierarchyMap.get(key) !== 0)
|
|
501
|
+
set.add(key);
|
|
502
|
+
});
|
|
503
|
+
while (set.size !== 0) {
|
|
504
|
+
for (const child of set.values()) {
|
|
505
|
+
this.findHierarchy(policyMap, subjectHierarchyMap, set, child);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
return subjectHierarchyMap;
|
|
509
|
+
}
|
|
510
|
+
findHierarchy(policyMap, subjectHierarchyMap, set, child) {
|
|
511
|
+
set.delete(child);
|
|
512
|
+
// eslint-disable-next-line
|
|
513
|
+
const parent = policyMap.get(child);
|
|
514
|
+
if (set.has(parent)) {
|
|
515
|
+
this.findHierarchy(policyMap, subjectHierarchyMap, set, parent);
|
|
516
|
+
}
|
|
517
|
+
// eslint-disable-next-line
|
|
518
|
+
subjectHierarchyMap.set(child, subjectHierarchyMap.get(parent) + 10);
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* get full name with domain
|
|
522
|
+
*/
|
|
523
|
+
getNameWithDomain(domain, name) {
|
|
524
|
+
return domain + defaultSeparator + name;
|
|
525
|
+
}
|
|
448
526
|
}
|
|
449
527
|
exports.Model = Model;
|
|
450
528
|
/**
|
|
@@ -319,6 +319,23 @@ export declare class SyncedEnforcer extends Enforcer {
|
|
|
319
319
|
* @return succeeds or not.
|
|
320
320
|
*/
|
|
321
321
|
removeFilteredNamedGroupingPolicy(ptype: string, fieldIndex: number, ...fieldValues: string[]): Promise<boolean>;
|
|
322
|
+
/**
|
|
323
|
+
* UpdateGroupingPolicy updates an rule to the current named policy.
|
|
324
|
+
*
|
|
325
|
+
* @param oldRule the old rule.
|
|
326
|
+
* @param newRule the new rule.
|
|
327
|
+
* @return succeeds or not.
|
|
328
|
+
*/
|
|
329
|
+
updateGroupingPolicy(oldRule: string[], newRule: string[]): Promise<boolean>;
|
|
330
|
+
/**
|
|
331
|
+
* updateNamedGroupingPolicy updates an rule to the current named policy.
|
|
332
|
+
*
|
|
333
|
+
* @param ptype the policy type, can be "g", "g2", "g3", ..
|
|
334
|
+
* @param oldRule the old rule.
|
|
335
|
+
* @param newRule the new rule.
|
|
336
|
+
* @return succeeds or not.
|
|
337
|
+
*/
|
|
338
|
+
updateNamedGroupingPolicy(ptype: string, oldRule: string[], newRule: string[]): Promise<boolean>;
|
|
322
339
|
/**
|
|
323
340
|
* add matching function to RoleManager by ptype
|
|
324
341
|
* @param ptype g
|
|
@@ -443,6 +443,27 @@ class SyncedEnforcer extends enforcer_1.Enforcer {
|
|
|
443
443
|
await this.lock.acquireAsync();
|
|
444
444
|
return super.removeFilteredNamedGroupingPolicy(ptype, fieldIndex, ...fieldValues).finally(() => this.lock.release());
|
|
445
445
|
}
|
|
446
|
+
/**
|
|
447
|
+
* UpdateGroupingPolicy updates an rule to the current named policy.
|
|
448
|
+
*
|
|
449
|
+
* @param oldRule the old rule.
|
|
450
|
+
* @param newRule the new rule.
|
|
451
|
+
* @return succeeds or not.
|
|
452
|
+
*/
|
|
453
|
+
async updateGroupingPolicy(oldRule, newRule) {
|
|
454
|
+
return super.updateGroupingPolicy(oldRule, newRule);
|
|
455
|
+
}
|
|
456
|
+
/**
|
|
457
|
+
* updateNamedGroupingPolicy updates an rule to the current named policy.
|
|
458
|
+
*
|
|
459
|
+
* @param ptype the policy type, can be "g", "g2", "g3", ..
|
|
460
|
+
* @param oldRule the old rule.
|
|
461
|
+
* @param newRule the new rule.
|
|
462
|
+
* @return succeeds or not.
|
|
463
|
+
*/
|
|
464
|
+
async updateNamedGroupingPolicy(ptype, oldRule, newRule) {
|
|
465
|
+
return super.updateNamedGroupingPolicy(ptype, oldRule, newRule);
|
|
466
|
+
}
|
|
446
467
|
/**
|
|
447
468
|
* add matching function to RoleManager by ptype
|
|
448
469
|
* @param ptype g
|
package/lib/esm/coreEnforcer.js
CHANGED
|
@@ -174,6 +174,7 @@ export class CoreEnforcer {
|
|
|
174
174
|
this.model.clearPolicy();
|
|
175
175
|
await this.adapter.loadPolicy(this.model);
|
|
176
176
|
this.sortPolicies();
|
|
177
|
+
this.model.sortPoliciesBySubjectHierarchy();
|
|
177
178
|
if (this.autoBuildRoleLinks) {
|
|
178
179
|
await this.buildRoleLinksInternal();
|
|
179
180
|
}
|
|
@@ -186,6 +187,8 @@ export class CoreEnforcer {
|
|
|
186
187
|
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
187
188
|
async loadFilteredPolicy(filter) {
|
|
188
189
|
this.model.clearPolicy();
|
|
190
|
+
this.sortPolicies();
|
|
191
|
+
this.model.sortPoliciesBySubjectHierarchy();
|
|
189
192
|
return this.loadIncrementalFilteredPolicy(filter);
|
|
190
193
|
}
|
|
191
194
|
/**
|
|
@@ -57,6 +57,7 @@ export class DefaultEffectorStream {
|
|
|
57
57
|
}
|
|
58
58
|
break;
|
|
59
59
|
case "priority(p_eft) || deny" /* PRIORITY */:
|
|
60
|
+
case "subjectPriority(p_eft) || deny" /* SUBJECT_PRIORITY */:
|
|
60
61
|
if (eft !== Effect.Indeterminate) {
|
|
61
62
|
this.res = eft === Effect.Allow;
|
|
62
63
|
this.done = true;
|
package/lib/esm/enforcer.d.ts
CHANGED
|
@@ -175,6 +175,10 @@ export declare class Enforcer extends ManagementEnforcer {
|
|
|
175
175
|
* But getImplicitPermissionsForUser("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]].
|
|
176
176
|
*/
|
|
177
177
|
getImplicitPermissionsForUser(user: string, ...domain: string[]): Promise<string[][]>;
|
|
178
|
+
/**
|
|
179
|
+
* getImplicitResourcesForUser returns all policies that user obtaining in domain.
|
|
180
|
+
*/
|
|
181
|
+
getImplicitResourcesForUser(user: string, ...domain: string[]): Promise<string[][]>;
|
|
178
182
|
/**
|
|
179
183
|
* getImplicitUsersForRole gets implicit users that a role has.
|
|
180
184
|
* Compared to getUsersForRole(), this function retrieves indirect users besides direct users.
|
package/lib/esm/enforcer.js
CHANGED
|
@@ -323,6 +323,43 @@ export class Enforcer extends ManagementEnforcer {
|
|
|
323
323
|
}
|
|
324
324
|
return res;
|
|
325
325
|
}
|
|
326
|
+
/**
|
|
327
|
+
* getImplicitResourcesForUser returns all policies that user obtaining in domain.
|
|
328
|
+
*/
|
|
329
|
+
async getImplicitResourcesForUser(user, ...domain) {
|
|
330
|
+
const permissions = await this.getImplicitPermissionsForUser(user, ...domain);
|
|
331
|
+
const res = [];
|
|
332
|
+
for (const permission of permissions) {
|
|
333
|
+
if (permission[0] === user) {
|
|
334
|
+
res.push(permission);
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
let resLocal = [[user]];
|
|
338
|
+
const tokensLength = permission.length;
|
|
339
|
+
const t = [];
|
|
340
|
+
for (const token of permission) {
|
|
341
|
+
if (token === permission[0]) {
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
const tokens = await this.getImplicitUsersForRole(token, ...domain);
|
|
345
|
+
tokens.push(token);
|
|
346
|
+
t.push(tokens);
|
|
347
|
+
}
|
|
348
|
+
for (let i = 0; i < tokensLength - 1; i++) {
|
|
349
|
+
const n = [];
|
|
350
|
+
for (const tokens of t[i]) {
|
|
351
|
+
for (const policy of resLocal) {
|
|
352
|
+
const t = [...policy];
|
|
353
|
+
t.push(tokens);
|
|
354
|
+
n.push(t);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
resLocal = n;
|
|
358
|
+
}
|
|
359
|
+
res.push(...resLocal);
|
|
360
|
+
}
|
|
361
|
+
return res;
|
|
362
|
+
}
|
|
326
363
|
/**
|
|
327
364
|
* getImplicitUsersForRole gets implicit users that a role has.
|
|
328
365
|
* Compared to getUsersForRole(), this function retrieves indirect users besides direct users.
|
|
@@ -367,6 +367,23 @@ export declare class ManagementEnforcer extends InternalEnforcer {
|
|
|
367
367
|
* @return succeeds or not.
|
|
368
368
|
*/
|
|
369
369
|
removeFilteredNamedGroupingPolicy(ptype: string, fieldIndex: number, ...fieldValues: string[]): Promise<boolean>;
|
|
370
|
+
/**
|
|
371
|
+
* UpdateGroupingPolicy updates an rule to the current named policy.
|
|
372
|
+
*
|
|
373
|
+
* @param oldRule the old rule.
|
|
374
|
+
* @param newRule the new rule.
|
|
375
|
+
* @return succeeds or not.
|
|
376
|
+
*/
|
|
377
|
+
updateGroupingPolicy(oldRule: string[], newRule: string[]): Promise<boolean>;
|
|
378
|
+
/**
|
|
379
|
+
* updateNamedGroupingPolicy updates an rule to the current named policy.
|
|
380
|
+
*
|
|
381
|
+
* @param ptype the policy type, can be "g", "g2", "g3", ..
|
|
382
|
+
* @param oldRule the old rule.
|
|
383
|
+
* @param newRule the new rule.
|
|
384
|
+
* @return succeeds or not.
|
|
385
|
+
*/
|
|
386
|
+
updateNamedGroupingPolicy(ptype: string, oldRule: string[], newRule: string[]): Promise<boolean>;
|
|
370
387
|
/**
|
|
371
388
|
* addFunction adds a customized function.
|
|
372
389
|
* @param name custom function name
|
|
@@ -463,6 +463,27 @@ export class ManagementEnforcer extends InternalEnforcer {
|
|
|
463
463
|
async removeFilteredNamedGroupingPolicy(ptype, fieldIndex, ...fieldValues) {
|
|
464
464
|
return this.removeFilteredPolicyInternal('g', ptype, fieldIndex, fieldValues, true);
|
|
465
465
|
}
|
|
466
|
+
/**
|
|
467
|
+
* UpdateGroupingPolicy updates an rule to the current named policy.
|
|
468
|
+
*
|
|
469
|
+
* @param oldRule the old rule.
|
|
470
|
+
* @param newRule the new rule.
|
|
471
|
+
* @return succeeds or not.
|
|
472
|
+
*/
|
|
473
|
+
async updateGroupingPolicy(oldRule, newRule) {
|
|
474
|
+
return this.updateNamedGroupingPolicy('g', oldRule, newRule);
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* updateNamedGroupingPolicy updates an rule to the current named policy.
|
|
478
|
+
*
|
|
479
|
+
* @param ptype the policy type, can be "g", "g2", "g3", ..
|
|
480
|
+
* @param oldRule the old rule.
|
|
481
|
+
* @param newRule the new rule.
|
|
482
|
+
* @return succeeds or not.
|
|
483
|
+
*/
|
|
484
|
+
async updateNamedGroupingPolicy(ptype, oldRule, newRule) {
|
|
485
|
+
return this.updatePolicyInternal('g', ptype, oldRule, newRule, true);
|
|
486
|
+
}
|
|
466
487
|
/**
|
|
467
488
|
* addFunction adds a customized function.
|
|
468
489
|
* @param name custom function name
|
package/lib/esm/model/model.d.ts
CHANGED
|
@@ -43,6 +43,19 @@ export declare class Model {
|
|
|
43
43
|
* return the field index in fieldMap, if no this field in fieldMap, add it.
|
|
44
44
|
*/
|
|
45
45
|
getFieldIndex(ptype: string, field: string): number;
|
|
46
|
+
/**
|
|
47
|
+
* sort policies by subject hieraichy
|
|
48
|
+
*/
|
|
49
|
+
sortPoliciesBySubjectHierarchy(): void;
|
|
50
|
+
/**
|
|
51
|
+
* Calculate the priority of each policy store in Map<string, number>
|
|
52
|
+
*/
|
|
53
|
+
getSubjectHierarchyMap(groupPolicies: string[][]): Map<string, number>;
|
|
54
|
+
findHierarchy(policyMap: Map<string, string>, subjectHierarchyMap: Map<string, number>, set: Set<string>, child: string): void;
|
|
55
|
+
/**
|
|
56
|
+
* get full name with domain
|
|
57
|
+
*/
|
|
58
|
+
getNameWithDomain(domain: string, name: string): string;
|
|
46
59
|
}
|
|
47
60
|
/**
|
|
48
61
|
* newModel creates a model.
|
package/lib/esm/model/model.js
CHANGED
|
@@ -16,6 +16,8 @@ import { Config } from '../config';
|
|
|
16
16
|
import { Assertion } from './assertion';
|
|
17
17
|
import { getLogger, logPrint } from '../log';
|
|
18
18
|
import { DefaultRoleManager } from '../rbac';
|
|
19
|
+
const defaultDomain = '';
|
|
20
|
+
const defaultSeparator = '::';
|
|
19
21
|
export const sectionNameMap = {
|
|
20
22
|
r: 'request_definition',
|
|
21
23
|
p: 'policy_definition',
|
|
@@ -423,6 +425,82 @@ export class Model {
|
|
|
423
425
|
assertion.fieldIndexMap.set(field, index);
|
|
424
426
|
return index;
|
|
425
427
|
}
|
|
428
|
+
/**
|
|
429
|
+
* sort policies by subject hieraichy
|
|
430
|
+
*/
|
|
431
|
+
sortPoliciesBySubjectHierarchy() {
|
|
432
|
+
var _a, _b, _c;
|
|
433
|
+
if (((_b = (_a = this.model.get('e')) === null || _a === void 0 ? void 0 : _a.get('e')) === null || _b === void 0 ? void 0 : _b.value) !== "subjectPriority(p_eft) || deny" /* SUBJECT_PRIORITY */) {
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
436
|
+
(_c = this.model.get('p')) === null || _c === void 0 ? void 0 : _c.forEach((assertion, ptype) => {
|
|
437
|
+
const domainIndex = this.getFieldIndex(ptype, "dom" /* Domain */);
|
|
438
|
+
const subIndex = this.getFieldIndex(ptype, "sub" /* Subject */);
|
|
439
|
+
// eslint-disable-next-line
|
|
440
|
+
const subjectHierarchyMap = this.getSubjectHierarchyMap(this.model.get('g').get('g').policy);
|
|
441
|
+
assertion.policy.sort((policyA, policyB) => {
|
|
442
|
+
const domainA = domainIndex === -1 ? defaultDomain : policyA[domainIndex];
|
|
443
|
+
const domainB = domainIndex === -1 ? defaultDomain : policyB[domainIndex];
|
|
444
|
+
// eslint-disable-next-line
|
|
445
|
+
const priorityA = subjectHierarchyMap.get(this.getNameWithDomain(domainA, policyA[subIndex]));
|
|
446
|
+
// eslint-disable-next-line
|
|
447
|
+
const priorityB = subjectHierarchyMap.get(this.getNameWithDomain(domainB, policyB[subIndex]));
|
|
448
|
+
return priorityB - priorityA;
|
|
449
|
+
});
|
|
450
|
+
});
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* Calculate the priority of each policy store in Map<string, number>
|
|
454
|
+
*/
|
|
455
|
+
getSubjectHierarchyMap(groupPolicies) {
|
|
456
|
+
const subjectHierarchyMap = new Map();
|
|
457
|
+
if (!groupPolicies) {
|
|
458
|
+
return subjectHierarchyMap;
|
|
459
|
+
}
|
|
460
|
+
const policyMap = new Map();
|
|
461
|
+
let domain = defaultDomain;
|
|
462
|
+
groupPolicies.forEach((policy) => {
|
|
463
|
+
if (policy.length !== 2)
|
|
464
|
+
domain = policy[this.getFieldIndex('p', "dom" /* Domain */)];
|
|
465
|
+
const child = this.getNameWithDomain(domain, policy[this.getFieldIndex('p', "sub" /* Subject */)]);
|
|
466
|
+
const parent = this.getNameWithDomain(domain, policy[this.getFieldIndex('p', "obj" /* Object */)]);
|
|
467
|
+
policyMap.set(child, parent);
|
|
468
|
+
if (!subjectHierarchyMap.has(child)) {
|
|
469
|
+
subjectHierarchyMap.set(child, 0);
|
|
470
|
+
}
|
|
471
|
+
if (!subjectHierarchyMap.has(parent)) {
|
|
472
|
+
subjectHierarchyMap.set(parent, 0);
|
|
473
|
+
}
|
|
474
|
+
subjectHierarchyMap.set(child, 1);
|
|
475
|
+
});
|
|
476
|
+
const set = new Set();
|
|
477
|
+
subjectHierarchyMap.forEach((_, key) => {
|
|
478
|
+
if (subjectHierarchyMap.get(key) !== 0)
|
|
479
|
+
set.add(key);
|
|
480
|
+
});
|
|
481
|
+
while (set.size !== 0) {
|
|
482
|
+
for (const child of set.values()) {
|
|
483
|
+
this.findHierarchy(policyMap, subjectHierarchyMap, set, child);
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
return subjectHierarchyMap;
|
|
487
|
+
}
|
|
488
|
+
findHierarchy(policyMap, subjectHierarchyMap, set, child) {
|
|
489
|
+
set.delete(child);
|
|
490
|
+
// eslint-disable-next-line
|
|
491
|
+
const parent = policyMap.get(child);
|
|
492
|
+
if (set.has(parent)) {
|
|
493
|
+
this.findHierarchy(policyMap, subjectHierarchyMap, set, parent);
|
|
494
|
+
}
|
|
495
|
+
// eslint-disable-next-line
|
|
496
|
+
subjectHierarchyMap.set(child, subjectHierarchyMap.get(parent) + 10);
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* get full name with domain
|
|
500
|
+
*/
|
|
501
|
+
getNameWithDomain(domain, name) {
|
|
502
|
+
return domain + defaultSeparator + name;
|
|
503
|
+
}
|
|
426
504
|
}
|
|
427
505
|
/**
|
|
428
506
|
* newModel creates a model.
|
|
@@ -319,6 +319,23 @@ export declare class SyncedEnforcer extends Enforcer {
|
|
|
319
319
|
* @return succeeds or not.
|
|
320
320
|
*/
|
|
321
321
|
removeFilteredNamedGroupingPolicy(ptype: string, fieldIndex: number, ...fieldValues: string[]): Promise<boolean>;
|
|
322
|
+
/**
|
|
323
|
+
* UpdateGroupingPolicy updates an rule to the current named policy.
|
|
324
|
+
*
|
|
325
|
+
* @param oldRule the old rule.
|
|
326
|
+
* @param newRule the new rule.
|
|
327
|
+
* @return succeeds or not.
|
|
328
|
+
*/
|
|
329
|
+
updateGroupingPolicy(oldRule: string[], newRule: string[]): Promise<boolean>;
|
|
330
|
+
/**
|
|
331
|
+
* updateNamedGroupingPolicy updates an rule to the current named policy.
|
|
332
|
+
*
|
|
333
|
+
* @param ptype the policy type, can be "g", "g2", "g3", ..
|
|
334
|
+
* @param oldRule the old rule.
|
|
335
|
+
* @param newRule the new rule.
|
|
336
|
+
* @return succeeds or not.
|
|
337
|
+
*/
|
|
338
|
+
updateNamedGroupingPolicy(ptype: string, oldRule: string[], newRule: string[]): Promise<boolean>;
|
|
322
339
|
/**
|
|
323
340
|
* add matching function to RoleManager by ptype
|
|
324
341
|
* @param ptype g
|
|
@@ -437,6 +437,27 @@ export class SyncedEnforcer extends Enforcer {
|
|
|
437
437
|
await this.lock.acquireAsync();
|
|
438
438
|
return super.removeFilteredNamedGroupingPolicy(ptype, fieldIndex, ...fieldValues).finally(() => this.lock.release());
|
|
439
439
|
}
|
|
440
|
+
/**
|
|
441
|
+
* UpdateGroupingPolicy updates an rule to the current named policy.
|
|
442
|
+
*
|
|
443
|
+
* @param oldRule the old rule.
|
|
444
|
+
* @param newRule the new rule.
|
|
445
|
+
* @return succeeds or not.
|
|
446
|
+
*/
|
|
447
|
+
async updateGroupingPolicy(oldRule, newRule) {
|
|
448
|
+
return super.updateGroupingPolicy(oldRule, newRule);
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* updateNamedGroupingPolicy updates an rule to the current named policy.
|
|
452
|
+
*
|
|
453
|
+
* @param ptype the policy type, can be "g", "g2", "g3", ..
|
|
454
|
+
* @param oldRule the old rule.
|
|
455
|
+
* @param newRule the new rule.
|
|
456
|
+
* @return succeeds or not.
|
|
457
|
+
*/
|
|
458
|
+
async updateNamedGroupingPolicy(ptype, oldRule, newRule) {
|
|
459
|
+
return super.updateNamedGroupingPolicy(ptype, oldRule, newRule);
|
|
460
|
+
}
|
|
440
461
|
/**
|
|
441
462
|
* add matching function to RoleManager by ptype
|
|
442
463
|
* @param ptype g
|
package/package.json
CHANGED