feat: Refactor GetFilteredPolicies to support multiple filters via POST (#4037)

This commit is contained in:
iderr
2025-08-04 07:51:25 -04:00
committed by GitHub
parent 124c28f1e1
commit 76f322861a
3 changed files with 94 additions and 23 deletions

View File

@@ -17,7 +17,6 @@ package controllers
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings"
"github.com/beego/beego/utils/pagination" "github.com/beego/beego/utils/pagination"
"github.com/casdoor/casdoor/object" "github.com/casdoor/casdoor/object"
@@ -200,37 +199,28 @@ func (c *ApiController) GetPolicies() {
// GetFilteredPolicies // GetFilteredPolicies
// @Title GetFilteredPolicies // @Title GetFilteredPolicies
// @Tag Enforcer API // @Tag Enforcer API
// @Description get filtered policies // @Description get filtered policies with support for multiple filters via POST body
// @Param id query string true "The id ( owner/name ) of enforcer" // @Param id query string true "The id ( owner/name ) of enforcer"
// @Param ptype query string false "Policy type, default is 'p'" // @Param body body []object.Filter true "Array of filter objects for multiple filters"
// @Param fieldIndex query int false "Field index for filtering"
// @Param fieldValues query string false "Field values for filtering, comma-separated"
// @Success 200 {array} xormadapter.CasbinRule // @Success 200 {array} xormadapter.CasbinRule
// @router /get-filtered-policies [get] // @router /get-filtered-policies [post]
func (c *ApiController) GetFilteredPolicies() { func (c *ApiController) GetFilteredPolicies() {
id := c.Input().Get("id") id := c.Input().Get("id")
ptype := c.Input().Get("ptype")
fieldIndexStr := c.Input().Get("fieldIndex")
fieldValuesStr := c.Input().Get("fieldValues")
if ptype == "" { var filters []object.Filter
ptype = "p" err := json.Unmarshal(c.Ctx.Input.RequestBody, &filters)
}
fieldIndex := util.ParseInt(fieldIndexStr)
var fieldValues []string
if fieldValuesStr != "" {
fieldValues = strings.Split(fieldValuesStr, ",")
}
policies, err := object.GetFilteredPolicies(id, ptype, fieldIndex, fieldValues...)
if err != nil { if err != nil {
c.ResponseError(err.Error()) c.ResponseError(err.Error())
return return
} }
c.ResponseOk(policies) filteredPolicies, err := object.GetFilteredPoliciesMulti(id, filters)
if err != nil {
c.ResponseError(err.Error())
return
}
c.ResponseOk(filteredPolicies)
} }
// UpdatePolicy // UpdatePolicy

View File

@@ -206,6 +206,13 @@ func GetPolicies(id string) ([]*xormadapter.CasbinRule, error) {
return res, nil return res, nil
} }
// Filter represents filter criteria with optional policy type
type Filter struct {
Ptype string `json:"ptype,omitempty"`
FieldIndex int `json:"fieldIndex"`
FieldValues []string `json:"fieldValues"`
}
func GetFilteredPolicies(id string, ptype string, fieldIndex int, fieldValues ...string) ([]*xormadapter.CasbinRule, error) { func GetFilteredPolicies(id string, ptype string, fieldIndex int, fieldValues ...string) ([]*xormadapter.CasbinRule, error) {
enforcer, err := GetInitializedEnforcer(id) enforcer, err := GetInitializedEnforcer(id)
if err != nil { if err != nil {
@@ -236,6 +243,80 @@ func GetFilteredPolicies(id string, ptype string, fieldIndex int, fieldValues ..
return res, nil return res, nil
} }
// GetFilteredPoliciesMulti applies multiple filters to policies
// Doing this in our loop is more efficient than using GetFilteredGroupingPolicy / GetFilteredPolicy which
// iterates over all policies again and again
func GetFilteredPoliciesMulti(id string, filters []Filter) ([]*xormadapter.CasbinRule, error) {
// Get all policies first
allPolicies, err := GetPolicies(id)
if err != nil {
return nil, err
}
// Filter policies based on multiple criteria
var filteredPolicies []*xormadapter.CasbinRule
if len(filters) == 0 {
// No filters, return all policies
return allPolicies, nil
} else {
for _, policy := range allPolicies {
matchesAllFilters := true
for _, filter := range filters {
// If no policy type is specified, set it to the default policy type
if filter.Ptype == "" {
filter.Ptype = "p"
}
// Check policy type
if policy.Ptype != filter.Ptype {
matchesAllFilters = false
break
}
// Check if field index is valid (0-5 for V0-V5)
if filter.FieldIndex < 0 || filter.FieldIndex > 5 {
matchesAllFilters = false
break
}
fieldValue := ""
switch filter.FieldIndex {
case 0:
fieldValue = policy.V0
case 1:
fieldValue = policy.V1
case 2:
fieldValue = policy.V2
case 3:
fieldValue = policy.V3
case 4:
fieldValue = policy.V4
case 5:
fieldValue = policy.V5
}
found := false
// Check if field value is in the list of expected values
for _, expectedValue := range filter.FieldValues {
if fieldValue == expectedValue {
found = true
break
}
}
if !found {
matchesAllFilters = false
break
}
}
if matchesAllFilters {
filteredPolicies = append(filteredPolicies, policy)
}
}
}
return filteredPolicies, nil
}
func UpdatePolicy(id string, ptype string, oldPolicy []string, newPolicy []string) (bool, error) { func UpdatePolicy(id string, ptype string, oldPolicy []string, newPolicy []string) (bool, error) {
enforcer, err := GetInitializedEnforcer(id) enforcer, err := GetInitializedEnforcer(id)
if err != nil { if err != nil {

View File

@@ -160,7 +160,7 @@ func initAPI() {
beego.Router("/api/add-adapter", &controllers.ApiController{}, "POST:AddAdapter") beego.Router("/api/add-adapter", &controllers.ApiController{}, "POST:AddAdapter")
beego.Router("/api/delete-adapter", &controllers.ApiController{}, "POST:DeleteAdapter") beego.Router("/api/delete-adapter", &controllers.ApiController{}, "POST:DeleteAdapter")
beego.Router("/api/get-policies", &controllers.ApiController{}, "GET:GetPolicies") beego.Router("/api/get-policies", &controllers.ApiController{}, "GET:GetPolicies")
beego.Router("/api/get-filtered-policies", &controllers.ApiController{}, "GET:GetFilteredPolicies") beego.Router("/api/get-filtered-policies", &controllers.ApiController{}, "POST:GetFilteredPolicies")
beego.Router("/api/update-policy", &controllers.ApiController{}, "POST:UpdatePolicy") beego.Router("/api/update-policy", &controllers.ApiController{}, "POST:UpdatePolicy")
beego.Router("/api/add-policy", &controllers.ApiController{}, "POST:AddPolicy") beego.Router("/api/add-policy", &controllers.ApiController{}, "POST:AddPolicy")
beego.Router("/api/remove-policy", &controllers.ApiController{}, "POST:RemovePolicy") beego.Router("/api/remove-policy", &controllers.ApiController{}, "POST:RemovePolicy")