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
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 97 additions and 36 deletions

View File

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

View File

@ -57,6 +57,40 @@ type PermissionRule struct {
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 {
session := GetSession(owner, -1, -1, field, value, "", "")
count, err := session.Count(&Permission{})
@ -195,10 +229,6 @@ func DeletePermission(permission *Permission) bool {
return affected != 0
}
func (permission *Permission) GetId() string {
return fmt.Sprintf("%s/%s", permission.Owner, permission.Name)
}
func GetPermissionsByUser(userId string) []*Permission {
permissions := []*Permission{}
err := adapter.Engine.Where("users like ?", "%"+userId+"%").Find(&permissions)

View File

@ -15,9 +15,11 @@
package object
import (
"fmt"
"strings"
"github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/config"
"github.com/casbin/casbin/v2/model"
xormadapter "github.com/casbin/xorm-adapter/v3"
"github.com/casdoor/casdoor/conf"
@ -36,26 +38,14 @@ func getEnforcer(permission *Permission) *casbin.Enforcer {
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)
m := model.Model{}
if permissionModel != nil {
modelText = permissionModel.ModelText
m, err = GetBuiltInModel(permissionModel.ModelText)
} else {
m, err = GetBuiltInModel("")
}
m, err := model.NewModelFromString(modelText)
if err != nil {
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
enforcer.LoadFilteredPolicy(xormadapter.Filter{
V5: []string{permission.Owner + "/" + permission.Name},
err = enforcer.LoadFilteredPolicy(xormadapter.Filter{
V5: []string{permission.GetId()},
})
if err != nil {
panic(err)
}
return enforcer
}
func getPolicies(permission *Permission) ([][]string, [][]string) {
var policies [][]string
var groupingPolicies [][]string
permissionId := permission.Owner + "/" + permission.Name
permissionId := permission.GetId()
domainExist := len(permission.Domains) > 0
for _, user := range permission.Users {
for _, resource := range permission.Resources {
@ -163,10 +156,8 @@ func Enforce(permissionRule *PermissionRule) bool {
permission := GetPermission(permissionRule.Id)
enforcer := getEnforcer(permission)
request := []interface{}{permissionRule.V0, permissionRule.V1, permissionRule.V2}
if permissionRule.V3 != "" {
request = append(request, permissionRule.V3)
}
request, _ := permissionRule.GetRequest(builtInAdapter, permissionRule.Id)
allow, err := enforcer.Enforce(request...)
if err != nil {
panic(err)
@ -177,11 +168,8 @@ func Enforce(permissionRule *PermissionRule) bool {
func BatchEnforce(permissionRules []PermissionRule) []bool {
var requests [][]interface{}
for _, permissionRule := range permissionRules {
if permissionRule.V3 != "" {
requests = append(requests, []interface{}{permissionRule.V0, permissionRule.V1, permissionRule.V2, permissionRule.V3})
} else {
requests = append(requests, []interface{}{permissionRule.V0, permissionRule.V1, permissionRule.V2})
}
request, _ := permissionRule.GetRequest(builtInAdapter, permissionRule.Id)
requests = append(requests, request)
}
permission := GetPermission(permissionRules[0].Id)
enforcer := getEnforcer(permission)
@ -226,3 +214,46 @@ func GetAllRoles(userId string) []string {
}
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
}
}