diff --git a/plugin/api/platform/api.go b/plugin/api/platform/api.go index 912c1c45..cab75663 100644 --- a/plugin/api/platform/api.go +++ b/plugin/api/platform/api.go @@ -58,48 +58,23 @@ func (h *PlatformAPI) searchCollection(w http.ResponseWriter, req *http.Request, h.WriteError(w, err.Error(), http.StatusInternalServerError) return } - if collName == "cluster" { - clusterFilter, hasAllPrivilege := h.GetClusterFilter(req, "id") - if !hasAllPrivilege && clusterFilter == nil { + if meta.GetSearchRequestBodyFilter != nil { + filter, hasAllPrivilege := meta.GetSearchRequestBodyFilter(h, req) + if !hasAllPrivilege && filter == nil { h.WriteJSON(w, elastic.SearchResponse{ }, http.StatusOK) return } - mapObj := util.MapStr{} - err = util.FromJSONBytes(queryDsl, &mapObj) - if err != nil { - log.Error(err) - h.WriteError(w, err.Error(), http.StatusInternalServerError) - return - } if !hasAllPrivilege { - must := []util.MapStr{ - clusterFilter, + queryDsl, err = h.rewriteQueryWithFilter(queryDsl, filter) + if err != nil { + log.Error(err) + h.WriteError(w, err.Error(), http.StatusInternalServerError) + return } - filterQ := util.MapStr{ - "bool": util.MapStr{ - "must": must, - }, - } - v, ok := mapObj["query"].(map[string]interface{}) - if ok { //exists query - newQuery := util.MapStr{ - "bool": util.MapStr{ - "filter": filterQ, - "must": []interface{}{v}, - }, - } - mapObj["query"] = newQuery - } else { - mapObj["query"] = util.MapStr{ - "bool": util.MapStr{ - "filter": filterQ, - }, - } - } - queryDsl = util.MustToJSONBytes(mapObj) } } + searchRes, err := client.SearchWithRawQueryDSL(orm.GetIndexName(meta.MatchObject), queryDsl) if err != nil { h.WriteError(w, err.Error(), http.StatusInternalServerError) @@ -112,6 +87,41 @@ func (h *PlatformAPI) searchCollection(w http.ResponseWriter, req *http.Request, h.WriteJSON(w, searchRes,http.StatusOK) } +func (h *PlatformAPI) rewriteQueryWithFilter(queryDsl []byte, filter util.MapStr) ([]byte, error){ + + mapObj := util.MapStr{} + err := util.FromJSONBytes(queryDsl, &mapObj) + if err != nil { + return nil, err + } + must := []util.MapStr{ + filter, + } + filterQ := util.MapStr{ + "bool": util.MapStr{ + "must": must, + }, + } + v, ok := mapObj["query"].(map[string]interface{}) + if ok { //exists query + newQuery := util.MapStr{ + "bool": util.MapStr{ + "filter": filterQ, + "must": []interface{}{v}, + }, + } + mapObj["query"] = newQuery + } else { + mapObj["query"] = util.MapStr{ + "bool": util.MapStr{ + "filter": filterQ, + }, + } + } + queryDsl = util.MustToJSONBytes(mapObj) + return queryDsl, nil +} + //getCollectionMeta returns metadata of target collection, includes backend index name func (h *PlatformAPI) getCollectionMeta(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { collName := ps.MustGetParameter("collection_name") diff --git a/plugin/api/platform/domain.go b/plugin/api/platform/domain.go index 750a31ae..f12ceefa 100644 --- a/plugin/api/platform/domain.go +++ b/plugin/api/platform/domain.go @@ -10,6 +10,9 @@ import ( "infini.sh/framework/core/elastic" "infini.sh/framework/core/event" "infini.sh/framework/core/model" + "infini.sh/framework/core/util" + "net/http" + "strings" "sync" ) @@ -47,6 +50,9 @@ func GetCollectionMetas() map[string]CollectionMeta{ }, }, MatchObject: &elastic.ElasticsearchConfig{}, + GetSearchRequestBodyFilter: func(api *PlatformAPI, req *http.Request) (util.MapStr, bool) { + return api.GetClusterFilter(req, "id") + }, }, "node": { Name: "node", @@ -83,6 +89,85 @@ func GetCollectionMetas() map[string]CollectionMeta{ }, }, MatchObject: &event.Activity{}, + GetSearchRequestBodyFilter: func(api *PlatformAPI, req *http.Request) (util.MapStr, bool) { + clusterFilter, hasAllPrivilege := api.GetClusterFilter(req, "metadata.labels.cluster_id") + if !hasAllPrivilege && clusterFilter == nil { + return clusterFilter, hasAllPrivilege + } + var filter []util.MapStr + if !hasAllPrivilege && clusterFilter != nil { + filter = append(filter, clusterFilter) + } + + hasAllPrivilege, indexPrivilege := api.GetCurrentUserIndex(req) + if !hasAllPrivilege && len(indexPrivilege) == 0 { + return nil, hasAllPrivilege + } + if !hasAllPrivilege { + indexShould := make([]interface{}, 0, len(indexPrivilege)) + for clusterID, indices := range indexPrivilege { + var ( + wildcardIndices []string + normalIndices []string + ) + for _, index := range indices { + if strings.Contains(index,"*") { + wildcardIndices = append(wildcardIndices, index) + continue + } + normalIndices = append(normalIndices, index) + } + subShould := []util.MapStr{} + if len(wildcardIndices) > 0 { + subShould = append(subShould, util.MapStr{ + "query_string": util.MapStr{ + "query": strings.Join(wildcardIndices, " "), + "fields": []string{"metadata.labels.index_name"}, + "default_operator": "OR", + }, + }) + } + if len(normalIndices) > 0 { + subShould = append(subShould, util.MapStr{ + "terms": util.MapStr{ + "metadata.labels.index_name": normalIndices, + }, + }) + } + indexShould = append(indexShould, util.MapStr{ + "bool": util.MapStr{ + "must": []util.MapStr{ + { + "wildcard": util.MapStr{ + "metadata.labels.cluster_id": util.MapStr{ + "value": clusterID, + }, + }, + }, + { + "bool": util.MapStr{ + "minimum_should_match": 1, + "should": subShould, + }, + }, + }, + }, + }) + } + indexFilter := util.MapStr{ + "bool": util.MapStr{ + "minimum_should_match": 1, + "should": indexShould, + }, + } + filter = append(filter, indexFilter) + } + return util.MapStr{ + "bool": util.MapStr{ + "must": filter, + }, + }, hasAllPrivilege + }, }, "alerting_rule": { Name: "alerting_rule", @@ -105,4 +190,8 @@ type CollectionMeta struct { RequirePermission map[string][]string `json:"require_permission"` //use for orm.GetIndexName to get real index name MatchObject interface{} `json:"match_object"` + //configure GetSearchRequestBodyFilter to filter search request dsl + GetSearchRequestBodyFilter SearchRequestBodyFilter } + +type SearchRequestBodyFilter func(api *PlatformAPI, req *http.Request) (util.MapStr, bool) \ No newline at end of file