Skip to content

Commit

Permalink
feat: add FieldIndexMap and constant (#1041)
Browse files Browse the repository at this point in the history
Signed-off-by: tangyang9464 <tangyang9464@163.com>
  • Loading branch information
tangyang9464 committed Jun 26, 2022
1 parent 314829c commit d471c72
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 69 deletions.
30 changes: 30 additions & 0 deletions constant/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright 2022 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 constant

const (
DomainIndex = "dom"
SubjectIndex = "sub"
ObjectIndex = "obj"
PriorityIndex = "priority"
)

const (
AllowOverrideEffect = "some(where (p_eft == allow))"
DenyOverrideEffect = "!some(where (p_eft == deny))"
AllowAndDenyEffect = "some(where (p_eft == allow)) && !some(where (p_eft == deny))"
PriorityEffect = "priority(p_eft) || deny"
SubjectPriorityEffect = "subjectPriority(p_eft) || deny"
)
14 changes: 9 additions & 5 deletions effector/default_effector.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@

package effector

import "errors"
import (
"errors"

"github.com/casbin/casbin/v2/constant"
)

// DefaultEffector is default effector for Casbin.
type DefaultEffector struct {
Expand All @@ -32,7 +36,7 @@ func (e *DefaultEffector) MergeEffects(expr string, effects []Effect, matches []
explainIndex := -1

switch expr {
case "some(where (p_eft == allow))":
case constant.AllowOverrideEffect:
if matches[policyIndex] == 0 {
break
}
Expand All @@ -42,7 +46,7 @@ func (e *DefaultEffector) MergeEffects(expr string, effects []Effect, matches []
explainIndex = policyIndex
break
}
case "!some(where (p_eft == deny))":
case constant.DenyOverrideEffect:
// only check the current policyIndex
if matches[policyIndex] != 0 && effects[policyIndex] == Deny {
result = Deny
Expand All @@ -53,7 +57,7 @@ func (e *DefaultEffector) MergeEffects(expr string, effects []Effect, matches []
if policyIndex == policyLength-1 {
result = Allow
}
case "some(where (p_eft == allow)) && !some(where (p_eft == deny))":
case constant.AllowAndDenyEffect:
// short-circuit if matched deny rule
if matches[policyIndex] != 0 && effects[policyIndex] == Deny {
result = Deny
Expand All @@ -80,7 +84,7 @@ func (e *DefaultEffector) MergeEffects(expr string, effects []Effect, matches []
break
}
}
case "priority(p_eft) || deny", "subjectPriority(p_eft) || deny":
case constant.PriorityEffect, constant.SubjectPriorityEffect:
// reverse merge, short-circuit may be earlier
for i := len(effects) - 1; i >= 0; i-- {
if matches[i] == 0 {
Expand Down
20 changes: 7 additions & 13 deletions internal_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,6 @@
package casbin

import (
"fmt"

Err "github.com/casbin/casbin/v2/errors"
"github.com/casbin/casbin/v2/model"
"github.com/casbin/casbin/v2/persist"
Expand Down Expand Up @@ -373,15 +371,11 @@ func (e *Enforcer) updateFilteredPolicies(sec string, ptype string, newRules [][
return ruleChanged, nil
}

func (e *Enforcer) getDomainIndex(ptype string) int {
p := e.model["p"][ptype]
pattern := fmt.Sprintf("%s_dom", ptype)
index := len(p.Tokens)
for i, token := range p.Tokens {
if token == pattern {
index = i
break
}
}
return index
func (e *Enforcer) GetFieldIndex(ptype string, field string) (int, error) {
return e.model.GetFieldIndex(ptype, field)
}

func (e *Enforcer) SetFieldIndex(ptype string, field string, index int) {
assertion := e.model["p"][ptype]
assertion.FieldIndexMap[field] = index
}
24 changes: 10 additions & 14 deletions model/assertion.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ import (
// Assertion represents an expression in a section of the model.
// For example: r = sub, obj, act
type Assertion struct {
Key string
Value string
Tokens []string
Policy [][]string
PolicyMap map[string]int
RM rbac.RoleManager

logger log.Logger
priorityIndex int
Key string
Value string
Tokens []string
Policy [][]string
PolicyMap map[string]int
RM rbac.RoleManager
FieldIndexMap map[string]int

logger log.Logger
}

func (ast *Assertion) buildIncrementalRoleLinks(rm rbac.RoleManager, op PolicyOp, rules [][]string) error {
Expand Down Expand Up @@ -93,10 +93,6 @@ func (ast *Assertion) setLogger(logger log.Logger) {
ast.logger = logger
}

func (ast *Assertion) initPriorityIndex() {
ast.priorityIndex = -1
}

func (ast *Assertion) copy() *Assertion {
tokens := append([]string(nil), ast.Tokens...)
policy := make([][]string, len(ast.Policy))
Expand All @@ -115,7 +111,7 @@ func (ast *Assertion) copy() *Assertion {
PolicyMap: policyMap,
Tokens: tokens,
Policy: policy,
priorityIndex: ast.priorityIndex,
FieldIndexMap: ast.FieldIndexMap,
}

return newAst
Expand Down
47 changes: 30 additions & 17 deletions model/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (
"strings"

"github.com/casbin/casbin/v2/config"
"github.com/casbin/casbin/v2/constant"
"github.com/casbin/casbin/v2/log"
"github.com/casbin/casbin/v2/util"
)
Expand Down Expand Up @@ -63,8 +64,8 @@ func (model Model) AddDef(sec string, key string, value string) bool {
ast.Key = key
ast.Value = value
ast.PolicyMap = make(map[string]int)
ast.FieldIndexMap = make(map[string]int)
ast.setLogger(model.GetLogger())
ast.initPriorityIndex()

if sec == "r" || sec == "p" {
ast.Tokens = strings.Split(ast.Value, ",")
Expand Down Expand Up @@ -216,17 +217,14 @@ func (model Model) PrintModel() {
}

func (model Model) SortPoliciesBySubjectHierarchy() error {
if model["e"]["e"].Value != "subjectPriority(p_eft) || deny" {
if model["e"]["e"].Value != constant.SubjectPriorityEffect {
return nil
}
subIndex := 0
domainIndex := -1
for ptype, assertion := range model["p"] {
for index, token := range assertion.Tokens {
if token == fmt.Sprintf("%s_dom", ptype) {
domainIndex = index
break
}
domainIndex, err := model.GetFieldIndex(ptype, constant.DomainIndex)
if err != nil {
domainIndex = -1
}
policies := assertion.Policy
subjectHierarchyMap, err := getSubjectHierarchyMap(model["g"]["g"].Policy)
Expand Down Expand Up @@ -308,22 +306,17 @@ func getNameWithDomain(domain string, name string) string {

func (model Model) SortPoliciesByPriority() error {
for ptype, assertion := range model["p"] {
for index, token := range assertion.Tokens {
if token == fmt.Sprintf("%s_priority", ptype) {
assertion.priorityIndex = index
break
}
}
if assertion.priorityIndex == -1 {
priorityIndex, err := model.GetFieldIndex(ptype, constant.PriorityIndex)
if err != nil {
continue
}
policies := assertion.Policy
sort.SliceStable(policies, func(i, j int) bool {
p1, err := strconv.Atoi(policies[i][assertion.priorityIndex])
p1, err := strconv.Atoi(policies[i][priorityIndex])
if err != nil {
return true
}
p2, err := strconv.Atoi(policies[j][assertion.priorityIndex])
p2, err := strconv.Atoi(policies[j][priorityIndex])
if err != nil {
return true
}
Expand Down Expand Up @@ -389,3 +382,23 @@ func (model Model) Copy() Model {
newModel.SetLogger(model.GetLogger())
return newModel
}

func (model Model) GetFieldIndex(ptype string, field string) (int, error) {
assertion := model["p"][ptype]
if index, ok := assertion.FieldIndexMap[field]; ok {
return index, nil
}
pattern := fmt.Sprintf("%s_"+field, ptype)
index := -1
for i, token := range assertion.Tokens {
if token == pattern {
index = i
break
}
}
if index == -1 {
return index, fmt.Errorf(field + " index is not set, please use enforcer.SetFieldIndex() to set index")
}
assertion.FieldIndexMap[field] = index
return index, nil
}
3 changes: 2 additions & 1 deletion model/model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"testing"

"github.com/casbin/casbin/v2/config"
"github.com/casbin/casbin/v2/constant"
)

var (
Expand Down Expand Up @@ -140,7 +141,7 @@ func testModelToText(t *testing.T, mData, mExpected string) {
expected := map[string]string{
"r": "sub, obj, act",
"p": "sub, obj, act",
"e": "some(where (p_eft == allow))",
"e": constant.AllowOverrideEffect,
"m": mExpected,
}
addData := func(ptype string) {
Expand Down
11 changes: 8 additions & 3 deletions model/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"strconv"
"strings"

"github.com/casbin/casbin/v2/constant"
"github.com/casbin/casbin/v2/rbac"
"github.com/casbin/casbin/v2/util"
)
Expand Down Expand Up @@ -148,11 +149,15 @@ func (model Model) AddPolicy(sec string, ptype string, rule []string) {
assertion.Policy = append(assertion.Policy, rule)
assertion.PolicyMap[strings.Join(rule, DefaultSep)] = len(model[sec][ptype].Policy) - 1

if sec == "p" && assertion.priorityIndex >= 0 {
if idxInsert, err := strconv.Atoi(rule[assertion.priorityIndex]); err == nil {
hasPriority := false
if _, ok := assertion.FieldIndexMap[constant.PriorityIndex]; ok {
hasPriority = true
}
if sec == "p" && hasPriority {
if idxInsert, err := strconv.Atoi(rule[assertion.FieldIndexMap[constant.PriorityIndex]]); err == nil {
i := len(assertion.Policy) - 1
for ; i > 0; i-- {
idx, err := strconv.Atoi(assertion.Policy[i-1][assertion.priorityIndex])
idx, err := strconv.Atoi(assertion.Policy[i-1][assertion.FieldIndexMap[constant.PriorityIndex]])
if err != nil {
break
}
Expand Down
32 changes: 25 additions & 7 deletions rbac_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package casbin

import (
"github.com/casbin/casbin/v2/constant"
"github.com/casbin/casbin/v2/errors"
"github.com/casbin/casbin/v2/util"
)
Expand Down Expand Up @@ -99,7 +100,11 @@ func (e *Enforcer) DeleteUser(user string) (bool, error) {
return res1, err
}

res2, err := e.RemoveFilteredPolicy(0, user)
subIndex, err := e.GetFieldIndex("p", constant.SubjectIndex)
if err != nil {
return false, err
}
res2, err := e.RemoveFilteredPolicy(subIndex, user)
return res1 || res2, err
}

Expand All @@ -112,7 +117,11 @@ func (e *Enforcer) DeleteRole(role string) (bool, error) {
return res1, err
}

res2, err := e.RemoveFilteredPolicy(0, role)
subIndex, err := e.GetFieldIndex("p", constant.SubjectIndex)
if err != nil {
return false, err
}
res2, err := e.RemoveFilteredPolicy(subIndex, role)
return res1 || res2, err
}

Expand Down Expand Up @@ -147,7 +156,11 @@ func (e *Enforcer) DeletePermissionForUser(user string, permission ...string) (b
// DeletePermissionsForUser deletes permissions for a user or role.
// Returns false if the user or role does not have any permissions (aka not affected).
func (e *Enforcer) DeletePermissionsForUser(user string) (bool, error) {
return e.RemoveFilteredPolicy(0, user)
subIndex, err := e.GetFieldIndex("p", constant.SubjectIndex)
if err != nil {
return false, err
}
return e.RemoveFilteredPolicy(subIndex, user)
}

// GetPermissionsForUser gets permissions for a user or role.
Expand All @@ -163,13 +176,18 @@ func (e *Enforcer) GetNamedPermissionsForUser(ptype string, user string, domain
continue
}
args := make([]string, len(assertion.Tokens))
args[0] = user
subIndex, err := e.GetFieldIndex("p", constant.SubjectIndex)
if err != nil {
subIndex = 0
}
args[subIndex] = user

if len(domain) > 0 {
index := e.getDomainIndex(ptype)
if index < len(assertion.Tokens) {
args[index] = domain[0]
index, err := e.GetFieldIndex(ptype, constant.DomainIndex)
if err != nil {
return permission
}
args[index] = domain[0]
}
perm := e.GetFilteredNamedPolicy(ptype, 0, args...)
permission = append(permission, perm...)
Expand Down

0 comments on commit d471c72

Please sign in to comment.