From 4f738a1548b1e44c3104e022dd9bec71cfef833d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 10 Jan 2026 12:55:10 +0000 Subject: [PATCH 1/5] Initial plan From 4b377b32f95497484af4e6d17aec90e680090a89 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 10 Jan 2026 13:06:00 +0000 Subject: [PATCH 2/5] Implement matcher-based GetImplicitPermissionsForUser for complex matchers Co-authored-by: hsluoyz <3787410+hsluoyz@users.noreply.github.com> --- rbac_api.go | 149 +++++++++++++++++++++++++------ rbac_api_complex_matcher_test.go | 131 +++++++++++++++++++++++++++ 2 files changed, 253 insertions(+), 27 deletions(-) create mode 100644 rbac_api_complex_matcher_test.go diff --git a/rbac_api.go b/rbac_api.go index c1ca4f7a3..850390930 100644 --- a/rbac_api.go +++ b/rbac_api.go @@ -319,49 +319,144 @@ func (e *Enforcer) GetImplicitPermissionsForUser(user string, domain ...string) // But you can specify the named policy "p2" to get: [["admin", "create"]] by GetNamedImplicitPermissionsForUser("p2","alice"). func (e *Enforcer) GetNamedImplicitPermissionsForUser(ptype string, gtype string, user string, domain ...string) ([][]string, error) { permission := make([][]string, 0) - rm := e.GetNamedRoleManager(gtype) - if rm == nil { - return nil, fmt.Errorf("role manager %s is not initialized", gtype) + + // Validate domain parameter + if len(domain) > 1 { + return nil, errors.ErrDomainParameter } - roles, err := e.GetNamedImplicitRolesForUser(gtype, user, domain...) - if err != nil { - return nil, err - } - policyRoles := make(map[string]struct{}, len(roles)+1) - policyRoles[user] = struct{}{} - for _, r := range roles { - policyRoles[r] = struct{}{} + // Get all policies for the specified policy type + if _, ok := e.model["p"][ptype]; !ok { + return permission, nil } - domainIndex, err := e.GetFieldIndex(ptype, constant.DomainIndex) - for _, rule := range e.model["p"][ptype].Policy { - if len(domain) == 0 { - if _, ok := policyRoles[rule[0]]; ok { - permission = append(permission, deepCopyPolicy(rule)) + // Get role manager for domain matching + rm := e.GetNamedRoleManager(gtype) + if rm == nil { + // If no role manager, just check direct permissions + subIndex, err := e.GetFieldIndex(ptype, constant.SubjectIndex) + if err != nil { + subIndex = 0 + } + + for _, rule := range e.model["p"][ptype].Policy { + if rule[subIndex] == user { + if e.policyMatchesDomain(ptype, rule, domain...) { + permission = append(permission, deepCopyPolicy(rule)) + } } - continue } - if len(domain) > 1 { - return nil, errors.ErrDomainParameter + return permission, nil + } + + // Get all roles for the user, considering complex matchers + rolesMap := make(map[string]bool) + rolesMap[user] = true // Include the user itself + + // Get roles with the specific domain if provided + if len(domain) > 0 { + roles, err := e.GetNamedImplicitRolesForUser(gtype, user, domain[0]) + if err != nil { + return nil, err + } + for _, role := range roles { + rolesMap[role] = true + } + + // Also get roles with wildcard domain + wildcardRoles, err := e.GetNamedImplicitRolesForUser(gtype, user, "*") + if err == nil { + for _, role := range wildcardRoles { + rolesMap[role] = true + } } + } else { + // No domain specified - get all possible roles + // This requires getting roles for all possible domains + roles, err := e.GetNamedImplicitRolesForUser(gtype, user) if err != nil { return nil, err } - d := domain[0] - matched := rm.Match(d, rule[domainIndex]) - if !matched { - continue + for _, role := range roles { + rolesMap[role] = true } - if _, ok := policyRoles[rule[0]]; ok { - newRule := deepCopyPolicy(rule) - newRule[domainIndex] = d - permission = append(permission, newRule) + } + + // Get subject index + subIndex, err := e.GetFieldIndex(ptype, constant.SubjectIndex) + if err != nil { + subIndex = 0 + } + + // Check each policy + for _, rule := range e.model["p"][ptype].Policy { + policySubject := rule[subIndex] + + // Check if the policy subject is the user or one of their roles + if rolesMap[policySubject] { + // Check if the policy domain matches the requested domain + if e.policyMatchesDomain(ptype, rule, domain...) { + // If domain is specified and policy has wildcard domain, replace it + if len(domain) > 0 { + domIndex, err := e.GetFieldIndex(ptype, constant.DomainIndex) + if err == nil && domIndex < len(rule) && rule[domIndex] == "*" { + // Replace wildcard domain with requested domain + newRule := deepCopyPolicy(rule) + newRule[domIndex] = domain[0] + permission = append(permission, newRule) + continue + } + } + permission = append(permission, deepCopyPolicy(rule)) + } } } + return permission, nil } +// policyMatchesDomain checks if a policy matches the requested domain +func (e *Enforcer) policyMatchesDomain(ptype string, policy []string, domain ...string) bool { + // If no domain requested, include all policies + if len(domain) == 0 { + return true + } + + // Get domain index + domIndex, err := e.GetFieldIndex(ptype, constant.DomainIndex) + if err != nil || domIndex >= len(policy) { + // No domain in policy - include it + return true + } + + policyDomain := policy[domIndex] + requestedDomain := domain[0] + + // Check for exact match + if policyDomain == requestedDomain { + return true + } + + // Check for wildcard in policy + if policyDomain == "*" { + return true + } + + // Use role manager to check for pattern matching if available + for _, rm := range e.rmMap { + if rm.Match(requestedDomain, policyDomain) { + return true + } + } + for _, crm := range e.condRmMap { + if crm.Match(requestedDomain, policyDomain) { + return true + } + } + + return false +} + // GetImplicitUsersForPermission gets implicit users for a permission. // For example: // p, admin, data1, read diff --git a/rbac_api_complex_matcher_test.go b/rbac_api_complex_matcher_test.go new file mode 100644 index 000000000..a7ca7dd6e --- /dev/null +++ b/rbac_api_complex_matcher_test.go @@ -0,0 +1,131 @@ +// Copyright 2017 The casbin Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package casbin + +import ( + "testing" + + "github.com/casbin/casbin/v3/util" +) + +// TestGetImplicitPermissionsForUserWithComplexMatcher tests the GetImplicitPermissionsForUser +// function with complex matchers that include wildcards and OR conditions. +// This addresses the issue: https://github.com/casbin/node-casbin/issues/481 +func TestGetImplicitPermissionsForUserWithComplexMatcher(t *testing.T) { + e, _ := NewEnforcer("/tmp/test_complex_matcher_model.conf", "/tmp/test_complex_matcher_policy.csv") + + // Test michael who has roles1 in tenant1 + // michael -> roles1 -> abstract_roles1 in tenant1 + // abstract_roles1 has permissions on devis with domain * + perms, err := e.GetImplicitPermissionsForUser("michael", "tenant1") + if err != nil { + t.Fatalf("GetImplicitPermissionsForUser failed: %v", err) + } + + t.Logf("Permissions for michael in tenant1: %v", perms) + + // Michael should have access to devis read and create because: + // - g(michael, abstract_roles1, tenant1) is true (through roles1) + // - p.dom == '*' matches any domain, and we replace * with the requested domain + expectedPerms := [][]string{ + {"abstract_roles1", "devis", "read", "tenant1"}, + {"abstract_roles1", "devis", "create", "tenant1"}, + } + + if !util.Set2DEquals(expectedPerms, perms) { + t.Errorf("Expected permissions %v, got %v", expectedPerms, perms) + } + + // Test thomas who has roles2 in tenant1 and tenant2 + perms, err = e.GetImplicitPermissionsForUser("thomas", "tenant1") + if err != nil { + t.Fatalf("GetImplicitPermissionsForUser failed: %v", err) + } + + t.Logf("Permissions for thomas in tenant1: %v", perms) + + // Thomas should have access to devis and organization because: + // - g(thomas, abstract_roles2, tenant1) is true (through roles2) + // - p.dom == '*' matches any domain, and we replace * with the requested domain + expectedPerms = [][]string{ + {"abstract_roles2", "devis", "read", "tenant1"}, + {"abstract_roles2", "organization", "read", "tenant1"}, + {"abstract_roles2", "organization", "write", "tenant1"}, + } + + if !util.Set2DEquals(expectedPerms, perms) { + t.Errorf("Expected permissions %v, got %v", expectedPerms, perms) + } + + // Test theo who has super_user with wildcard domain + perms, err = e.GetImplicitPermissionsForUser("theo", "any_tenant") + if err != nil { + t.Fatalf("GetImplicitPermissionsForUser failed: %v", err) + } + + t.Logf("Permissions for theo in any_tenant: %v", perms) + + // Theo should have access to all abstract_roles2 permissions because: + // - g(theo, abstract_roles2, '*') is true (through super_user) + // - p.dom == '*' matches any domain, and we replace * with the requested domain + expectedPerms = [][]string{ + {"abstract_roles2", "devis", "read", "any_tenant"}, + {"abstract_roles2", "organization", "read", "any_tenant"}, + {"abstract_roles2", "organization", "write", "any_tenant"}, + } + + if !util.Set2DEquals(expectedPerms, perms) { + t.Errorf("Expected permissions %v, got %v", expectedPerms, perms) + } + + // Verify enforcement also works correctly + allowed, err := e.Enforce("michael", "devis", "read", "tenant1") + if err != nil { + t.Fatalf("Enforce failed: %v", err) + } + if !allowed { + t.Error("michael should be allowed to read devis in tenant1") + } + + allowed, err = e.Enforce("theo", "organization", "write", "any_tenant") + if err != nil { + t.Fatalf("Enforce failed: %v", err) + } + if !allowed { + t.Error("theo should be allowed to write organization in any_tenant") + } +} + +// TestGetImplicitPermissionsForUserWithoutDomain tests that GetImplicitPermissionsForUser +// works correctly when no domain is specified with a domain-based model +func TestGetImplicitPermissionsForUserWithoutDomain(t *testing.T) { + e, _ := NewEnforcer("/tmp/test_complex_matcher_model.conf", "/tmp/test_complex_matcher_policy.csv") + + // When no domain is specified with a domain-based model, behavior depends on + // whether the grouping policies include domain-less entries. + // In this model, all grouping policies have domains, so no roles are returned without domain + perms, err := e.GetImplicitPermissionsForUser("michael") + if err != nil { + t.Fatalf("GetImplicitPermissionsForUser failed: %v", err) + } + + t.Logf("Permissions for michael (no domain): %v", perms) + + // With this specific model/policy setup, no permissions are returned without domain + // because all role assignments have specific domains + if len(perms) != 0 { + t.Logf("Note: Got %d permissions without domain: %v", len(perms), perms) + } +} From c870c31a258861f549578a81297c3fffe9096eb9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 10 Jan 2026 13:08:05 +0000 Subject: [PATCH 3/5] Add documentation for complex matcher support in GetImplicitPermissionsForUser Co-authored-by: hsluoyz <3787410+hsluoyz@users.noreply.github.com> --- rbac_api.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/rbac_api.go b/rbac_api.go index 850390930..9078ffd59 100644 --- a/rbac_api.go +++ b/rbac_api.go @@ -310,6 +310,12 @@ func (e *Enforcer) GetImplicitPermissionsForUser(user string, domain ...string) // GetNamedImplicitPermissionsForUser gets implicit permissions for a user or role by named policy. // Compared to GetNamedPermissionsForUser(), this function retrieves permissions for inherited roles. +// +// This function now supports complex matchers including: +// - Wildcard domains (e.g., g(r.sub, p.sub, '*')) +// - OR conditions in matchers (e.g., g(r.sub, p.sub, r.dom) || g(r.sub, p.sub, '*')) +// - Domain pattern matching +// // For example: // p, admin, data1, read // p2, admin, create @@ -317,6 +323,14 @@ func (e *Enforcer) GetImplicitPermissionsForUser(user string, domain ...string) // // GetImplicitPermissionsForUser("alice") can only get: [["admin", "data1", "read"]], whose policy is default policy "p" // But you can specify the named policy "p2" to get: [["admin", "create"]] by GetNamedImplicitPermissionsForUser("p2","alice"). +// +// For complex matchers with wildcard domains: +// p, role1, data, read, * +// g, user1, role1, tenant1 +// g, user1, role1, * +// +// GetImplicitPermissionsForUser("user1", "tenant1") will return: [["role1", "data", "read", "tenant1"]] +// (Note: wildcard domains in policies are replaced with the requested domain) func (e *Enforcer) GetNamedImplicitPermissionsForUser(ptype string, gtype string, user string, domain ...string) ([][]string, error) { permission := make([][]string, 0) From fda114eb00e037834e14e11a21d2c13d7ffa95bf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 10 Jan 2026 13:53:31 +0000 Subject: [PATCH 4/5] Fix test file paths - move from /tmp to examples directory Co-authored-by: hsluoyz <3787410+hsluoyz@users.noreply.github.com> --- examples/rbac_with_complex_matcher_model.conf | 14 ++++++++++ examples/rbac_with_complex_matcher_policy.csv | 26 +++++++++++++++++++ rbac_api_complex_matcher_test.go | 4 +-- 3 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 examples/rbac_with_complex_matcher_model.conf create mode 100644 examples/rbac_with_complex_matcher_policy.csv diff --git a/examples/rbac_with_complex_matcher_model.conf b/examples/rbac_with_complex_matcher_model.conf new file mode 100644 index 000000000..ba39549de --- /dev/null +++ b/examples/rbac_with_complex_matcher_model.conf @@ -0,0 +1,14 @@ +[request_definition] +r = sub, obj, act, dom + +[policy_definition] +p = sub, obj, act, dom + +[role_definition] +g = _, _, _ + +[policy_effect] +e = some(where (p.eft == allow)) + +[matchers] +m = (g(r.sub, p.sub, r.dom) || g(r.sub, p.sub, '*')) && (p.dom == '*' || r.dom == p.dom) && r.obj == p.obj && r.act == p.act diff --git a/examples/rbac_with_complex_matcher_policy.csv b/examples/rbac_with_complex_matcher_policy.csv new file mode 100644 index 000000000..bbba695f3 --- /dev/null +++ b/examples/rbac_with_complex_matcher_policy.csv @@ -0,0 +1,26 @@ +p, abstract_roles1, devis, read, * +p, abstract_roles1, devis, create, * + +p, abstract_roles2, devis, read, * +p, abstract_roles2, organization, read, * +p, abstract_roles2, organization, write, * + +g, roles1, abstract_roles1, tenant1 +g, roles1, abstract_roles1, tenant2 +g, roles1, abstract_roles1, tenant3 + +g, roles2, abstract_roles2, tenant1 +g, roles2, abstract_roles2, tenant2 +g, roles2, abstract_roles2, tenant3 + +g, super_user, abstract_roles2, * + +g, michael, roles1, tenant1 +g, antoine, roles1, tenant2 +g, kevin, roles1, tenant3 + +g, thomas, roles2, tenant1 +g, thomas, roles2, tenant2 +g, lucie, roles2, tenant3 + +g, theo, super_user, * diff --git a/rbac_api_complex_matcher_test.go b/rbac_api_complex_matcher_test.go index a7ca7dd6e..8a95b7cfb 100644 --- a/rbac_api_complex_matcher_test.go +++ b/rbac_api_complex_matcher_test.go @@ -24,7 +24,7 @@ import ( // function with complex matchers that include wildcards and OR conditions. // This addresses the issue: https://github.com/casbin/node-casbin/issues/481 func TestGetImplicitPermissionsForUserWithComplexMatcher(t *testing.T) { - e, _ := NewEnforcer("/tmp/test_complex_matcher_model.conf", "/tmp/test_complex_matcher_policy.csv") + e, _ := NewEnforcer("examples/rbac_with_complex_matcher_model.conf", "examples/rbac_with_complex_matcher_policy.csv") // Test michael who has roles1 in tenant1 // michael -> roles1 -> abstract_roles1 in tenant1 @@ -111,7 +111,7 @@ func TestGetImplicitPermissionsForUserWithComplexMatcher(t *testing.T) { // TestGetImplicitPermissionsForUserWithoutDomain tests that GetImplicitPermissionsForUser // works correctly when no domain is specified with a domain-based model func TestGetImplicitPermissionsForUserWithoutDomain(t *testing.T) { - e, _ := NewEnforcer("/tmp/test_complex_matcher_model.conf", "/tmp/test_complex_matcher_policy.csv") + e, _ := NewEnforcer("examples/rbac_with_complex_matcher_model.conf", "examples/rbac_with_complex_matcher_policy.csv") // When no domain is specified with a domain-based model, behavior depends on // whether the grouping policies include domain-less entries. From cc163bacd0bfc113d65b38a89192f735c5640e05 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 10 Jan 2026 16:29:57 +0000 Subject: [PATCH 5/5] Fix golangci-lint issues: add periods to comments, reduce nesting, format with goimports Co-authored-by: hsluoyz <3787410+hsluoyz@users.noreply.github.com> --- rbac_api.go | 62 +++++++++++++++++--------------- rbac_api_complex_matcher_test.go | 24 ++++++------- 2 files changed, 45 insertions(+), 41 deletions(-) diff --git a/rbac_api.go b/rbac_api.go index 9078ffd59..c27c4617d 100644 --- a/rbac_api.go +++ b/rbac_api.go @@ -330,10 +330,10 @@ func (e *Enforcer) GetImplicitPermissionsForUser(user string, domain ...string) // g, user1, role1, * // // GetImplicitPermissionsForUser("user1", "tenant1") will return: [["role1", "data", "read", "tenant1"]] -// (Note: wildcard domains in policies are replaced with the requested domain) +// (Note: wildcard domains in policies are replaced with the requested domain). func (e *Enforcer) GetNamedImplicitPermissionsForUser(ptype string, gtype string, user string, domain ...string) ([][]string, error) { permission := make([][]string, 0) - + // Validate domain parameter if len(domain) > 1 { return nil, errors.ErrDomainParameter @@ -352,7 +352,7 @@ func (e *Enforcer) GetNamedImplicitPermissionsForUser(ptype string, gtype string if err != nil { subIndex = 0 } - + for _, rule := range e.model["p"][ptype].Policy { if rule[subIndex] == user { if e.policyMatchesDomain(ptype, rule, domain...) { @@ -366,7 +366,7 @@ func (e *Enforcer) GetNamedImplicitPermissionsForUser(ptype string, gtype string // Get all roles for the user, considering complex matchers rolesMap := make(map[string]bool) rolesMap[user] = true // Include the user itself - + // Get roles with the specific domain if provided if len(domain) > 0 { roles, err := e.GetNamedImplicitRolesForUser(gtype, user, domain[0]) @@ -376,7 +376,7 @@ func (e *Enforcer) GetNamedImplicitPermissionsForUser(ptype string, gtype string for _, role := range roles { rolesMap[role] = true } - + // Also get roles with wildcard domain wildcardRoles, err := e.GetNamedImplicitRolesForUser(gtype, user, "*") if err == nil { @@ -405,57 +405,61 @@ func (e *Enforcer) GetNamedImplicitPermissionsForUser(ptype string, gtype string // Check each policy for _, rule := range e.model["p"][ptype].Policy { policySubject := rule[subIndex] - + // Check if the policy subject is the user or one of their roles - if rolesMap[policySubject] { - // Check if the policy domain matches the requested domain - if e.policyMatchesDomain(ptype, rule, domain...) { - // If domain is specified and policy has wildcard domain, replace it - if len(domain) > 0 { - domIndex, err := e.GetFieldIndex(ptype, constant.DomainIndex) - if err == nil && domIndex < len(rule) && rule[domIndex] == "*" { - // Replace wildcard domain with requested domain - newRule := deepCopyPolicy(rule) - newRule[domIndex] = domain[0] - permission = append(permission, newRule) - continue - } - } - permission = append(permission, deepCopyPolicy(rule)) + if !rolesMap[policySubject] { + continue + } + + // Check if the policy domain matches the requested domain + if !e.policyMatchesDomain(ptype, rule, domain...) { + continue + } + + // If domain is specified and policy has wildcard domain, replace it + if len(domain) > 0 { + domIndex, err := e.GetFieldIndex(ptype, constant.DomainIndex) + if err == nil && domIndex < len(rule) && rule[domIndex] == "*" { + // Replace wildcard domain with requested domain + newRule := deepCopyPolicy(rule) + newRule[domIndex] = domain[0] + permission = append(permission, newRule) + continue } } + permission = append(permission, deepCopyPolicy(rule)) } - + return permission, nil } -// policyMatchesDomain checks if a policy matches the requested domain +// policyMatchesDomain checks if a policy matches the requested domain. func (e *Enforcer) policyMatchesDomain(ptype string, policy []string, domain ...string) bool { // If no domain requested, include all policies if len(domain) == 0 { return true } - + // Get domain index domIndex, err := e.GetFieldIndex(ptype, constant.DomainIndex) if err != nil || domIndex >= len(policy) { // No domain in policy - include it return true } - + policyDomain := policy[domIndex] requestedDomain := domain[0] - + // Check for exact match if policyDomain == requestedDomain { return true } - + // Check for wildcard in policy if policyDomain == "*" { return true } - + // Use role manager to check for pattern matching if available for _, rm := range e.rmMap { if rm.Match(requestedDomain, policyDomain) { @@ -467,7 +471,7 @@ func (e *Enforcer) policyMatchesDomain(ptype string, policy []string, domain ... return true } } - + return false } diff --git a/rbac_api_complex_matcher_test.go b/rbac_api_complex_matcher_test.go index 8a95b7cfb..8f92070b2 100644 --- a/rbac_api_complex_matcher_test.go +++ b/rbac_api_complex_matcher_test.go @@ -33,9 +33,9 @@ func TestGetImplicitPermissionsForUserWithComplexMatcher(t *testing.T) { if err != nil { t.Fatalf("GetImplicitPermissionsForUser failed: %v", err) } - + t.Logf("Permissions for michael in tenant1: %v", perms) - + // Michael should have access to devis read and create because: // - g(michael, abstract_roles1, tenant1) is true (through roles1) // - p.dom == '*' matches any domain, and we replace * with the requested domain @@ -43,7 +43,7 @@ func TestGetImplicitPermissionsForUserWithComplexMatcher(t *testing.T) { {"abstract_roles1", "devis", "read", "tenant1"}, {"abstract_roles1", "devis", "create", "tenant1"}, } - + if !util.Set2DEquals(expectedPerms, perms) { t.Errorf("Expected permissions %v, got %v", expectedPerms, perms) } @@ -53,9 +53,9 @@ func TestGetImplicitPermissionsForUserWithComplexMatcher(t *testing.T) { if err != nil { t.Fatalf("GetImplicitPermissionsForUser failed: %v", err) } - + t.Logf("Permissions for thomas in tenant1: %v", perms) - + // Thomas should have access to devis and organization because: // - g(thomas, abstract_roles2, tenant1) is true (through roles2) // - p.dom == '*' matches any domain, and we replace * with the requested domain @@ -64,7 +64,7 @@ func TestGetImplicitPermissionsForUserWithComplexMatcher(t *testing.T) { {"abstract_roles2", "organization", "read", "tenant1"}, {"abstract_roles2", "organization", "write", "tenant1"}, } - + if !util.Set2DEquals(expectedPerms, perms) { t.Errorf("Expected permissions %v, got %v", expectedPerms, perms) } @@ -74,9 +74,9 @@ func TestGetImplicitPermissionsForUserWithComplexMatcher(t *testing.T) { if err != nil { t.Fatalf("GetImplicitPermissionsForUser failed: %v", err) } - + t.Logf("Permissions for theo in any_tenant: %v", perms) - + // Theo should have access to all abstract_roles2 permissions because: // - g(theo, abstract_roles2, '*') is true (through super_user) // - p.dom == '*' matches any domain, and we replace * with the requested domain @@ -85,7 +85,7 @@ func TestGetImplicitPermissionsForUserWithComplexMatcher(t *testing.T) { {"abstract_roles2", "organization", "read", "any_tenant"}, {"abstract_roles2", "organization", "write", "any_tenant"}, } - + if !util.Set2DEquals(expectedPerms, perms) { t.Errorf("Expected permissions %v, got %v", expectedPerms, perms) } @@ -109,7 +109,7 @@ func TestGetImplicitPermissionsForUserWithComplexMatcher(t *testing.T) { } // TestGetImplicitPermissionsForUserWithoutDomain tests that GetImplicitPermissionsForUser -// works correctly when no domain is specified with a domain-based model +// works correctly when no domain is specified with a domain-based model. func TestGetImplicitPermissionsForUserWithoutDomain(t *testing.T) { e, _ := NewEnforcer("examples/rbac_with_complex_matcher_model.conf", "examples/rbac_with_complex_matcher_policy.csv") @@ -120,9 +120,9 @@ func TestGetImplicitPermissionsForUserWithoutDomain(t *testing.T) { if err != nil { t.Fatalf("GetImplicitPermissionsForUser failed: %v", err) } - + t.Logf("Permissions for michael (no domain): %v", perms) - + // With this specific model/policy setup, no permissions are returned without domain // because all role assignments have specific domains if len(perms) != 0 {