blob: d349185265f2537d2f81e2d7460cf84375b40967 [file] [log] [blame]
// 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 (
"sync"
"testing"
"github.com/casbin/casbin/v3/model"
fileadapter "github.com/casbin/casbin/v3/persist/file-adapter"
"github.com/casbin/casbin/v3/util"
)
func TestKeyMatchModelInMemory(t *testing.T) {
m := model.NewModel()
m.AddDef("r", "r", "sub, obj, act")
m.AddDef("p", "p", "sub, obj, act")
m.AddDef("e", "e", "some(where (p.eft == allow))")
m.AddDef("m", "m", "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)")
a := fileadapter.NewAdapter("examples/keymatch_policy.csv")
e, _ := NewEnforcer(m, a)
testEnforce(t, e, "alice", "/alice_data/resource1", "GET", true)
testEnforce(t, e, "alice", "/alice_data/resource1", "POST", true)
testEnforce(t, e, "alice", "/alice_data/resource2", "GET", true)
testEnforce(t, e, "alice", "/alice_data/resource2", "POST", false)
testEnforce(t, e, "alice", "/bob_data/resource1", "GET", false)
testEnforce(t, e, "alice", "/bob_data/resource1", "POST", false)
testEnforce(t, e, "alice", "/bob_data/resource2", "GET", false)
testEnforce(t, e, "alice", "/bob_data/resource2", "POST", false)
testEnforce(t, e, "bob", "/alice_data/resource1", "GET", false)
testEnforce(t, e, "bob", "/alice_data/resource1", "POST", false)
testEnforce(t, e, "bob", "/alice_data/resource2", "GET", true)
testEnforce(t, e, "bob", "/alice_data/resource2", "POST", false)
testEnforce(t, e, "bob", "/bob_data/resource1", "GET", false)
testEnforce(t, e, "bob", "/bob_data/resource1", "POST", true)
testEnforce(t, e, "bob", "/bob_data/resource2", "GET", false)
testEnforce(t, e, "bob", "/bob_data/resource2", "POST", true)
testEnforce(t, e, "cathy", "/cathy_data", "GET", true)
testEnforce(t, e, "cathy", "/cathy_data", "POST", true)
testEnforce(t, e, "cathy", "/cathy_data", "DELETE", false)
e, _ = NewEnforcer(m)
_ = a.LoadPolicy(e.GetModel())
testEnforce(t, e, "alice", "/alice_data/resource1", "GET", true)
testEnforce(t, e, "alice", "/alice_data/resource1", "POST", true)
testEnforce(t, e, "alice", "/alice_data/resource2", "GET", true)
testEnforce(t, e, "alice", "/alice_data/resource2", "POST", false)
testEnforce(t, e, "alice", "/bob_data/resource1", "GET", false)
testEnforce(t, e, "alice", "/bob_data/resource1", "POST", false)
testEnforce(t, e, "alice", "/bob_data/resource2", "GET", false)
testEnforce(t, e, "alice", "/bob_data/resource2", "POST", false)
testEnforce(t, e, "bob", "/alice_data/resource1", "GET", false)
testEnforce(t, e, "bob", "/alice_data/resource1", "POST", false)
testEnforce(t, e, "bob", "/alice_data/resource2", "GET", true)
testEnforce(t, e, "bob", "/alice_data/resource2", "POST", false)
testEnforce(t, e, "bob", "/bob_data/resource1", "GET", false)
testEnforce(t, e, "bob", "/bob_data/resource1", "POST", true)
testEnforce(t, e, "bob", "/bob_data/resource2", "GET", false)
testEnforce(t, e, "bob", "/bob_data/resource2", "POST", true)
testEnforce(t, e, "cathy", "/cathy_data", "GET", true)
testEnforce(t, e, "cathy", "/cathy_data", "POST", true)
testEnforce(t, e, "cathy", "/cathy_data", "DELETE", false)
}
func TestKeyMatchWithRBACInDomain(t *testing.T) {
e, _ := NewEnforcer("examples/keymatch_with_rbac_in_domain.conf", "examples/keymatch_with_rbac_in_domain.csv")
testDomainEnforce(t, e, "Username==test2", "engines/engine1", "*", "attach", true)
}
func TestKeyMatchModelInMemoryDeny(t *testing.T) {
m := model.NewModel()
m.AddDef("r", "r", "sub, obj, act")
m.AddDef("p", "p", "sub, obj, act")
m.AddDef("e", "e", "!some(where (p.eft == deny))")
m.AddDef("m", "m", "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)")
a := fileadapter.NewAdapter("examples/keymatch_policy.csv")
e, _ := NewEnforcer(m, a)
testEnforce(t, e, "alice", "/alice_data/resource2", "POST", true)
}
func TestRBACModelInMemoryIndeterminate(t *testing.T) {
m := model.NewModel()
m.AddDef("r", "r", "sub, obj, act")
m.AddDef("p", "p", "sub, obj, act")
m.AddDef("g", "g", "_, _")
m.AddDef("e", "e", "some(where (p.eft == allow))")
m.AddDef("m", "m", "g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act")
e, _ := NewEnforcer(m)
_, _ = e.AddPermissionForUser("alice", "data1", "invalid")
testEnforce(t, e, "alice", "data1", "read", false)
}
func TestRBACModelInMemory(t *testing.T) {
m := model.NewModel()
m.AddDef("r", "r", "sub, obj, act")
m.AddDef("p", "p", "sub, obj, act")
m.AddDef("g", "g", "_, _")
m.AddDef("e", "e", "some(where (p.eft == allow))")
m.AddDef("m", "m", "g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act")
e, _ := NewEnforcer(m)
_, _ = e.AddPermissionForUser("alice", "data1", "read")
_, _ = e.AddPermissionForUser("bob", "data2", "write")
_, _ = e.AddPermissionForUser("data2_admin", "data2", "read")
_, _ = e.AddPermissionForUser("data2_admin", "data2", "write")
_, _ = e.AddRoleForUser("alice", "data2_admin")
testEnforce(t, e, "alice", "data1", "read", true)
testEnforce(t, e, "alice", "data1", "write", false)
testEnforce(t, e, "alice", "data2", "read", true)
testEnforce(t, e, "alice", "data2", "write", true)
testEnforce(t, e, "bob", "data1", "read", false)
testEnforce(t, e, "bob", "data1", "write", false)
testEnforce(t, e, "bob", "data2", "read", false)
testEnforce(t, e, "bob", "data2", "write", true)
}
func TestRBACModelInMemory2(t *testing.T) {
text :=
`
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
`
m, _ := model.NewModelFromString(text)
// The above is the same as:
// m := NewModel()
// m.LoadModelFromText(text)
e, _ := NewEnforcer(m)
_, _ = e.AddPermissionForUser("alice", "data1", "read")
_, _ = e.AddPermissionForUser("bob", "data2", "write")
_, _ = e.AddPermissionForUser("data2_admin", "data2", "read")
_, _ = e.AddPermissionForUser("data2_admin", "data2", "write")
_, _ = e.AddRoleForUser("alice", "data2_admin")
testEnforce(t, e, "alice", "data1", "read", true)
testEnforce(t, e, "alice", "data1", "write", false)
testEnforce(t, e, "alice", "data2", "read", true)
testEnforce(t, e, "alice", "data2", "write", true)
testEnforce(t, e, "bob", "data1", "read", false)
testEnforce(t, e, "bob", "data1", "write", false)
testEnforce(t, e, "bob", "data2", "read", false)
testEnforce(t, e, "bob", "data2", "write", true)
}
func TestNotUsedRBACModelInMemory(t *testing.T) {
m := model.NewModel()
m.AddDef("r", "r", "sub, obj, act")
m.AddDef("p", "p", "sub, obj, act")
m.AddDef("g", "g", "_, _")
m.AddDef("e", "e", "some(where (p.eft == allow))")
m.AddDef("m", "m", "g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act")
e, _ := NewEnforcer(m)
_, _ = e.AddPermissionForUser("alice", "data1", "read")
_, _ = e.AddPermissionForUser("bob", "data2", "write")
testEnforce(t, e, "alice", "data1", "read", true)
testEnforce(t, e, "alice", "data1", "write", false)
testEnforce(t, e, "alice", "data2", "read", false)
testEnforce(t, e, "alice", "data2", "write", false)
testEnforce(t, e, "bob", "data1", "read", false)
testEnforce(t, e, "bob", "data1", "write", false)
testEnforce(t, e, "bob", "data2", "read", false)
testEnforce(t, e, "bob", "data2", "write", true)
}
func TestMatcherUsingInOperator(t *testing.T) {
// From file config
e, _ := NewEnforcer("examples/rbac_model_matcher_using_in_op.conf")
_, _ = e.AddPermissionForUser("alice", "data1", "read")
testEnforce(t, e, "alice", "data1", "read", true)
testEnforce(t, e, "alice", "data2", "read", true)
testEnforce(t, e, "alice", "data3", "read", true)
testEnforce(t, e, "anyone", "data1", "read", false)
testEnforce(t, e, "anyone", "data2", "read", true)
testEnforce(t, e, "anyone", "data3", "read", true)
}
func TestMatcherUsingInOperatorBracket(t *testing.T) {
e, _ := NewEnforcer("examples/rbac_model_matcher_using_in_op_bracket.conf")
_, _ = e.AddPermissionForUser("alice", "data1", "read")
testEnforce(t, e, "alice", "data1", "read", true)
testEnforce(t, e, "alice", "data2", "read", true)
testEnforce(t, e, "alice", "data3", "read", true)
testEnforce(t, e, "anyone", "data1", "read", false)
testEnforce(t, e, "anyone", "data2", "read", true)
testEnforce(t, e, "anyone", "data3", "read", true)
}
func TestReloadPolicy(t *testing.T) {
e, _ := NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")
_ = e.LoadPolicy()
testGetPolicy(t, e, [][]string{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"data2_admin", "data2", "read"}, {"data2_admin", "data2", "write"}})
}
func TestSavePolicy(t *testing.T) {
e, _ := NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")
_ = e.SavePolicy()
}
func TestClearPolicy(t *testing.T) {
e, _ := NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")
e.ClearPolicy()
}
func TestEnableEnforce(t *testing.T) {
e, _ := NewEnforcer("examples/basic_model.conf", "examples/basic_policy.csv")
e.EnableEnforce(false)
testEnforce(t, e, "alice", "data1", "read", true)
testEnforce(t, e, "alice", "data1", "write", true)
testEnforce(t, e, "alice", "data2", "read", true)
testEnforce(t, e, "alice", "data2", "write", true)
testEnforce(t, e, "bob", "data1", "read", true)
testEnforce(t, e, "bob", "data1", "write", true)
testEnforce(t, e, "bob", "data2", "read", true)
testEnforce(t, e, "bob", "data2", "write", true)
e.EnableEnforce(true)
testEnforce(t, e, "alice", "data1", "read", true)
testEnforce(t, e, "alice", "data1", "write", false)
testEnforce(t, e, "alice", "data2", "read", false)
testEnforce(t, e, "alice", "data2", "write", false)
testEnforce(t, e, "bob", "data1", "read", false)
testEnforce(t, e, "bob", "data1", "write", false)
testEnforce(t, e, "bob", "data2", "read", false)
testEnforce(t, e, "bob", "data2", "write", true)
}
func TestEnableLog(t *testing.T) {
// This test is now a no-op since the logger has been removed
// Keeping it for backward compatibility, but it just tests enforcement
e, _ := NewEnforcer("examples/basic_model.conf", "examples/basic_policy.csv")
testEnforce(t, e, "alice", "data1", "read", true)
testEnforce(t, e, "alice", "data1", "write", false)
testEnforce(t, e, "alice", "data2", "read", false)
testEnforce(t, e, "alice", "data2", "write", false)
testEnforce(t, e, "bob", "data1", "read", false)
testEnforce(t, e, "bob", "data1", "write", false)
testEnforce(t, e, "bob", "data2", "read", false)
testEnforce(t, e, "bob", "data2", "write", true)
}
func TestEnableAutoSave(t *testing.T) {
e, _ := NewEnforcer("examples/basic_model.conf", "examples/basic_policy.csv")
e.EnableAutoSave(false)
// Because AutoSave is disabled, the policy change only affects the policy in Casbin enforcer,
// it doesn't affect the policy in the storage.
_, _ = e.RemovePolicy("alice", "data1", "read")
// Reload the policy from the storage to see the effect.
_ = e.LoadPolicy()
testEnforce(t, e, "alice", "data1", "read", true)
testEnforce(t, e, "alice", "data1", "write", false)
testEnforce(t, e, "alice", "data2", "read", false)
testEnforce(t, e, "alice", "data2", "write", false)
testEnforce(t, e, "bob", "data1", "read", false)
testEnforce(t, e, "bob", "data1", "write", false)
testEnforce(t, e, "bob", "data2", "read", false)
testEnforce(t, e, "bob", "data2", "write", true)
e.EnableAutoSave(true)
// Because AutoSave is enabled, the policy change not only affects the policy in Casbin enforcer,
// but also affects the policy in the storage.
_, _ = e.RemovePolicy("alice", "data1", "read")
// However, the file adapter doesn't implement the AutoSave feature, so enabling it has no effect at all here.
// Reload the policy from the storage to see the effect.
_ = e.LoadPolicy()
testEnforce(t, e, "alice", "data1", "read", true) // Will not be false here.
testEnforce(t, e, "alice", "data1", "write", false)
testEnforce(t, e, "alice", "data2", "read", false)
testEnforce(t, e, "alice", "data2", "write", false)
testEnforce(t, e, "bob", "data1", "read", false)
testEnforce(t, e, "bob", "data1", "write", false)
testEnforce(t, e, "bob", "data2", "read", false)
testEnforce(t, e, "bob", "data2", "write", true)
}
func TestInitWithAdapter(t *testing.T) {
adapter := fileadapter.NewAdapter("examples/basic_policy.csv")
e, _ := NewEnforcer("examples/basic_model.conf", adapter)
testEnforce(t, e, "alice", "data1", "read", true)
testEnforce(t, e, "alice", "data1", "write", false)
testEnforce(t, e, "alice", "data2", "read", false)
testEnforce(t, e, "alice", "data2", "write", false)
testEnforce(t, e, "bob", "data1", "read", false)
testEnforce(t, e, "bob", "data1", "write", false)
testEnforce(t, e, "bob", "data2", "read", false)
testEnforce(t, e, "bob", "data2", "write", true)
}
func TestRoleLinks(t *testing.T) {
e, _ := NewEnforcer("examples/rbac_model.conf")
e.EnableAutoBuildRoleLinks(false)
_ = e.BuildRoleLinks()
_, _ = e.Enforce("user501", "data9", "read")
}
func TestEnforceConcurrency(t *testing.T) {
defer func() {
if r := recover(); r != nil {
t.Errorf("Enforce is not concurrent")
}
}()
e, _ := NewEnforcer("examples/rbac_model.conf")
_ = e.LoadModel()
var wg sync.WaitGroup
// Simulate concurrency (maybe use a timer?)
for i := 1; i <= 10000; i++ {
wg.Add(1)
go func() {
_, _ = e.Enforce("user501", "data9", "read")
wg.Done()
}()
}
wg.Wait()
}
func TestGetAndSetModel(t *testing.T) {
e, _ := NewEnforcer("examples/basic_model.conf", "examples/basic_policy.csv")
e2, _ := NewEnforcer("examples/basic_with_root_model.conf", "examples/basic_policy.csv")
testEnforce(t, e, "root", "data1", "read", false)
e.SetModel(e2.GetModel())
testEnforce(t, e, "root", "data1", "read", true)
}
func TestGetAndSetAdapterInMem(t *testing.T) {
e, _ := NewEnforcer("examples/basic_model.conf", "examples/basic_policy.csv")
e2, _ := NewEnforcer("examples/basic_model.conf", "examples/basic_inverse_policy.csv")
testEnforce(t, e, "alice", "data1", "read", true)
testEnforce(t, e, "alice", "data1", "write", false)
a2 := e2.GetAdapter()
e.SetAdapter(a2)
_ = e.LoadPolicy()
testEnforce(t, e, "alice", "data1", "read", false)
testEnforce(t, e, "alice", "data1", "write", true)
}
func TestSetAdapterFromFile(t *testing.T) {
e, _ := NewEnforcer("examples/basic_model.conf")
testEnforce(t, e, "alice", "data1", "read", false)
a := fileadapter.NewAdapter("examples/basic_policy.csv")
e.SetAdapter(a)
_ = e.LoadPolicy()
testEnforce(t, e, "alice", "data1", "read", true)
}
func TestInitEmpty(t *testing.T) {
e, _ := NewEnforcer()
m := model.NewModel()
m.AddDef("r", "r", "sub, obj, act")
m.AddDef("p", "p", "sub, obj, act")
m.AddDef("e", "e", "some(where (p.eft == allow))")
m.AddDef("m", "m", "r.sub == p.sub && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)")
a := fileadapter.NewAdapter("examples/keymatch_policy.csv")
e.SetModel(m)
e.SetAdapter(a)
_ = e.LoadPolicy()
testEnforce(t, e, "alice", "/alice_data/resource1", "GET", true)
}
func testEnforceEx(t *testing.T, e *Enforcer, sub, obj, act interface{}, res []string) {
t.Helper()
_, myRes, _ := e.EnforceEx(sub, obj, act)
if ok := util.ArrayEquals(res, myRes); !ok {
t.Error("Key: ", myRes, ", supposed to be ", res)
}
}
func TestEnforceEx(t *testing.T) {
e, _ := NewEnforcer("examples/basic_model.conf", "examples/basic_policy.csv")
testEnforceEx(t, e, "alice", "data1", "read", []string{"alice", "data1", "read"})
testEnforceEx(t, e, "alice", "data1", "write", []string{})
testEnforceEx(t, e, "alice", "data2", "read", []string{})
testEnforceEx(t, e, "alice", "data2", "write", []string{})
testEnforceEx(t, e, "bob", "data1", "read", []string{})
testEnforceEx(t, e, "bob", "data1", "write", []string{})
testEnforceEx(t, e, "bob", "data2", "read", []string{})
testEnforceEx(t, e, "bob", "data2", "write", []string{"bob", "data2", "write"})
e, _ = NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")
testEnforceEx(t, e, "alice", "data1", "read", []string{"alice", "data1", "read"})
testEnforceEx(t, e, "alice", "data1", "write", []string{})
testEnforceEx(t, e, "alice", "data2", "read", []string{"data2_admin", "data2", "read"})
testEnforceEx(t, e, "alice", "data2", "write", []string{"data2_admin", "data2", "write"})
testEnforceEx(t, e, "bob", "data1", "read", []string{})
testEnforceEx(t, e, "bob", "data1", "write", []string{})
testEnforceEx(t, e, "bob", "data2", "read", []string{})
testEnforceEx(t, e, "bob", "data2", "write", []string{"bob", "data2", "write"})
e, _ = NewEnforcer("examples/priority_model.conf", "examples/priority_policy.csv")
testEnforceEx(t, e, "alice", "data1", "read", []string{"alice", "data1", "read", "allow"})
testEnforceEx(t, e, "alice", "data1", "write", []string{"data1_deny_group", "data1", "write", "deny"})
testEnforceEx(t, e, "alice", "data2", "read", []string{})
testEnforceEx(t, e, "alice", "data2", "write", []string{})
testEnforceEx(t, e, "bob", "data1", "write", []string{})
testEnforceEx(t, e, "bob", "data2", "read", []string{"data2_allow_group", "data2", "read", "allow"})
testEnforceEx(t, e, "bob", "data2", "write", []string{"bob", "data2", "write", "deny"})
e, _ = NewEnforcer("examples/abac_model.conf")
obj := struct{ Owner string }{Owner: "alice"}
testEnforceEx(t, e, "alice", obj, "write", []string{})
}
func TestEnforceExLog(t *testing.T) {
// This test was previously named for logging, but actually tests EnforceEx explain functionality
// Logger parameter has been removed, but the test still validates explain behavior
e, _ := NewEnforcer("examples/basic_model.conf", "examples/basic_policy.csv")
testEnforceEx(t, e, "alice", "data1", "read", []string{"alice", "data1", "read"})
testEnforceEx(t, e, "alice", "data1", "write", []string{})
testEnforceEx(t, e, "alice", "data2", "read", []string{})
testEnforceEx(t, e, "alice", "data2", "write", []string{})
testEnforceEx(t, e, "bob", "data1", "read", []string{})
testEnforceEx(t, e, "bob", "data1", "write", []string{})
testEnforceEx(t, e, "bob", "data2", "read", []string{})
testEnforceEx(t, e, "bob", "data2", "write", []string{"bob", "data2", "write"})
}
func testBatchEnforce(t *testing.T, e *Enforcer, requests [][]interface{}, results []bool) {
t.Helper()
myRes, _ := e.BatchEnforce(requests)
if len(myRes) != len(results) {
t.Errorf("%v supposed to be %v", myRes, results)
}
for i, v := range myRes {
if v != results[i] {
t.Errorf("%v supposed to be %v", myRes, results)
}
}
}
func TestBatchEnforce(t *testing.T) {
e, _ := NewEnforcer("examples/basic_model.conf", "examples/basic_policy.csv")
results := []bool{true, true, false}
testBatchEnforce(t, e, [][]interface{}{{"alice", "data1", "read"}, {"bob", "data2", "write"}, {"jack", "data3", "read"}}, results)
}
func TestSubjectPriority(t *testing.T) {
e, _ := NewEnforcer("examples/subject_priority_model.conf", "examples/subject_priority_policy.csv")
testBatchEnforce(t, e, [][]interface{}{
{"jane", "data1", "read"},
{"alice", "data1", "read"},
}, []bool{
true, true,
})
}
func TestSubjectPriorityWithDomain(t *testing.T) {
e, _ := NewEnforcer("examples/subject_priority_model_with_domain.conf", "examples/subject_priority_policy_with_domain.csv")
testBatchEnforce(t, e, [][]interface{}{
{"alice", "data1", "domain1", "write"},
{"bob", "data2", "domain2", "write"},
}, []bool{
true, true,
})
}
func TestSubjectPriorityInFilter(t *testing.T) {
e, _ := NewEnforcer()
adapter := fileadapter.NewFilteredAdapter("examples/subject_priority_policy_with_domain.csv")
_ = e.InitWithAdapter("examples/subject_priority_model_with_domain.conf", adapter)
if err := e.loadFilteredPolicy(&fileadapter.Filter{
P: []string{"", "", "domain1"},
}); err != nil {
t.Errorf("unexpected error in LoadFilteredPolicy: %v", err)
}
testBatchEnforce(t, e, [][]interface{}{
{"alice", "data1", "domain1", "write"},
{"admin", "data1", "domain1", "write"},
}, []bool{
true, false,
})
}
func TestMultiplePolicyDefinitions(t *testing.T) {
e, _ := NewEnforcer("examples/multiple_policy_definitions_model.conf", "examples/multiple_policy_definitions_policy.csv")
enforceContext := NewEnforceContext("2")
enforceContext.EType = "e"
testBatchEnforce(t, e, [][]interface{}{
{"alice", "data2", "read"},
{enforceContext, struct{ Age int }{Age: 70}, "/data1", "read"},
{enforceContext, struct{ Age int }{Age: 30}, "/data1", "read"},
}, []bool{
true, false, true,
})
}
func TestPriorityExplicit(t *testing.T) {
e, _ := NewEnforcer("examples/priority_model_explicit.conf", "examples/priority_policy_explicit.csv")
testBatchEnforce(t, e, [][]interface{}{
{"alice", "data1", "write"},
{"alice", "data1", "read"},
{"bob", "data2", "read"},
{"bob", "data2", "write"},
{"data1_deny_group", "data1", "read"},
{"data1_deny_group", "data1", "write"},
{"data2_allow_group", "data2", "read"},
{"data2_allow_group", "data2", "write"},
}, []bool{
true, true, false, true, false, false, true, true,
})
_, err := e.AddPolicy("1", "bob", "data2", "write", "deny")
if err != nil {
t.Fatalf("Add Policy: %v", err)
}
testBatchEnforce(t, e, [][]interface{}{
{"alice", "data1", "write"},
{"alice", "data1", "read"},
{"bob", "data2", "read"},
{"bob", "data2", "write"},
{"data1_deny_group", "data1", "read"},
{"data1_deny_group", "data1", "write"},
{"data2_allow_group", "data2", "read"},
{"data2_allow_group", "data2", "write"},
}, []bool{
true, true, false, false, false, false, true, true,
})
}
func TestFailedToLoadPolicy(t *testing.T) {
e, _ := NewEnforcer("examples/rbac_with_pattern_model.conf", "examples/rbac_with_pattern_policy.csv")
e.AddNamedMatchingFunc("g2", "matchingFunc", util.KeyMatch2)
testEnforce(t, e, "alice", "/book/1", "GET", true)
testEnforce(t, e, "bob", "/pen/3", "GET", true)
e.SetAdapter(fileadapter.NewAdapter("not found"))
_ = e.LoadPolicy()
testEnforce(t, e, "alice", "/book/1", "GET", true)
testEnforce(t, e, "bob", "/pen/3", "GET", true)
}
func TestReloadPolicyWithFunc(t *testing.T) {
e, _ := NewEnforcer("examples/rbac_with_pattern_model.conf", "examples/rbac_with_pattern_policy.csv")
e.AddNamedMatchingFunc("g2", "matchingFunc", util.KeyMatch2)
testEnforce(t, e, "alice", "/book/1", "GET", true)
testEnforce(t, e, "bob", "/pen/3", "GET", true)
_ = e.LoadPolicy()
testEnforce(t, e, "alice", "/book/1", "GET", true)
testEnforce(t, e, "bob", "/pen/3", "GET", true)
}
func TestEvalPriority(t *testing.T) {
e, _ := NewEnforcer("examples/eval_operator_model.conf", "examples/eval_operator_policy.csv")
testEnforce(t, e, "admin", "users", "write", true)
testEnforce(t, e, "admin", "none", "write", false)
testEnforce(t, e, "user", "users", "write", false)
}
func TestLinkConditionFunc(t *testing.T) {
TrueFunc := func(args ...string) (bool, error) {
if len(args) != 0 {
return args[0] == "_" || args[0] == "true", nil
}
return false, nil
}
FalseFunc := func(args ...string) (bool, error) {
if len(args) != 0 {
return args[0] == "_" || args[0] == "false", nil
}
return false, nil
}
m, _ := model.NewModelFromFile("examples/rbac_with_temporal_roles_model.conf")
e, _ := NewEnforcer(m)
_, _ = e.AddPolicies([][]string{
{"alice", "data1", "read"},
{"alice", "data1", "write"},
{"data2_admin", "data2", "read"},
{"data2_admin", "data2", "write"},
{"data3_admin", "data3", "read"},
{"data3_admin", "data3", "write"},
{"data4_admin", "data4", "read"},
{"data4_admin", "data4", "write"},
{"data5_admin", "data5", "read"},
{"data5_admin", "data5", "write"},
})
_, _ = e.AddGroupingPolicies([][]string{
{"alice", "data2_admin", "_", "_"},
{"alice", "data3_admin", "_", "_"},
{"alice", "data4_admin", "_", "_"},
{"alice", "data5_admin", "_", "_"},
})
e.AddNamedLinkConditionFunc("g", "alice", "data2_admin", TrueFunc)
e.AddNamedLinkConditionFunc("g", "alice", "data3_admin", TrueFunc)
e.AddNamedLinkConditionFunc("g", "alice", "data4_admin", FalseFunc)
e.AddNamedLinkConditionFunc("g", "alice", "data5_admin", FalseFunc)
e.SetNamedLinkConditionFuncParams("g", "alice", "data2_admin", "true")
e.SetNamedLinkConditionFuncParams("g", "alice", "data3_admin", "not true")
e.SetNamedLinkConditionFuncParams("g", "alice", "data4_admin", "false")
e.SetNamedLinkConditionFuncParams("g", "alice", "data5_admin", "not false")
testEnforce(t, e, "alice", "data1", "read", true)
testEnforce(t, e, "alice", "data1", "write", true)
testEnforce(t, e, "alice", "data2", "read", true)
testEnforce(t, e, "alice", "data2", "write", true)
testEnforce(t, e, "alice", "data3", "read", false)
testEnforce(t, e, "alice", "data3", "write", false)
testEnforce(t, e, "alice", "data4", "read", true)
testEnforce(t, e, "alice", "data4", "write", true)
testEnforce(t, e, "alice", "data5", "read", false)
testEnforce(t, e, "alice", "data5", "write", false)
m, _ = model.NewModelFromFile("examples/rbac_with_domain_temporal_roles_model.conf")
e, _ = NewEnforcer(m)
_, _ = e.AddPolicies([][]string{
{"alice", "domain1", "data1", "read"},
{"alice", "domain1", "data1", "write"},
{"data2_admin", "domain2", "data2", "read"},
{"data2_admin", "domain2", "data2", "write"},
{"data3_admin", "domain3", "data3", "read"},
{"data3_admin", "domain3", "data3", "write"},
{"data4_admin", "domain4", "data4", "read"},
{"data4_admin", "domain4", "data4", "write"},
{"data5_admin", "domain5", "data5", "read"},
{"data5_admin", "domain5", "data5", "write"},
})
_, _ = e.AddGroupingPolicies([][]string{
{"alice", "data2_admin", "domain2", "_", "_"},
{"alice", "data3_admin", "domain3", "_", "_"},
{"alice", "data4_admin", "domain4", "_", "_"},
{"alice", "data5_admin", "domain5", "_", "_"},
})
e.AddNamedDomainLinkConditionFunc("g", "alice", "data2_admin", "domain2", TrueFunc)
e.AddNamedDomainLinkConditionFunc("g", "alice", "data3_admin", "domain3", TrueFunc)
e.AddNamedDomainLinkConditionFunc("g", "alice", "data4_admin", "domain4", FalseFunc)
e.AddNamedDomainLinkConditionFunc("g", "alice", "data5_admin", "domain5", FalseFunc)
e.SetNamedDomainLinkConditionFuncParams("g", "alice", "data2_admin", "domain2", "true")
e.SetNamedDomainLinkConditionFuncParams("g", "alice", "data3_admin", "domain3", "not true")
e.SetNamedDomainLinkConditionFuncParams("g", "alice", "data4_admin", "domain4", "false")
e.SetNamedDomainLinkConditionFuncParams("g", "alice", "data5_admin", "domain5", "not false")
testDomainEnforce(t, e, "alice", "domain1", "data1", "read", true)
testDomainEnforce(t, e, "alice", "domain1", "data1", "write", true)
testDomainEnforce(t, e, "alice", "domain2", "data2", "read", true)
testDomainEnforce(t, e, "alice", "domain2", "data2", "write", true)
testDomainEnforce(t, e, "alice", "domain3", "data3", "read", false)
testDomainEnforce(t, e, "alice", "domain3", "data3", "write", false)
testDomainEnforce(t, e, "alice", "domain4", "data4", "read", true)
testDomainEnforce(t, e, "alice", "domain4", "data4", "write", true)
testDomainEnforce(t, e, "alice", "domain5", "data5", "read", false)
testDomainEnforce(t, e, "alice", "domain5", "data5", "write", false)
}