Skip to content

Commit d0fc49f

Browse files
committed
fix: stackoverflow in getImplicitRolesForUser
1 parent d88bece commit d0fc49f

File tree

4 files changed

+44
-9
lines changed

4 files changed

+44
-9
lines changed
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# https://github.com/casbin/node-casbin/issues/150
2+
[request_definition]
3+
r = sub, obj, act
4+
5+
[policy_definition]
6+
p = sub, obj, act
7+
8+
[role_definition]
9+
g = _, _
10+
11+
[policy_effect]
12+
e = some(where (p.eft == allow))
13+
14+
[matchers]
15+
m = g(r.sub, p.sub) && r.obj == p.obj && regexMatch(r.act, p.act)
16+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
p, book_admin , /book/1, GET
2+
p, pen_admin , /pen/1, GET
3+
4+
g, *, book_admin
5+
g, *, pen_admin

src/enforcer.ts

+12-8
Original file line numberDiff line numberDiff line change
@@ -280,16 +280,20 @@ export class Enforcer extends ManagementEnforcer {
280280
* But getImplicitRolesForUser("alice") will get: ["role:admin", "role:user"].
281281
*/
282282
public async getImplicitRolesForUser(name: string, ...domain: string[]): Promise<string[]> {
283-
const res: string[] = [];
284-
const roles = await this.rm.getRoles(name, ...domain);
285-
res.push(...roles);
286-
287-
for (const n of roles) {
288-
const role = await this.getImplicitRolesForUser(n, ...domain);
289-
res.push(...role);
283+
const res = new Set<string>();
284+
const q = [name];
285+
let n: string | undefined;
286+
while ((n = q.shift()) != undefined) {
287+
const role = await this.getRoleManager().getRoles(n, ...domain);
288+
role.forEach(r => {
289+
if (!res.has(r)) {
290+
res.add(r);
291+
q.push(r);
292+
}
293+
});
290294
}
291295

292-
return res;
296+
return Array.from(res);
293297
}
294298

295299
/**

test/model.test.ts

+11-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
import * as _ from 'lodash';
1616
import { DefaultRoleManager, Enforcer, newEnforcer, newModel } from '../src';
17-
import { keyMatch2Func, keyMatch3Func } from '../src/util';
17+
import { keyMatch2Func, keyMatch3Func, keyMatchFunc } from '../src/util';
1818

1919
async function testEnforce(e: Enforcer, sub: string, obj: any, act: string, res: boolean): Promise<void> {
2020
await expect(e.enforce(sub, obj, act)).resolves.toBe(res);
@@ -334,3 +334,13 @@ test('TestRBACModelWithPattern', async () => {
334334
await testEnforce(e, 'bob', '/pen2/1', 'GET', true);
335335
await testEnforce(e, 'bob', '/pen2/2', 'GET', true);
336336
});
337+
338+
test('TestNodeCasbin150', async () => {
339+
const e = await newEnforcer('examples/issues/node_casbin_150_model.conf', 'examples/issues/node_casbin_150_policy.csv');
340+
341+
const rm = e.getRoleManager() as DefaultRoleManager;
342+
await rm.addMatchingFunc('KeyMatch', keyMatchFunc);
343+
await e.buildRoleLinks();
344+
345+
await e.getImplicitRolesForUser('alice');
346+
});

0 commit comments

Comments
 (0)