nezha/cmd/dashboard/controller/controller.go
2024-10-23 20:37:29 +08:00

132 lines
3.5 KiB
Go

package controller
import (
"errors"
"fmt"
"log"
"net/http"
"strings"
jwt "github.com/appleboy/gin-jwt/v2"
"github.com/gin-contrib/pprof"
"github.com/gin-gonic/gin"
swaggerfiles "github.com/swaggo/files"
ginSwagger "github.com/swaggo/gin-swagger"
docs "github.com/naiba/nezha/cmd/dashboard/docs"
"github.com/naiba/nezha/model"
"github.com/naiba/nezha/service/singleton"
)
func ServeWeb() http.Handler {
gin.SetMode(gin.ReleaseMode)
r := gin.Default()
docs.SwaggerInfo.BasePath = "/api/v1"
if singleton.Conf.Debug {
gin.SetMode(gin.DebugMode)
pprof.Register(r)
}
if singleton.Conf.Debug {
r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerfiles.Handler))
}
r.Use(recordPath)
routers(r)
return r
}
func routers(r *gin.Engine) {
authMiddleware, err := jwt.New(initParams())
if err != nil {
log.Fatal("JWT Error:" + err.Error())
}
if err := authMiddleware.MiddlewareInit(); err != nil {
log.Fatal("authMiddleware.MiddlewareInit Error:" + err.Error())
}
api := r.Group("api/v1")
api.POST("/login", authMiddleware.LoginHandler)
optionalAuth := api.Group("", optionalAuthMiddleware(authMiddleware))
optionalAuth.GET("/ws/server", commonHandler(serverStream))
optionalAuth.GET("/server-group", commonHandler(listServerGroup))
auth := api.Group("", authMiddleware.MiddlewareFunc())
auth.GET("/refresh_token", authMiddleware.RefreshHandler)
auth.POST("/terminal", commonHandler(createTerminal))
auth.GET("/ws/terminal/:id", commonHandler(terminalStream))
auth.GET("/user", commonHandler(listUser))
auth.POST("/user", commonHandler(createUser))
auth.POST("/batch-delete/user", commonHandler(batchDeleteUser))
auth.POST("/server-group", commonHandler(createServerGroup))
auth.PATCH("/server-group/:id", commonHandler(updateServerGroup))
auth.POST("/batch-delete/server-group", commonHandler(batchDeleteServerGroup))
auth.GET("/server", commonHandler(listServer))
auth.PATCH("/server/:id", commonHandler(updateServer))
auth.POST("/batch-delete/server", commonHandler(batchDeleteServer))
auth.GET("/ddns", commonHandler(listDDNS))
auth.GET("/ddns/providers", commonHandler(listProviders))
auth.POST("/ddns", commonHandler(createDDNS))
auth.PATCH("/ddns/:id", commonHandler(updateDDNS))
auth.POST("/batch-delete/ddns", commonHandler(batchDeleteDDNS))
}
func recordPath(c *gin.Context) {
url := c.Request.URL.String()
for _, p := range c.Params {
url = strings.Replace(url, p.Value, ":"+p.Key, 1)
}
c.Set("MatchedPath", url)
}
func newErrorResponse(err error) model.CommonResponse[any] {
return model.CommonResponse[any]{
Success: false,
Error: err.Error(),
}
}
type handlerFunc[T any] func(c *gin.Context) (T, error)
// There are many error types in gorm, so create a custom type to represent all
// gorm errors here instead
type gormError struct {
msg string
a []interface{}
}
func newGormError(format string, args ...interface{}) error {
return &gormError{
msg: format,
a: args,
}
}
func (ge *gormError) Error() string {
return fmt.Sprintf(ge.msg, ge.a...)
}
func commonHandler[T any](handler handlerFunc[T]) func(*gin.Context) {
return func(c *gin.Context) {
data, err := handler(c)
if err == nil {
c.JSON(http.StatusOK, model.CommonResponse[T]{Success: true, Data: data})
return
}
if _, ok := err.(*gormError); ok {
log.Printf("NEZHA>> gorm error: %v", err)
c.JSON(http.StatusOK, newErrorResponse(errors.New("database error")))
return
} else {
c.JSON(http.StatusOK, newErrorResponse(err))
return
}
}
}