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 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
@@ -0,0 +1,7 @@
1
+ p, admin, data1, domain1, write, deny
2
+ p, alice, data1, domain1, write, allow
3
+ p, admin, data2, domain2, write, deny
4
+ p, bob, data2, domain2, write, allow
5
+
6
+ g, alice, admin, domain1
7
+ g, bob, admin, domain2
@@ -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;
@@ -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.
@@ -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
@@ -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.
@@ -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
@@ -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;
@@ -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.
@@ -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
@@ -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.
@@ -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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "casbin",
3
- "version": "5.21.0",
3
+ "version": "5.23.0",
4
4
  "description": "An authorization library that supports access control models like ACL, RBAC, ABAC in Node.JS",
5
5
  "main": "lib/cjs/index.js",
6
6
  "typings": "lib/cjs/index.d.ts",