diff --git a/examples/rbac_with_domains_policy2.csv b/examples/rbac_with_domains_policy2.csv new file mode 100644 index 00000000..baa06f06 --- /dev/null +++ b/examples/rbac_with_domains_policy2.csv @@ -0,0 +1,9 @@ +p, admin, domain1, data1, read +p, admin, domain1, data1, write +p, admin, domain2, data2, read +p, admin, domain2, data2, write +p, user, domain3, data2, read +g, alice, admin, domain1 +g, alice, admin, domain2 +g, bob, admin, domain2 +g, bob, user, domain3 diff --git a/src/enforcer.ts b/src/enforcer.ts index 9ca947ce..f784c138 100644 --- a/src/enforcer.ts +++ b/src/enforcer.ts @@ -464,6 +464,30 @@ export class Enforcer extends ManagementEnforcer { return res.filter((n) => !inherits.some((m) => n === m)); } + + /** + * getDomainsForUser gets all domains that a user has. + */ + public async getDomainsForUser(user: string): Promise { + const domains: string[] = []; + for (const rm of this.rmMap.values()) { + const domain = await rm.getDomains(user); + domains.push(...domain); + } + return domains; + } + + /** + * getAllDomains gets all domains. + */ + public async getAllDomains(): Promise { + const domains: string[] = []; + for (const rm of this.rmMap.values()) { + const domain = await rm.getAllDomains(); + domains.push(...domain); + } + return arrayRemoveDuplicates(domains); + } } export async function newEnforcerWithClass(enforcer: new () => T, ...params: any[]): Promise { diff --git a/src/rbac/defaultRoleManager.ts b/src/rbac/defaultRoleManager.ts index 9d8f39b6..5271f83a 100644 --- a/src/rbac/defaultRoleManager.ts +++ b/src/rbac/defaultRoleManager.ts @@ -352,4 +352,48 @@ export class DefaultRoleManager implements RoleManager { }); } } + + /** + * getDomains gets domains that a user has. + */ + public async getDomains(name: string): Promise { + const domains: string[] = []; + this.allDomains.forEach((roles, domain) => { + // Skip the default domain if there are other domains + if (domain === DEFAULT_DOMAIN && this.allDomains.size > 1) { + return; + } + const role = roles.get(name); + if (role) { + // Check if role has any roles it inherits OR if any other role inherits from it + const hasRoles = role.getRoles().length > 0; + const hasUsers = this.hasUserForRole(roles, name); + if (hasRoles || hasUsers) { + domains.push(domain); + } + } + }); + return domains; + } + + /** + * getAllDomains gets all domains. + */ + public async getAllDomains(): Promise { + const domains = Array.from(this.allDomains.keys()); + // Filter out the default domain if there are other domains + if (domains.length > 1) { + return domains.filter((d) => d !== DEFAULT_DOMAIN); + } + return domains; + } + + private hasUserForRole(roles: Roles, name: string): boolean { + for (const role of roles.values()) { + if (role.hasDirectRole(name)) { + return true; + } + } + return false; + } } diff --git a/src/rbac/roleManager.ts b/src/rbac/roleManager.ts index 54d99c38..4c3afb7e 100644 --- a/src/rbac/roleManager.ts +++ b/src/rbac/roleManager.ts @@ -36,4 +36,8 @@ export interface RoleManager { getUsers(name: string, ...domain: string[]): Promise; // PrintRoles prints all the roles to log. printRoles(): Promise; + // GetDomains gets domains that a user has + getDomains(name: string): Promise; + // GetAllDomains gets all domains + getAllDomains(): Promise; } diff --git a/test/rbacwDomainAPI.test.ts b/test/rbacwDomainAPI.test.ts index c8b8855e..ea29bd81 100644 --- a/test/rbacwDomainAPI.test.ts +++ b/test/rbacwDomainAPI.test.ts @@ -29,3 +29,26 @@ test('test getUsersForRoleInDomain', async () => { expect(await e.getUsersForRoleInDomain('superadmin', 'domain1')).toEqual([]); expect(await e.getUsersForRoleInDomain('superadmin', 'domain2')).toEqual([]); }); + +test('test getDomainsForUser', async () => { + const e = await newEnforcer('examples/rbac_with_domains_model.conf', 'examples/rbac_with_domains_policy2.csv'); + + let myRes = await e.getDomainsForUser('alice'); + myRes.sort(); + expect(myRes).toEqual(['domain1', 'domain2']); + + myRes = await e.getDomainsForUser('bob'); + myRes.sort(); + expect(myRes).toEqual(['domain2', 'domain3']); + + myRes = await e.getDomainsForUser('user'); + expect(myRes).toEqual(['domain3']); +}); + +test('test getAllDomains', async () => { + const e = await newEnforcer('examples/rbac_with_domains_model.conf', 'examples/rbac_with_domains_policy.csv'); + + const myRes = await e.getAllDomains(); + myRes.sort(); + expect(myRes).toEqual(['domain1', 'domain2']); +});