Priority Model
Casbin can apply priority to policies: when multiple policies match, the one with highest priority wins (and can produce allow or deny).
Implicit priority (policy order)
Policy order defines priority: first in the list has highest priority. Use this effect:
[policy_effect]
e = priority(p.eft) || deny
Explicit priority (numeric field)
Add a priority field to the policy; lower number = higher priority. Non-numeric values are treated as lowest priority. See casbin#550.
The default priority field name is priority. For another name (e.g. customized_priority), call e.SetFieldIndex("p", constant.PriorityIndex, index) after init and reload policy. Example: TestCustomizedFieldIndex.
Example with explicit priority in policy:
[policy_definition]
p = customized_priority, sub, obj, act, eft
Golang code example:
e, _ := NewEnforcer("./example/priority_model_explicit_customized.conf",
"./example/priority_policy_explicit_customized.csv")
// Due to the customized priority token, the enforcer fails to handle the priority.
ok, err := e.Enforce("bob", "data2", "read") // the result will be `true, nil`
// Set PriorityIndex and reload
e.SetFieldIndex("p", constant.PriorityIndex, 0)
err := e.LoadPolicy()
if err != nil {
log.Fatalf("LoadPolicy: %v", err)
}
ok, err := e.Enforce("bob", "data2", "read") // the result will be `false, nil`
:::
Only AddPolicy and AddPolicies respect explicit priority. Do not change the priority field via UpdatePolicy.
Full model:
[request_definition]
r = sub, obj, act
[policy_definition]
p = priority, sub, obj, act, eft
[role_definition]
g = _, _
[policy_effect]
e = priority(p.eft) || deny
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
policy.csv
p, 10, data1_deny_group, data1, read, deny
p, 10, data1_deny_group, data1, write, deny
p, 10, data2_allow_group, data2, read, allow
p, 10, data2_allow_group, data2, write, allow
p, 1, alice, data1, write, allow
p, 1, alice, data1, read, allow
p, 1, bob, data2, read, deny
g, bob, data2_allow_group
g, alice, data1_deny_group
request:
alice, data1, write --> true // because `p, 1, alice, data1, write, allow` has the highest priority
bob, data2, read --> false
bob, data2, write --> true // because bob has the role of `data2_allow_group` which has the right to write data2, and there's no deny policy with higher priority