feat: fix compatibility issue between Casbin request and model (#1478)

This commit is contained in:
Yaodong Yu
2023-01-15 12:06:10 +08:00
committed by GitHub
parent c66561dc9a
commit d0741e3705
3 changed files with 97 additions and 36 deletions

View File

@@ -68,14 +68,14 @@ func getModel(owner string, name string) *Model {
return nil return nil
} }
model := Model{Owner: owner, Name: name} m := Model{Owner: owner, Name: name}
existed, err := adapter.Engine.Get(&model) existed, err := adapter.Engine.Get(&m)
if err != nil { if err != nil {
panic(err) panic(err)
} }
if existed { if existed {
return &model return &m
} else { } else {
return nil return nil
} }

View File

@@ -57,6 +57,40 @@ type PermissionRule struct {
Id string `xorm:"varchar(100) index not null default ''" json:"id"` Id string `xorm:"varchar(100) index not null default ''" json:"id"`
} }
const (
builtInAvailableField = 5 // Casdoor built-in adapter, use V5 to filter permission, so has 5 available field
builtInAdapter = "permission_rule"
)
func (p *Permission) GetId() string {
return util.GetId(p.Owner, p.Name)
}
func (p *PermissionRule) GetRequest(adapterName string, permissionId string) ([]interface{}, error) {
request := []interface{}{p.V0, p.V1, p.V2}
if p.V3 != "" {
request = append(request, p.V3)
}
if p.V4 != "" {
request = append(request, p.V4)
}
if adapterName == builtInAdapter {
if p.V5 != "" {
return nil, fmt.Errorf("too many parameters. The maximum parameter number cannot exceed %d", builtInAvailableField)
}
request = append(request, permissionId)
return request, nil
} else {
if p.V5 != "" {
request = append(request, p.V5)
}
return request, nil
}
}
func GetPermissionCount(owner, field, value string) int { func GetPermissionCount(owner, field, value string) int {
session := GetSession(owner, -1, -1, field, value, "", "") session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Permission{}) count, err := session.Count(&Permission{})
@@ -195,10 +229,6 @@ func DeletePermission(permission *Permission) bool {
return affected != 0 return affected != 0
} }
func (permission *Permission) GetId() string {
return fmt.Sprintf("%s/%s", permission.Owner, permission.Name)
}
func GetPermissionsByUser(userId string) []*Permission { func GetPermissionsByUser(userId string) []*Permission {
permissions := []*Permission{} permissions := []*Permission{}
err := adapter.Engine.Where("users like ?", "%"+userId+"%").Find(&permissions) err := adapter.Engine.Where("users like ?", "%"+userId+"%").Find(&permissions)

View File

@@ -15,9 +15,11 @@
package object package object
import ( import (
"fmt"
"strings" "strings"
"github.com/casbin/casbin/v2" "github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/config"
"github.com/casbin/casbin/v2/model" "github.com/casbin/casbin/v2/model"
xormadapter "github.com/casbin/xorm-adapter/v3" xormadapter "github.com/casbin/xorm-adapter/v3"
"github.com/casdoor/casdoor/conf" "github.com/casdoor/casdoor/conf"
@@ -36,26 +38,14 @@ func getEnforcer(permission *Permission) *casbin.Enforcer {
panic(err) panic(err)
} }
modelText := `
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act, "", "", permissionId
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act`
permissionModel := getModel(permission.Owner, permission.Model) permissionModel := getModel(permission.Owner, permission.Model)
m := model.Model{}
if permissionModel != nil { if permissionModel != nil {
modelText = permissionModel.ModelText m, err = GetBuiltInModel(permissionModel.ModelText)
} else {
m, err = GetBuiltInModel("")
} }
m, err := model.NewModelFromString(modelText)
if err != nil { if err != nil {
panic(err) panic(err)
} }
@@ -66,16 +56,19 @@ m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act`
} }
// load Policy with a specific Permission // load Policy with a specific Permission
enforcer.LoadFilteredPolicy(xormadapter.Filter{ err = enforcer.LoadFilteredPolicy(xormadapter.Filter{
V5: []string{permission.Owner + "/" + permission.Name}, V5: []string{permission.GetId()},
}) })
if err != nil {
panic(err)
}
return enforcer return enforcer
} }
func getPolicies(permission *Permission) ([][]string, [][]string) { func getPolicies(permission *Permission) ([][]string, [][]string) {
var policies [][]string var policies [][]string
var groupingPolicies [][]string var groupingPolicies [][]string
permissionId := permission.Owner + "/" + permission.Name permissionId := permission.GetId()
domainExist := len(permission.Domains) > 0 domainExist := len(permission.Domains) > 0
for _, user := range permission.Users { for _, user := range permission.Users {
for _, resource := range permission.Resources { for _, resource := range permission.Resources {
@@ -163,10 +156,8 @@ func Enforce(permissionRule *PermissionRule) bool {
permission := GetPermission(permissionRule.Id) permission := GetPermission(permissionRule.Id)
enforcer := getEnforcer(permission) enforcer := getEnforcer(permission)
request := []interface{}{permissionRule.V0, permissionRule.V1, permissionRule.V2} request, _ := permissionRule.GetRequest(builtInAdapter, permissionRule.Id)
if permissionRule.V3 != "" {
request = append(request, permissionRule.V3)
}
allow, err := enforcer.Enforce(request...) allow, err := enforcer.Enforce(request...)
if err != nil { if err != nil {
panic(err) panic(err)
@@ -177,11 +168,8 @@ func Enforce(permissionRule *PermissionRule) bool {
func BatchEnforce(permissionRules []PermissionRule) []bool { func BatchEnforce(permissionRules []PermissionRule) []bool {
var requests [][]interface{} var requests [][]interface{}
for _, permissionRule := range permissionRules { for _, permissionRule := range permissionRules {
if permissionRule.V3 != "" { request, _ := permissionRule.GetRequest(builtInAdapter, permissionRule.Id)
requests = append(requests, []interface{}{permissionRule.V0, permissionRule.V1, permissionRule.V2, permissionRule.V3}) requests = append(requests, request)
} else {
requests = append(requests, []interface{}{permissionRule.V0, permissionRule.V1, permissionRule.V2})
}
} }
permission := GetPermission(permissionRules[0].Id) permission := GetPermission(permissionRules[0].Id)
enforcer := getEnforcer(permission) enforcer := getEnforcer(permission)
@@ -226,3 +214,46 @@ func GetAllRoles(userId string) []string {
} }
return res return res
} }
func GetBuiltInModel(modelText string) (model.Model, error) {
if modelText == "" {
modelText = `
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act, "", "", permissionId
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act`
return model.NewModelFromString(modelText)
} else {
cfg, err := config.NewConfigFromText(modelText)
if err != nil {
return nil, err
}
// load [policy_definition]
policyDefinition := strings.Split(cfg.String("policy_definition::p"), ",")
fieldsNum := len(policyDefinition)
if fieldsNum > builtInAvailableField {
panic(fmt.Errorf("the maximum policy_definition field number cannot exceed %d", builtInAvailableField))
}
// filled empty field with "" and V5 with "permissionId"
for i := builtInAvailableField - fieldsNum; i > 0; i-- {
policyDefinition = append(policyDefinition, "")
}
policyDefinition = append(policyDefinition, "permissionId")
m, _ := model.NewModelFromString(modelText)
m.AddDef("p", "p", strings.Join(policyDefinition, ","))
return m, err
}
}