From 57bf0976f193a01355b1c185fde6500d375fd04f Mon Sep 17 00:00:00 2001 From: liugq Date: Wed, 1 Nov 2023 10:57:53 +0800 Subject: [PATCH] add collection search api (#212) add search api for front component ListView Reviewed-on: https://git.infini.ltd/infini/console/pulls/212 Co-authored-by: liugq Co-committed-by: liugq --- plugin/api/init.go | 2 + plugin/api/platform/api.go | 92 ++++++++++++++++++++++++++++++++ plugin/api/platform/domain.go | 98 +++++++++++++++++++++++++++++++++++ 3 files changed, 192 insertions(+) create mode 100644 plugin/api/platform/api.go create mode 100644 plugin/api/platform/domain.go diff --git a/plugin/api/init.go b/plugin/api/init.go index 3dff42d6..a76fb5fa 100644 --- a/plugin/api/init.go +++ b/plugin/api/init.go @@ -4,6 +4,7 @@ import ( "infini.sh/console/plugin/api/data" "infini.sh/console/plugin/api/email" "infini.sh/console/plugin/api/license" + "infini.sh/console/plugin/api/platform" "path" "infini.sh/console/config" @@ -79,4 +80,5 @@ func Init(cfg *config.AppConfig) { license.InitAPI() email.InitAPI() data.InitAPI() + platform.InitAPI() } diff --git a/plugin/api/platform/api.go b/plugin/api/platform/api.go new file mode 100644 index 00000000..f3a9672f --- /dev/null +++ b/plugin/api/platform/api.go @@ -0,0 +1,92 @@ +/* Copyright © INFINI Ltd. All rights reserved. + * Web: https://infinilabs.com + * Email: hello#infini.ltd */ + +package platform + +import ( + "fmt" + "infini.sh/framework/core/api" + "infini.sh/framework/core/api/rbac" + "infini.sh/framework/core/elastic" + "infini.sh/framework/core/global" + "infini.sh/framework/core/orm" + "infini.sh/framework/core/util" + "io" + "net/http" + httprouter "infini.sh/framework/core/api/router" + log "github.com/cihub/seelog" +) + +type PlatformAPI struct { + api.Handler +} + +func InitAPI() { + papi := PlatformAPI{} + api.HandleAPIMethod(api.POST, "/collection/:collection_name/_search", papi.searchCollection) + api.HandleAPIMethod(api.GET, "/collection/:collection_name/metadata", papi.RequireLogin(papi.getCollectionMeta)) +} + +func (h *PlatformAPI) searchCollection(w http.ResponseWriter, req *http.Request, ps httprouter.Params) { + collName := ps.MustGetParameter("collection_name") + collMetas := GetCollectionMetas() + var ( + meta CollectionMeta + ok bool + ) + if meta, ok = collMetas[collName]; !ok { + h.WriteError(w, fmt.Sprintf("metadata of collection [%s] not found", collName), http.StatusInternalServerError) + return + } + if api.IsAuthEnable(){ + claims, err := rbac.ValidateLogin(req.Header.Get("Authorization")) + if err != nil { + h.WriteError(w, err.Error(), http.StatusUnauthorized) + return + } + err = rbac.ValidatePermission(claims, meta.RequirePermission["read"]) + if err != nil { + h.WriteError(w, err.Error(), http.StatusForbidden) + return + } + } + client := elastic.GetClient(global.MustLookupString(elastic.GlobalSystemElasticsearchID)) + queryDsl, err := io.ReadAll(req.Body) + if err != nil { + log.Error(err) + h.WriteError(w, err.Error(), http.StatusInternalServerError) + return + } + searchRes, err := client.SearchWithRawQueryDSL(orm.GetIndexName(meta.MatchObject), queryDsl) + if err != nil { + h.WriteError(w, err.Error(), http.StatusInternalServerError) + return + } + if searchRes.StatusCode != http.StatusOK { + h.WriteError(w, string(searchRes.RawResult.Body), http.StatusInternalServerError) + return + } + h.WriteJSON(w, searchRes,http.StatusOK) +} + +//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") + collMetas := GetCollectionMetas() + var ( + meta CollectionMeta + ok bool + ) + if meta, ok = collMetas[collName]; !ok { + h.WriteError(w, fmt.Sprintf("metadata of collection [%s] not found", collName), http.StatusInternalServerError) + return + } + indexName := orm.GetIndexName(meta.MatchObject) + h.WriteJSON(w, util.MapStr{ + "collection_name": collName, + "metadata": util.MapStr{ + "index_name": indexName, + }, + }, http.StatusOK) +} \ No newline at end of file diff --git a/plugin/api/platform/domain.go b/plugin/api/platform/domain.go new file mode 100644 index 00000000..1607f011 --- /dev/null +++ b/plugin/api/platform/domain.go @@ -0,0 +1,98 @@ +/* Copyright © INFINI Ltd. All rights reserved. + * Web: https://infinilabs.com + * Email: hello#infini.ltd */ + +package platform + +import ( + "infini.sh/framework/core/api/rbac/enum" + "infini.sh/framework/core/elastic" + "infini.sh/framework/core/event" + "infini.sh/framework/core/model" + "sync" +) + +var ( + collectionMetas map[string]CollectionMeta + metasInitOnce sync.Once +) + +func GetCollectionMetas() map[string]CollectionMeta{ + metasInitOnce.Do(func() { + collectionMetas = map[string]CollectionMeta{ + "gateway": { + Name: "gateway", + RequirePermission: map[string][]string{ + "read": { + enum.PermissionGatewayInstanceRead, + }, + }, + MatchObject: &model.Instance{}, + }, + "agent": { + Name: "agent", + RequirePermission: map[string][]string{ + "read": { + enum.PermissionAgentInstanceRead, + }, + }, + MatchObject: &model.Instance{}, + }, + "cluster": { + Name: "cluster", + RequirePermission: map[string][]string{ + "read": { + enum.PermissionElasticsearchClusterRead, + }, + }, + MatchObject: &elastic.ElasticsearchConfig{}, + }, + "node": { + Name: "node", + RequirePermission: map[string][]string{ + "read": { + enum.PermissionElasticsearchNodeRead, + }, + }, + MatchObject: &elastic.NodeConfig{}, + }, + "index": { + Name: "index", + RequirePermission: map[string][]string{ + "read": { + enum.PermissionElasticsearchIndexRead, + }, + }, + MatchObject: &elastic.IndexConfig{}, + }, + "command": { + Name: "command", + RequirePermission: map[string][]string{ + "read": { + enum.PermissionCommandRead, + }, + }, + MatchObject: &elastic.CommonCommand{}, + }, + "activity": { + Name: "activity", + RequirePermission: map[string][]string{ + "read": { + enum.PermissionActivityRead, + }, + }, + MatchObject: &event.Activity{}, + }, + } + }) + return collectionMetas +} +//CollectionMeta includes information about how to visit backend index +type CollectionMeta struct { + //collection name + Name string `json:"name"` + //permissions required to visit collection + RequirePermission map[string][]string `json:"require_permission"` + //use for orm.GetIndexName to get real index name + MatchObject interface{} `json:"match_object"` +}