casbin 5.14.0-beta.4 → 5.15.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 +11 -23
- package/README.md +13 -37
- package/{es → lib/cjs}/cachedEnforcer.d.ts +0 -0
- package/lib/{cachedEnforcer.js → cjs/cachedEnforcer.js} +1 -1
- package/{es → lib/cjs}/config.d.ts +4 -3
- package/lib/{config.js → cjs/config.js} +16 -8
- package/{es → lib/cjs}/coreEnforcer.d.ts +7 -8
- package/lib/{coreEnforcer.js → cjs/coreEnforcer.js} +18 -34
- package/{es → lib/cjs}/effect/defaultEffector.d.ts +0 -0
- package/lib/{effect → cjs/effect}/defaultEffector.js +0 -0
- package/lib/{effect → cjs/effect}/defaultEffectorStream.d.ts +2 -1
- package/lib/{effect → cjs/effect}/defaultEffectorStream.js +10 -1
- package/{es → lib/cjs}/effect/effector.d.ts +0 -0
- package/lib/{effect → cjs/effect}/effector.js +0 -0
- package/lib/{effect → cjs/effect}/effectorStream.d.ts +1 -1
- package/lib/{effect → cjs/effect}/effectorStream.js +0 -0
- package/{es → lib/cjs}/effect/index.d.ts +0 -0
- package/lib/{effect → cjs/effect}/index.js +1 -1
- package/lib/{enforcer.d.ts → cjs/enforcer.d.ts} +13 -40
- package/lib/{enforcer.js → cjs/enforcer.js} +21 -54
- package/{es → lib/cjs}/frontend.d.ts +0 -0
- package/lib/{frontend.js → cjs/frontend.js} +0 -0
- package/lib/{index.d.ts → cjs/index.d.ts} +0 -1
- package/lib/{index.js → cjs/index.js} +3 -17
- package/{es → lib/cjs}/internalEnforcer.d.ts +0 -0
- package/lib/{internalEnforcer.js → cjs/internalEnforcer.js} +0 -0
- package/{es → lib/cjs}/log/defaultLogger.d.ts +0 -0
- package/lib/{log → cjs/log}/defaultLogger.js +0 -0
- package/{es → lib/cjs}/log/index.d.ts +0 -0
- package/lib/{log → cjs/log}/index.js +1 -1
- package/{es → lib/cjs}/log/logUtil.d.ts +0 -0
- package/lib/{log → cjs/log}/logUtil.js +0 -0
- package/{es → lib/cjs}/log/logger.d.ts +0 -0
- package/lib/{log → cjs/log}/logger.js +0 -0
- package/{es → lib/cjs}/managementEnforcer.d.ts +0 -0
- package/lib/{managementEnforcer.js → cjs/managementEnforcer.js} +0 -0
- package/{es → lib/cjs}/model/assertion.d.ts +0 -0
- package/lib/{model → cjs/model}/assertion.js +1 -20
- package/{es → lib/cjs}/model/functionMap.d.ts +0 -0
- package/lib/{model → cjs/model}/functionMap.js +1 -20
- package/{es → lib/cjs}/model/index.d.ts +0 -0
- package/lib/{model → cjs/model}/index.js +1 -1
- package/lib/{model → cjs/model}/model.d.ts +6 -2
- package/lib/{model → cjs/model}/model.js +16 -26
- package/{es → lib/cjs}/persist/adapter.d.ts +0 -0
- package/lib/{persist → cjs/persist}/adapter.js +0 -0
- package/{es → lib/cjs}/persist/batchAdapter.d.ts +0 -0
- package/lib/{persist → cjs/persist}/batchAdapter.js +0 -0
- package/lib/cjs/persist/batchFileAdapter.d.ts +14 -0
- package/lib/cjs/persist/batchFileAdapter.js +19 -0
- package/{es → lib/cjs}/persist/defaultFilteredAdapter.d.ts +3 -3
- package/lib/{persist → cjs/persist}/defaultFilteredAdapter.js +11 -6
- package/lib/{persist/memoryAdapter.d.ts → cjs/persist/fileAdapter.d.ts} +21 -22
- package/lib/cjs/persist/fileAdapter.js +112 -0
- package/{es → lib/cjs}/persist/filteredAdapter.d.ts +0 -0
- package/lib/{persist → cjs/persist}/filteredAdapter.js +0 -0
- package/{es → lib/cjs}/persist/helper.d.ts +0 -0
- package/lib/{persist → cjs/persist}/helper.js +6 -2
- package/{es → lib/cjs}/persist/index.d.ts +3 -1
- package/lib/{persist → cjs/persist}/index.js +4 -2
- package/lib/cjs/persist/stringAdapter.d.ts +32 -0
- package/lib/cjs/persist/stringAdapter.js +57 -0
- package/{es → lib/cjs}/persist/updatableAdapter.d.ts +0 -0
- package/lib/{persist → cjs/persist}/updatableAdapter.js +0 -0
- package/{es → lib/cjs}/persist/watcher.d.ts +0 -0
- package/lib/{persist → cjs/persist}/watcher.js +0 -0
- package/{es → lib/cjs}/rbac/defaultRoleManager.d.ts +0 -0
- package/lib/{rbac → cjs/rbac}/defaultRoleManager.js +0 -0
- package/{es → lib/cjs}/rbac/index.d.ts +0 -0
- package/lib/{rbac → cjs/rbac}/index.js +1 -1
- package/{es → lib/cjs}/rbac/roleManager.d.ts +0 -0
- package/lib/{rbac → cjs/rbac}/roleManager.js +0 -0
- package/lib/{syncedEnforcer.d.ts → cjs/syncedEnforcer.d.ts} +2 -2
- package/lib/{syncedEnforcer.js → cjs/syncedEnforcer.js} +4 -7
- package/{es → lib/cjs}/util/builtinOperators.d.ts +0 -0
- package/lib/{util → cjs/util}/builtinOperators.js +2 -12
- package/{es → lib/cjs}/util/index.d.ts +0 -0
- package/lib/{util → cjs/util}/index.js +1 -1
- package/{es → lib/cjs}/util/ip.d.ts +0 -0
- package/lib/{util → cjs/util}/ip.js +0 -0
- package/{es → lib/cjs}/util/util.d.ts +3 -3
- package/lib/{util → cjs/util}/util.js +29 -58
- package/lib/{cachedEnforcer.d.ts → esm/cachedEnforcer.d.ts} +0 -0
- package/{es → lib/esm}/cachedEnforcer.js +1 -1
- package/lib/{config.d.ts → esm/config.d.ts} +4 -3
- package/{es → lib/esm}/config.js +14 -6
- package/lib/{coreEnforcer.d.ts → esm/coreEnforcer.d.ts} +7 -8
- package/{es → lib/esm}/coreEnforcer.js +18 -34
- package/lib/{effect → esm/effect}/defaultEffector.d.ts +0 -0
- package/{es → lib/esm}/effect/defaultEffector.js +0 -0
- package/{es → lib/esm}/effect/defaultEffectorStream.d.ts +2 -1
- package/{es → lib/esm}/effect/defaultEffectorStream.js +10 -1
- package/lib/{effect → esm/effect}/effector.d.ts +0 -0
- package/{es → lib/esm}/effect/effector.js +0 -0
- package/{es → lib/esm}/effect/effectorStream.d.ts +1 -1
- package/{es → lib/esm}/effect/effectorStream.js +0 -1
- package/lib/{effect → esm/effect}/index.d.ts +0 -0
- package/{es → lib/esm}/effect/index.js +0 -0
- package/{es → lib/esm}/enforcer.d.ts +13 -40
- package/{es → lib/esm}/enforcer.js +22 -55
- package/lib/{frontend.d.ts → esm/frontend.d.ts} +0 -0
- package/{es → lib/esm}/frontend.js +0 -0
- package/{es → lib/esm}/index.d.ts +0 -1
- package/{es → lib/esm}/index.js +0 -1
- package/lib/{internalEnforcer.d.ts → esm/internalEnforcer.d.ts} +0 -0
- package/{es → lib/esm}/internalEnforcer.js +0 -0
- package/lib/{log → esm/log}/defaultLogger.d.ts +0 -0
- package/{es → lib/esm}/log/defaultLogger.js +0 -0
- package/lib/{log → esm/log}/index.d.ts +0 -0
- package/{es → lib/esm}/log/index.js +0 -0
- package/lib/{log → esm/log}/logUtil.d.ts +0 -0
- package/{es → lib/esm}/log/logUtil.js +0 -0
- package/lib/{log → esm/log}/logger.d.ts +0 -0
- package/{es → lib/esm}/log/logger.js +0 -1
- package/lib/{managementEnforcer.d.ts → esm/managementEnforcer.d.ts} +0 -0
- package/{es → lib/esm}/managementEnforcer.js +0 -0
- package/lib/{model → esm/model}/assertion.d.ts +0 -0
- package/{es → lib/esm}/model/assertion.js +0 -0
- package/lib/{model → esm/model}/functionMap.d.ts +0 -0
- package/{es → lib/esm}/model/functionMap.js +0 -0
- package/lib/{model → esm/model}/index.d.ts +0 -0
- package/{es → lib/esm}/model/index.js +0 -0
- package/{es → lib/esm}/model/model.d.ts +6 -2
- package/{es → lib/esm}/model/model.js +13 -5
- package/lib/{persist → esm/persist}/adapter.d.ts +0 -0
- package/{es → lib/esm}/persist/adapter.js +0 -1
- package/lib/{persist → esm/persist}/batchAdapter.d.ts +0 -0
- package/lib/esm/persist/batchAdapter.js +0 -0
- package/lib/esm/persist/batchFileAdapter.d.ts +14 -0
- package/lib/esm/persist/batchFileAdapter.js +15 -0
- package/lib/{persist → esm/persist}/defaultFilteredAdapter.d.ts +3 -3
- package/{es → lib/esm}/persist/defaultFilteredAdapter.js +12 -7
- package/{es/persist/memoryAdapter.d.ts → lib/esm/persist/fileAdapter.d.ts} +21 -22
- package/lib/esm/persist/fileAdapter.js +108 -0
- package/lib/{persist → esm/persist}/filteredAdapter.d.ts +0 -0
- package/lib/esm/persist/filteredAdapter.js +0 -0
- package/lib/{persist → esm/persist}/helper.d.ts +0 -0
- package/{es → lib/esm}/persist/helper.js +6 -2
- package/lib/{persist → esm/persist}/index.d.ts +3 -1
- package/{es → lib/esm}/persist/index.js +3 -1
- package/lib/esm/persist/stringAdapter.d.ts +32 -0
- package/lib/esm/persist/stringAdapter.js +53 -0
- package/lib/{persist → esm/persist}/updatableAdapter.d.ts +0 -0
- package/{es → lib/esm}/persist/updatableAdapter.js +0 -1
- package/lib/{persist → esm/persist}/watcher.d.ts +0 -0
- package/{es → lib/esm}/persist/watcher.js +0 -1
- package/lib/{rbac → esm/rbac}/defaultRoleManager.d.ts +0 -0
- package/{es → lib/esm}/rbac/defaultRoleManager.js +0 -0
- package/lib/{rbac → esm/rbac}/index.d.ts +0 -0
- package/{es → lib/esm}/rbac/index.js +0 -0
- package/lib/{rbac → esm/rbac}/roleManager.d.ts +0 -0
- package/{es → lib/esm}/rbac/roleManager.js +0 -1
- package/{es → lib/esm}/syncedEnforcer.d.ts +2 -2
- package/{es → lib/esm}/syncedEnforcer.js +3 -3
- package/lib/{util → esm/util}/builtinOperators.d.ts +0 -0
- package/{es → lib/esm}/util/builtinOperators.js +2 -9
- package/lib/{util → esm/util}/index.d.ts +0 -0
- package/{es → lib/esm}/util/index.js +0 -0
- package/lib/{util → esm/util}/ip.d.ts +0 -0
- package/{es → lib/esm}/util/ip.js +0 -0
- package/lib/{util → esm/util}/util.d.ts +3 -3
- package/{es → lib/esm}/util/util.js +27 -56
- package/package.json +15 -29
- package/dist/casbin.esm.js +0 -3
- package/dist/casbin.esm.js.map +0 -1
- package/dist/casbin.js +0 -3
- package/dist/casbin.js.map +0 -1
- package/dist/casbin.mjs +0 -3
- package/dist/casbin.mjs.map +0 -1
- package/es/enforceContext.d.ts +0 -10
- package/es/enforceContext.js +0 -13
- package/es/persist/batchAdapter.js +0 -1
- package/es/persist/filteredAdapter.js +0 -1
- package/es/persist/memoryAdapter.js +0 -93
- package/examples/mulitple_policy.csv +0 -2
- package/lib/enforceContext.d.ts +0 -10
- package/lib/enforceContext.js +0 -18
- package/lib/persist/memoryAdapter.js +0 -97
package/CHANGELOG.md
CHANGED
|
@@ -1,42 +1,30 @@
|
|
|
1
|
-
|
|
1
|
+
## [5.15.1](https://github.com/casbin/node-casbin/compare/v5.15.0...v5.15.1) (2022-04-27)
|
|
2
2
|
|
|
3
3
|
|
|
4
|
-
###
|
|
4
|
+
### Bug Fixes
|
|
5
5
|
|
|
6
|
-
*
|
|
6
|
+
* EnforceEx return allow reason ([#363](https://github.com/casbin/node-casbin/issues/363)) ([6353283](https://github.com/casbin/node-casbin/commit/635328328caf200093e89443d32e9f2fa736509a))
|
|
7
7
|
|
|
8
|
-
# [5.
|
|
8
|
+
# [5.15.0](https://github.com/casbin/node-casbin/compare/v5.14.0...v5.15.0) (2022-04-15)
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
###
|
|
11
|
+
### Features
|
|
12
12
|
|
|
13
|
-
*
|
|
13
|
+
* [#357](https://github.com/casbin/node-casbin/issues/357) Support keyMatch5 ([#359](https://github.com/casbin/node-casbin/issues/359)) ([e6a6d8a](https://github.com/casbin/node-casbin/commit/e6a6d8ab253af70bb46ef7c27c6ebf48c55d76c8))
|
|
14
14
|
|
|
15
|
-
# [5.14.0
|
|
15
|
+
# [5.14.0](https://github.com/casbin/node-casbin/compare/v5.13.2...v5.14.0) (2022-03-18)
|
|
16
16
|
|
|
17
17
|
|
|
18
|
-
###
|
|
18
|
+
### Features
|
|
19
19
|
|
|
20
|
-
*
|
|
20
|
+
* **rbac:** add `getUsersForRoleInDomain` & `getRolesForUserInDomain` ([#351](https://github.com/casbin/node-casbin/issues/351)) ([4896ca2](https://github.com/casbin/node-casbin/commit/4896ca260c2f35672b9b520969898155ec616f0b)), closes [#304](https://github.com/casbin/node-casbin/issues/304)
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
## [5.13.2](https://github.com/casbin/node-casbin/compare/v5.13.1...v5.13.2) (2022-03-02)
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
### Bug Fixes
|
|
26
26
|
|
|
27
|
-
*
|
|
28
|
-
* rename StringAdapter to MemoryAdapter ([0b1019a](https://github.com/casbin/node-casbin/commit/0b1019aa2324ea4ea4c37119728dadac1bcf1fc3))
|
|
29
|
-
* use csv-like format ([3b54c93](https://github.com/casbin/node-casbin/commit/3b54c934d0d9d08a4af18799c1292f9dc728e6a4))
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
### Features
|
|
33
|
-
|
|
34
|
-
* add policyArrayToString and policyStringToArray to util ([0f66bc1](https://github.com/casbin/node-casbin/commit/0f66bc1b2fcddfd9c6e847dd06fd4a5f53c55fa9))
|
|
35
|
-
* Extend multiple sections type of escapeAssertion ([#180](https://github.com/casbin/node-casbin/issues/180)) ([33c784c](https://github.com/casbin/node-casbin/commit/33c784cbdc0d650ba75b8177b69f41dc0ca11fae))
|
|
36
|
-
* implement csv parser ([968a232](https://github.com/casbin/node-casbin/commit/968a23237b3193e594910f5f798bf349d6bff04c))
|
|
37
|
-
* implement string adapater ([0c59cae](https://github.com/casbin/node-casbin/commit/0c59cae0eba851509ff754b6f523a4feafc11f80))
|
|
38
|
-
* Multiple sections type ([cc58c57](https://github.com/casbin/node-casbin/commit/cc58c57ae4a7c3202c7217497bef8016df93fe26))
|
|
39
|
-
* RBAC with Domains API ([3e38bb5](https://github.com/casbin/node-casbin/commit/3e38bb5a7223657fae21896ba2e0b9b39e099481))
|
|
27
|
+
* *matcher result should be boolean or number* for KeyGet2 ([#347](https://github.com/casbin/node-casbin/issues/347)) ([0257078](https://github.com/casbin/node-casbin/commit/0257078e1302f5ef081ec143afe5c470f4f862e9))
|
|
40
28
|
|
|
41
29
|
## [5.13.1](https://github.com/casbin/node-casbin/compare/v5.13.0...v5.13.1) (2022-02-22)
|
|
42
30
|
|
package/README.md
CHANGED
|
@@ -40,58 +40,34 @@
|
|
|
40
40
|
|
|
41
41
|
https://casbin.org/docs/en/overview
|
|
42
42
|
|
|
43
|
-
## Feature
|
|
44
|
-
|
|
45
|
-
- 😎 Written in TypeScript to provide the type definitions
|
|
46
|
-
- 🎯 Support multiple access model such as ACL, RBAC, ABAC
|
|
47
|
-
- 🎮 Run everywhere on JavaScript platforms such as WEB, Node.js, React-Native, Electron, etc.
|
|
48
|
-
|
|
49
43
|
## Installation
|
|
50
44
|
|
|
51
45
|
```shell script
|
|
52
46
|
# NPM
|
|
53
|
-
npm install casbin
|
|
47
|
+
npm install casbin --save
|
|
54
48
|
|
|
55
49
|
# Yarn
|
|
56
|
-
yarn add casbin
|
|
50
|
+
yarn add casbin
|
|
57
51
|
```
|
|
58
52
|
|
|
59
53
|
## Get started
|
|
60
54
|
|
|
61
|
-
New
|
|
62
|
-
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
p = sub, obj, act
|
|
71
|
-
[role_definition]
|
|
72
|
-
g = _, _
|
|
73
|
-
[policy_effect]
|
|
74
|
-
e = some(where (p.eft == allow))
|
|
75
|
-
[matchers]
|
|
76
|
-
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
|
|
77
|
-
`);
|
|
78
|
-
|
|
79
|
-
const adapter = new MemoryAdapter(`
|
|
80
|
-
p, alice, data1, read
|
|
81
|
-
p, bob, data2, write
|
|
82
|
-
p, data2_admin, data2, read
|
|
83
|
-
p, data2_admin, data2, write
|
|
84
|
-
g, alice, data2_admin
|
|
85
|
-
`);
|
|
86
|
-
|
|
87
|
-
const enforcer = await newEnforcer(model, adapter);
|
|
55
|
+
New a `node-casbin` enforcer with a model file and a policy file, see [Model](#official-model) section for details:
|
|
56
|
+
|
|
57
|
+
```node.js
|
|
58
|
+
// For Node.js:
|
|
59
|
+
const { newEnforcer } = require('casbin');
|
|
60
|
+
// For browser:
|
|
61
|
+
// import { newEnforcer } from 'casbin';
|
|
62
|
+
|
|
63
|
+
const enforcer = await newEnforcer('basic_model.conf', 'basic_policy.csv');
|
|
88
64
|
```
|
|
89
65
|
|
|
90
66
|
> **Note**: you can also initialize an enforcer with policy in DB instead of file, see [Persistence](#policy-persistence) section for details.
|
|
91
67
|
|
|
92
68
|
Add an enforcement hook into your code right before the access happens:
|
|
93
69
|
|
|
94
|
-
```
|
|
70
|
+
```node.js
|
|
95
71
|
const sub = 'alice'; // the user that wants to access a resource.
|
|
96
72
|
const obj = 'data1'; // the resource that is going to be accessed.
|
|
97
73
|
const act = 'read'; // the operation that the user performs on the resource.
|
|
@@ -111,7 +87,7 @@ if (res) {
|
|
|
111
87
|
Besides the static policy file, `node-casbin` also provides API for permission management at run-time.
|
|
112
88
|
For example, You can get all the roles assigned to a user as below:
|
|
113
89
|
|
|
114
|
-
```
|
|
90
|
+
```node.js
|
|
115
91
|
const roles = await enforcer.getRolesForUser('alice');
|
|
116
92
|
```
|
|
117
93
|
|
|
File without changes
|
|
@@ -65,7 +65,7 @@ class CachedEnforcer extends enforcer_1.Enforcer {
|
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
67
|
exports.CachedEnforcer = CachedEnforcer;
|
|
68
|
-
// newCachedEnforcer creates a cached enforcer via
|
|
68
|
+
// newCachedEnforcer creates a cached enforcer via file or DB.
|
|
69
69
|
async function newCachedEnforcer(...params) {
|
|
70
70
|
return enforcer_1.newEnforcerWithClass(CachedEnforcer, ...params);
|
|
71
71
|
}
|
|
@@ -16,10 +16,10 @@ export declare class Config implements ConfigInterface {
|
|
|
16
16
|
/**
|
|
17
17
|
* newConfig create an empty configuration representation from file.
|
|
18
18
|
*
|
|
19
|
-
* @param
|
|
19
|
+
* @param confName the path of the model file.
|
|
20
20
|
* @return the constructor of Config.
|
|
21
21
|
*/
|
|
22
|
-
static newConfig(
|
|
22
|
+
static newConfig(confName: string): Config;
|
|
23
23
|
/**
|
|
24
24
|
* newConfigFromText create an empty configuration representation from text.
|
|
25
25
|
*
|
|
@@ -31,7 +31,8 @@ export declare class Config implements ConfigInterface {
|
|
|
31
31
|
* addConfig adds a new section->key:value to the configuration.
|
|
32
32
|
*/
|
|
33
33
|
private addConfig;
|
|
34
|
-
private
|
|
34
|
+
private parse;
|
|
35
|
+
private parseBuffer;
|
|
35
36
|
private write;
|
|
36
37
|
getBool(key: string): boolean;
|
|
37
38
|
getInt(key: string): number;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Config = void 0;
|
|
2
4
|
// Copyright 2018 The Casbin Authors. All Rights Reserved.
|
|
3
5
|
//
|
|
4
6
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -12,8 +14,7 @@
|
|
|
12
14
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
15
|
// See the License for the specific language governing permissions and
|
|
14
16
|
// limitations under the License.
|
|
15
|
-
|
|
16
|
-
exports.Config = void 0;
|
|
17
|
+
const fs_1 = require("fs");
|
|
17
18
|
class Config {
|
|
18
19
|
constructor() {
|
|
19
20
|
this.data = new Map();
|
|
@@ -21,12 +22,12 @@ class Config {
|
|
|
21
22
|
/**
|
|
22
23
|
* newConfig create an empty configuration representation from file.
|
|
23
24
|
*
|
|
24
|
-
* @param
|
|
25
|
+
* @param confName the path of the model file.
|
|
25
26
|
* @return the constructor of Config.
|
|
26
27
|
*/
|
|
27
|
-
static newConfig(
|
|
28
|
+
static newConfig(confName) {
|
|
28
29
|
const config = new Config();
|
|
29
|
-
config.
|
|
30
|
+
config.parse(confName);
|
|
30
31
|
return config;
|
|
31
32
|
}
|
|
32
33
|
/**
|
|
@@ -37,7 +38,7 @@ class Config {
|
|
|
37
38
|
*/
|
|
38
39
|
static newConfigFromText(text) {
|
|
39
40
|
const config = new Config();
|
|
40
|
-
config.
|
|
41
|
+
config.parseBuffer(Buffer.from(text));
|
|
41
42
|
return config;
|
|
42
43
|
}
|
|
43
44
|
/**
|
|
@@ -60,8 +61,15 @@ class Config {
|
|
|
60
61
|
return false;
|
|
61
62
|
}
|
|
62
63
|
}
|
|
63
|
-
|
|
64
|
-
const
|
|
64
|
+
parse(path) {
|
|
65
|
+
const buf = fs_1.readFileSync(path);
|
|
66
|
+
this.parseBuffer(buf);
|
|
67
|
+
}
|
|
68
|
+
parseBuffer(buf) {
|
|
69
|
+
const lines = buf
|
|
70
|
+
.toString()
|
|
71
|
+
.split('\n')
|
|
72
|
+
.filter((v) => v);
|
|
65
73
|
const linesCount = lines.length;
|
|
66
74
|
let section = '';
|
|
67
75
|
let currentLine = '';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Effector } from './effect';
|
|
2
2
|
import { FunctionMap, Model, PolicyOp } from './model';
|
|
3
|
-
import { Adapter, Watcher } from './persist';
|
|
3
|
+
import { Adapter, FilteredAdapter, Watcher, BatchAdapter, UpdatableAdapter } from './persist';
|
|
4
4
|
import { RoleManager } from './rbac';
|
|
5
5
|
import { MatchingFunc } from './rbac';
|
|
6
6
|
/**
|
|
@@ -12,8 +12,7 @@ export declare class CoreEnforcer {
|
|
|
12
12
|
protected fm: FunctionMap;
|
|
13
13
|
protected eft: Effector;
|
|
14
14
|
private matcherMap;
|
|
15
|
-
|
|
16
|
-
protected adapter: Adapter;
|
|
15
|
+
protected adapter: UpdatableAdapter | FilteredAdapter | Adapter | BatchAdapter;
|
|
17
16
|
protected watcher: Watcher | null;
|
|
18
17
|
protected rmMap: Map<string, RoleManager>;
|
|
19
18
|
protected enabled: boolean;
|
|
@@ -22,7 +21,7 @@ export declare class CoreEnforcer {
|
|
|
22
21
|
protected autoNotifyWatcher: boolean;
|
|
23
22
|
private getExpression;
|
|
24
23
|
/**
|
|
25
|
-
* loadModel reloads the model from the model CONF
|
|
24
|
+
* loadModel reloads the model from the model CONF file.
|
|
26
25
|
* Because the policy is attached to a model,
|
|
27
26
|
* so the policy is invalidated and needs to be reloaded by calling LoadPolicy().
|
|
28
27
|
*/
|
|
@@ -84,17 +83,17 @@ export declare class CoreEnforcer {
|
|
|
84
83
|
initRmMap(): void;
|
|
85
84
|
sortPolicies(): void;
|
|
86
85
|
/**
|
|
87
|
-
* loadPolicy reloads the policy from
|
|
86
|
+
* loadPolicy reloads the policy from file/database.
|
|
88
87
|
*/
|
|
89
88
|
loadPolicy(): Promise<void>;
|
|
90
89
|
/**
|
|
91
|
-
* loadFilteredPolicy reloads a filtered policy from
|
|
90
|
+
* loadFilteredPolicy reloads a filtered policy from file/database.
|
|
92
91
|
*
|
|
93
92
|
* @param filter the filter used to specify which type of policy should be loaded.
|
|
94
93
|
*/
|
|
95
94
|
loadFilteredPolicy(filter: any): Promise<boolean>;
|
|
96
95
|
/**
|
|
97
|
-
* LoadIncrementalFilteredPolicy append a filtered policy from
|
|
96
|
+
* LoadIncrementalFilteredPolicy append a filtered policy from file/database.
|
|
98
97
|
*
|
|
99
98
|
* @param filter the filter used to specify which type of policy should be appended.
|
|
100
99
|
*/
|
|
@@ -107,7 +106,7 @@ export declare class CoreEnforcer {
|
|
|
107
106
|
isFiltered(): boolean;
|
|
108
107
|
/**
|
|
109
108
|
* savePolicy saves the current policy (usually after changed with
|
|
110
|
-
* Casbin API) back to
|
|
109
|
+
* Casbin API) back to file/database.
|
|
111
110
|
*/
|
|
112
111
|
savePolicy(): Promise<boolean>;
|
|
113
112
|
/**
|
|
@@ -18,7 +18,6 @@ const expression_eval_1 = require("expression-eval");
|
|
|
18
18
|
const effect_1 = require("./effect");
|
|
19
19
|
const model_1 = require("./model");
|
|
20
20
|
const rbac_1 = require("./rbac");
|
|
21
|
-
const enforceContext_1 = require("./enforceContext");
|
|
22
21
|
const util_1 = require("./util");
|
|
23
22
|
const log_1 = require("./log");
|
|
24
23
|
/**
|
|
@@ -29,7 +28,6 @@ class CoreEnforcer {
|
|
|
29
28
|
this.fm = model_1.FunctionMap.loadFunctionMap();
|
|
30
29
|
this.eft = new effect_1.DefaultEffector();
|
|
31
30
|
this.matcherMap = new Map();
|
|
32
|
-
this.defaultEnforceContext = new enforceContext_1.EnforceContext('r', 'p', 'e', 'm');
|
|
33
31
|
this.watcher = null;
|
|
34
32
|
this.enabled = true;
|
|
35
33
|
this.autoSave = true;
|
|
@@ -48,7 +46,7 @@ class CoreEnforcer {
|
|
|
48
46
|
return expression;
|
|
49
47
|
}
|
|
50
48
|
/**
|
|
51
|
-
* loadModel reloads the model from the model CONF
|
|
49
|
+
* loadModel reloads the model from the model CONF file.
|
|
52
50
|
* Because the policy is attached to a model,
|
|
53
51
|
* so the policy is invalidated and needs to be reloaded by calling LoadPolicy().
|
|
54
52
|
*/
|
|
@@ -155,7 +153,7 @@ class CoreEnforcer {
|
|
|
155
153
|
}
|
|
156
154
|
}
|
|
157
155
|
/**
|
|
158
|
-
* loadPolicy reloads the policy from
|
|
156
|
+
* loadPolicy reloads the policy from file/database.
|
|
159
157
|
*/
|
|
160
158
|
async loadPolicy() {
|
|
161
159
|
this.model.clearPolicy();
|
|
@@ -166,7 +164,7 @@ class CoreEnforcer {
|
|
|
166
164
|
}
|
|
167
165
|
}
|
|
168
166
|
/**
|
|
169
|
-
* loadFilteredPolicy reloads a filtered policy from
|
|
167
|
+
* loadFilteredPolicy reloads a filtered policy from file/database.
|
|
170
168
|
*
|
|
171
169
|
* @param filter the filter used to specify which type of policy should be loaded.
|
|
172
170
|
*/
|
|
@@ -176,7 +174,7 @@ class CoreEnforcer {
|
|
|
176
174
|
return this.loadIncrementalFilteredPolicy(filter);
|
|
177
175
|
}
|
|
178
176
|
/**
|
|
179
|
-
* LoadIncrementalFilteredPolicy append a filtered policy from
|
|
177
|
+
* LoadIncrementalFilteredPolicy append a filtered policy from file/database.
|
|
180
178
|
*
|
|
181
179
|
* @param filter the filter used to specify which type of policy should be appended.
|
|
182
180
|
*/
|
|
@@ -207,7 +205,7 @@ class CoreEnforcer {
|
|
|
207
205
|
}
|
|
208
206
|
/**
|
|
209
207
|
* savePolicy saves the current policy (usually after changed with
|
|
210
|
-
* Casbin API) back to
|
|
208
|
+
* Casbin API) back to file/database.
|
|
211
209
|
*/
|
|
212
210
|
async savePolicy() {
|
|
213
211
|
if (this.isFiltered()) {
|
|
@@ -313,7 +311,7 @@ class CoreEnforcer {
|
|
|
313
311
|
await this.model.buildRoleLinks(this.rmMap);
|
|
314
312
|
}
|
|
315
313
|
}
|
|
316
|
-
*privateEnforce(asyncCompile = true, explain = false,
|
|
314
|
+
*privateEnforce(asyncCompile = true, explain = false, ...rvals) {
|
|
317
315
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
318
316
|
if (!this.enabled) {
|
|
319
317
|
return true;
|
|
@@ -328,19 +326,19 @@ class CoreEnforcer {
|
|
|
328
326
|
const rm = value.rm;
|
|
329
327
|
functions[key] = util_1.generateGFunction(rm);
|
|
330
328
|
});
|
|
331
|
-
const expString = (_b = (_a = this.model.model.get('m')) === null || _a === void 0 ? void 0 : _a.get(
|
|
329
|
+
const expString = (_b = (_a = this.model.model.get('m')) === null || _a === void 0 ? void 0 : _a.get('m')) === null || _b === void 0 ? void 0 : _b.value;
|
|
332
330
|
if (!expString) {
|
|
333
331
|
throw new Error('Unable to find matchers in model');
|
|
334
332
|
}
|
|
335
|
-
const effectExpr = (_d = (_c = this.model.model.get('e')) === null || _c === void 0 ? void 0 : _c.get(
|
|
333
|
+
const effectExpr = (_d = (_c = this.model.model.get('e')) === null || _c === void 0 ? void 0 : _c.get('e')) === null || _d === void 0 ? void 0 : _d.value;
|
|
336
334
|
if (!effectExpr) {
|
|
337
335
|
throw new Error('Unable to find policy_effect in model');
|
|
338
336
|
}
|
|
339
337
|
const HasEval = util_1.hasEval(expString);
|
|
340
338
|
let expression = undefined;
|
|
341
|
-
const p = (_e = this.model.model.get('p')) === null || _e === void 0 ? void 0 : _e.get(
|
|
339
|
+
const p = (_e = this.model.model.get('p')) === null || _e === void 0 ? void 0 : _e.get('p');
|
|
342
340
|
const policyLen = (_f = p === null || p === void 0 ? void 0 : p.policy) === null || _f === void 0 ? void 0 : _f.length;
|
|
343
|
-
const rTokens = (_h = (_g = this.model.model.get('r')) === null || _g === void 0 ? void 0 : _g.get(
|
|
341
|
+
const rTokens = (_h = (_g = this.model.model.get('r')) === null || _g === void 0 ? void 0 : _g.get('r')) === null || _h === void 0 ? void 0 : _h.tokens;
|
|
344
342
|
const rTokensLen = rTokens === null || rTokens === void 0 ? void 0 : rTokens.length;
|
|
345
343
|
const effectStream = this.eft.newStream(effectExpr);
|
|
346
344
|
if (policyLen && policyLen !== 0) {
|
|
@@ -412,9 +410,11 @@ class CoreEnforcer {
|
|
|
412
410
|
eftRes = effect_1.Effect.Indeterminate;
|
|
413
411
|
}
|
|
414
412
|
}
|
|
415
|
-
const [res, done] = effectStream.pushEffect(eftRes);
|
|
416
|
-
if (
|
|
413
|
+
const [res, rec, done] = effectStream.pushEffect(eftRes);
|
|
414
|
+
if (rec) {
|
|
417
415
|
explainIndex = i;
|
|
416
|
+
}
|
|
417
|
+
if (done) {
|
|
418
418
|
break;
|
|
419
419
|
}
|
|
420
420
|
}
|
|
@@ -473,11 +473,7 @@ class CoreEnforcer {
|
|
|
473
473
|
* @return whether to allow the request.
|
|
474
474
|
*/
|
|
475
475
|
enforceSync(...rvals) {
|
|
476
|
-
|
|
477
|
-
const enforceContext = rvals.shift();
|
|
478
|
-
return util_1.generatorRunSync(this.privateEnforce(false, false, enforceContext, ...rvals));
|
|
479
|
-
}
|
|
480
|
-
return util_1.generatorRunSync(this.privateEnforce(false, false, this.defaultEnforceContext, ...rvals));
|
|
476
|
+
return util_1.generatorRunSync(this.privateEnforce(false, false, ...rvals));
|
|
481
477
|
}
|
|
482
478
|
/**
|
|
483
479
|
* If the matchers does not contain an asynchronous method, call it faster.
|
|
@@ -490,11 +486,7 @@ class CoreEnforcer {
|
|
|
490
486
|
* @return whether to allow the request and the reason rule.
|
|
491
487
|
*/
|
|
492
488
|
enforceExSync(...rvals) {
|
|
493
|
-
|
|
494
|
-
const enforceContext = rvals.shift();
|
|
495
|
-
return util_1.generatorRunSync(this.privateEnforce(false, true, enforceContext, ...rvals));
|
|
496
|
-
}
|
|
497
|
-
return util_1.generatorRunSync(this.privateEnforce(false, true, this.defaultEnforceContext, ...rvals));
|
|
489
|
+
return util_1.generatorRunSync(this.privateEnforce(false, true, ...rvals));
|
|
498
490
|
}
|
|
499
491
|
/**
|
|
500
492
|
* Same as enforceSync. To be removed.
|
|
@@ -511,11 +503,7 @@ class CoreEnforcer {
|
|
|
511
503
|
* @return whether to allow the request.
|
|
512
504
|
*/
|
|
513
505
|
async enforce(...rvals) {
|
|
514
|
-
|
|
515
|
-
const enforceContext = rvals.shift();
|
|
516
|
-
return util_1.generatorRunAsync(this.privateEnforce(true, false, enforceContext, ...rvals));
|
|
517
|
-
}
|
|
518
|
-
return util_1.generatorRunAsync(this.privateEnforce(true, false, this.defaultEnforceContext, ...rvals));
|
|
506
|
+
return util_1.generatorRunAsync(this.privateEnforce(true, false, ...rvals));
|
|
519
507
|
}
|
|
520
508
|
/**
|
|
521
509
|
* enforce decides whether a "subject" can access a "object" with
|
|
@@ -526,11 +514,7 @@ class CoreEnforcer {
|
|
|
526
514
|
* @return whether to allow the request and the reason rule.
|
|
527
515
|
*/
|
|
528
516
|
async enforceEx(...rvals) {
|
|
529
|
-
|
|
530
|
-
const enforceContext = rvals.shift();
|
|
531
|
-
return util_1.generatorRunAsync(this.privateEnforce(true, true, enforceContext, ...rvals));
|
|
532
|
-
}
|
|
533
|
-
return util_1.generatorRunAsync(this.privateEnforce(true, true, this.defaultEnforceContext, ...rvals));
|
|
517
|
+
return util_1.generatorRunAsync(this.privateEnforce(true, true, ...rvals));
|
|
534
518
|
}
|
|
535
519
|
/**
|
|
536
520
|
* batchEnforce enforces each request and returns result in a bool array.
|
|
File without changes
|
|
File without changes
|
|
@@ -6,8 +6,9 @@ import { Effect } from './effector';
|
|
|
6
6
|
export declare class DefaultEffectorStream implements EffectorStream {
|
|
7
7
|
private done;
|
|
8
8
|
private res;
|
|
9
|
+
private rec;
|
|
9
10
|
private readonly expr;
|
|
10
11
|
constructor(expr: string);
|
|
11
12
|
current(): boolean;
|
|
12
|
-
pushEffect(eft: Effect): [boolean, boolean];
|
|
13
|
+
pushEffect(eft: Effect): [boolean, boolean, boolean];
|
|
13
14
|
}
|
|
@@ -22,6 +22,7 @@ class DefaultEffectorStream {
|
|
|
22
22
|
constructor(expr) {
|
|
23
23
|
this.done = false;
|
|
24
24
|
this.res = false;
|
|
25
|
+
this.rec = false;
|
|
25
26
|
this.expr = expr;
|
|
26
27
|
}
|
|
27
28
|
current() {
|
|
@@ -33,6 +34,7 @@ class DefaultEffectorStream {
|
|
|
33
34
|
if (eft === effector_1.Effect.Allow) {
|
|
34
35
|
this.res = true;
|
|
35
36
|
this.done = true;
|
|
37
|
+
this.rec = true;
|
|
36
38
|
}
|
|
37
39
|
break;
|
|
38
40
|
case '!some(where (p_eft == deny))':
|
|
@@ -40,27 +42,34 @@ class DefaultEffectorStream {
|
|
|
40
42
|
if (eft === effector_1.Effect.Deny) {
|
|
41
43
|
this.res = false;
|
|
42
44
|
this.done = true;
|
|
45
|
+
this.rec = true;
|
|
43
46
|
}
|
|
44
47
|
break;
|
|
45
48
|
case 'some(where (p_eft == allow)) && !some(where (p_eft == deny))':
|
|
46
49
|
if (eft === effector_1.Effect.Allow) {
|
|
47
50
|
this.res = true;
|
|
51
|
+
this.rec = true;
|
|
48
52
|
}
|
|
49
53
|
else if (eft === effector_1.Effect.Deny) {
|
|
50
54
|
this.res = false;
|
|
51
55
|
this.done = true;
|
|
56
|
+
this.rec = true;
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
this.rec = false;
|
|
52
60
|
}
|
|
53
61
|
break;
|
|
54
62
|
case 'priority(p_eft) || deny':
|
|
55
63
|
if (eft !== effector_1.Effect.Indeterminate) {
|
|
56
64
|
this.res = eft === effector_1.Effect.Allow;
|
|
57
65
|
this.done = true;
|
|
66
|
+
this.rec = true;
|
|
58
67
|
}
|
|
59
68
|
break;
|
|
60
69
|
default:
|
|
61
70
|
throw new Error('unsupported effect');
|
|
62
71
|
}
|
|
63
|
-
return [this.res, this.done];
|
|
72
|
+
return [this.res, this.rec, this.done];
|
|
64
73
|
}
|
|
65
74
|
}
|
|
66
75
|
exports.DefaultEffectorStream = DefaultEffectorStream;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -20,7 +20,7 @@ var __createBinding = (this && this.__createBinding) || (Object.create ? (functi
|
|
|
20
20
|
o[k2] = m[k];
|
|
21
21
|
}));
|
|
22
22
|
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
23
|
-
for (var p in m) if (p !== "default" && !
|
|
23
|
+
for (var p in m) if (p !== "default" && !exports.hasOwnProperty(p)) __createBinding(exports, m, p);
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
__exportStar(require("./effector"), exports);
|
|
@@ -6,12 +6,19 @@ import { Adapter } from './persist';
|
|
|
6
6
|
*/
|
|
7
7
|
export declare class Enforcer extends ManagementEnforcer {
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
* @param
|
|
9
|
+
* initWithFile initializes an enforcer with a model file and a policy file.
|
|
10
|
+
* @param modelPath model file path
|
|
11
|
+
* @param policyPath policy file path
|
|
12
|
+
* @param lazyLoad lazyLoad whether to load policy at initial time
|
|
13
|
+
*/
|
|
14
|
+
initWithFile(modelPath: string, policyPath: string, lazyLoad?: boolean): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* initWithFile initializes an enforcer with a model file and a policy file.
|
|
17
|
+
* @param modelPath model file path
|
|
11
18
|
* @param policyString policy CSV string
|
|
12
19
|
* @param lazyLoad whether to load policy at initial time
|
|
13
20
|
*/
|
|
14
|
-
initWithString(
|
|
21
|
+
initWithString(modelPath: string, policyString: string, lazyLoad?: boolean): Promise<void>;
|
|
15
22
|
/**
|
|
16
23
|
* initWithAdapter initializes an enforcer with a database adapter.
|
|
17
24
|
* @param modelPath model file path
|
|
@@ -61,16 +68,6 @@ export declare class Enforcer extends ManagementEnforcer {
|
|
|
61
68
|
* @return succeeds or not.
|
|
62
69
|
*/
|
|
63
70
|
addRoleForUser(user: string, role: string, domain?: string): Promise<boolean>;
|
|
64
|
-
/**
|
|
65
|
-
* addRoleForUserInDomain adds a role for a user.
|
|
66
|
-
* Returns false if the user already has the role (aka not affected).
|
|
67
|
-
*
|
|
68
|
-
* @param user the user.
|
|
69
|
-
* @param role the role.
|
|
70
|
-
* @param domain the domain.
|
|
71
|
-
* @return succeeds or not.
|
|
72
|
-
*/
|
|
73
|
-
addRoleForUserInDomain(user: string, role: string, domain: string): Promise<boolean>;
|
|
74
71
|
/**
|
|
75
72
|
* deleteRoleForUser deletes a role for a user.
|
|
76
73
|
* Returns false if the user does not have the role (aka not affected).
|
|
@@ -81,16 +78,6 @@ export declare class Enforcer extends ManagementEnforcer {
|
|
|
81
78
|
* @return succeeds or not.
|
|
82
79
|
*/
|
|
83
80
|
deleteRoleForUser(user: string, role: string, domain?: string): Promise<boolean>;
|
|
84
|
-
/**
|
|
85
|
-
* deleteRoleForUserInDomain deletes a role for a user.
|
|
86
|
-
* Returns false if the user does not have the role (aka not affected).
|
|
87
|
-
*
|
|
88
|
-
* @param user the user.
|
|
89
|
-
* @param role the role.
|
|
90
|
-
* @param domain the domain.
|
|
91
|
-
* @return succeeds or not.
|
|
92
|
-
*/
|
|
93
|
-
deleteRoleForUserInDomain(user: string, role: string, domain?: string): Promise<boolean>;
|
|
94
81
|
/**
|
|
95
82
|
* deleteRolesForUser deletes all roles for a user.
|
|
96
83
|
* Returns false if the user does not have any roles (aka not affected).
|
|
@@ -100,15 +87,6 @@ export declare class Enforcer extends ManagementEnforcer {
|
|
|
100
87
|
* @return succeeds or not.
|
|
101
88
|
*/
|
|
102
89
|
deleteRolesForUser(user: string, domain?: string): Promise<boolean>;
|
|
103
|
-
/**
|
|
104
|
-
* deleteRolesForUserInDomain deletes all roles for a user.
|
|
105
|
-
* Returns false if the user does not have any roles (aka not affected).
|
|
106
|
-
*
|
|
107
|
-
* @param user the user.
|
|
108
|
-
* @param domain the domain.
|
|
109
|
-
* @return succeeds or not.
|
|
110
|
-
*/
|
|
111
|
-
deleteRolesForUserInDomain(user: string, domain?: string): Promise<boolean>;
|
|
112
90
|
/**
|
|
113
91
|
* deleteUser deletes a user.
|
|
114
92
|
* Returns false if the user does not exist (aka not affected).
|
|
@@ -197,11 +175,6 @@ export declare class Enforcer extends ManagementEnforcer {
|
|
|
197
175
|
* But getImplicitPermissionsForUser("alice") will get: [["admin", "data1", "read"], ["alice", "data2", "read"]].
|
|
198
176
|
*/
|
|
199
177
|
getImplicitPermissionsForUser(user: string, ...domain: string[]): Promise<string[][]>;
|
|
200
|
-
/**
|
|
201
|
-
* getPermissionsForUserInDomain gets implicit permissions for a user or role.
|
|
202
|
-
* Compared to getPermissionsForUser(), this function retrieves permissions for inherited roles.
|
|
203
|
-
*/
|
|
204
|
-
getPermissionsForUserInDomain(user: string, domain: string): Promise<string[][]>;
|
|
205
178
|
/**
|
|
206
179
|
* getImplicitUsersForRole gets implicit users that a role has.
|
|
207
180
|
* Compared to getUsersForRole(), this function retrieves indirect users besides direct users.
|
|
@@ -245,11 +218,11 @@ export declare class Enforcer extends ManagementEnforcer {
|
|
|
245
218
|
}
|
|
246
219
|
export declare function newEnforcerWithClass<T extends Enforcer>(enforcer: new () => T, ...params: any[]): Promise<T>;
|
|
247
220
|
/**
|
|
248
|
-
* newEnforcer creates an enforcer via
|
|
221
|
+
* newEnforcer creates an enforcer via file or DB.
|
|
249
222
|
*
|
|
250
|
-
*
|
|
223
|
+
* File:
|
|
251
224
|
* ```js
|
|
252
|
-
* const e = new Enforcer('
|
|
225
|
+
* const e = new Enforcer('path/to/basic_model.conf', 'path/to/basic_policy.csv');
|
|
253
226
|
* ```
|
|
254
227
|
*
|
|
255
228
|
* MySQL DB:
|