Skip to content

Commit

Permalink
feat: support updateGroupingPolicy(), updateNamedGroupingPolicy()
Browse files Browse the repository at this point in the history
…, `getImplicitResourcesForUser()` (#419)
  • Loading branch information
imp2002 committed Feb 1, 2023
1 parent abf7623 commit 46c0f3a
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 0 deletions.
38 changes: 38 additions & 0 deletions src/enforcer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,44 @@ export class Enforcer extends ManagementEnforcer {
return res;
}

/**
* getImplicitResourcesForUser returns all policies that user obtaining in domain.
*/
public async getImplicitResourcesForUser(user: string, ...domain: string[]): Promise<string[][]> {
const permissions = await this.getImplicitPermissionsForUser(user, ...domain);
const res: string[][] = [];
for (const permission of permissions) {
if (permission[0] === user) {
res.push(permission);
continue;
}
let resLocal: string[][] = [[user]];
const tokensLength: number = permission.length;
const t: string[][] = [];
for (const token of permission) {
if (token === permission[0]) {
continue;
}
const tokens: string[] = await this.getImplicitUsersForRole(token, ...domain);
tokens.push(token);
t.push(tokens);
}
for (let i = 0; i < tokensLength - 1; i++) {
const n: string[][] = [];
for (const tokens of t[i]) {
for (const policy of resLocal) {
const t: string[] = [...policy];
t.push(tokens);
n.push(t);
}
}
resLocal = n;
}
res.push(...resLocal);
}
return res;
}

/**
* getImplicitUsersForRole gets implicit users that a role has.
* Compared to getUsersForRole(), this function retrieves indirect users besides direct users.
Expand Down
23 changes: 23 additions & 0 deletions src/managementEnforcer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,29 @@ export class ManagementEnforcer extends InternalEnforcer {
return this.removeFilteredPolicyInternal('g', ptype, fieldIndex, fieldValues, true);
}

/**
* UpdateGroupingPolicy updates an rule to the current named policy.
*
* @param oldRule the old rule.
* @param newRule the new rule.
* @return succeeds or not.
*/
public async updateGroupingPolicy(oldRule: string[], newRule: string[]): Promise<boolean> {
return this.updateNamedGroupingPolicy('g', oldRule, newRule);
}

/**
* updateNamedGroupingPolicy updates an rule to the current named policy.
*
* @param ptype the policy type, can be "g", "g2", "g3", ..
* @param oldRule the old rule.
* @param newRule the new rule.
* @return succeeds or not.
*/
public async updateNamedGroupingPolicy(ptype: string, oldRule: string[], newRule: string[]): Promise<boolean> {
return this.updatePolicyInternal('g', ptype, oldRule, newRule, true);
}

/**
* addFunction adds a customized function.
* @param name custom function name
Expand Down
23 changes: 23 additions & 0 deletions src/syncedEnforcer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,29 @@ export class SyncedEnforcer extends Enforcer {
return super.removeFilteredNamedGroupingPolicy(ptype, fieldIndex, ...fieldValues).finally(() => this.lock.release());
}

/**
* UpdateGroupingPolicy updates an rule to the current named policy.
*
* @param oldRule the old rule.
* @param newRule the new rule.
* @return succeeds or not.
*/
public async updateGroupingPolicy(oldRule: string[], newRule: string[]): Promise<boolean> {
return super.updateGroupingPolicy(oldRule, newRule);
}

/**
* updateNamedGroupingPolicy updates an rule to the current named policy.
*
* @param ptype the policy type, can be "g", "g2", "g3", ..
* @param oldRule the old rule.
* @param newRule the new rule.
* @return succeeds or not.
*/
public async updateNamedGroupingPolicy(ptype: string, oldRule: string[], newRule: string[]): Promise<boolean> {
return super.updateNamedGroupingPolicy(ptype, oldRule, newRule);
}

/**
* add matching function to RoleManager by ptype
* @param ptype g
Expand Down
24 changes: 24 additions & 0 deletions test/managementAPI.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,3 +353,27 @@ test('removeNamedGroupingPolicies', async () => {
const removed = await e.removeNamedGroupingPolicies('g', groupingRules);
expect(removed).toBe(true);
});

test('updateGroupingPolicy', async () => {
const a = new FileAdapter('examples/rbac_policy.csv');
e.setAdapter(a);

let groupingPolicy = await e.getGroupingPolicy();
testArray2DEquals(groupingPolicy, [['alice', 'data2_admin']]);

const updated = e.updateGroupingPolicy(['alice', 'data2_admin'], ['alice', 'update_test']);
groupingPolicy = await e.getGroupingPolicy();
testArray2DEquals(groupingPolicy, [['alice', 'update_test']]);
});

test('updateNamedGroupingPolicy', async () => {
const a = new FileAdapter('examples/rbac_policy.csv');
e.setAdapter(a);

let groupingPolicy = await e.getGroupingPolicy();
testArray2DEquals(groupingPolicy, [['alice', 'data2_admin']]);

const updated = e.updateNamedGroupingPolicy('g', ['alice', 'data2_admin'], ['alice', 'update_test']);
groupingPolicy = await e.getGroupingPolicy();
testArray2DEquals(groupingPolicy, [['alice', 'update_test']]);
});
22 changes: 22 additions & 0 deletions test/rbacAPI.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,28 @@ test('test getImplicitPermissionsForUser', async () => {
]);
});

test('test getImplicitResourcesForUser', async () => {
const e = await newEnforcer('examples/rbac_with_pattern_model.conf', 'examples/rbac_with_pattern_policy.csv');
expect(await e.getImplicitResourcesForUser('alice')).toEqual([
['alice', '/pen/1', 'GET'],
['alice', '/pen2/1', 'GET'],
['alice', '/book/*', 'GET'],
['alice', '/book/:id', 'GET'],
['alice', '/book2/{id}', 'GET'],
['alice', 'book_group', 'GET'],
]);
expect(await e.getImplicitResourcesForUser('bob')).toEqual([
['bob', '/pen/:id', 'GET'],
['bob', '/pen2/{id}', 'GET'],
['bob', 'pen_group', 'GET'],
]);
expect(await e.getImplicitResourcesForUser('cathy')).toEqual([
['cathy', '/pen/:id', 'GET'],
['cathy', '/pen2/{id}', 'GET'],
['cathy', 'pen_group', 'GET'],
]);
});

test('test deleteRolesForUser', async () => {
const e = await newEnforcer('examples/rbac_model.conf', 'examples/rbac_with_hierarchy_policy.csv');
expect(await e.hasPermissionForUser('bob', 'data2', 'write')).toEqual(true);
Expand Down

0 comments on commit 46c0f3a

Please sign in to comment.