@sang6196 neither is needed. You can use regex match in g rules, so only one rule
I went from this model:
const stringModel = `
[request_definition]
r = user, dom, obj, act, tag
[policy_definition]
p = role, dom, obj, act, tag
[policy_effect]
e = some(where (p.eft == allow))
[role_definition]
g = _, _, _
g2 = _, _
[matchers]
m = g(r.user, p.role, r.tag) && g2(p.role, r.dom) && keyMatch(r.tag, p.tag) && keyMatch(r.act, p.act) && (keyMatch(r.obj, p.obj) || keyMatch2(r.obj, p.obj))
`
func TestDefaultRbac(t *testing.T) {
m, _ := model.NewModelFromString(stringModel)
e, _ := casbin.NewEnforcer(m, false)
e.AddPolicies([][]string{
{"reader", "org1", "/project", "GET", "project_*"},
{"editor", "org1", "/project", "DELETE", "project_*"},
{"reader2", "org2", "/project", "GET", "project_*"},
})
e.AddNamedGroupingPolicies("g", [][]string{
{"tom", "reader", "project_1"},
{"tom", "reader", "project_2"},
{"tom", "reader", "project_3"},
{"tom", "editor", "project_5"},
{"henk", "reader2", "project_6"},
})
e.AddNamedGroupingPolicies("g2", [][]string{
{"reader", "org1"},
{"reader2", "org2"},
{"editor", "org1"},
})
enforcer := func(user, dom, obj, act, tag string, expect bool) {
resp, _ := e.Enforce(user, dom, obj, act, tag)
if resp != expect {
t.Errorf("Response is for %s %s %s %s %s %t expected to be %t", user, dom, obj, act, tag, resp, expect)
}
}
enforcer("tom", "org1", "/project", "GET", "project_1", true)
enforcer("tom", "org1", "/project", "DELETE", "project_1", false)
enforcer("tom", "org1", "/project", "DELETE", "project_5", true)
enforcer("tom", "org2", "/project", "GET", "project_6", false)
enforcer("henk", "org2", "/project", "GET", "project_6", true)
}
to this, I left out the whole org part since the roles will be unique per org and are therefore implicity tied to an org:
const stringModel2 = `
[request_definition]
r = user, obj, act, tag
[policy_definition]
p = role, obj, act, tag
[policy_effect]
e = some(where (p.eft == allow))
[role_definition]
g = _, _, _
[matchers]
m = g(r.user, p.role, r.tag) && keyMatch(r.tag, p.tag) && keyMatch(r.act, p.act) && (keyMatch(r.obj, p.obj) || keyMatch2(r.obj, p.obj))
`
func TestDefaultRbac2(t *testing.T) {
m, _ := model.NewModelFromString(stringModel2)
e, _ := casbin.NewEnforcer(m, false)
e.AddPolicies([][]string{
{"reader", "/project", "GET", "project_*"},
{"editor", "/project", "DELETE", "project_*"},
{"reader2", "/project", "GET", "project_*"},
})
e.AddNamedGroupingPolicies("g", [][]string{
{"tom", "reader", "project_1"},
{"tom", "reader", "project_2"},
{"tom", "reader", "project_3"},
{"tom", "editor", "project_5"},
{"henk", "reader2", "project_6"},
})
enforcer := func(user, obj, act, tag string, expect bool) {
resp, _ := e.Enforce(user, obj, act, tag)
if resp != expect {
t.Errorf("Response is for %s %s %s %s %t expected to be %t", user, obj, act, tag, resp, expect)
}
}
enforcer("tom", "/project", "GET", "project_1", true)
enforcer("tom", "/project", "DELETE", "project_1", false)
enforcer("tom", "/project", "DELETE", "project_5", true)
enforcer("tom", "/project", "GET", "project_6", false)
enforcer("henk", "/project", "GET", "project_6", true)
}
Both do the same thing one is explicit with role + org combination and the other is implicit. E.g. reader is part of org1 and reader2 is part of org2
I plan to make a custom adapter https://casbin.org/docs/adapters/ that loads the filtered policy for each request and checks it.
that loads the filtered policy for each request and checks it. for endpoints that need it
Join the conversation
Sign up to reply, like and follow topics.
Suggested Topics
Want to read more? Browse other topics in Casbin or view latest topics.
1 / 2
May 2024
