Skip to content
Merged
42 changes: 41 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ async function myFunction() {
await e.loadPolicy();

// Check the permission.
e.enforce('alice', 'data1', 'read');
await e.enforce('alice', 'data1', 'read');

// Modify the policy.
// await e.addPolicy(...);
Expand All @@ -70,6 +70,46 @@ async function myFunction() {
}
```

## Simple Filter Example

```typescript
import { newEnforcer } from 'casbin';
import TypeORMAdapter from 'typeorm-adapter';

async function myFunction() {
// Initialize a TypeORM adapter and use it in a Node-Casbin enforcer:
// The adapter can not automatically create database.
// But the adapter will automatically and use the table named "casbin_rule".
// I think ORM should not automatically create databases.
const a = await TypeORMAdapter.newAdapter({
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: '',
database: 'casbin',
});


const e = await newEnforcer('examples/rbac_model.conf', a);

// Load the filtered policy from DB.
await e.loadFilteredPolicy({
'ptype': 'p',
'v0': 'alice'
});

// Check the permission.
await e.enforce('alice', 'data1', 'read');

// Modify the policy.
// await e.addPolicy(...);
// await e.removePolicy(...);

// Save the policy back to DB.
await e.savePolicy();
}
```
## Getting Help

- [Node-Casbin](https://github.com/casbin/node-casbin)
Expand Down
20 changes: 17 additions & 3 deletions src/adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

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

/**
* TypeORMAdapter represents the TypeORM adapter for policy storage.
* TypeORMAdapter represents the TypeORM filtered adapter for policy storage.
*/
export default class TypeORMAdapter implements Adapter {
export default class TypeORMAdapter implements FilteredAdapter {
private option: ConnectionOptions;
private typeorm: Connection;
private filtered = false;

private constructor(option: ConnectionOptions) {
this.option = option;
}

public isFiltered(): boolean {
return this.filtered;
}

/**
* newAdapter is the constructor.
* @param option typeorm connection option
Expand Down Expand Up @@ -80,6 +85,15 @@ export default class TypeORMAdapter implements Adapter {
}
}

// Loading policies based on filter condition
public async loadFilteredPolicy(model: Model, filter: object) {
const filteredLines = await getRepository(this.getCasbinRuleConstructor(), this.option.name).find(filter);
for (const line of filteredLines) {
this.loadPolicyLine(line, model);
}
this.filtered = true;
}

private savePolicyLine(ptype: string, rule: string[]): GenericCasbinRule {
const line = new (this.getCasbinRuleConstructor())();

Expand Down
9 changes: 9 additions & 0 deletions test/adapter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ function testGetPolicy(e: Enforcer, res: string[][]) {
expect(Util.array2DEquals(res, myRes)).toBe(true);
}

function testGetFilteredPolicy(e: Enforcer, res: string[]) {
const myRes = e.getFilteredNamedPolicy('p', 0, 'alice')[0];
expect(Util.arrayEquals(res, myRes)).toBe(true);
}

test('TestAdapter', async () => {
const a = await TypeORMAdapter.newAdapter({
type: 'mysql',
Expand Down Expand Up @@ -66,6 +71,10 @@ test('TestAdapter', async () => {
['data2_admin', 'data2', 'read'],
['data2_admin', 'data2', 'write']]);

// load filtered policies
await a.loadFilteredPolicy(e.getModel(), { ptype: 'p', v0: 'alice'});
testGetFilteredPolicy(e, ['alice', 'data1', 'read']);

// Add policy to DB
await a.addPolicy('', 'p', ['role', 'res', 'action']);
e = await Enforcer.newEnforcer('examples/rbac_model.conf', a);
Expand Down