Skip to content

Commit

Permalink
fix: Fix failing typeorm-adapter with ACL model (#61)
Browse files Browse the repository at this point in the history
Signed-off-by: Oleksandr Andriienko <oandriie@redhat.com>
  • Loading branch information
AndrienkoAleksandr committed Jul 18, 2023
1 parent 0d056ab commit 612a9c9
Show file tree
Hide file tree
Showing 7 changed files with 153 additions and 6 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -4,3 +4,4 @@ node_modules
lib
yarn-error.log
package-lock.json
coverage
11 changes: 11 additions & 0 deletions examples/acl_model.conf
@@ -0,0 +1,11 @@
[request_definition]
r = sub, obj, act

[policy_definition]
p = sub, obj, act

[policy_effect]
e = some(where (p.eft == allow))

[matchers]
m = r.sub == p.sub && r.obj == p.obj && r.act == p.act
2 changes: 2 additions & 0 deletions examples/acl_policy.csv
@@ -0,0 +1,2 @@
p, alice, data1, read
p, bob, data2, write
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -8,7 +8,7 @@
"precommit": "lint-staged",
"prepublish": "yarn run lint && yarn build",
"build": "rimraf lib && tsc",
"coverage": "jest --coverage",
"coverage": "jest --coverage --runInBand",
"lint": "tslint \"src/**/*.ts\"",
"fix": "tslint \"src/**/*.ts\" --fix",
"test": "jest --runInBand",
Expand Down
12 changes: 7 additions & 5 deletions src/adapter.ts
Expand Up @@ -195,11 +195,13 @@ export default class TypeORMAdapter implements FilteredAdapter {
}

astMap = model.model.get('g');
// @ts-ignore
for (const [ptype, ast] of astMap) {
for (const rule of ast.policy) {
const line = this.savePolicyLine(ptype, rule);
lines.push(line);
if (astMap) {
// @ts-ignore
for (const [ptype, ast] of astMap) {
for (const rule of ast.policy) {
const line = this.savePolicyLine(ptype, rule);
lines.push(line);
}
}
}

Expand Down
131 changes: 131 additions & 0 deletions test/adapter-with-acl-model.test.ts
@@ -0,0 +1,131 @@
// Copyright 2018 The Casbin Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import { Enforcer, Util } from 'casbin';
import TypeORMAdapter from '../src/index';
import { connectionConfig } from './config';

test(
'TestAdapter',
async () => {
const a = await TypeORMAdapter.newAdapter(connectionConfig);
try {
// Because the DB is empty at first,
// so we need to load the policy from the file adapter (.CSV) first.
let e = new Enforcer();

await e.initWithFile(
'examples/acl_model.conf',
'examples/acl_policy.csv',
);

// This is a trick to save the current policy to the DB.
// We can't call e.savePolicy() because the adapter in the enforcer is still the file adapter.
// The current policy means the policy in the Node-Casbin enforcer (aka in memory).
await a.savePolicy(e.getModel());

// Clear the current policy.
e.clearPolicy();
expect(await e.getPolicy()).toEqual([]);

// Load the policy from DB.
await a.loadPolicy(e.getModel());
expect(await e.getPolicy()).toEqual([
['alice', 'data1', 'read'],
['bob', 'data2', 'write'],
]);

// Note: you don't need to look at the above code
// if you already have a working DB with policy inside.

// Now the DB has policy, so we can provide a normal use case.
// Create an adapter and an enforcer.
// newEnforcer() will load the policy automatically.
e = new Enforcer();
await e.initWithAdapter('examples/rbac_model.conf', a);
expect(await e.getPolicy()).toEqual([
['alice', 'data1', 'read'],
['bob', 'data2', 'write'],
]);

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

// Add policy to DB
await a.addPolicy('', 'p', ['role', 'res', 'action']);
e = new Enforcer();
await e.initWithAdapter('examples/rbac_model.conf', a);
expect(await e.getPolicy()).toEqual([
['alice', 'data1', 'read'],
['bob', 'data2', 'write'],
['role', 'res', 'action'],
]);

await a.addPolicies('', 'p', [
['role1', 'res1', 'action1'],
['role2', 'res2', 'action2'],
['role3', 'res3', 'action3'],
['role4', 'res4', 'action4'],
['role5', 'res5', 'action5'],
]);
e = new Enforcer();
await e.initWithAdapter('examples/rbac_model.conf', a);
expect(await e.getPolicy()).toEqual([
['alice', 'data1', 'read'],
['bob', 'data2', 'write'],
['role', 'res', 'action'],
['role1', 'res1', 'action1'],
['role2', 'res2', 'action2'],
['role3', 'res3', 'action3'],
['role4', 'res4', 'action4'],
['role5', 'res5', 'action5'],
]);

// Remove policy from DB
await a.removePolicy('', 'p', ['role', 'res', 'action']);
e = new Enforcer();
await e.initWithAdapter('examples/rbac_model.conf', a);
expect(await e.getPolicy()).toEqual([
['alice', 'data1', 'read'],
['bob', 'data2', 'write'],
['role1', 'res1', 'action1'],
['role2', 'res2', 'action2'],
['role3', 'res3', 'action3'],
['role4', 'res4', 'action4'],
['role5', 'res5', 'action5'],
]);

await a.removePolicies('', 'p', [
['role1', 'res1', 'action1'],
['role2', 'res2', 'action2'],
['role3', 'res3', 'action3'],
['role4', 'res4', 'action4'],
['role5', 'res5', 'action5'],
]);
e = new Enforcer();
await e.initWithAdapter('examples/rbac_model.conf', a);
expect(await e.getPolicy()).toEqual([
['alice', 'data1', 'read'],
['bob', 'data2', 'write'],
]);
} finally {
a.close();
}
},
60 * 1000,
);
File renamed without changes.

0 comments on commit 612a9c9

Please sign in to comment.