Skip to content

Commit 4d68d28

Browse files
committed
feat: prevent wildcard deletion in deleteUser/deleteRole APIs (#519)
1 parent d8a7cba commit 4d68d28

2 files changed

Lines changed: 102 additions & 0 deletions

File tree

src/enforcer.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,12 @@ export class Enforcer extends ManagementEnforcer {
165165
* @return succeeds or not.
166166
*/
167167
public async deleteRoleForUser(user: string, role: string, domain?: string): Promise<boolean> {
168+
if (!user) {
169+
throw new Error('user must not be empty');
170+
}
171+
if (!role) {
172+
throw new Error('role must not be empty');
173+
}
168174
if (domain === undefined) {
169175
return this.removeGroupingPolicy(user, role);
170176
} else {
@@ -181,6 +187,9 @@ export class Enforcer extends ManagementEnforcer {
181187
* @return succeeds or not.
182188
*/
183189
public async deleteRolesForUser(user: string, domain?: string): Promise<boolean> {
190+
if (!user) {
191+
throw new Error('user must not be empty');
192+
}
184193
if (domain === undefined) {
185194
const subIndex = this.getFieldIndex('p', FieldIndex.Subject);
186195
return this.removeFilteredGroupingPolicy(subIndex, user);
@@ -197,6 +206,9 @@ export class Enforcer extends ManagementEnforcer {
197206
* @return succeeds or not.
198207
*/
199208
public async deleteUser(user: string): Promise<boolean> {
209+
if (!user) {
210+
throw new Error('user must not be empty');
211+
}
200212
const subIndex = this.getFieldIndex('p', FieldIndex.Subject);
201213
const res1 = await this.removeFilteredGroupingPolicy(subIndex, user);
202214
const res2 = await this.removeFilteredPolicy(subIndex, user);
@@ -211,6 +223,9 @@ export class Enforcer extends ManagementEnforcer {
211223
* @return succeeds or not.
212224
*/
213225
public async deleteRole(role: string): Promise<boolean> {
226+
if (!role) {
227+
throw new Error('role must not be empty');
228+
}
214229
const subIndex = this.getFieldIndex('p', FieldIndex.Subject);
215230
const res1 = await this.removeFilteredGroupingPolicy(subIndex, role);
216231
const res2 = await this.removeFilteredPolicy(subIndex, role);
@@ -225,6 +240,9 @@ export class Enforcer extends ManagementEnforcer {
225240
* @return succeeds or not.
226241
*/
227242
public async deletePermission(...permission: string[]): Promise<boolean> {
243+
if (permission.length === 0) {
244+
throw new Error('permission must not be empty');
245+
}
228246
return this.removeFilteredPolicy(1, ...permission);
229247
}
230248

@@ -250,6 +268,9 @@ export class Enforcer extends ManagementEnforcer {
250268
* @return succeeds or not.
251269
*/
252270
public async deletePermissionForUser(user: string, ...permission: string[]): Promise<boolean> {
271+
if (!user) {
272+
throw new Error('user must not be empty');
273+
}
253274
permission.unshift(user);
254275
return this.removePolicy(...permission);
255276
}
@@ -262,6 +283,9 @@ export class Enforcer extends ManagementEnforcer {
262283
* @return succeeds or not.
263284
*/
264285
public async deletePermissionsForUser(user: string): Promise<boolean> {
286+
if (!user) {
287+
throw new Error('user must not be empty');
288+
}
265289
const subIndex = this.getFieldIndex('p', FieldIndex.Subject);
266290
return this.removeFilteredPolicy(subIndex, user);
267291
}

test/rbacAPI.test.ts

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,81 @@ test('test rbac with multiple policy definitions', async () => {
219219
['admin', 'create'],
220220
]);
221221
});
222+
223+
test('test deleteUser with empty string should throw error', async () => {
224+
const e = await newEnforcer('examples/rbac_model.conf', 'examples/rbac_with_hierarchy_policy.csv');
225+
226+
// Store initial state
227+
const initialGPolicies = await e.getGroupingPolicy();
228+
const initialPPolicies = await e.getPolicy();
229+
expect(initialGPolicies.length).toBeGreaterThan(0);
230+
expect(initialPPolicies.length).toBeGreaterThan(0);
231+
232+
// Attempt to delete with empty string should throw
233+
await expect(e.deleteUser('')).rejects.toThrow('user must not be empty');
234+
235+
// Verify nothing was deleted
236+
expect(await e.getGroupingPolicy()).toEqual(initialGPolicies);
237+
expect(await e.getPolicy()).toEqual(initialPPolicies);
238+
});
239+
240+
test('test deleteRole with empty string should throw error', async () => {
241+
const e = await newEnforcer('examples/rbac_model.conf', 'examples/rbac_with_hierarchy_policy.csv');
242+
243+
const initialGPolicies = await e.getGroupingPolicy();
244+
const initialPPolicies = await e.getPolicy();
245+
expect(initialGPolicies.length).toBeGreaterThan(0);
246+
expect(initialPPolicies.length).toBeGreaterThan(0);
247+
248+
await expect(e.deleteRole('')).rejects.toThrow('role must not be empty');
249+
250+
expect(await e.getGroupingPolicy()).toEqual(initialGPolicies);
251+
expect(await e.getPolicy()).toEqual(initialPPolicies);
252+
});
253+
254+
test('test deletePermissionsForUser with empty string should throw error', async () => {
255+
const e = await newEnforcer('examples/rbac_model.conf', 'examples/rbac_with_hierarchy_policy.csv');
256+
257+
const initialPPolicies = await e.getPolicy();
258+
expect(initialPPolicies.length).toBeGreaterThan(0);
259+
260+
await expect(e.deletePermissionsForUser('')).rejects.toThrow('user must not be empty');
261+
262+
expect(await e.getPolicy()).toEqual(initialPPolicies);
263+
});
264+
265+
test('test deleteRolesForUser with empty string should throw error', async () => {
266+
const e = await newEnforcer('examples/rbac_model.conf', 'examples/rbac_with_hierarchy_policy.csv');
267+
268+
const initialGPolicies = await e.getGroupingPolicy();
269+
expect(initialGPolicies.length).toBeGreaterThan(0);
270+
271+
await expect(e.deleteRolesForUser('')).rejects.toThrow('user must not be empty');
272+
273+
expect(await e.getGroupingPolicy()).toEqual(initialGPolicies);
274+
});
275+
276+
test('test deleteRoleForUser with empty strings should throw error', async () => {
277+
const e = await newEnforcer('examples/rbac_model.conf', 'examples/rbac_with_hierarchy_policy.csv');
278+
279+
await expect(e.deleteRoleForUser('', 'admin')).rejects.toThrow('user must not be empty');
280+
await expect(e.deleteRoleForUser('alice', '')).rejects.toThrow('role must not be empty');
281+
await expect(e.deleteRoleForUser('', '')).rejects.toThrow('user must not be empty');
282+
});
283+
284+
test('test deletePermissionForUser with empty string should throw error', async () => {
285+
const e = await newEnforcer('examples/rbac_model.conf', 'examples/rbac_with_hierarchy_policy.csv');
286+
287+
await expect(e.deletePermissionForUser('', 'data1', 'read')).rejects.toThrow('user must not be empty');
288+
});
289+
290+
test('test deletePermission with empty array should throw error', async () => {
291+
const e = await newEnforcer('examples/rbac_model.conf', 'examples/rbac_with_hierarchy_policy.csv');
292+
293+
const initialPPolicies = await e.getPolicy();
294+
expect(initialPPolicies.length).toBeGreaterThan(0);
295+
296+
await expect(e.deletePermission()).rejects.toThrow('permission must not be empty');
297+
298+
expect(await e.getPolicy()).toEqual(initialPPolicies);
299+
});

0 commit comments

Comments
 (0)