Skip to content

Commit aab0c33

Browse files
authored
Added support for Loading Filtered Policies from DB (#23)
* Added support for loadingfilteredpolicies * Update README.md Added support for loading filtered policies * Added new method to load filtered policies * Code fixed for filteredpolicy * code fixed for filteredpolicy * code fixed for filteredpolicy * Code fixed for filteredadapter * code fixed in test class * code updated * FilteredAdapter * FilteredAdapter implementation for loading filtered policies FilteredAdapter * All review comments incorporated for FilteredAdapter
1 parent a4fa850 commit aab0c33

File tree

3 files changed

+67
-4
lines changed

3 files changed

+67
-4
lines changed

README.md

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ async function myFunction() {
5959
await e.loadPolicy();
6060

6161
// Check the permission.
62-
e.enforce('alice', 'data1', 'read');
62+
await e.enforce('alice', 'data1', 'read');
6363

6464
// Modify the policy.
6565
// await e.addPolicy(...);
@@ -70,6 +70,46 @@ async function myFunction() {
7070
}
7171
```
7272

73+
## Simple Filter Example
74+
75+
```typescript
76+
import { newEnforcer } from 'casbin';
77+
import TypeORMAdapter from 'typeorm-adapter';
78+
79+
async function myFunction() {
80+
// Initialize a TypeORM adapter and use it in a Node-Casbin enforcer:
81+
// The adapter can not automatically create database.
82+
// But the adapter will automatically and use the table named "casbin_rule".
83+
// I think ORM should not automatically create databases.
84+
const a = await TypeORMAdapter.newAdapter({
85+
type: 'mysql',
86+
host: 'localhost',
87+
port: 3306,
88+
username: 'root',
89+
password: '',
90+
database: 'casbin',
91+
});
92+
93+
94+
const e = await newEnforcer('examples/rbac_model.conf', a);
95+
96+
// Load the filtered policy from DB.
97+
await e.loadFilteredPolicy({
98+
'ptype': 'p',
99+
'v0': 'alice'
100+
});
101+
102+
// Check the permission.
103+
await e.enforce('alice', 'data1', 'read');
104+
105+
// Modify the policy.
106+
// await e.addPolicy(...);
107+
// await e.removePolicy(...);
108+
109+
// Save the policy back to DB.
110+
await e.savePolicy();
111+
}
112+
```
73113
## Getting Help
74114

75115
- [Node-Casbin](https://github.com/casbin/node-casbin)

src/adapter.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
import {Adapter, Helper, Model} from 'casbin';
15+
import {Helper, Model, FilteredAdapter} from 'casbin';
1616
import {CasbinRule} from './casbinRule';
1717
import {Connection, ConnectionOptions, createConnection, getRepository, getConnection} from 'typeorm';
1818
import {CasbinMongoRule} from './casbinMongoRule';
@@ -21,16 +21,21 @@ type GenericCasbinRule = CasbinRule | CasbinMongoRule;
2121
type CasbinRuleConstructor = new (...args: any[]) => GenericCasbinRule;
2222

2323
/**
24-
* TypeORMAdapter represents the TypeORM adapter for policy storage.
24+
* TypeORMAdapter represents the TypeORM filtered adapter for policy storage.
2525
*/
26-
export default class TypeORMAdapter implements Adapter {
26+
export default class TypeORMAdapter implements FilteredAdapter {
2727
private option: ConnectionOptions;
2828
private typeorm: Connection;
29+
private filtered = false;
2930

3031
private constructor(option: ConnectionOptions) {
3132
this.option = option;
3233
}
3334

35+
public isFiltered(): boolean {
36+
return this.filtered;
37+
}
38+
3439
/**
3540
* newAdapter is the constructor.
3641
* @param option typeorm connection option
@@ -80,6 +85,15 @@ export default class TypeORMAdapter implements Adapter {
8085
}
8186
}
8287

88+
// Loading policies based on filter condition
89+
public async loadFilteredPolicy(model: Model, filter: object) {
90+
const filteredLines = await getRepository(this.getCasbinRuleConstructor(), this.option.name).find(filter);
91+
for (const line of filteredLines) {
92+
this.loadPolicyLine(line, model);
93+
}
94+
this.filtered = true;
95+
}
96+
8397
private savePolicyLine(ptype: string, rule: string[]): GenericCasbinRule {
8498
const line = new (this.getCasbinRuleConstructor())();
8599

test/adapter.test.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ function testGetPolicy(e: Enforcer, res: string[][]) {
2222
expect(Util.array2DEquals(res, myRes)).toBe(true);
2323
}
2424

25+
function testGetFilteredPolicy(e: Enforcer, res: string[]) {
26+
const myRes = e.getFilteredNamedPolicy('p', 0, 'alice')[0];
27+
expect(Util.arrayEquals(res, myRes)).toBe(true);
28+
}
29+
2530
test('TestAdapter', async () => {
2631
const a = await TypeORMAdapter.newAdapter({
2732
type: 'mysql',
@@ -66,6 +71,10 @@ test('TestAdapter', async () => {
6671
['data2_admin', 'data2', 'read'],
6772
['data2_admin', 'data2', 'write']]);
6873

74+
// load filtered policies
75+
await a.loadFilteredPolicy(e.getModel(), { ptype: 'p', v0: 'alice'});
76+
testGetFilteredPolicy(e, ['alice', 'data1', 'read']);
77+
6978
// Add policy to DB
7079
await a.addPolicy('', 'p', ['role', 'res', 'action']);
7180
e = await Enforcer.newEnforcer('examples/rbac_model.conf', a);

0 commit comments

Comments
 (0)