mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-02-04 12:40:07 +00:00
add "network page" api (#460)
* add network api * a minor change * only show service name if unauthorized * update * 除了 load/初始化 避免在 singleton 进行查询等操作 --------- Co-authored-by: naiba <hi@nai.ba>
This commit is contained in:
@@ -55,6 +55,10 @@ func routers(r *gin.Engine) {
|
||||
optionalAuth.GET("/ws/server", commonHandler(serverStream))
|
||||
optionalAuth.GET("/server-group", commonHandler(listServerGroup))
|
||||
|
||||
optionalAuth.GET("/service", commonHandler(listService))
|
||||
optionalAuth.GET("/service/:id", commonHandler(listServiceHistory))
|
||||
optionalAuth.GET("/service/server", commonHandler(listServerWithServices))
|
||||
|
||||
optionalAuth.GET("/setting", commonHandler(listConfig))
|
||||
|
||||
auth := api.Group("", authMiddleware.MiddlewareFunc())
|
||||
@@ -71,7 +75,6 @@ func routers(r *gin.Engine) {
|
||||
auth.POST("/user", commonHandler(createUser))
|
||||
auth.POST("/batch-delete/user", commonHandler(batchDeleteUser))
|
||||
|
||||
auth.GET("/service", commonHandler(listService))
|
||||
auth.POST("/service", commonHandler(createService))
|
||||
auth.PATCH("/service/:id", commonHandler(updateService))
|
||||
auth.POST("/batch-delete/service", commonHandler(batchDeleteService))
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/jinzhu/copier"
|
||||
|
||||
"github.com/naiba/nezha/model"
|
||||
"github.com/naiba/nezha/service/singleton"
|
||||
"gorm.io/gorm"
|
||||
@@ -17,7 +20,7 @@ import (
|
||||
// @Security BearerAuth
|
||||
// @Schemes
|
||||
// @Description List service
|
||||
// @Tags auth required
|
||||
// @Tags common
|
||||
// @Produce json
|
||||
// @Success 200 {object} model.CommonResponse[model.ServiceResponse]
|
||||
// @Router /service [get]
|
||||
@@ -29,10 +32,16 @@ func listService(c *gin.Context) (*model.ServiceResponse, error) {
|
||||
var statsStore map[uint64]model.CycleTransferStats
|
||||
copier.Copy(&stats, singleton.ServiceSentinelShared.LoadStats())
|
||||
copier.Copy(&statsStore, singleton.AlertsCycleTransferStatsStore)
|
||||
_, isMember := c.Get(model.CtxKeyAuthorizedUser)
|
||||
authorized := isMember // TODO || isViewPasswordVerfied
|
||||
for k, service := range stats {
|
||||
if !service.Service.EnableShowInService {
|
||||
delete(stats, k)
|
||||
}
|
||||
if !authorized {
|
||||
service.Service = &model.Service{Name: service.Service.Name}
|
||||
stats[k] = service
|
||||
}
|
||||
}
|
||||
return []interface {
|
||||
}{
|
||||
@@ -49,6 +58,114 @@ func listService(c *gin.Context) (*model.ServiceResponse, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// List service histories by server id
|
||||
// @Summary List service histories by server id
|
||||
// @Security BearerAuth
|
||||
// @Schemes
|
||||
// @Description List service histories by server id
|
||||
// @Tags common
|
||||
// @param id path uint true "Server ID"
|
||||
// @Produce json
|
||||
// @Success 200 {object} model.CommonResponse[[]model.ServiceInfos]
|
||||
// @Router /service/{id} [get]
|
||||
func listServiceHistory(c *gin.Context) ([]*model.ServiceInfos, error) {
|
||||
idStr := c.Param("id")
|
||||
id, err := strconv.ParseUint(idStr, 10, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
singleton.ServerLock.RLock()
|
||||
server, ok := singleton.ServerList[id]
|
||||
if !ok {
|
||||
return nil, errors.New("server not found")
|
||||
}
|
||||
|
||||
_, isMember := c.Get(model.CtxKeyAuthorizedUser)
|
||||
authorized := isMember // TODO || isViewPasswordVerfied
|
||||
|
||||
if server.HideForGuest && !authorized {
|
||||
return nil, errors.New("unauthorized")
|
||||
}
|
||||
singleton.ServerLock.RUnlock()
|
||||
|
||||
var serviceHistories []*model.ServiceHistory
|
||||
if err := singleton.DB.Model(&model.ServiceHistory{}).Select("service_id, created_at, server_id, avg_delay").
|
||||
Where("server_id = ?", id).Where("created_at >= ?", time.Now().Add(-24*time.Hour)).Order("service_id, created_at").
|
||||
Scan(&serviceHistories).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
singleton.ServiceSentinelShared.ServicesLock.RLock()
|
||||
defer singleton.ServiceSentinelShared.ServicesLock.RUnlock()
|
||||
singleton.ServerLock.RLock()
|
||||
defer singleton.ServerLock.RUnlock()
|
||||
|
||||
var sortedServiceIDs []uint64
|
||||
resultMap := make(map[uint64]*model.ServiceInfos)
|
||||
for _, history := range serviceHistories {
|
||||
infos, ok := resultMap[history.ServiceID]
|
||||
if !ok {
|
||||
infos = &model.ServiceInfos{
|
||||
ServiceID: history.ServiceID,
|
||||
ServerID: history.ServerID,
|
||||
// ServiceName: singleton.ServiceSentinel.Services[history.ServiceID].Name,
|
||||
ServerName: singleton.ServerList[history.ServerID].Name,
|
||||
}
|
||||
resultMap[history.ServiceID] = infos
|
||||
sortedServiceIDs = append(sortedServiceIDs, history.ServiceID)
|
||||
}
|
||||
infos.CreatedAt = append(infos.CreatedAt, history.CreatedAt.Truncate(time.Minute).Unix()*1000)
|
||||
infos.AvgDelay = append(infos.AvgDelay, history.AvgDelay)
|
||||
}
|
||||
|
||||
ret := make([]*model.ServiceInfos, 0, len(sortedServiceIDs))
|
||||
for _, id := range sortedServiceIDs {
|
||||
ret = append(ret, resultMap[id])
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// List server with service
|
||||
// @Summary List server with service
|
||||
// @Security BearerAuth
|
||||
// @Schemes
|
||||
// @Description List server with service
|
||||
// @Tags common
|
||||
// @Produce json
|
||||
// @Success 200 {object} model.CommonResponse[[]uint64]
|
||||
// @Router /service/server [get]
|
||||
func listServerWithServices(c *gin.Context) ([]uint64, error) {
|
||||
var serverIdsWithService []uint64
|
||||
if err := singleton.DB.Model(&model.ServiceHistory{}).
|
||||
Select("distinct(server_id)").
|
||||
Where("server_id != 0").
|
||||
Find(&serverIdsWithService).Error; err != nil {
|
||||
return nil, newGormError("%v", err)
|
||||
}
|
||||
|
||||
_, isMember := c.Get(model.CtxKeyAuthorizedUser)
|
||||
authorized := isMember // TODO || isViewPasswordVerfied
|
||||
|
||||
var ret []uint64
|
||||
for _, id := range serverIdsWithService {
|
||||
singleton.ServerLock.RLock()
|
||||
server, ok := singleton.ServerList[id]
|
||||
if !ok {
|
||||
singleton.ServerLock.RUnlock()
|
||||
return nil, errors.New("server not found")
|
||||
}
|
||||
|
||||
if !server.HideForGuest || authorized {
|
||||
ret = append(ret, id)
|
||||
}
|
||||
singleton.ServerLock.RUnlock()
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Create service
|
||||
// @Summary Create service
|
||||
// @Security BearerAuth
|
||||
|
||||
Reference in New Issue
Block a user