From f329687b4777e547918436e523c30ec5e712be07 Mon Sep 17 00:00:00 2001 From: Bingchang Chen <19990626.love@163.com> Date: Mon, 13 Dec 2021 23:31:53 +0800 Subject: [PATCH] fix: multi-level inheritance with different domains (#931) Signed-off-by: abingcbc --- rbac/default-role-manager/role_manager.go | 65 ++++++++++++------- .../default-role-manager/role_manager_test.go | 11 ++++ 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/rbac/default-role-manager/role_manager.go b/rbac/default-role-manager/role_manager.go index eb590837..27c0b10d 100644 --- a/rbac/default-role-manager/role_manager.go +++ b/rbac/default-role-manager/role_manager.go @@ -214,35 +214,52 @@ func (rm *RoleManager) HasLink(name1 string, name2 string, domains ...string) (b matchedDomain := rm.getPatternDomain(domains[0]) - for _, domainName := range matchedDomain { + roleQueue := []string{name1} + inherited := make(map[string]bool) - domainValue, _ := rm.allDomains.LoadOrStore(domainName, &Roles{}) - domain := domainValue.(*Roles) - - if rm.hasPattern { - flag := false - domain.Range(func(key, value interface{}) bool { - if rm.match(name1, key.(string)) && value.(*Role).hasRoleWithMatchingFunc(name2, rm.maxHierarchyLevel, rm.match) { - flag = true - return false + for len(roleQueue) != 0 { + role := roleQueue[0] + roleQueue = roleQueue[1:] + if _, ok := inherited[role]; ok { + continue + } + inherited[role] = true + + for _, domainName := range matchedDomain { + + domainValue, _ := rm.allDomains.LoadOrStore(domainName, &Roles{}) + domain := domainValue.(*Roles) + + if rm.hasPattern { + flag := false + domain.Range(func(key, value interface{}) bool { + if rm.match(role, key.(string)) && value.(*Role).hasRoleWithMatchingFunc(name2, rm.maxHierarchyLevel, rm.match) { + flag = true + return false + } + return true + }) + if flag { + return true, nil + } + } else { + role1Value, ok := domain.Load(role) + if !ok { + continue + } + role1 := role1Value.(*Role) + result := role1.hasRole(name2, rm.maxHierarchyLevel) + if result { + return true, nil + } else { + for _, r := range role1.roles { + roleQueue = append(roleQueue, r.name) + } } - return true - }) - if flag { - return true, nil - } - } else { - role1Value, ok := domain.Load(name1) - if !ok { - continue - } - role1 := role1Value.(*Role) - result := role1.hasRole(name2, rm.maxHierarchyLevel) - if result { - return true, nil } } } + return false, nil default: return false, errors.ERR_DOMAIN_PARAMETER diff --git a/rbac/default-role-manager/role_manager_test.go b/rbac/default-role-manager/role_manager_test.go index 10612086..4abc158a 100644 --- a/rbac/default-role-manager/role_manager_test.go +++ b/rbac/default-role-manager/role_manager_test.go @@ -299,3 +299,14 @@ func TestMatchingFuncOrder(t *testing.T) { testRole(t, rm, "u1", "g1", true) testRole(t, rm, "u1", "g2", true) } + +func TestDomainMatchingFuncWithDifferentDomain(t *testing.T) { + rm := NewRoleManager(10) + rm.AddDomainMatchingFunc("keyMatch", util.KeyMatch) + + _ = rm.AddLink("alice", "editor", "*") + _ = rm.AddLink("editor", "admin", "domain1") + + testDomainRole(t, rm, "alice", "admin", "domain1", true) + testDomainRole(t, rm, "alice", "admin", "domain2", false) +}