feat: sync deployed v1.0.0-rc.38-custom.42

Sync production source including routing, billing, Astra detection and public uptime. Update custom build instructions and license packaging.
This commit is contained in:
cneicy committed 2026-09-26 04:49:11 +08:00
1 parent aa6c3f50f4
commit ceddfd3d6b
828 files changed
+122253 -13702

No files matched your search

+19 -1
View File
@@ -24,7 +24,17 @@ func SetApiRouter(router *gin.Engine) {
apiRouter.GET("/setup", controller.GetSetup)
apiRouter.POST("/setup", anonymousRequestBodyLimit, controller.PostSetup)
apiRouter.GET("/status", controller.GetStatus)
apiRouter.GET("/uptime/status", controller.GetUptimeKumaStatus)
apiRouter.GET("/uptime/status", controller.GetGroupStatus)
apiRouter.GET("/group-status", controller.GetSiteGroupStatus)
apiRouter.GET("/group-status/artwork/:id", controller.GetSiteDetectionArtwork)
apiRouter.GET("/uptime/admin", middleware.AdminAuth(), controller.GetStatusPageAdmin)
apiRouter.PUT("/uptime/group", middleware.AdminAuth(), middleware.SessionCookieOriginGuard(), controller.UpdateStatusPageGroup)
apiRouter.POST("/uptime/group/reset", middleware.AdminAuth(), middleware.SessionCookieOriginGuard(), controller.UpdateStatusPageGroup)
apiRouter.GET("/detections/artwork/:id", controller.GetDetectionArtwork)
apiRouter.POST("/detection-proxy/v1/responses", controller.DetectionProxy)
apiRouter.POST("/detections/estimate", middleware.UserAuth(), middleware.SessionCookieOriginGuard(), controller.EstimateDetection)
apiRouter.POST("/detections", middleware.UserAuth(), middleware.SessionCookieOriginGuard(), controller.CreateUserDetection)
apiRouter.GET("/detections/:id", middleware.UserAuth(), controller.GetUserDetection)
apiRouter.GET("/models", middleware.UserAuth(), controller.DashboardListModels)
apiRouter.GET("/status/test", middleware.AdminAuth(), controller.TestStatus)
apiRouter.GET("/notice", controller.GetNotice)
@@ -204,9 +214,14 @@ func SetApiRouter(router *gin.Engine) {
optionRoute.Use(middleware.RootAuth())
{
optionRoute.GET("/", controller.GetOptions)
optionRoute.GET("/request_policy", controller.GetRequestPolicy)
optionRoute.PATCH("/request_policy", controller.UpdateRequestPolicy)
optionRoute.PUT("/", controller.UpdateOption)
optionRoute.PUT("/passkey/domains", controller.UpdatePasskeyDomains)
optionRoute.GET("/model_pricing", controller.GetModelPricingConfig)
optionRoute.PATCH("/model_pricing", controller.UpdateModelPricingConfig)
optionRoute.POST("/model_pricing/convert", controller.PreviewModelPricingConversion)
optionRoute.POST("/model_pricing/preview", controller.PreviewModelPricing)
optionRoute.POST("/payment_compliance", controller.ConfirmPaymentCompliance)
optionRoute.GET("/channel_affinity_cache", controller.GetChannelAffinityCacheStats)
optionRoute.DELETE("/channel_affinity_cache", controller.ClearChannelAffinityCache)
@@ -272,6 +287,7 @@ func SetApiRouter(router *gin.Engine) {
tokenRoute.GET("/", controller.GetAllTokens)
tokenRoute.GET("/search", middleware.SearchRateLimit(), controller.SearchTokens)
tokenRoute.GET("/auto-groups", controller.GetTokenAutoGroups)
tokenRoute.POST("/routing-preview", controller.PreviewTokenRouting)
tokenRoute.GET("/:id", controller.GetToken)
tokenRoute.POST("/:id/key", middleware.CriticalRateLimit(), middleware.DisableCache(), controller.GetTokenKey)
tokenRoute.POST("/", controller.AddToken)
@@ -306,6 +322,7 @@ func SetApiRouter(router *gin.Engine) {
apiRouter.GET("/audit", middleware.DisableCache(), middleware.AdminAuth(), middleware.RequirePermission(authz.AuditRead), controller.GetAuditLogs)
apiRouter.GET("/audit/self", middleware.DisableCache(), middleware.UserAuth(), controller.GetAuditLogs)
logRoute := apiRouter.Group("/log")
logRoute.GET("/attempts/:request_id", middleware.UserAuth(), controller.GetRelayAttempts)
logRoute.GET("/", middleware.AdminAuth(), controller.GetAllLogs)
logRoute.GET("/stat", middleware.AdminAuth(), controller.GetLogsStat)
logRoute.GET("/self/stat", middleware.UserAuth(), controller.GetLogsSelfStat)
@@ -319,6 +336,7 @@ func SetApiRouter(router *gin.Engine) {
{
systemTaskRoute.POST("/log-cleanup", controller.CreateLogCleanupSystemTask)
systemTaskRoute.GET("/list", controller.ListSystemTasks)
systemTaskRoute.DELETE("/history", controller.DeleteSystemTaskHistory)
systemTaskRoute.GET("/current", controller.GetCurrentSystemTask)
systemTaskRoute.GET("/:task_id", controller.GetSystemTask)
}
+4
View File
@@ -37,9 +37,11 @@ func registerChannelRoutes(apiRouter *gin.RouterGroup) {
}
var channelPermissionRoutes = []permissionRoute{
{method: http.MethodPost, path: "/fingerprint/test", permission: authz.ChannelOperate, handler: controller.TestAstraFingerprint},
{method: http.MethodGet, path: "/", permission: authz.ChannelRead, handler: controller.GetAllChannels},
{method: http.MethodGet, path: "/search", permission: authz.ChannelRead, handler: controller.SearchChannels},
{method: http.MethodGet, path: "/models", permission: authz.ChannelRead, handler: controller.ChannelListModels},
{method: http.MethodGet, path: "/default_base_urls", permission: authz.ChannelRead, handler: controller.GetChannelDefaultBaseURLs},
{method: http.MethodGet, path: "/models_enabled", permission: authz.ChannelRead, handler: controller.EnabledListModels},
{method: http.MethodGet, path: "/ops", permission: authz.ChannelRead, handler: controller.GetChannelOps},
{method: http.MethodGet, path: "/:id", permission: authz.ChannelRead, handler: controller.GetChannel},
@@ -59,6 +61,8 @@ var channelPermissionRoutes = []permissionRoute{
{method: http.MethodPost, path: "/batch", permission: authz.ChannelSensitiveWrite, handler: controller.DeleteChannelBatch},
{method: http.MethodPost, path: "/fix", permission: authz.ChannelOperate, handler: controller.FixChannelsAbilities},
{method: http.MethodGet, path: "/fetch_models/:id", permission: authz.ChannelOperate, handler: controller.FetchUpstreamModels},
{method: http.MethodGet, path: "/:id/vllm/status", permission: authz.ChannelRead, handler: controller.GetVLLMChannelStatus},
{method: http.MethodGet, path: "/:id/sglang/status", permission: authz.ChannelRead, handler: controller.GetSGLangChannelStatus},
{method: http.MethodPost, path: "/fetch_models", permission: authz.ChannelSensitiveWrite, handler: controller.FetchModels},
{method: http.MethodPost, path: "/:id/codex/refresh", permission: authz.ChannelSensitiveWrite, handler: controller.RefreshCodexChannelCredential},
{method: http.MethodGet, path: "/:id/codex/usage", permission: authz.ChannelRead, handler: controller.GetCodexChannelUsage},
+15 -1
View File
@@ -2,6 +2,7 @@ package router
import (
"net/http"
"net/http/httptest"
"reflect"
"testing"
@@ -12,7 +13,20 @@ import (
"github.com/stretchr/testify/require"
)
func TestChannelStatusRoutesUseOperatePermission(t *testing.T) {
func TestChannelDefaultBaseURLsRequireReadPermission(t *testing.T) {
assertChannelRoutePermission(t, http.MethodGet, "/default_base_urls", authz.ChannelRead, controller.GetChannelDefaultBaseURLs)
gin.SetMode(gin.TestMode)
engine := gin.New()
registerChannelRoutes(engine.Group("/api"))
recorder := httptest.NewRecorder()
engine.ServeHTTP(recorder, httptest.NewRequest(http.MethodGet, "/api/channel/default_base_urls", nil))
assert.Equal(t, http.StatusUnauthorized, recorder.Code)
}
func TestChannelStatusRoutesUseExpectedPermissions(t *testing.T) {
assertChannelRoutePermission(t, http.MethodGet, "/:id/vllm/status", authz.ChannelRead, controller.GetVLLMChannelStatus)
assertChannelRoutePermission(t, http.MethodGet, "/:id/sglang/status", authz.ChannelRead, controller.GetSGLangChannelStatus)
assertChannelRoutePermission(t, http.MethodPost, "/:id/status", authz.ChannelOperate, controller.UpdateChannelStatus)
assertChannelRoutePermission(t, http.MethodPost, "/status/batch", authz.ChannelOperate, controller.BatchUpdateChannelStatus)
assertChannelRoutePermission(t, http.MethodPut, "/", authz.ChannelWrite, controller.UpdateChannel)
+16
View File
@@ -1,6 +1,8 @@
package router
import (
"strings"
"github.com/QuantumNous/new-api/constant"
"github.com/QuantumNous/new-api/controller"
"github.com/QuantumNous/new-api/middleware"
@@ -70,6 +72,11 @@ func SetRelayRouter(router *gin.Engine) {
relayV1Router.Use(middleware.RouteTag("relay"))
relayV1Router.Use(middleware.SystemPerformanceCheck())
relayV1Router.Use(middleware.TokenAuth())
{
// Responses WebSocket route. Channel selection happens after the first
// response.create event; each event runs the ordinary request limiter.
relayV1Router.GET("/responses", controller.ResponsesWebSocket)
}
relayV1Router.Use(middleware.ModelRequestRateLimit())
{
// WebSocket 路由(统一到 Relay)
@@ -181,6 +188,15 @@ func SetRelayRouter(router *gin.Engine) {
//relayMjRouter.Use()
relayGeminiRouter := router.Group("/v1beta")
// :countTokens is not implemented. Answer it like an unregistered route
// before auth/channel selection instead of silently relaying it as
// generateContent (#7283).
relayGeminiRouter.Use(func(c *gin.Context) {
if strings.HasSuffix(c.Request.URL.Path, ":countTokens") {
controller.RelayNotFound(c)
c.Abort()
}
})
relayGeminiRouter.Use(middleware.RouteTag("relay"))
relayGeminiRouter.Use(middleware.SystemPerformanceCheck())
relayGeminiRouter.Use(middleware.TokenAuth())