casbin 5.35.0 → 5.37.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.37.0](https://github.com/casbin/node-casbin/compare/v5.36.0...v5.37.0) (2025-01-10)
2
+
3
+
4
+ ### Features
5
+
6
+ * use empty array [] as reason for enforceEx() ([#496](https://github.com/casbin/node-casbin/issues/496)) ([c951a8f](https://github.com/casbin/node-casbin/commit/c951a8fd6afb70ecdbbf76e3424ec5107133e254))
7
+
8
+ # [5.36.0](https://github.com/casbin/node-casbin/compare/v5.35.0...v5.36.0) (2024-11-22)
9
+
10
+
11
+ ### Features
12
+
13
+ * add BracketAwareCsvParser to parse CSV file better ([#494](https://github.com/casbin/node-casbin/issues/494)) ([4c73883](https://github.com/casbin/node-casbin/commit/4c738831ebbf71f8f3a6ccac8495644c09a5e5dd))
14
+
1
15
  # [5.35.0](https://github.com/casbin/node-casbin/compare/v5.34.0...v5.35.0) (2024-11-20)
2
16
 
3
17
 
@@ -352,7 +352,7 @@ class CoreEnforcer {
352
352
  }
353
353
  }
354
354
  *privateEnforce(asyncCompile = true, explain = false, matcher, enforceContext = new enforceContext_1.EnforceContext('r', 'p', 'e', 'm'), ...rvals) {
355
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
355
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
356
356
  if (!this.enabled) {
357
357
  return true;
358
358
  }
@@ -504,7 +504,7 @@ class CoreEnforcer {
504
504
  if (explainIndex === -1) {
505
505
  return [res, []];
506
506
  }
507
- return [res, p === null || p === void 0 ? void 0 : p.policy[explainIndex]];
507
+ return [res, ((_k = p === null || p === void 0 ? void 0 : p.policy) === null || _k === void 0 ? void 0 : _k[explainIndex]) || []];
508
508
  }
509
509
  return res;
510
510
  }
@@ -29,11 +29,11 @@ class FileAdapter {
29
29
  async loadPolicyFile(model, handler) {
30
30
  const bodyBuf = await (this.fs ? this.fs : fileSystem_1.mustGetDefaultFileSystem()).readFileSync(this.filePath);
31
31
  const lines = bodyBuf.toString().split('\n');
32
- lines.forEach((n, index) => {
33
- if (!n) {
32
+ lines.forEach((line) => {
33
+ if (!line || line.trim().startsWith('#')) {
34
34
  return;
35
35
  }
36
- handler(n, model);
36
+ handler(line, model);
37
37
  });
38
38
  }
39
39
  /**
@@ -1,4 +1,21 @@
1
1
  import { Model } from '../model';
2
+ export interface IPolicyParser {
3
+ parse(line: string): string[][] | null;
4
+ }
5
+ export declare class BasicCsvParser implements IPolicyParser {
6
+ parse(line: string): string[][] | null;
7
+ }
8
+ export declare class BracketAwareCsvParser implements IPolicyParser {
9
+ private readonly baseParser;
10
+ constructor(baseParser?: IPolicyParser);
11
+ parse(line: string): string[][] | null;
12
+ }
13
+ export declare class PolicyLoader {
14
+ private readonly parser;
15
+ constructor(parser?: IPolicyParser);
16
+ loadPolicyLine(line: string, model: Model): void;
17
+ }
2
18
  export declare class Helper {
19
+ private static readonly policyLoader;
3
20
  static loadPolicyLine(line: string, model: Model): void;
4
21
  }
@@ -1,21 +1,67 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Helper = void 0;
3
+ exports.Helper = exports.PolicyLoader = exports.BracketAwareCsvParser = exports.BasicCsvParser = void 0;
4
4
  const sync_1 = require("csv-parse/sync");
5
- class Helper {
6
- static loadPolicyLine(line, model) {
5
+ class BasicCsvParser {
6
+ parse(line) {
7
7
  if (!line || line.trimStart().charAt(0) === '#') {
8
- return;
8
+ return null;
9
9
  }
10
- const tokens = sync_1.parse(line, {
10
+ return sync_1.parse(line, {
11
11
  delimiter: ',',
12
12
  skip_empty_lines: true,
13
13
  trim: true,
14
+ relax_quotes: true,
14
15
  });
16
+ }
17
+ }
18
+ exports.BasicCsvParser = BasicCsvParser;
19
+ class BracketAwareCsvParser {
20
+ constructor(baseParser = new BasicCsvParser()) {
21
+ this.baseParser = baseParser;
22
+ }
23
+ parse(line) {
24
+ const rawTokens = this.baseParser.parse(line);
25
+ if (!rawTokens || !rawTokens[0]) {
26
+ return null;
27
+ }
28
+ const tokens = rawTokens[0];
29
+ const processedTokens = [];
30
+ let currentToken = '';
31
+ let bracketCount = 0;
32
+ for (const token of tokens) {
33
+ for (const char of token) {
34
+ if (char === '(')
35
+ bracketCount++;
36
+ else if (char === ')')
37
+ bracketCount--;
38
+ }
39
+ currentToken += (currentToken ? ',' : '') + token;
40
+ if (bracketCount === 0) {
41
+ processedTokens.push(currentToken);
42
+ currentToken = '';
43
+ }
44
+ }
45
+ if (bracketCount !== 0) {
46
+ throw new Error(`Unmatched brackets in policy line: ${line}`);
47
+ }
48
+ return processedTokens.length > 0 ? [processedTokens] : null;
49
+ }
50
+ }
51
+ exports.BracketAwareCsvParser = BracketAwareCsvParser;
52
+ class PolicyLoader {
53
+ constructor(parser = new BracketAwareCsvParser()) {
54
+ this.parser = parser;
55
+ }
56
+ loadPolicyLine(line, model) {
57
+ const tokens = this.parser.parse(line);
15
58
  if (!tokens || !tokens[0]) {
16
59
  return;
17
60
  }
18
- const key = tokens[0][0];
61
+ let key = tokens[0][0].trim();
62
+ if (key.startsWith('"') && key.endsWith('"')) {
63
+ key = key.slice(1, -1);
64
+ }
19
65
  const sec = key.substring(0, 1);
20
66
  const item = model.model.get(sec);
21
67
  if (!item) {
@@ -25,7 +71,20 @@ class Helper {
25
71
  if (!policy) {
26
72
  return;
27
73
  }
28
- policy.policy.push(tokens[0].slice(1));
74
+ const values = tokens[0].slice(1).map((v) => {
75
+ if (v.startsWith('"') && v.endsWith('"')) {
76
+ v = v.slice(1, -1);
77
+ }
78
+ return v.replace(/""/g, '"').trim();
79
+ });
80
+ policy.policy.push(values);
81
+ }
82
+ }
83
+ exports.PolicyLoader = PolicyLoader;
84
+ class Helper {
85
+ static loadPolicyLine(line, model) {
86
+ Helper.policyLoader.loadPolicyLine(line, model);
29
87
  }
30
88
  }
31
89
  exports.Helper = Helper;
90
+ Helper.policyLoader = new PolicyLoader();
@@ -349,7 +349,7 @@ export class CoreEnforcer {
349
349
  }
350
350
  }
351
351
  *privateEnforce(asyncCompile = true, explain = false, matcher, enforceContext = new EnforceContext('r', 'p', 'e', 'm'), ...rvals) {
352
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
352
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
353
353
  if (!this.enabled) {
354
354
  return true;
355
355
  }
@@ -501,7 +501,7 @@ export class CoreEnforcer {
501
501
  if (explainIndex === -1) {
502
502
  return [res, []];
503
503
  }
504
- return [res, p === null || p === void 0 ? void 0 : p.policy[explainIndex]];
504
+ return [res, ((_k = p === null || p === void 0 ? void 0 : p.policy) === null || _k === void 0 ? void 0 : _k[explainIndex]) || []];
505
505
  }
506
506
  return res;
507
507
  }
@@ -26,11 +26,11 @@ export class FileAdapter {
26
26
  async loadPolicyFile(model, handler) {
27
27
  const bodyBuf = await (this.fs ? this.fs : mustGetDefaultFileSystem()).readFileSync(this.filePath);
28
28
  const lines = bodyBuf.toString().split('\n');
29
- lines.forEach((n, index) => {
30
- if (!n) {
29
+ lines.forEach((line) => {
30
+ if (!line || line.trim().startsWith('#')) {
31
31
  return;
32
32
  }
33
- handler(n, model);
33
+ handler(line, model);
34
34
  });
35
35
  }
36
36
  /**
@@ -1,4 +1,21 @@
1
1
  import { Model } from '../model';
2
+ export interface IPolicyParser {
3
+ parse(line: string): string[][] | null;
4
+ }
5
+ export declare class BasicCsvParser implements IPolicyParser {
6
+ parse(line: string): string[][] | null;
7
+ }
8
+ export declare class BracketAwareCsvParser implements IPolicyParser {
9
+ private readonly baseParser;
10
+ constructor(baseParser?: IPolicyParser);
11
+ parse(line: string): string[][] | null;
12
+ }
13
+ export declare class PolicyLoader {
14
+ private readonly parser;
15
+ constructor(parser?: IPolicyParser);
16
+ loadPolicyLine(line: string, model: Model): void;
17
+ }
2
18
  export declare class Helper {
19
+ private static readonly policyLoader;
3
20
  static loadPolicyLine(line: string, model: Model): void;
4
21
  }
@@ -1,18 +1,62 @@
1
1
  import { parse } from 'csv-parse/sync';
2
- export class Helper {
3
- static loadPolicyLine(line, model) {
2
+ export class BasicCsvParser {
3
+ parse(line) {
4
4
  if (!line || line.trimStart().charAt(0) === '#') {
5
- return;
5
+ return null;
6
6
  }
7
- const tokens = parse(line, {
7
+ return parse(line, {
8
8
  delimiter: ',',
9
9
  skip_empty_lines: true,
10
10
  trim: true,
11
+ relax_quotes: true,
11
12
  });
13
+ }
14
+ }
15
+ export class BracketAwareCsvParser {
16
+ constructor(baseParser = new BasicCsvParser()) {
17
+ this.baseParser = baseParser;
18
+ }
19
+ parse(line) {
20
+ const rawTokens = this.baseParser.parse(line);
21
+ if (!rawTokens || !rawTokens[0]) {
22
+ return null;
23
+ }
24
+ const tokens = rawTokens[0];
25
+ const processedTokens = [];
26
+ let currentToken = '';
27
+ let bracketCount = 0;
28
+ for (const token of tokens) {
29
+ for (const char of token) {
30
+ if (char === '(')
31
+ bracketCount++;
32
+ else if (char === ')')
33
+ bracketCount--;
34
+ }
35
+ currentToken += (currentToken ? ',' : '') + token;
36
+ if (bracketCount === 0) {
37
+ processedTokens.push(currentToken);
38
+ currentToken = '';
39
+ }
40
+ }
41
+ if (bracketCount !== 0) {
42
+ throw new Error(`Unmatched brackets in policy line: ${line}`);
43
+ }
44
+ return processedTokens.length > 0 ? [processedTokens] : null;
45
+ }
46
+ }
47
+ export class PolicyLoader {
48
+ constructor(parser = new BracketAwareCsvParser()) {
49
+ this.parser = parser;
50
+ }
51
+ loadPolicyLine(line, model) {
52
+ const tokens = this.parser.parse(line);
12
53
  if (!tokens || !tokens[0]) {
13
54
  return;
14
55
  }
15
- const key = tokens[0][0];
56
+ let key = tokens[0][0].trim();
57
+ if (key.startsWith('"') && key.endsWith('"')) {
58
+ key = key.slice(1, -1);
59
+ }
16
60
  const sec = key.substring(0, 1);
17
61
  const item = model.model.get(sec);
18
62
  if (!item) {
@@ -22,6 +66,18 @@ export class Helper {
22
66
  if (!policy) {
23
67
  return;
24
68
  }
25
- policy.policy.push(tokens[0].slice(1));
69
+ const values = tokens[0].slice(1).map((v) => {
70
+ if (v.startsWith('"') && v.endsWith('"')) {
71
+ v = v.slice(1, -1);
72
+ }
73
+ return v.replace(/""/g, '"').trim();
74
+ });
75
+ policy.policy.push(values);
76
+ }
77
+ }
78
+ export class Helper {
79
+ static loadPolicyLine(line, model) {
80
+ Helper.policyLoader.loadPolicyLine(line, model);
26
81
  }
27
82
  }
83
+ Helper.policyLoader = new PolicyLoader();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "casbin",
3
- "version": "5.35.0",
3
+ "version": "5.37.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",
@@ -52,7 +52,7 @@
52
52
  "@casbin/expression-eval": "^5.3.0",
53
53
  "await-lock": "^2.0.1",
54
54
  "buffer": "^6.0.3",
55
- "csv-parse": "^5.3.5",
55
+ "csv-parse": "^5.5.6",
56
56
  "minimatch": "^7.4.2"
57
57
  },
58
58
  "files": [