TestCachedGFunctionAfterBuildRoleLinks tests the specific scenario mentioned in the bug report: adding grouping policies and calling BuildRoleLinks() manually should properly invalidate the cache.
(t *testing.T)
| 154 | // TestCachedGFunctionAfterBuildRoleLinks tests the specific scenario mentioned in the bug report: |
| 155 | // adding grouping policies and calling BuildRoleLinks() manually should properly invalidate the cache. |
| 156 | func TestCachedGFunctionAfterBuildRoleLinks(t *testing.T) { |
| 157 | e, err := NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv") |
| 158 | if err != nil { |
| 159 | t.Fatalf("Failed to create enforcer: %v", err) |
| 160 | } |
| 161 | |
| 162 | // First, make some enforce calls to ensure the g() function closure is created and cached |
| 163 | // This will cache "bob" NOT having data2_admin role in the g() function's sync.Map |
| 164 | for i := 0; i < 3; i++ { |
| 165 | ok, enforceErr := e.Enforce("bob", "data2", "read") |
| 166 | if enforceErr != nil { |
| 167 | t.Fatalf("Enforce failed on iteration %d: %v", i, enforceErr) |
| 168 | } |
| 169 | if ok { |
| 170 | t.Errorf("bob should not have read access to data2 on iteration %d (before adding role)", i) |
| 171 | } |
| 172 | } |
| 173 | |
| 174 | // Disable autoBuildRoleLinks to manually control when role links are rebuilt |
| 175 | e.EnableAutoBuildRoleLinks(false) |
| 176 | |
| 177 | // Manually add the grouping policy to the model (bypassing BuildIncrementalRoleLinks) |
| 178 | // This simulates the scenario where policies are loaded from database |
| 179 | err = e.model.AddPolicy("g", "g", []string{"bob", "data2_admin"}) |
| 180 | if err != nil { |
| 181 | t.Fatalf("Failed to add grouping policy to model: %v", err) |
| 182 | } |
| 183 | |
| 184 | // Manually build role links as mentioned in the issue |
| 185 | // This is the key part - BuildRoleLinks() should invalidate the matcher map cache |
| 186 | err = e.BuildRoleLinks() |
| 187 | if err != nil { |
| 188 | t.Fatalf("Failed to build role links: %v", err) |
| 189 | } |
| 190 | |
| 191 | // Now bob should have read access to data2 through the data2_admin role |
| 192 | // This is where the bug would manifest - if BuildRoleLinks() doesn't invalidate the cache, |
| 193 | // the old g() function closure with "bob->data2_admin = false" cached will still be used |
| 194 | ok, err := e.Enforce("bob", "data2", "read") |
| 195 | if err != nil { |
| 196 | t.Fatalf("Enforce failed after BuildRoleLinks: %v", err) |
| 197 | } |
| 198 | if !ok { |
| 199 | t.Error("bob should have read access to data2 after BuildRoleLinks() - this indicates the g() function cache was not properly invalidated") |
| 200 | } |
| 201 | } |
nothing calls this directly
no test coverage detected
searching dependent graphs…