3x-ui/web/controller/xui.go
Claude aa90303d92
fix: update module path and all imports to saeederamy/3x-ui fork
- Update go.mod module path from mhsanaei/3x-ui/v3 to saeederamy/3x-ui/v3
- Update all 73 Go files' import paths accordingly
- Fix README.fa_IR.md install command to point to fork's main branch

The fork was referencing the original repo's module path in go.mod and all
Go source imports, making it dependent on MHSanaei's namespace at build time.

https://claude.ai/code/session_01M6d5atbWjuLTj6UwRHoK5m
2026-05-18 20:18:52 +00:00

95 lines
2.9 KiB
Go

package controller
import (
"net/http"
"github.com/saeederamy/3x-ui/v3/web/entity"
"github.com/saeederamy/3x-ui/v3/web/middleware"
"github.com/saeederamy/3x-ui/v3/web/session"
"github.com/gin-gonic/gin"
)
// XUIController is the main controller for the X-UI panel, managing sub-controllers.
type XUIController struct {
BaseController
settingController *SettingController
xraySettingController *XraySettingController
}
// NewXUIController creates a new XUIController and initializes its routes.
func NewXUIController(g *gin.RouterGroup) *XUIController {
a := &XUIController{}
a.initRouter(g)
return a
}
// initRouter sets up the main panel routes and initializes sub-controllers.
func (a *XUIController) initRouter(g *gin.RouterGroup) {
g = g.Group("/panel")
g.Use(a.checkLogin)
g.Use(middleware.CSRFMiddleware())
g.GET("/", a.index)
g.GET("/inbounds", a.inbounds)
g.GET("/nodes", a.nodes)
g.GET("/settings", a.settings)
g.GET("/xray", a.xraySettings)
g.GET("/api-docs", a.apiDocs)
// SPA pages built by Vite don't have a server-rendered <meta name="csrf-token">,
// so they fetch the session token via this endpoint at startup and replay it
// on subsequent unsafe requests through axios.
g.GET("/csrf-token", a.csrfToken)
a.settingController = NewSettingController(g)
a.xraySettingController = NewXraySettingController(g)
}
// All four panel pages now serve the Vue 3 builds from web/dist/
// instead of rendering the legacy Go templates. Each handler is a
// thin wrapper around serveDistPage so the basePath injection +
// no-cache headers stay centralised.
// index renders the main panel index page.
func (a *XUIController) index(c *gin.Context) {
serveDistPage(c, "index.html")
}
// inbounds renders the inbounds management page.
func (a *XUIController) inbounds(c *gin.Context) {
serveDistPage(c, "inbounds.html")
}
// nodes renders the multi-panel nodes management page.
func (a *XUIController) nodes(c *gin.Context) {
serveDistPage(c, "nodes.html")
}
// settings renders the settings management page.
func (a *XUIController) settings(c *gin.Context) {
serveDistPage(c, "settings.html")
}
// xraySettings renders the Xray settings page.
func (a *XUIController) xraySettings(c *gin.Context) {
serveDistPage(c, "xray.html")
}
// apiDocs renders the in-panel API documentation page.
func (a *XUIController) apiDocs(c *gin.Context) {
serveDistPage(c, "api-docs.html")
}
// csrfToken returns the session CSRF token to authenticated SPA clients.
// The endpoint is GET (a safe method) so it bypasses CSRFMiddleware itself,
// but checkLogin still gates the response — anonymous callers get 401/redirect.
func (a *XUIController) csrfToken(c *gin.Context) {
token, err := session.EnsureCSRFToken(c)
if err != nil {
c.JSON(http.StatusInternalServerError, entity.Msg{Success: false, Msg: err.Error()})
return
}
c.JSON(http.StatusOK, entity.Msg{Success: true, Obj: token})
}