mirror of
https://github.com/casdoor/casdoor.git
synced 2025-08-12 16:57:47 +08:00
Compare commits
5 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f5b4cd7fab | ||
![]() |
76f322861a | ||
![]() |
124c28f1e1 | ||
![]() |
e0d9cc7ed1 | ||
![]() |
75c1ae4366 |
@@ -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
|
||||||
|
@@ -20,6 +20,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
"github.com/mitchellh/mapstructure"
|
"github.com/mitchellh/mapstructure"
|
||||||
@@ -64,6 +65,25 @@ func (idp *CustomIdProvider) GetToken(code string) (*oauth2.Token, error) {
|
|||||||
return idp.Config.Exchange(ctx, code)
|
return idp.Config.Exchange(ctx, code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getNestedValue(data map[string]interface{}, path string) (interface{}, error) {
|
||||||
|
keys := strings.Split(path, ".")
|
||||||
|
var val interface{} = data
|
||||||
|
|
||||||
|
for _, key := range keys {
|
||||||
|
m, ok := val.(map[string]interface{})
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("path '%s' is not valid: %s is not a map", path, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
val, ok = m[key]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("key '%s' not found in path '%s'", key, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return val, nil
|
||||||
|
}
|
||||||
|
|
||||||
type CustomUserInfo struct {
|
type CustomUserInfo struct {
|
||||||
Id string `mapstructure:"id"`
|
Id string `mapstructure:"id"`
|
||||||
Username string `mapstructure:"username"`
|
Username string `mapstructure:"username"`
|
||||||
@@ -108,11 +128,11 @@ func (idp *CustomIdProvider) GetUserInfo(token *oauth2.Token) (*UserInfo, error)
|
|||||||
|
|
||||||
// map user info
|
// map user info
|
||||||
for k, v := range idp.UserMapping {
|
for k, v := range idp.UserMapping {
|
||||||
_, ok := dataMap[v]
|
val, err := getNestedValue(dataMap, v)
|
||||||
if !ok {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("cannot find %s in user from custom provider", v)
|
return nil, fmt.Errorf("cannot find %s in user from custom provider: %v", v, err)
|
||||||
}
|
}
|
||||||
dataMap[k] = dataMap[v]
|
dataMap[k] = val
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to parse id to string
|
// try to parse id to string
|
||||||
|
@@ -16,6 +16,7 @@ package object
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"slices"
|
||||||
|
|
||||||
"github.com/casbin/casbin/v2"
|
"github.com/casbin/casbin/v2"
|
||||||
"github.com/casdoor/casdoor/util"
|
"github.com/casdoor/casdoor/util"
|
||||||
@@ -206,6 +207,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,omitempty"`
|
||||||
|
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 +244,78 @@ 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 {
|
||||||
|
// Default policy type if unspecified
|
||||||
|
if filter.Ptype == "" {
|
||||||
|
filter.Ptype = "p"
|
||||||
|
}
|
||||||
|
// Always check policy type
|
||||||
|
if policy.Ptype != filter.Ptype {
|
||||||
|
matchesAllFilters = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
// If FieldIndex is nil, only filter via ptype (skip field-value checks)
|
||||||
|
if filter.FieldIndex == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
fieldIndex := *filter.FieldIndex
|
||||||
|
// If FieldIndex is out of range, also only filter via ptype
|
||||||
|
if fieldIndex < 0 || fieldIndex > 5 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
var fieldValue string
|
||||||
|
switch 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
|
||||||
|
}
|
||||||
|
|
||||||
|
// When FieldIndex is provided and valid, enforce FieldValues (if any)
|
||||||
|
if len(filter.FieldValues) > 0 && !slices.Contains(filter.FieldValues, fieldValue) {
|
||||||
|
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 {
|
||||||
|
@@ -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")
|
||||||
|
@@ -174,7 +174,11 @@ class ProviderEditPage extends React.Component {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
provider.userMapping[key] = value;
|
if (value === "") {
|
||||||
|
delete provider.userMapping[key];
|
||||||
|
} else {
|
||||||
|
provider.userMapping[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({
|
this.setState({
|
||||||
provider: provider,
|
provider: provider,
|
||||||
|
@@ -1109,8 +1109,7 @@ class LoginPage extends React.Component {
|
|||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then((credentialRequestOptions) => {
|
.then((credentialRequestOptions) => {
|
||||||
if ("status" in credentialRequestOptions) {
|
if ("status" in credentialRequestOptions) {
|
||||||
Setting.showMessage("error", credentialRequestOptions.msg);
|
return Promise.reject(new Error(credentialRequestOptions.msg));
|
||||||
throw credentialRequestOptions.status.msg;
|
|
||||||
}
|
}
|
||||||
credentialRequestOptions.publicKey.challenge = UserWebauthnBackend.webAuthnBufferDecode(credentialRequestOptions.publicKey.challenge);
|
credentialRequestOptions.publicKey.challenge = UserWebauthnBackend.webAuthnBufferDecode(credentialRequestOptions.publicKey.challenge);
|
||||||
|
|
||||||
@@ -1169,7 +1168,7 @@ class LoginPage extends React.Component {
|
|||||||
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}${error}`);
|
Setting.showMessage("error", `${i18next.t("general:Failed to connect to server")}${error}`);
|
||||||
});
|
});
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
Setting.showMessage("error", `${error}`);
|
Setting.showMessage("error", `${error.message}`);
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.setState({
|
this.setState({
|
||||||
loginLoading: false,
|
loginLoading: false,
|
||||||
|
Reference in New Issue
Block a user