Skip to content

Commit

Permalink
Merge pull request #37 from kenjones-cisco/feature/role-manager-inter…
Browse files Browse the repository at this point in the history
…face

Feature: Define RoleManager as interface
  • Loading branch information
hsluoyz committed Aug 30, 2017
2 parents 748b815 + ef81f10 commit 24e6518
Show file tree
Hide file tree
Showing 9 changed files with 335 additions and 216 deletions.
18 changes: 18 additions & 0 deletions README.md
Expand Up @@ -175,6 +175,24 @@ RESTful | [keymatch_model.conf](https://github.com/casbin/casbin/blob/master/exa
Deny-override | [rbac_model_with_deny.conf](https://github.com/casbin/casbin/blob/master/examples/rbac_model_with_deny.conf) | [rbac_policy_with_deny.csv](https://github.com/casbin/casbin/blob/master/examples/rbac_policy_with_deny.csv)
Priority | [priority_model.conf](https://github.com/casbin/casbin/blob/master/examples/priority_model.conf) | [priority_policy.csv](https://github.com/casbin/casbin/blob/master/examples/priority_policy.csv)

## RoleManager

To use a custom RoleManager implementation.

```go

type myCustomRoleManager struct {} // assumes the type satisfies the RoleManager interface

func newRoleManager() rbac.RoleManagerConstructor {
return func() rbac.RoleManager {
return &myCustomRoleManager{}
}
}

e := casbin.NewEnforcer("path/to/model.conf", "path/to/policy.csv")
e.SetRoleManager(newRoleManager())
```

## How to use Casbin as a service?

- [Go-Simple-API-Gateway](https://github.com/Soontao/go-simple-api-gateway): A simple API gateway written by golang, supports for authentication and authorization
Expand Down
10 changes: 9 additions & 1 deletion enforcer.go
Expand Up @@ -22,6 +22,7 @@ import (
"github.com/casbin/casbin/file-adapter"
"github.com/casbin/casbin/model"
"github.com/casbin/casbin/persist"
"github.com/casbin/casbin/rbac"
"github.com/casbin/casbin/util"
)

Expand All @@ -40,6 +41,7 @@ type Enforcer struct {
modelPath string
model model.Model
fm model.FunctionMap
rmc rbac.RoleManagerConstructor

adapter persist.Adapter

Expand All @@ -55,6 +57,7 @@ type Enforcer struct {
// e := casbin.NewEnforcer("path/to/basic_model.conf", a)
func NewEnforcer(params ...interface{}) *Enforcer {
e := &Enforcer{}
e.rmc = rbac.DefaultRoleManager()

parsedParamLen := 0
if len(params) >= 1 && reflect.TypeOf(params[len(params)-1]).Kind() == reflect.Bool {
Expand Down Expand Up @@ -182,6 +185,11 @@ func (e *Enforcer) SetAdapter(adapter persist.Adapter) {
e.adapter = adapter
}

// SetRoleManager sets the constructor function for creating a RoleManager.
func (e *Enforcer) SetRoleManager(rmc rbac.RoleManagerConstructor) {
e.rmc = rmc
}

// ClearPolicy clears all policy.
func (e *Enforcer) ClearPolicy() {
e.model.ClearPolicy()
Expand All @@ -196,7 +204,7 @@ func (e *Enforcer) LoadPolicy() error {
}

e.model.PrintPolicy()
e.model.BuildRoleLinks()
e.model.BuildRoleLinks(e.rmc)
return nil
}

Expand Down
6 changes: 3 additions & 3 deletions management_api.go
Expand Up @@ -144,7 +144,7 @@ func (e *Enforcer) AddGroupingPolicy(params ...interface{}) bool {
ruleAdded = e.addPolicy("g", "g", policy)
}

e.model.BuildRoleLinks()
e.model.BuildRoleLinks(e.rmc)
return ruleAdded
}

Expand All @@ -162,14 +162,14 @@ func (e *Enforcer) RemoveGroupingPolicy(params ...interface{}) bool {
ruleRemoved = e.removePolicy("g", "g", policy)
}

e.model.BuildRoleLinks()
e.model.BuildRoleLinks(e.rmc)
return ruleRemoved
}

// RemoveFilteredGroupingPolicy removes a role inheritance rule from the current policy, field filters can be specified.
func (e *Enforcer) RemoveFilteredGroupingPolicy(fieldIndex int, fieldValues ...string) bool {
ruleRemoved := e.removeFilteredPolicy("g", "g", fieldIndex, fieldValues...)
e.model.BuildRoleLinks()
e.model.BuildRoleLinks(e.rmc)
return ruleRemoved
}

Expand Down
6 changes: 3 additions & 3 deletions model/assertion.go
Expand Up @@ -26,11 +26,11 @@ type Assertion struct {
Value string
Tokens []string
Policy [][]string
RM *rbac.RoleManager
RM rbac.RoleManager
}

func (ast *Assertion) buildRoleLinks() {
ast.RM = rbac.NewRoleManager(10)
func (ast *Assertion) buildRoleLinks(rmc rbac.RoleManagerConstructor) {
ast.RM = rmc()
for _, rule := range ast.Policy {
if len(rule) == 2 {
ast.RM.AddLink(rule[0], rule[1])
Expand Down
5 changes: 3 additions & 2 deletions model/policy.go
Expand Up @@ -15,13 +15,14 @@
package model

import (
"github.com/casbin/casbin/rbac"
"github.com/casbin/casbin/util"
)

// BuildRoleLinks initializes the roles in RBAC.
func (model Model) BuildRoleLinks() {
func (model Model) BuildRoleLinks(rmc rbac.RoleManagerConstructor) {
for _, ast := range model["g"] {
ast.buildRoleLinks()
ast.buildRoleLinks(rmc)
}
}

Expand Down
46 changes: 46 additions & 0 deletions model_test.go
Expand Up @@ -16,6 +16,8 @@ package casbin

import (
"testing"

"github.com/casbin/casbin/rbac"
)

func testEnforce(t *testing.T, e *Enforcer, sub string, obj interface{}, act string, res bool) {
Expand Down Expand Up @@ -211,6 +213,50 @@ func TestRBACModelWithDeny(t *testing.T) {
testEnforce(t, e, "bob", "data2", "write", true)
}

type testCustomRoleManager struct{}

func (rm *testCustomRoleManager) AddLink(name1 string, name2 string, domain ...string) {}
func (rm *testCustomRoleManager) DeleteLink(name1 string, name2 string, domain ...string) {}
func (rm *testCustomRoleManager) HasLink(name1 string, name2 string, domain ...string) bool {
if name1 == "alice" && name2 == "alice" {
return true
} else if name1 == "alice" && name2 == "data2_admin" {
return true
} else if name1 == "bob" && name2 == "bob" {
return true
}
return false
}
func (rm *testCustomRoleManager) GetRoles(name string, domain ...string) []string {
return []string{}
}
func (rm *testCustomRoleManager) GetUsers(name string) []string {
return []string{}
}
func (rm *testCustomRoleManager) PrintRoles() {}

func newTestCustomRoleManager() rbac.RoleManagerConstructor {
return func() rbac.RoleManager {
return &testCustomRoleManager{}
}
}

func TestRBACModelWithCustomRoleManager(t *testing.T) {
e := NewEnforcer("examples/rbac_model.conf", "examples/rbac_policy.csv")
e.SetRoleManager(newTestCustomRoleManager())
e.LoadModel()
_ = e.LoadPolicy()

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)
}

type testResource struct {
Name string
Owner string
Expand Down

0 comments on commit 24e6518

Please sign in to comment.