Merge Go frontend (apiserver + xcecli) into meson build

This commit is contained in:
Rongsong Shen 2026-04-14 11:20:17 +08:00
parent 43dc12a36c
commit c9dc8c4676
205 changed files with 30793 additions and 328 deletions

View file

@ -0,0 +1,143 @@
package middleware
import (
"apiserver/common"
"apiserver/controllers"
"apiserver/models"
"apiserver/utils"
logger "apiserver/utils"
"bytes"
"encoding/json"
"errors"
"io"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v4"
"go.uber.org/zap"
)
func ValidateHandler() gin.HandlerFunc {
logger.Debug("Enter ValidateHandler() function")
return func(ctx *gin.Context) {
if isExcludedPath(ctx.Request.URL.Path) {
ctx.Next()
return
}
validateHeader()(ctx)
if ctx.IsAborted() {
return
}
flag := !strings.Contains("multipart/form-data", ctx.Request.Header.Get("Content-Type"))
if ctx.Request.Method == http.MethodPost && flag == false {
isValidBody, err := validateRequestBody(ctx)
if err != nil || !isValidBody {
controllers.ReturnError(ctx, common.INVALID_PARAMS_CODE,
common.ERROR_READ_REQUEST_BODY_MSG+": "+err.Error(), nil)
return
}
}
if ctx.IsAborted() {
return
}
ctx.Next()
}
}
func isExcludedPath(path string) bool {
allowed := false
// define some excluded paths
excludedPaths := []string{
"/ping",
"/xce/v1/auth/logon",
"/swagger/*any",
"/xce/v1/auth/logout",
}
for _, excludedPath := range excludedPaths {
if strings.HasPrefix(path, excludedPath[:len(excludedPath)-1]) { // 去掉最后的 *
allowed = true
break
}
}
return allowed
}
// Token validation middleware
func validateHeader() gin.HandlerFunc {
logger.Debug("Enter validateHeader() function")
return func(ctx *gin.Context) {
//continue to validate token
token := ctx.GetHeader("Authorization")
if token == "" {
logger.Error("Token is empty")
controllers.ReturnError(ctx, common.ERROR_AUTH_CHECK_TOKEN_CODE,
common.ERROR_AUTH_CHECK_TOKEN_EMPTY_MSG, nil)
ctx.Abort()
return
}
// Validate token (this is a placeholder for your actual token validation logic)
isValid, err := isValidToken(strings.TrimPrefix(token, "Bearer "), ctx.ClientIP())
if err != nil {
logger.Error("Validate token error", zap.Error(err))
controllers.ReturnError(ctx, common.ERROR_AUTH_CHECK_TOKEN_CODE,
common.ERROR_AUTH_MSG+": "+err.Error(), nil)
ctx.Abort()
return
}
if !isValid {
logger.Error("Token is invalid")
controllers.ReturnError(ctx, common.ERROR_AUTH_CHECK_TOKEN_CODE,
common.ERROR_AUTH_MSG, nil)
ctx.Abort()
return
}
}
}
func isValidToken(tokenString string, IP string) (bool, error) {
token, err := jwt.ParseWithClaims(tokenString, &models.JWTClaims{}, func(token *jwt.Token) (interface{}, error) {
return []byte(utils.AuthenticationYamlConfig.Token.SecretKey), nil
})
if err != nil {
return false, err
}
if claims, ok := token.Claims.(*models.JWTClaims); ok && token.Valid {
if claims.IP == IP {
return true, nil
}
}
return false, nil
}
func validateRequestBody(ctx *gin.Context) (bool, error) {
logger.Debug("Enter validateRequestBody function")
// read request body and resolve EOF error
body, err := ctx.GetRawData()
if err != nil {
logger.Error("Failed to read request body", zap.Error(err))
ctx.Abort()
return false, err
}
if len(body) == 0 {
logger.Error("Request body is empty")
ctx.Abort()
return false, errors.New(common.ERROR_REQUEST_BODY_EMPTY_MSG)
}
// reset request body
ctx.Request.Body = io.NopCloser(bytes.NewBuffer(body))
// check request body is valid
if !json.Valid(body) {
logger.Error("Request body is not valid", zap.Error(err))
ctx.Abort()
return false, errors.New(common.ERROR_REQUEST_BODY_NOT_JSON_MSG)
}
return true, nil
}