203 lines
5.2 KiB
Go
203 lines
5.2 KiB
Go
// Licensed to the Apache Software Foundation (ASF) under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you 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 model
|
|
|
|
import (
|
|
"errors"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/casbin/casbin/v3/rbac"
|
|
)
|
|
|
|
// 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
|
|
ParamsTokens []string
|
|
Policy [][]string
|
|
PolicyMap map[string]int
|
|
RM rbac.RoleManager
|
|
CondRM rbac.ConditionalRoleManager
|
|
FieldIndexMap map[string]int
|
|
FieldIndexMutex sync.RWMutex
|
|
}
|
|
|
|
func (ast *Assertion) buildIncrementalRoleLinks(rm rbac.RoleManager, op PolicyOp, rules [][]string) error {
|
|
ast.RM = rm
|
|
count := strings.Count(ast.Value, "_")
|
|
if count < 2 {
|
|
return errors.New("the number of \"_\" in role definition should be at least 2")
|
|
}
|
|
|
|
for _, rule := range rules {
|
|
if len(rule) < count {
|
|
return errors.New("grouping policy elements do not meet role definition")
|
|
}
|
|
if len(rule) > count {
|
|
rule = rule[:count]
|
|
}
|
|
switch op {
|
|
case PolicyAdd:
|
|
err := rm.AddLink(rule[0], rule[1], rule[2:]...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
case PolicyRemove:
|
|
err := rm.DeleteLink(rule[0], rule[1], rule[2:]...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (ast *Assertion) buildRoleLinks(rm rbac.RoleManager) error {
|
|
ast.RM = rm
|
|
count := strings.Count(ast.Value, "_")
|
|
if count < 2 {
|
|
return errors.New("the number of \"_\" in role definition should be at least 2")
|
|
}
|
|
for _, rule := range ast.Policy {
|
|
if len(rule) < count {
|
|
return errors.New("grouping policy elements do not meet role definition")
|
|
}
|
|
if len(rule) > count {
|
|
rule = rule[:count]
|
|
}
|
|
err := ast.RM.AddLink(rule[0], rule[1], rule[2:]...)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ast *Assertion) buildIncrementalConditionalRoleLinks(condRM rbac.ConditionalRoleManager, op PolicyOp, rules [][]string) error {
|
|
ast.CondRM = condRM
|
|
count := strings.Count(ast.Value, "_")
|
|
if count < 2 {
|
|
return errors.New("the number of \"_\" in role definition should be at least 2")
|
|
}
|
|
|
|
for _, rule := range rules {
|
|
if len(rule) < count {
|
|
return errors.New("grouping policy elements do not meet role definition")
|
|
}
|
|
if len(rule) > count {
|
|
rule = rule[:count]
|
|
}
|
|
|
|
var err error
|
|
domainRule := rule[2:len(ast.Tokens)]
|
|
|
|
switch op {
|
|
case PolicyAdd:
|
|
err = ast.addConditionalRoleLink(rule, domainRule)
|
|
case PolicyRemove:
|
|
err = ast.CondRM.DeleteLink(rule[0], rule[1], rule[2:]...)
|
|
}
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ast *Assertion) buildConditionalRoleLinks(condRM rbac.ConditionalRoleManager) error {
|
|
ast.CondRM = condRM
|
|
count := strings.Count(ast.Value, "_")
|
|
if count < 2 {
|
|
return errors.New("the number of \"_\" in role definition should be at least 2")
|
|
}
|
|
for _, rule := range ast.Policy {
|
|
if len(rule) < count {
|
|
return errors.New("grouping policy elements do not meet role definition")
|
|
}
|
|
if len(rule) > count {
|
|
rule = rule[:count]
|
|
}
|
|
|
|
domainRule := rule[2:len(ast.Tokens)]
|
|
|
|
err := ast.addConditionalRoleLink(rule, domainRule)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// addConditionalRoleLink adds Link to rbac.ConditionalRoleManager and sets the parameters for LinkConditionFunc.
|
|
func (ast *Assertion) addConditionalRoleLink(rule []string, domainRule []string) error {
|
|
var err error
|
|
if len(domainRule) == 0 {
|
|
err = ast.CondRM.AddLink(rule[0], rule[1])
|
|
if err == nil {
|
|
ast.CondRM.SetLinkConditionFuncParams(rule[0], rule[1], rule[len(ast.Tokens):]...)
|
|
}
|
|
} else {
|
|
domain := domainRule[0]
|
|
err = ast.CondRM.AddLink(rule[0], rule[1], domain)
|
|
if err == nil {
|
|
ast.CondRM.SetDomainLinkConditionFuncParams(rule[0], rule[1], domain, rule[len(ast.Tokens):]...)
|
|
}
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (ast *Assertion) copy() *Assertion {
|
|
tokens := append([]string(nil), ast.Tokens...)
|
|
policy := make([][]string, len(ast.Policy))
|
|
|
|
for i, p := range ast.Policy {
|
|
policy[i] = append(policy[i], p...)
|
|
}
|
|
policyMap := make(map[string]int)
|
|
for k, v := range ast.PolicyMap {
|
|
policyMap[k] = v
|
|
}
|
|
|
|
ast.FieldIndexMutex.RLock()
|
|
fieldIndexMap := make(map[string]int)
|
|
for k, v := range ast.FieldIndexMap {
|
|
fieldIndexMap[k] = v
|
|
}
|
|
ast.FieldIndexMutex.RUnlock()
|
|
|
|
newAst := &Assertion{
|
|
Key: ast.Key,
|
|
Value: ast.Value,
|
|
PolicyMap: policyMap,
|
|
Tokens: tokens,
|
|
Policy: policy,
|
|
FieldIndexMap: fieldIndexMap,
|
|
ParamsTokens: append([]string(nil), ast.ParamsTokens...),
|
|
RM: ast.RM,
|
|
CondRM: ast.CondRM,
|
|
}
|
|
|
|
return newAst
|
|
}
|