Files
trihuy-russian/web/controller/api.go
T

95 lines
2.9 KiB
Go
Raw Normal View History

2023-02-09 22:48:06 +03:30
package controller
2023-05-19 00:31:05 +03:30
import (
"net/http"
2026-05-09 17:38:48 +02:00
"strings"
"github.com/mhsanaei/3x-ui/v2/web/middleware"
2025-09-19 10:05:43 +02:00
"github.com/mhsanaei/3x-ui/v2/web/service"
"github.com/mhsanaei/3x-ui/v2/web/session"
2023-05-19 00:31:05 +03:30
"github.com/gin-gonic/gin"
)
2023-02-09 22:48:06 +03:30
2025-09-20 09:35:50 +02:00
// APIController handles the main API routes for the 3x-ui panel, including inbounds and server management.
2023-04-02 02:30:15 +04:30
type APIController struct {
2023-04-09 23:13:18 +03:30
BaseController
inboundController *InboundController
2025-09-09 01:22:43 +02:00
serverController *ServerController
2026-05-09 17:38:48 +02:00
nodeController *NodeController
settingService service.SettingService
userService service.UserService
2023-05-19 00:31:05 +03:30
Tgbot service.Tgbot
2023-02-09 22:48:06 +03:30
}
2025-09-20 09:35:50 +02:00
// NewAPIController creates a new APIController instance and initializes its routes.
func NewAPIController(g *gin.RouterGroup, customGeo *service.CustomGeoService) *APIController {
2023-04-09 23:13:18 +03:30
a := &APIController{}
a.initRouter(g, customGeo)
2023-04-09 23:13:18 +03:30
return a
2023-02-09 22:48:06 +03:30
}
// checkAPIAuth is a middleware that returns 404 for unauthenticated API requests
2026-05-09 17:38:48 +02:00
// to hide the existence of API endpoints from unauthorized users.
//
// Two auth paths are accepted:
// 1. Authorization: Bearer <apiToken> — used by remote central panels
// polling this instance as a node. Matches via constant-time compare.
// Sets c.Set("api_authed", true) so CSRFMiddleware can short-circuit.
// 2. Existing session cookie — used by browsers logged into the panel UI.
//
// Anything else falls through to a 404 so the API endpoints remain hidden.
func (a *APIController) checkAPIAuth(c *gin.Context) {
2026-05-09 17:38:48 +02:00
auth := c.GetHeader("Authorization")
if strings.HasPrefix(auth, "Bearer ") {
tok := strings.TrimPrefix(auth, "Bearer ")
if a.settingService.MatchApiToken(tok) {
// Handlers like InboundController.addInbound assume a logged-in
// user (inbound.UserId = user.Id). Bearer callers have no
// session, so attach the first user as a fallback. Single-user
// panels are the norm here.
if u, err := a.userService.GetFirstUser(); err == nil {
session.SetAPIAuthUser(c, u)
}
c.Set("api_authed", true)
c.Next()
return
}
}
if !session.IsLogin(c) {
c.AbortWithStatus(http.StatusNotFound)
return
}
c.Next()
}
2025-09-20 09:35:50 +02:00
// initRouter sets up the API routes for inbounds, server, and other endpoints.
func (a *APIController) initRouter(g *gin.RouterGroup, customGeo *service.CustomGeoService) {
2025-09-09 01:22:43 +02:00
// Main API group
api := g.Group("/panel/api")
api.Use(a.checkAPIAuth)
api.Use(middleware.CSRFMiddleware())
2025-09-09 01:22:43 +02:00
// Inbounds API
inbounds := api.Group("/inbounds")
a.inboundController = NewInboundController(inbounds)
// Server API
server := api.Group("/server")
a.serverController = NewServerController(server)
2026-05-09 17:38:48 +02:00
// Nodes API — multi-panel management
nodes := api.Group("/nodes")
a.nodeController = NewNodeController(nodes)
NewCustomGeoController(api.Group("/custom-geo"), customGeo)
2025-09-09 01:22:43 +02:00
// Extra routes
api.GET("/backuptotgbot", a.BackuptoTgbot)
2023-04-25 18:46:09 +03:30
}
2023-05-19 00:31:05 +03:30
2025-09-20 09:35:50 +02:00
// BackuptoTgbot sends a backup of the panel data to Telegram bot admins.
2025-09-09 01:22:43 +02:00
func (a *APIController) BackuptoTgbot(c *gin.Context) {
2023-05-21 03:29:27 +04:30
a.Tgbot.SendBackupToAdmins()
2023-05-19 00:31:05 +03:30
}