casbin 5.26.2 → 5.27.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/CHANGELOG.md CHANGED
@@ -1,3 +1,17 @@
1
+ ## [5.27.1](https://github.com/casbin/node-casbin/compare/v5.27.0...v5.27.1) (2023-09-19)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * KeyMatch5 does not match the expected result ([#458](https://github.com/casbin/node-casbin/issues/458)) ([0df458d](https://github.com/casbin/node-casbin/commit/0df458dde1f7a061167b978e16e712d208944f39))
7
+
8
+ # [5.27.0](https://github.com/casbin/node-casbin/compare/v5.26.2...v5.27.0) (2023-08-30)
9
+
10
+
11
+ ### Features
12
+
13
+ * add `enforceWithMatcher` & `enforceExWithMatcher` ([#453](https://github.com/casbin/node-casbin/issues/453)) ([a85192f](https://github.com/casbin/node-casbin/commit/a85192f382fc164107d3117b4490cf8dd072c0e5))
14
+
1
15
  ## [5.26.2](https://github.com/casbin/node-casbin/compare/v5.26.1...v5.26.2) (2023-07-29)
2
16
 
3
17
 
@@ -227,6 +227,17 @@ export declare class CoreEnforcer {
227
227
  * @return whether to allow the request.
228
228
  */
229
229
  enforce(...rvals: any[]): Promise<boolean>;
230
+ /**
231
+ * enforceWithMatcher decides whether a "subject" can access a "object" with
232
+ * the operation "action" but with the matcher passed,
233
+ * input parameters are usually: (matcher, sub, obj, act).
234
+ *
235
+ * @param matcher matcher string.
236
+ * @param rvals the request needs to be mediated, usually an array
237
+ * of strings, can be class instances if ABAC is used.
238
+ * @return whether to allow the request.
239
+ */
240
+ enforceWithMatcher(matcher: string, ...rvals: any[]): Promise<boolean>;
230
241
  /**
231
242
  * enforce decides whether a "subject" can access a "object" with
232
243
  * the operation "action", input parameters are usually: (sub, obj, act).
@@ -236,6 +247,17 @@ export declare class CoreEnforcer {
236
247
  * @return whether to allow the request and the reason rule.
237
248
  */
238
249
  enforceEx(...rvals: any[]): Promise<[boolean, string[]]>;
250
+ /**
251
+ * enforceExWithMatcher decides whether a "subject" can access a "object" with
252
+ * the operation "action" but with the matcher passed,
253
+ * input parameters are usually: (matcher, sub, obj, act).
254
+ *
255
+ * @param matcher matcher string.
256
+ * @param rvals the request needs to be mediated, usually an array
257
+ * of strings, can be class instances if ABAC is used.
258
+ * @return whether to allow the request and the reason rule.
259
+ */
260
+ enforceExWithMatcher(matcher: string, ...rvals: any[]): Promise<[boolean, string[]]>;
239
261
  /**
240
262
  * batchEnforce enforces each request and returns result in a bool array.
241
263
  * @param rvals the request need to be mediated, usually an array
@@ -349,7 +349,7 @@ class CoreEnforcer {
349
349
  await this.model.buildRoleLinks(this.rmMap);
350
350
  }
351
351
  }
352
- *privateEnforce(asyncCompile = true, explain = false, enforceContext = new enforceContext_1.EnforceContext('r', 'p', 'e', 'm'), ...rvals) {
352
+ *privateEnforce(asyncCompile = true, explain = false, matcher, enforceContext = new enforceContext_1.EnforceContext('r', 'p', 'e', 'm'), ...rvals) {
353
353
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
354
354
  if (!this.enabled) {
355
355
  return true;
@@ -364,7 +364,13 @@ class CoreEnforcer {
364
364
  const rm = value.rm;
365
365
  functions[key] = asyncCompile ? util_1.generateGFunction(rm) : util_1.generateSyncedGFunction(rm);
366
366
  });
367
- const expString = (_b = (_a = this.model.model.get('m')) === null || _a === void 0 ? void 0 : _a.get(enforceContext.mType)) === null || _b === void 0 ? void 0 : _b.value;
367
+ let expString;
368
+ if (!matcher) {
369
+ expString = (_b = (_a = this.model.model.get('m')) === null || _a === void 0 ? void 0 : _a.get(enforceContext.mType)) === null || _b === void 0 ? void 0 : _b.value;
370
+ }
371
+ else {
372
+ expString = util_1.removeComments(util_1.escapeAssertion(matcher));
373
+ }
368
374
  if (!expString) {
369
375
  throw new Error('Unable to find matchers in model');
370
376
  }
@@ -513,9 +519,9 @@ class CoreEnforcer {
513
519
  enforceSync(...rvals) {
514
520
  if (rvals[0] instanceof enforceContext_1.EnforceContext) {
515
521
  const enforceContext = rvals.shift();
516
- return util_1.generatorRunSync(this.privateEnforce(false, false, enforceContext, ...rvals));
522
+ return util_1.generatorRunSync(this.privateEnforce(false, false, '', enforceContext, ...rvals));
517
523
  }
518
- return util_1.generatorRunSync(this.privateEnforce(false, false, this.defaultEnforceContext, ...rvals));
524
+ return util_1.generatorRunSync(this.privateEnforce(false, false, '', this.defaultEnforceContext, ...rvals));
519
525
  }
520
526
  /**
521
527
  * If the matchers does not contain an asynchronous method, call it faster.
@@ -530,9 +536,9 @@ class CoreEnforcer {
530
536
  enforceExSync(...rvals) {
531
537
  if (rvals[0] instanceof enforceContext_1.EnforceContext) {
532
538
  const enforceContext = rvals.shift();
533
- return util_1.generatorRunSync(this.privateEnforce(false, true, enforceContext, ...rvals));
539
+ return util_1.generatorRunSync(this.privateEnforce(false, true, '', enforceContext, ...rvals));
534
540
  }
535
- return util_1.generatorRunSync(this.privateEnforce(false, true, this.defaultEnforceContext, ...rvals));
541
+ return util_1.generatorRunSync(this.privateEnforce(false, true, '', this.defaultEnforceContext, ...rvals));
536
542
  }
537
543
  /**
538
544
  * Same as enforceSync. To be removed.
@@ -551,9 +557,26 @@ class CoreEnforcer {
551
557
  async enforce(...rvals) {
552
558
  if (rvals[0] instanceof enforceContext_1.EnforceContext) {
553
559
  const enforceContext = rvals.shift();
554
- return util_1.generatorRunAsync(this.privateEnforce(true, false, enforceContext, ...rvals));
560
+ return util_1.generatorRunAsync(this.privateEnforce(true, false, '', enforceContext, ...rvals));
555
561
  }
556
- return util_1.generatorRunAsync(this.privateEnforce(true, false, this.defaultEnforceContext, ...rvals));
562
+ return util_1.generatorRunAsync(this.privateEnforce(true, false, '', this.defaultEnforceContext, ...rvals));
563
+ }
564
+ /**
565
+ * enforceWithMatcher decides whether a "subject" can access a "object" with
566
+ * the operation "action" but with the matcher passed,
567
+ * input parameters are usually: (matcher, sub, obj, act).
568
+ *
569
+ * @param matcher matcher string.
570
+ * @param rvals the request needs to be mediated, usually an array
571
+ * of strings, can be class instances if ABAC is used.
572
+ * @return whether to allow the request.
573
+ */
574
+ async enforceWithMatcher(matcher, ...rvals) {
575
+ if (rvals[0] instanceof enforceContext_1.EnforceContext) {
576
+ const enforceContext = rvals.shift();
577
+ return util_1.generatorRunAsync(this.privateEnforce(true, false, matcher, enforceContext, ...rvals));
578
+ }
579
+ return util_1.generatorRunAsync(this.privateEnforce(true, false, matcher, this.defaultEnforceContext, ...rvals));
557
580
  }
558
581
  /**
559
582
  * enforce decides whether a "subject" can access a "object" with
@@ -566,9 +589,26 @@ class CoreEnforcer {
566
589
  async enforceEx(...rvals) {
567
590
  if (rvals[0] instanceof enforceContext_1.EnforceContext) {
568
591
  const enforceContext = rvals.shift();
569
- return util_1.generatorRunAsync(this.privateEnforce(true, true, enforceContext, ...rvals));
592
+ return util_1.generatorRunAsync(this.privateEnforce(true, true, '', enforceContext, ...rvals));
593
+ }
594
+ return util_1.generatorRunAsync(this.privateEnforce(true, true, '', this.defaultEnforceContext, ...rvals));
595
+ }
596
+ /**
597
+ * enforceExWithMatcher decides whether a "subject" can access a "object" with
598
+ * the operation "action" but with the matcher passed,
599
+ * input parameters are usually: (matcher, sub, obj, act).
600
+ *
601
+ * @param matcher matcher string.
602
+ * @param rvals the request needs to be mediated, usually an array
603
+ * of strings, can be class instances if ABAC is used.
604
+ * @return whether to allow the request and the reason rule.
605
+ */
606
+ async enforceExWithMatcher(matcher, ...rvals) {
607
+ if (rvals[0] instanceof enforceContext_1.EnforceContext) {
608
+ const enforceContext = rvals.shift();
609
+ return util_1.generatorRunAsync(this.privateEnforce(true, true, matcher, enforceContext, ...rvals));
570
610
  }
571
- return util_1.generatorRunAsync(this.privateEnforce(true, true, this.defaultEnforceContext, ...rvals));
611
+ return util_1.generatorRunAsync(this.privateEnforce(true, true, matcher, this.defaultEnforceContext, ...rvals));
572
612
  }
573
613
  /**
574
614
  * batchEnforce enforces each request and returns result in a bool array.
@@ -208,10 +208,18 @@ exports.keyMatch4Func = keyMatch4Func;
208
208
  // For example, "/foo/bar?status=1&type=2" matches "/foo/bar"
209
209
  function KeyMatch5(key1, key2) {
210
210
  const i = key1.indexOf('?');
211
- if (i === -1) {
212
- return key1 === key2;
211
+ if (i !== -1) {
212
+ key1 = key1.slice(0, i);
213
+ }
214
+ key2 = key2.replace(/\/\*/g, '/.*');
215
+ const regexp = new RegExp(/(.*){[^/]+}(.*)/g);
216
+ for (;;) {
217
+ if (!key2.includes('/{')) {
218
+ break;
219
+ }
220
+ key2 = key2.replace(regexp, '$1[^/]+$2');
213
221
  }
214
- return key1.slice(0, i) === key2;
222
+ return regexMatch(key1, '^' + key2 + '$');
215
223
  }
216
224
  // keyMatch5Func is the wrapper for KeyMatch5.
217
225
  function keyMatch5Func(...args) {
@@ -227,6 +227,17 @@ export declare class CoreEnforcer {
227
227
  * @return whether to allow the request.
228
228
  */
229
229
  enforce(...rvals: any[]): Promise<boolean>;
230
+ /**
231
+ * enforceWithMatcher decides whether a "subject" can access a "object" with
232
+ * the operation "action" but with the matcher passed,
233
+ * input parameters are usually: (matcher, sub, obj, act).
234
+ *
235
+ * @param matcher matcher string.
236
+ * @param rvals the request needs to be mediated, usually an array
237
+ * of strings, can be class instances if ABAC is used.
238
+ * @return whether to allow the request.
239
+ */
240
+ enforceWithMatcher(matcher: string, ...rvals: any[]): Promise<boolean>;
230
241
  /**
231
242
  * enforce decides whether a "subject" can access a "object" with
232
243
  * the operation "action", input parameters are usually: (sub, obj, act).
@@ -236,6 +247,17 @@ export declare class CoreEnforcer {
236
247
  * @return whether to allow the request and the reason rule.
237
248
  */
238
249
  enforceEx(...rvals: any[]): Promise<[boolean, string[]]>;
250
+ /**
251
+ * enforceExWithMatcher decides whether a "subject" can access a "object" with
252
+ * the operation "action" but with the matcher passed,
253
+ * input parameters are usually: (matcher, sub, obj, act).
254
+ *
255
+ * @param matcher matcher string.
256
+ * @param rvals the request needs to be mediated, usually an array
257
+ * of strings, can be class instances if ABAC is used.
258
+ * @return whether to allow the request and the reason rule.
259
+ */
260
+ enforceExWithMatcher(matcher: string, ...rvals: any[]): Promise<[boolean, string[]]>;
239
261
  /**
240
262
  * batchEnforce enforces each request and returns result in a bool array.
241
263
  * @param rvals the request need to be mediated, usually an array
@@ -16,7 +16,7 @@ import { DefaultEffector, Effect } from './effect';
16
16
  import { FunctionMap, newModelFromFile } from './model';
17
17
  import { DefaultRoleManager } from './rbac';
18
18
  import { EnforceContext } from './enforceContext';
19
- import { escapeAssertion, generateGFunction, generateSyncedGFunction, getEvalValue, hasEval, replaceEval, generatorRunSync, generatorRunAsync, customIn, bracketCompatible, } from './util';
19
+ import { escapeAssertion, generateGFunction, generateSyncedGFunction, getEvalValue, hasEval, replaceEval, generatorRunSync, generatorRunAsync, customIn, bracketCompatible, removeComments, } from './util';
20
20
  import { getLogger, logPrint } from './log';
21
21
  /**
22
22
  * CoreEnforcer defines the core functionality of an enforcer.
@@ -346,7 +346,7 @@ export class CoreEnforcer {
346
346
  await this.model.buildRoleLinks(this.rmMap);
347
347
  }
348
348
  }
349
- *privateEnforce(asyncCompile = true, explain = false, enforceContext = new EnforceContext('r', 'p', 'e', 'm'), ...rvals) {
349
+ *privateEnforce(asyncCompile = true, explain = false, matcher, enforceContext = new EnforceContext('r', 'p', 'e', 'm'), ...rvals) {
350
350
  var _a, _b, _c, _d, _e, _f, _g, _h, _j;
351
351
  if (!this.enabled) {
352
352
  return true;
@@ -361,7 +361,13 @@ export class CoreEnforcer {
361
361
  const rm = value.rm;
362
362
  functions[key] = asyncCompile ? generateGFunction(rm) : generateSyncedGFunction(rm);
363
363
  });
364
- const expString = (_b = (_a = this.model.model.get('m')) === null || _a === void 0 ? void 0 : _a.get(enforceContext.mType)) === null || _b === void 0 ? void 0 : _b.value;
364
+ let expString;
365
+ if (!matcher) {
366
+ expString = (_b = (_a = this.model.model.get('m')) === null || _a === void 0 ? void 0 : _a.get(enforceContext.mType)) === null || _b === void 0 ? void 0 : _b.value;
367
+ }
368
+ else {
369
+ expString = removeComments(escapeAssertion(matcher));
370
+ }
365
371
  if (!expString) {
366
372
  throw new Error('Unable to find matchers in model');
367
373
  }
@@ -510,9 +516,9 @@ export class CoreEnforcer {
510
516
  enforceSync(...rvals) {
511
517
  if (rvals[0] instanceof EnforceContext) {
512
518
  const enforceContext = rvals.shift();
513
- return generatorRunSync(this.privateEnforce(false, false, enforceContext, ...rvals));
519
+ return generatorRunSync(this.privateEnforce(false, false, '', enforceContext, ...rvals));
514
520
  }
515
- return generatorRunSync(this.privateEnforce(false, false, this.defaultEnforceContext, ...rvals));
521
+ return generatorRunSync(this.privateEnforce(false, false, '', this.defaultEnforceContext, ...rvals));
516
522
  }
517
523
  /**
518
524
  * If the matchers does not contain an asynchronous method, call it faster.
@@ -527,9 +533,9 @@ export class CoreEnforcer {
527
533
  enforceExSync(...rvals) {
528
534
  if (rvals[0] instanceof EnforceContext) {
529
535
  const enforceContext = rvals.shift();
530
- return generatorRunSync(this.privateEnforce(false, true, enforceContext, ...rvals));
536
+ return generatorRunSync(this.privateEnforce(false, true, '', enforceContext, ...rvals));
531
537
  }
532
- return generatorRunSync(this.privateEnforce(false, true, this.defaultEnforceContext, ...rvals));
538
+ return generatorRunSync(this.privateEnforce(false, true, '', this.defaultEnforceContext, ...rvals));
533
539
  }
534
540
  /**
535
541
  * Same as enforceSync. To be removed.
@@ -548,9 +554,26 @@ export class CoreEnforcer {
548
554
  async enforce(...rvals) {
549
555
  if (rvals[0] instanceof EnforceContext) {
550
556
  const enforceContext = rvals.shift();
551
- return generatorRunAsync(this.privateEnforce(true, false, enforceContext, ...rvals));
557
+ return generatorRunAsync(this.privateEnforce(true, false, '', enforceContext, ...rvals));
552
558
  }
553
- return generatorRunAsync(this.privateEnforce(true, false, this.defaultEnforceContext, ...rvals));
559
+ return generatorRunAsync(this.privateEnforce(true, false, '', this.defaultEnforceContext, ...rvals));
560
+ }
561
+ /**
562
+ * enforceWithMatcher decides whether a "subject" can access a "object" with
563
+ * the operation "action" but with the matcher passed,
564
+ * input parameters are usually: (matcher, sub, obj, act).
565
+ *
566
+ * @param matcher matcher string.
567
+ * @param rvals the request needs to be mediated, usually an array
568
+ * of strings, can be class instances if ABAC is used.
569
+ * @return whether to allow the request.
570
+ */
571
+ async enforceWithMatcher(matcher, ...rvals) {
572
+ if (rvals[0] instanceof EnforceContext) {
573
+ const enforceContext = rvals.shift();
574
+ return generatorRunAsync(this.privateEnforce(true, false, matcher, enforceContext, ...rvals));
575
+ }
576
+ return generatorRunAsync(this.privateEnforce(true, false, matcher, this.defaultEnforceContext, ...rvals));
554
577
  }
555
578
  /**
556
579
  * enforce decides whether a "subject" can access a "object" with
@@ -563,9 +586,26 @@ export class CoreEnforcer {
563
586
  async enforceEx(...rvals) {
564
587
  if (rvals[0] instanceof EnforceContext) {
565
588
  const enforceContext = rvals.shift();
566
- return generatorRunAsync(this.privateEnforce(true, true, enforceContext, ...rvals));
589
+ return generatorRunAsync(this.privateEnforce(true, true, '', enforceContext, ...rvals));
590
+ }
591
+ return generatorRunAsync(this.privateEnforce(true, true, '', this.defaultEnforceContext, ...rvals));
592
+ }
593
+ /**
594
+ * enforceExWithMatcher decides whether a "subject" can access a "object" with
595
+ * the operation "action" but with the matcher passed,
596
+ * input parameters are usually: (matcher, sub, obj, act).
597
+ *
598
+ * @param matcher matcher string.
599
+ * @param rvals the request needs to be mediated, usually an array
600
+ * of strings, can be class instances if ABAC is used.
601
+ * @return whether to allow the request and the reason rule.
602
+ */
603
+ async enforceExWithMatcher(matcher, ...rvals) {
604
+ if (rvals[0] instanceof EnforceContext) {
605
+ const enforceContext = rvals.shift();
606
+ return generatorRunAsync(this.privateEnforce(true, true, matcher, enforceContext, ...rvals));
567
607
  }
568
- return generatorRunAsync(this.privateEnforce(true, true, this.defaultEnforceContext, ...rvals));
608
+ return generatorRunAsync(this.privateEnforce(true, true, matcher, this.defaultEnforceContext, ...rvals));
569
609
  }
570
610
  /**
571
611
  * batchEnforce enforces each request and returns result in a bool array.
@@ -199,10 +199,18 @@ function keyMatch4Func(...args) {
199
199
  // For example, "/foo/bar?status=1&type=2" matches "/foo/bar"
200
200
  function KeyMatch5(key1, key2) {
201
201
  const i = key1.indexOf('?');
202
- if (i === -1) {
203
- return key1 === key2;
202
+ if (i !== -1) {
203
+ key1 = key1.slice(0, i);
204
+ }
205
+ key2 = key2.replace(/\/\*/g, '/.*');
206
+ const regexp = new RegExp(/(.*){[^/]+}(.*)/g);
207
+ for (;;) {
208
+ if (!key2.includes('/{')) {
209
+ break;
210
+ }
211
+ key2 = key2.replace(regexp, '$1[^/]+$2');
204
212
  }
205
- return key1.slice(0, i) === key2;
213
+ return regexMatch(key1, '^' + key2 + '$');
206
214
  }
207
215
  // keyMatch5Func is the wrapper for KeyMatch5.
208
216
  function keyMatch5Func(...args) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "casbin",
3
- "version": "5.26.2",
3
+ "version": "5.27.1",
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",