164 lines
4.5 KiB
Go
164 lines
4.5 KiB
Go
//go:build ignore
|
|
|
|
package main
|
|
|
|
import (
|
|
"log"
|
|
"xboard-go/internal/config"
|
|
"xboard-go/internal/database"
|
|
"xboard-go/internal/handler"
|
|
"xboard-go/internal/middleware"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
func main() {
|
|
// Initialize configuration
|
|
config.LoadConfig()
|
|
|
|
// Initialize database
|
|
database.InitDB()
|
|
|
|
// Initialize Gin router
|
|
r := gin.Default()
|
|
|
|
// Short-link Subscription (Root level)
|
|
r.GET("/s/:token", handler.Subscribe)
|
|
|
|
// Static Assets for Admin Dist
|
|
r.Static("/admin-assets", "./frontend/admin")
|
|
|
|
// Global Middleware
|
|
r.Use(gin.Recovery())
|
|
|
|
// API Groups
|
|
v1 := r.Group("/api/v1")
|
|
{
|
|
// Passport (Auth)
|
|
passport := v1.Group("/passport")
|
|
{
|
|
passport.POST("/login", handler.Login)
|
|
passport.POST("/register", handler.Register)
|
|
}
|
|
|
|
// Authenticated Routes
|
|
auth := v1.Group("")
|
|
auth.Use(middleware.Auth())
|
|
{
|
|
user := auth.Group("/user")
|
|
{
|
|
user.GET("/info", handler.UserInfo)
|
|
}
|
|
}
|
|
|
|
// Node (UniProxy) Routes
|
|
server := v1.Group("/server")
|
|
server.Use(middleware.NodeAuth())
|
|
{
|
|
uniProxy := server.Group("/uniProxy")
|
|
{
|
|
uniProxy.GET("/user", handler.NodeUser)
|
|
uniProxy.POST("/push", handler.NodePush)
|
|
}
|
|
}
|
|
|
|
// Admin Portal Entry (Direct)
|
|
v1.GET("/:path", handler.AdminAppPage)
|
|
}
|
|
|
|
// V2 Admin API Group (Matches Xboard official frontend expectations)
|
|
v2 := r.Group("/api/v2")
|
|
{
|
|
// All admin endpoints are prefixed with the secure path
|
|
admin := v2.Group("/:path")
|
|
admin.Use(middleware.AdminAuth())
|
|
{
|
|
// Config
|
|
configGrp := admin.Group("/config")
|
|
{
|
|
configGrp.GET("/fetch", handler.AdminConfigFetch)
|
|
configGrp.POST("/save", handler.AdminConfigSave)
|
|
configGrp.GET("/getEmailTemplate", handler.AdminGetEmailTemplate)
|
|
configGrp.GET("/getThemeTemplate", handler.AdminGetThemeTemplate)
|
|
}
|
|
|
|
// Dashboard / Stat
|
|
statGrp := admin.Group("/stat")
|
|
{
|
|
statGrp.GET("/getOverride", handler.AdminDashboardSummary)
|
|
statGrp.GET("/getStats", handler.AdminDashboardSummary) // Fallback
|
|
statGrp.GET("/getTrafficRank", handler.AdminGetTrafficRank)
|
|
statGrp.GET("/getOrder", handler.AdminGetOrderStats)
|
|
}
|
|
|
|
// Essential Resources
|
|
admin.GET("/plan/fetch", handler.AdminPlansFetch)
|
|
admin.POST("/plan/save", handler.AdminPlanSave)
|
|
admin.POST("/plan/drop", handler.AdminPlanDrop)
|
|
admin.POST("/plan/sort", handler.AdminPlanSort)
|
|
|
|
admin.GET("/user/fetch", handler.AdminUsersFetch)
|
|
admin.POST("/user/update", handler.AdminUserUpdate)
|
|
admin.POST("/user/ban", handler.AdminUserBan)
|
|
admin.POST("/user/delete", handler.AdminUserDelete)
|
|
|
|
admin.GET("/order/fetch", handler.AdminOrdersFetch)
|
|
admin.POST("/order/paid", handler.AdminOrderPaid)
|
|
admin.POST("/order/cancel", handler.AdminOrderCancel)
|
|
|
|
admin.GET("/coupon/fetch", handler.AdminCouponsFetch)
|
|
admin.POST("/coupon/save", handler.AdminCouponSave)
|
|
admin.POST("/coupon/drop", handler.AdminCouponDrop)
|
|
|
|
admin.GET("/ticket/fetch", handler.AdminTicketsFetch)
|
|
|
|
// Knowledge Base
|
|
knowledgeGrp := admin.Group("/knowledge")
|
|
{
|
|
knowledgeGrp.GET("/fetch", handler.AdminKnowledgeFetch)
|
|
knowledgeGrp.POST("/save", handler.AdminKnowledgeSave)
|
|
knowledgeGrp.POST("/drop", handler.AdminKnowledgeDrop)
|
|
knowledgeGrp.POST("/sort", handler.AdminKnowledgeSort)
|
|
}
|
|
|
|
// Gift Card
|
|
giftCardGrp := admin.Group("/gift-card")
|
|
{
|
|
giftCardGrp.GET("/fetch", handler.AdminGiftCardFetch)
|
|
giftCardGrp.POST("/save", handler.AdminGiftCardSave)
|
|
giftCardGrp.POST("/generate", handler.AdminGiftCardGenerate)
|
|
}
|
|
|
|
// Traffic Reset
|
|
trafficResetGrp := admin.Group("/traffic-reset")
|
|
{
|
|
trafficResetGrp.GET("/fetch", handler.AdminTrafficResetFetch)
|
|
}
|
|
|
|
// Servers / Nodes
|
|
admin.GET("/server/group/fetch", handler.AdminServerGroupsFetch)
|
|
admin.POST("/server/group/save", handler.AdminServerGroupSave)
|
|
admin.POST("/server/group/drop", handler.AdminServerGroupDrop)
|
|
|
|
admin.GET("/server/manage/getNodes", handler.AdminServerManageGetNodes)
|
|
admin.POST("/server/manage/save", handler.AdminServerManageSave)
|
|
admin.POST("/server/manage/drop", handler.AdminServerManageDrop)
|
|
admin.POST("/server/manage/sort", handler.AdminServerManageSort)
|
|
}
|
|
}
|
|
|
|
|
|
// SPA Fallback for Admin
|
|
r.NoRoute(func(c *gin.Context) {
|
|
// If path starts with secure admin path, serve the admin app
|
|
// This allows React Router to handle sub-paths like /admin/nodes
|
|
handler.AdminAppPage(c)
|
|
})
|
|
|
|
// Start server
|
|
log.Printf("Server starting on port %s", config.AppConfig.AppPort)
|
|
if err := r.Run(":" + config.AppConfig.AppPort); err != nil {
|
|
log.Fatalf("Failed to start server: %v", err)
|
|
}
|
|
}
|