diff --git a/http/router.go b/http/router.go index 3cb6db6dbd3241bd9fd4fef1853e97c2e578e0bd..00af869b8165ca74f18744d8c32b88d160a86b7e 100644 --- a/http/router.go +++ b/http/router.go @@ -7,19 +7,20 @@ import ( "github.com/gin-contrib/gzip" "github.com/gin-contrib/pprof" "github.com/gin-gonic/gin" - "github.com/toolkits/csrf" "github.com/didi/nightingale/v5/config" ) func configRoutes(r *gin.Engine) { - csrfMid := csrf.Middleware(csrf.Options{ - Secret: config.Config.HTTP.CsrfSecret, - ErrorFunc: func(c *gin.Context) { - c.JSON(452, gin.H{"err": "csrf token mismatch"}) - c.Abort() - }, - }) + /* + csrfMid := csrf.Middleware(csrf.Options{ + Secret: config.Config.HTTP.CsrfSecret, + ErrorFunc: func(c *gin.Context) { + c.JSON(452, gin.H{"err": "csrf token mismatch"}) + c.Abort() + }, + }) + */ if config.Config.HTTP.Pprof { pprof.Register(r, "/api/debug/pprof") @@ -51,12 +52,14 @@ func configRoutes(r *gin.Engine) { } // for brower, expose location in nginx.conf - pages := r.Group("/api/n9e", csrfMid) + pages := r.Group("/api/n9e") { - pages.GET("/csrf", func(c *gin.Context) { - renderData(c, csrf.GetToken(c), nil) - }) + /* + pages.GET("/csrf", func(c *gin.Context) { + renderData(c, csrf.GetToken(c), nil) + }) + */ pages.GET("/roles", rolesGet) pages.GET("/self/profile", selfProfileGet) @@ -83,6 +86,8 @@ func configRoutes(r *gin.Engine) { pages.DELETE("/user-group/:id", login(), userGroupDel) pages.GET("/classpaths", login(), classpathListGets) + pages.GET("/classpaths/tree", login(), classpathListNodeGets) + pages.GET("/classpaths/tree-node/:id", login(), classpathListNodeGetsById) pages.POST("/classpaths", login(), classpathAdd) pages.PUT("/classpath/:id", login(), classpathPut) pages.DELETE("/classpath/:id", login(), classpathDel) @@ -180,7 +185,7 @@ func configRoutes(r *gin.Engine) { } // for brower, expose location in nginx.conf - pagesV2 := r.Group("/api/n9e/v2", csrfMid) + pagesV2 := r.Group("/api/n9e/v2") { pagesV2.POST("/collect-rules", login(), collectRulesAdd) } @@ -188,135 +193,19 @@ func configRoutes(r *gin.Engine) { // for thirdparty, do not expose location in nginx.conf v1 := r.Group("/v1/n9e") { - v1.GET("/roles", rolesGet) - v1.GET("/self/profile", selfProfileGet) - v1.PUT("/self/profile", selfProfilePut) - v1.PUT("/self/password", selfPasswordPut) - v1.GET("/self/token", selfTokenGets) - v1.POST("/self/token", selfTokenPost) - v1.PUT("/self/token", selfTokenPut) - v1.GET("/users", login(), userGets) - v1.POST("/users", admin(), userAddPost) - v1.GET("/user/:id/profile", login(), userProfileGet) - v1.PUT("/user/:id/profile", admin(), userProfilePut) - v1.PUT("/user/:id/status", admin(), userStatusPut) - v1.PUT("/user/:id/password", admin(), userPasswordPut) - v1.DELETE("/user/:id", admin(), userDel) - - v1.GET("/user-groups", login(), userGroupListGet) - v1.GET("/user-groups/mine", login(), userGroupMineGet) - v1.POST("/user-groups", login(), userGroupAdd) - v1.PUT("/user-group/:id", login(), userGroupPut) - v1.GET("/user-group/:id", login(), userGroupGet) - v1.POST("/user-group/:id/members", login(), userGroupMemberAdd) - v1.DELETE("/user-group/:id/members", login(), userGroupMemberDel) - v1.DELETE("/user-group/:id", login(), userGroupDel) - - v1.GET("/classpaths", login(), classpathListGets) - v1.POST("/classpaths", login(), classpathAdd) - v1.PUT("/classpath/:id", login(), classpathPut) - v1.DELETE("/classpath/:id", login(), classpathDel) - v1.POST("/classpath/:id/resources", login(), classpathAddResources) - v1.DELETE("/classpath/:id/resources", login(), classpathDelResources) - v1.GET("/classpath/:id/resources", login(), classpathGetsResources) - - v1.GET("/classpaths/favorites", login(), classpathFavoriteGet) - v1.POST("/classpath/:id/favorites", login(), classpathFavoriteAdd) - v1.DELETE("/classpath/:id/favorites", login(), classpathFavoriteDel) - - v1.GET("/resources", login(), resourcesQuery) - v1.PUT("/resources/note", resourceNotePut) - v1.PUT("/resources/tags", resourceTagsPut) - v1.PUT("/resources/classpaths", resourceClasspathsPut) - v1.PUT("/resources/mute", resourceMutePut) - v1.GET("/resource/:id", login(), resourceGet) - v1.DELETE("/resource/:id", login(), resourceDel) - - v1.GET("/classpath/:id/collect-rules", login(), collectRuleGets) - - v1.GET("/mutes", login(), muteGets) - v1.POST("/mutes", login(), muteAdd) - v1.GET("/mute/:id", login(), muteGet) - v1.DELETE("/mute/:id", login(), muteDel) - - v1.GET("/dashboards", login(), dashboardGets) - v1.POST("/dashboards", login(), dashboardAdd) - v1.GET("/dashboard/:id", login(), dashboardGet) - v1.PUT("/dashboard/:id", login(), dashboardPut) - v1.DELETE("/dashboard/:id", login(), dashboardDel) - v1.POST("/dashboard/:id/favorites", login(), dashboardFavoriteAdd) - v1.DELETE("/dashboard/:id/favorites", login(), dashboardFavoriteDel) - v1.GET("/dashboard/:id/chart-groups", login(), chartGroupGets) - v1.POST("/dashboard/:id/chart-groups", login(), chartGroupAdd) - - v1.PUT("/chart-groups", login(), chartGroupsPut) - v1.DELETE("/chart-group/:id", login(), chartGroupDel) - v1.GET("/chart-group/:id/charts", login(), chartGets) - v1.POST("/chart-group/:id/charts", login(), chartAdd) - v1.PUT("/chart/:id", login(), chartPut) - v1.DELETE("/chart/:id", login(), chartDel) - v1.PUT("/charts/configs", login(), chartConfigsPut) - v1.GET("/charts/tmps", login(), chartTmpGets) - v1.POST("/charts/tmps", login(), chartTmpAdd) - - v1.GET("/alert-rule-groups", login(), alertRuleGroupGets) - v1.POST("/alert-rule-groups", login(), alertRuleGroupAdd) - v1.GET("/alert-rule-group/:id", login(), alertRuleGroupGet) - v1.PUT("/alert-rule-group/:id", login(), alertRuleGroupPut) - v1.DELETE("/alert-rule-group/:id", login(), alertRuleGroupDel) - - v1.GET("/alert-rule-groups/favorites", login(), alertRuleGroupFavoriteGet) - v1.DELETE("/alert-rule-group/:id/favorites", login(), alertRuleGroupFavoriteDel) - v1.POST("/alert-rule-group/:id/favorites", login(), alertRuleGroupFavoriteAdd) - - v1.GET("/alert-rule-group/:id/alert-rules", login(), alertRuleOfGroupGet) - v1.DELETE("/alert-rule-group/:id/alert-rules", login(), alertRuleOfGroupDel) - - v1.POST("/alert-rules", login(), alertRuleAdd) - v1.PUT("/alert-rules/status", login(), alertRuleStatusPut) - v1.PUT("/alert-rules/notify-groups", login(), alertRuleNotifyGroupsPut) - v1.PUT("/alert-rules/notify-channels", login(), alertRuleNotifyChannelsPut) - v1.PUT("/alert-rules/append-tags", login(), alertRuleAppendTagsPut) - v1.GET("/alert-rule/:id", login(), alertRuleGet) - v1.PUT("/alert-rule/:id", login(), alertRulePut) - v1.DELETE("/alert-rule/:id", login(), alertRuleDel) - - v1.GET("/alert-events", login(), alertEventGets) - v1.DELETE("/alert-events", login(), alertEventsDel) - v1.GET("/alert-event/:id", login(), alertEventGet) - v1.DELETE("/alert-event/:id", login(), alertEventDel) - - v1.GET("/history-alert-events", login(), historyAlertEventGets) - v1.GET("/history-alert-event/:id", login(), historyAlertEventGet) - - v1.POST("/collect-rules", login(), collectRuleAdd) - v1.DELETE("/collect-rules", login(), collectRuleDel) - v1.PUT("/collect-rule/:id", login(), collectRulePut) - v1.GET("/collect-rules-belong-to-ident", collectRuleGetsByIdent) - v1.GET("/collect-rules-summary", collectRuleSummaryGetByIdent) - - v1.GET("/metric-descriptions", metricDescriptionGets) - v1.POST("/metric-descriptions", login(), metricDescriptionAdd) - v1.DELETE("/metric-descriptions", login(), metricDescriptionDel) - v1.PUT("/metric-description/:id", login(), metricDescriptionPut) - - v1.GET("/contact-channels", contactChannelsGet) - v1.GET("/notify-channels", notifyChannelsGet) - - v1.POST("/push", PushData) - - v1.GET("/status", Status) - v1.POST("/query", GetData) v1.POST("/instant-query", GetDataInstant) v1.POST("/tag-keys", GetTagKeys) v1.POST("/tag-values", GetTagValues) - v1.POST("/tag-metrics", GetMetrics) v1.POST("/tag-pairs", GetTagPairs) - v1.GET("/check-promql", checkPromeQl) + v1.POST("/tag-metrics", GetMetrics) + v1.POST("/push", PushData) + v1.GET("/collect-rules-belong-to-ident", collectRuleGetsByIdent) + v1.GET("/collect-rules-summary", collectRuleSummaryGetByIdent) v1.GET("/can-do-op-by-name", login(), canDoOpByName) v1.GET("/can-do-op-by-token", login(), canDoOpByToken) + } push := r.Group("/v1/n9e/series").Use(gzip.Gzip(gzip.DefaultCompression)) diff --git a/http/router_classpath.go b/http/router_classpath.go index 76c8d45facc0c8f88ff09018c688c27ad82fa44d..3c80f6eea4b71ea2ac0e3536020e606b1610cfef 100644 --- a/http/router_classpath.go +++ b/http/router_classpath.go @@ -24,6 +24,21 @@ func classpathListGets(c *gin.Context) { }, nil) } +func classpathListNodeGets(c *gin.Context) { + query := queryStr(c, "query", "") + + list, err := models.ClasspathNodeGets(query) + dangerous(err) + + renderData(c, list, nil) +} + +func classpathListNodeGetsById(c *gin.Context) { + cp := Classpath(urlParamInt64(c, "id")) + children, err := cp.DirectChildren() + renderData(c, children, err) +} + func classpathFavoriteGet(c *gin.Context) { lst, err := loginUser(c).FavoriteClasspaths() renderData(c, lst, err) diff --git a/models/classpath.go b/models/classpath.go index 46f0a564231c2832a49af0bad8926198dce4401e..5e68b4daad66bb1fa613d63679819b1f921897d4 100644 --- a/models/classpath.go +++ b/models/classpath.go @@ -19,6 +19,14 @@ type Classpath struct { UpdateBy string `json:"update_by"` } +type ClasspathNode struct { + Id int64 `json:"id"` + Path string `json:"path"` + Note string `json:"note"` + Preset int `json:"preset"` + Children []*ClasspathNode `json:"children"` +} + func (c *Classpath) TableName() string { return "classpath" } @@ -104,7 +112,6 @@ func ClasspathGets(query string, limit, offset int) ([]Classpath, error) { q := "%" + query + "%" session = session.Where("path like ?", q) } - var objs []Classpath err := session.Find(&objs) if err != nil { @@ -151,7 +158,7 @@ func ClasspathGet(where string, args ...interface{}) (*Classpath, error) { func ClasspathGetsByPrefix(prefix string) ([]Classpath, error) { var objs []Classpath - err := DB.Where("path like ?", prefix+"%").Find(&objs) + err := DB.Where("path like ?", prefix+"%").OrderBy("path").Find(&objs) if err != nil { logger.Errorf("mysql.error: query classpath fail: %v", err) return objs, internalServerError @@ -218,3 +225,94 @@ func (c *Classpath) AddResources(idents []string) error { func (c *Classpath) DelResources(idents []string) error { return ClasspathResourceDel(c.Id, idents) } + +func ClasspathNodeGets(query string) ([]*ClasspathNode, error) { + session := DB.OrderBy("path") + if query != "" { + q := "%" + query + "%" + session = session.Where("path like ?", q) + } + var objs []Classpath + err := session.Find(&objs) + if err != nil { + logger.Errorf("mysql.error: query classpath fail: %v", err) + return []*ClasspathNode{}, internalServerError + } + + if len(objs) == 0 { + return []*ClasspathNode{}, nil + } + pcs := ClasspathNodeAllChildren(objs) + + return pcs, nil +} + +func (cp *Classpath) DirectChildren() ([]Classpath, error) { + var pcs []Classpath + objs, err := ClasspathGetsByPrefix(cp.Path) + if err != nil { + logger.Errorf("mysql.error: query prefix classpath fail: %v", err) + return []Classpath{}, internalServerError + } + if len(objs) < 2 { + return []Classpath{}, nil + } + + pre := objs[1] + path := pre.Path[len(objs[0].Path):] + pre.Path = path + pcs = append(pcs, pre) + + for _, cp := range objs[2:] { + has := strings.HasPrefix(cp.Path, pre.Path) + if !has { + path := cp.Path[len(objs[0].Path):] + pre.Path = path + pcs = append(pcs, pre) + pre = cp + } + } + + return pcs, nil +} + +func ClasspathNodeAllChildren(cps []Classpath) []*ClasspathNode { + var node ClasspathNode + for _, cp := range cps { + ListInsert(cp, &node) + } + + return node.Children +} + +func ListInsert(obj Classpath, node *ClasspathNode) { + path := obj.Path + has := true + for { + if len(node.Children) == 0 { + break + } + children := node.Children[len(node.Children)-1] + prefix := children.Path + has = strings.HasPrefix(path, prefix) + if !has { + break + } + path = path[len(prefix):] + node = children + } + + newNode := ToClasspathNode(obj, path) + node.Children = append(node.Children, &newNode) +} + +func ToClasspathNode(cp Classpath, path string) ClasspathNode { + var obj ClasspathNode + obj.Id = cp.Id + obj.Path = path + obj.Note = cp.Note + obj.Preset = cp.Preset + obj.Children = []*ClasspathNode{} + + return obj +}