mirror of
https://github.com/0xJacky/nginx-ui.git
synced 2025-05-11 10:25:52 +02:00
enhance(wip): error handle
This commit is contained in:
parent
3f95ae5d90
commit
650196d06a
93 changed files with 5228 additions and 3738 deletions
21
api/api.go
21
api/api.go
|
@ -1,9 +1,12 @@
|
|||
package api
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"github.com/0xJacky/Nginx-UI/model"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/uozi-tech/cosy"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"gorm.io/gorm"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
|
@ -13,9 +16,21 @@ func CurrentUser(c *gin.Context) *model.User {
|
|||
|
||||
func ErrHandler(c *gin.Context, err error) {
|
||||
logger.GetLogger().Errorln(err)
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"message": err.Error(),
|
||||
})
|
||||
var cErr *cosy.Error
|
||||
switch {
|
||||
case errors.Is(err, gorm.ErrRecordNotFound):
|
||||
c.JSON(http.StatusNotFound, &cosy.Error{
|
||||
Code: http.StatusNotFound,
|
||||
Message: gorm.ErrRecordNotFound.Error(),
|
||||
})
|
||||
case errors.As(err, &cErr):
|
||||
c.JSON(http.StatusInternalServerError, cErr)
|
||||
default:
|
||||
c.JSON(http.StatusInternalServerError, &cosy.Error{
|
||||
Code: http.StatusInternalServerError,
|
||||
Message: err.Error(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func SetSSEHeaders(c *gin.Context) {
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
package nginx
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
import (
|
||||
"github.com/0xJacky/Nginx-UI/api/nginx_log"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func InitRouter(r *gin.RouterGroup) {
|
||||
r.POST("ngx/build_config", BuildNginxConfig)
|
||||
|
@ -10,10 +13,6 @@ func InitRouter(r *gin.RouterGroup) {
|
|||
r.POST("nginx/restart", Restart)
|
||||
r.POST("nginx/test", Test)
|
||||
r.GET("nginx/status", Status)
|
||||
r.POST("nginx_log", GetNginxLogPage)
|
||||
r.POST("nginx_log", nginx_log.GetNginxLogPage)
|
||||
r.GET("nginx/directives", GetDirectives)
|
||||
}
|
||||
|
||||
func InitNginxLogRouter(r *gin.RouterGroup) {
|
||||
r.GET("nginx_log", Log)
|
||||
}
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
package nginx
|
||||
package nginx_log
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/internal/cache"
|
||||
"github.com/0xJacky/Nginx-UI/internal/helper"
|
||||
"github.com/0xJacky/Nginx-UI/internal/nginx"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/0xJacky/Nginx-UI/internal/nginx_log"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/hpcloud/tail"
|
||||
|
@ -70,7 +67,7 @@ func GetNginxLogPage(c *gin.Context) {
|
|||
c.JSON(http.StatusInternalServerError, nginxLogPageResp{
|
||||
Error: "log file is not regular file",
|
||||
})
|
||||
logger.Error("log file is not regular file:", logPath)
|
||||
logger.Errorf("log file is not regular file: %s", logPath)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -132,30 +129,7 @@ func GetNginxLogPage(c *gin.Context) {
|
|||
})
|
||||
}
|
||||
|
||||
// isLogPathUnderWhiteList checks if the log path is under one of the paths in LogDirWhiteList
|
||||
func isLogPathUnderWhiteList(path string) bool {
|
||||
cacheKey := fmt.Sprintf("isLogPathUnderWhiteList:%s", path)
|
||||
res, ok := cache.Get(cacheKey)
|
||||
// no cache, check it
|
||||
if !ok {
|
||||
for _, whitePath := range settings.NginxSettings.LogDirWhiteList {
|
||||
if helper.IsUnderDirectory(path, whitePath) {
|
||||
cache.Set(cacheKey, true, 0)
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
return res.(bool)
|
||||
}
|
||||
|
||||
func getLogPath(control *controlStruct) (logPath string, err error) {
|
||||
if len(settings.NginxSettings.LogDirWhiteList) == 0 {
|
||||
err = errors.New("The settings.NginxSettings.LogDirWhiteList has not been configured. " +
|
||||
"For security reasons, please configure a whitelist of log directories. " +
|
||||
"Please visit https://nginxui.com/guide/config-nginx.html for more information.")
|
||||
return
|
||||
}
|
||||
switch control.Type {
|
||||
case "site":
|
||||
var config *nginx.NgxConfig
|
||||
|
@ -167,12 +141,12 @@ func getLogPath(control *controlStruct) (logPath string, err error) {
|
|||
}
|
||||
|
||||
if control.ServerIdx >= len(config.Servers) {
|
||||
err = errors.New("serverIdx out of range")
|
||||
err = nginx_log.ErrServerIdxOutOfRange
|
||||
return
|
||||
}
|
||||
|
||||
if control.DirectiveIdx >= len(config.Servers[control.ServerIdx].Directives) {
|
||||
err = errors.New("DirectiveIdx out of range")
|
||||
err = nginx_log.ErrDirectiveIdxOutOfRange
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -181,12 +155,12 @@ func getLogPath(control *controlStruct) (logPath string, err error) {
|
|||
case "access_log", "error_log":
|
||||
// ok
|
||||
default:
|
||||
err = errors.New("directive.Params neither access_log nor error_log")
|
||||
err = nginx_log.ErrLogDirective
|
||||
return
|
||||
}
|
||||
|
||||
if directive.Params == "" {
|
||||
err = errors.New("directive.Params is empty")
|
||||
err = nginx_log.ErrDirectiveParamsIsEmpty
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -200,8 +174,7 @@ func getLogPath(control *controlStruct) (logPath string, err error) {
|
|||
path := nginx.GetErrorLogPath()
|
||||
|
||||
if path == "" {
|
||||
err = errors.New("settings.NginxLogSettings.ErrorLogPath is empty," +
|
||||
" refer to https://nginxui.com/guide/config-nginx.html for more information")
|
||||
err = nginx_log.ErrErrorLogPathIsEmpty
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -210,8 +183,7 @@ func getLogPath(control *controlStruct) (logPath string, err error) {
|
|||
path := nginx.GetAccessLogPath()
|
||||
|
||||
if path == "" {
|
||||
err = errors.New("settings.NginxLogSettings.AccessLogPath is empty," +
|
||||
" refer to https://nginxui.com/guide/config-nginx.html for more information")
|
||||
err = nginx_log.ErrAccessLogPathIsEmpty
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -219,9 +191,8 @@ func getLogPath(control *controlStruct) (logPath string, err error) {
|
|||
}
|
||||
|
||||
// check if logPath is under one of the paths in LogDirWhiteList
|
||||
if !isLogPathUnderWhiteList(logPath) {
|
||||
err = errors.New("The log path is not under the paths in LogDirWhiteList.")
|
||||
return "", err
|
||||
if !nginx_log.IsLogPathUnderWhiteList(logPath) {
|
||||
return "", nginx_log.ErrLogPathIsNotUnderTheLogDirWhiteList
|
||||
}
|
||||
return
|
||||
}
|
7
api/nginx_log/router.go
Normal file
7
api/nginx_log/router.go
Normal file
|
@ -0,0 +1,7 @@
|
|||
package nginx_log
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
|
||||
func InitRouter(r *gin.RouterGroup) {
|
||||
r.GET("nginx_log", Log)
|
||||
}
|
|
@ -6,7 +6,7 @@ import (
|
|||
"github.com/0xJacky/Nginx-UI/internal/chatbot"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
"github.com/sashabaranov/go-openai"
|
||||
"github.com/uozi-tech/cosy"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
|
|
|
@ -2,7 +2,6 @@ package user
|
|||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"github.com/0xJacky/Nginx-UI/api"
|
||||
"github.com/0xJacky/Nginx-UI/internal/cache"
|
||||
"github.com/0xJacky/Nginx-UI/internal/passkey"
|
||||
|
@ -77,23 +76,17 @@ func Start2FASecureSessionByOTP(c *gin.Context) {
|
|||
}
|
||||
u := api.CurrentUser(c)
|
||||
if !u.EnabledOTP() {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"message": "User has not configured OTP as 2FA",
|
||||
})
|
||||
api.ErrHandler(c, user.ErrUserNotEnabledOTPAs2FA)
|
||||
return
|
||||
}
|
||||
|
||||
if json.OTP == "" && json.RecoveryCode == "" {
|
||||
c.JSON(http.StatusBadRequest, LoginResponse{
|
||||
Message: "The user has enabled OTP as 2FA",
|
||||
})
|
||||
api.ErrHandler(c, user.ErrOTPOrRecoveryCodeEmpty)
|
||||
return
|
||||
}
|
||||
|
||||
if err := user.VerifyOTP(u, json.OTP, json.RecoveryCode); err != nil {
|
||||
c.JSON(http.StatusBadRequest, LoginResponse{
|
||||
Message: "Invalid OTP or recovery code",
|
||||
})
|
||||
api.ErrHandler(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -106,7 +99,7 @@ func Start2FASecureSessionByOTP(c *gin.Context) {
|
|||
|
||||
func BeginStart2FASecureSessionByPasskey(c *gin.Context) {
|
||||
if !passkey.Enabled() {
|
||||
api.ErrHandler(c, fmt.Errorf("WebAuthn settings are not configured"))
|
||||
api.ErrHandler(c, user.ErrWebAuthnNotConfigured)
|
||||
return
|
||||
}
|
||||
webauthnInstance := passkey.GetInstance()
|
||||
|
@ -126,13 +119,13 @@ func BeginStart2FASecureSessionByPasskey(c *gin.Context) {
|
|||
|
||||
func FinishStart2FASecureSessionByPasskey(c *gin.Context) {
|
||||
if !passkey.Enabled() {
|
||||
api.ErrHandler(c, fmt.Errorf("WebAuthn settings are not configured"))
|
||||
api.ErrHandler(c, user.ErrWebAuthnNotConfigured)
|
||||
return
|
||||
}
|
||||
passkeySessionID := c.GetHeader("X-Passkey-Session-ID")
|
||||
sessionDataBytes, ok := cache.Get(passkeySessionID)
|
||||
if !ok {
|
||||
api.ErrHandler(c, fmt.Errorf("session not found"))
|
||||
api.ErrHandler(c, user.ErrSessionNotFound)
|
||||
return
|
||||
}
|
||||
sessionData := sessionDataBytes.(*webauthn.SessionData)
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
"github.com/0xJacky/Nginx-UI/query"
|
||||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
"github.com/uozi-tech/cosy"
|
||||
"github.com/uozi-tech/cosy/logger"
|
||||
"math/rand/v2"
|
||||
|
@ -25,12 +25,10 @@ type LoginUser struct {
|
|||
}
|
||||
|
||||
const (
|
||||
ErrPasswordIncorrect = 4031
|
||||
ErrMaxAttempts = 4291
|
||||
ErrUserBanned = 4033
|
||||
Enabled2FA = 199
|
||||
Error2FACode = 4034
|
||||
LoginSuccess = 200
|
||||
ErrMaxAttempts = 4291
|
||||
Enabled2FA = 199
|
||||
Error2FACode = 4034
|
||||
LoginSuccess = 200
|
||||
)
|
||||
|
||||
type LoginResponse struct {
|
||||
|
@ -73,15 +71,9 @@ func Login(c *gin.Context) {
|
|||
time.Sleep(random * time.Second)
|
||||
switch {
|
||||
case errors.Is(err, user.ErrPasswordIncorrect):
|
||||
c.JSON(http.StatusForbidden, LoginResponse{
|
||||
Message: "Password incorrect",
|
||||
Code: ErrPasswordIncorrect,
|
||||
})
|
||||
c.JSON(http.StatusForbidden, user.ErrPasswordIncorrect)
|
||||
case errors.Is(err, user.ErrUserBanned):
|
||||
c.JSON(http.StatusForbidden, LoginResponse{
|
||||
Message: "The user is banned",
|
||||
Code: ErrUserBanned,
|
||||
})
|
||||
c.JSON(http.StatusForbidden, user.ErrUserBanned)
|
||||
default:
|
||||
api.ErrHandler(c, err)
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/0xJacky/Nginx-UI/settings"
|
||||
"github.com/casdoor/casdoor-go-sdk/casdoorsdk"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/pkg/errors"
|
||||
"errors"
|
||||
"github.com/uozi-tech/cosy"
|
||||
"gorm.io/gorm"
|
||||
"net/http"
|
||||
|
|
|
@ -53,7 +53,7 @@ func FinishPasskeyRegistration(c *gin.Context) {
|
|||
webauthnInstance := passkey.GetInstance()
|
||||
sessionDataBytes, ok := cache.Get(buildCachePasskeyRegKey(cUser.ID))
|
||||
if !ok {
|
||||
api.ErrHandler(c, fmt.Errorf("session not found"))
|
||||
api.ErrHandler(c, user.ErrSessionNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -87,7 +87,7 @@ func FinishPasskeyRegistration(c *gin.Context) {
|
|||
|
||||
func BeginPasskeyLogin(c *gin.Context) {
|
||||
if !passkey.Enabled() {
|
||||
api.ErrHandler(c, fmt.Errorf("WebAuthn settings are not configured"))
|
||||
api.ErrHandler(c, user.ErrWebAuthnNotConfigured)
|
||||
return
|
||||
}
|
||||
webauthnInstance := passkey.GetInstance()
|
||||
|
@ -107,13 +107,13 @@ func BeginPasskeyLogin(c *gin.Context) {
|
|||
|
||||
func FinishPasskeyLogin(c *gin.Context) {
|
||||
if !passkey.Enabled() {
|
||||
api.ErrHandler(c, fmt.Errorf("WebAuthn settings are not configured"))
|
||||
api.ErrHandler(c, user.ErrWebAuthnNotConfigured)
|
||||
return
|
||||
}
|
||||
sessionId := c.GetHeader("X-Passkey-Session-ID")
|
||||
sessionDataBytes, ok := cache.Get(sessionId)
|
||||
if !ok {
|
||||
api.ErrHandler(c, fmt.Errorf("session not found"))
|
||||
api.ErrHandler(c, user.ErrSessionNotFound)
|
||||
return
|
||||
}
|
||||
webauthnInstance := passkey.GetInstance()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue