Another casbin implementation in golang.
go get github.com/sdcxtech/casbinpackage main
import (
"fmt"
"strings"
"github.com/sdcxtech/casbin"
"github.com/sdcxtech/casbin/core"
"github.com/sdcxtech/casbin/effector"
"github.com/sdcxtech/casbin/load"
)
func main() {
policy, _ := core.NewAssertionSchema("sub, obj, act")
request, _ := core.NewAssertionSchema("sub, obj, act")
roles := core.RolesSchema{
"g": {Type: core.RoleTypeWithoutDomain},
}
matchers, _ := core.MatchersConfig{
Roles: roles,
Define: map[string]string{
"m": "g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act",
},
}.New()
model := core.NewModel(policy, request, roles, effector.NewAllowOverride(), matchers)
policies := strings.NewReader(`
p, staff, order, get
g, admin, staff
`)
enforcer, _ := casbin.NewEnforcer(model, load.NewCSVIterator(policies))
allow, _ := enforcer.Enforce(casbin.Request("admin", "order", "get"))
fmt.Println(allow) // true
}Models can also be loaded from a viper.Viper instance, so the concrete file
format can be TOML, YAML, JSON, or anything else Viper supports.
[request_definition]
r = "sub, dom, obj, act"
[policy_definition]
p = "sub, obj, act, eft"
[role_definition]
g = "_, _, _"
g1 = "_, _"
[policy_effect]
type = "allow-and-deny"
key = "eft"
[matchers]
m = "g(r.sub, p.sub, r.dom) && r.obj == p.obj && r.act == p.act"model, err := load.ModelFromViper(v)Supported effect types:
allow-override: allow when any policy matches. No effect field is required.deny-override: allow unless a matched policy has effectdeny.allow-and-deny: allow when a policy with effectallowmatches and no matched policy has effectdeny.
deny-override and allow-and-deny require policy_effect.key to name a
policy field whose value is allow or deny.
Use load.NewCSVIterator to load policy and role rows from an io.Reader.
The first CSV column is the section key, such as p for policies or g for a
role relation. Lines starting with # are comments.
p, staff, order, get
g, admin, staffFor a role definition with domain (g = "_, _, _"), role rows use
from, to, domain:
g, alice, admin, tenant1Matchers are CEL expressions. Request values are available as r.<field>,
policy values are available as p.<field>, and role functions use the names
from [role_definition].
You can register string match helpers as CEL extension functions:
model, err := load.ModelFromViper(
v,
load.ExtensionFuncs(
keymatch.ToExtensionFunc("globMatch", keymatch.GlobMatch),
keymatch.ToExtensionFunc("regexMatch", keymatch.NewRegexMatch()),
keymatch.ToExtensionFunc("ipMatch", keymatch.IPMatch),
),
)Then use them from a matcher:
[matchers]
m = "g(r.sub, p.sub) && globMatch(r.obj, p.obj) && r.act == p.act"Enforce accepts options for one call without changing the enforcer:
casbin.UseMatcher(name)selects a matcher other than the defaultm.casbin.WithRawPolicies(rows)injects extra raw policies for this call.casbin.WithPolicies(policies)injects parsed policies for this call.casbin.OnlyInjectedPolicies()ignores the enforcer's loaded policies.casbin.WithRoleGraphs(key, graphs...)injects role graphs for this call.
- Use google Common Expression Language as the matcher expression language.
- Assertion field in policy and request only can be
stringtype. So there is no support forABACmodel. - Only implement the core feature checking permissions. Not include policies and roles management which should be implemented in a different Bounded Context.
Released under the MIT License.