api.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. package controller
  2. import (
  3. "net/http"
  4. "strings"
  5. "github.com/mhsanaei/3x-ui/v3/internal/web/middleware"
  6. "github.com/mhsanaei/3x-ui/v3/internal/web/service"
  7. "github.com/mhsanaei/3x-ui/v3/internal/web/service/integration"
  8. "github.com/mhsanaei/3x-ui/v3/internal/web/service/panel"
  9. "github.com/mhsanaei/3x-ui/v3/internal/web/service/tgbot"
  10. "github.com/mhsanaei/3x-ui/v3/internal/web/session"
  11. "github.com/gin-gonic/gin"
  12. )
  13. // APIController handles the main API routes for the 3x-ui panel, including inbounds and server management.
  14. type APIController struct {
  15. BaseController
  16. inboundController *InboundController
  17. serverController *ServerController
  18. nodeController *NodeController
  19. settingController *SettingController
  20. xraySettingController *XraySettingController
  21. settingService service.SettingService
  22. userService panel.UserService
  23. apiTokenService panel.ApiTokenService
  24. Tgbot tgbot.Tgbot
  25. }
  26. // NewAPIController creates a new APIController instance and initializes its routes.
  27. func NewAPIController(g *gin.RouterGroup, customGeo *integration.CustomGeoService) *APIController {
  28. a := &APIController{}
  29. a.initRouter(g, customGeo)
  30. return a
  31. }
  32. func (a *APIController) checkAPIAuth(c *gin.Context) {
  33. auth := c.GetHeader("Authorization")
  34. if after, ok := strings.CutPrefix(auth, "Bearer "); ok {
  35. tok := after
  36. if a.apiTokenService.Match(tok) {
  37. if u, err := a.userService.GetFirstUser(); err == nil {
  38. session.SetAPIAuthUser(c, u)
  39. }
  40. c.Set("api_authed", true)
  41. c.Next()
  42. return
  43. }
  44. }
  45. if !session.IsLogin(c) {
  46. if c.GetHeader("X-Requested-With") == "XMLHttpRequest" {
  47. c.AbortWithStatus(http.StatusUnauthorized)
  48. } else {
  49. c.AbortWithStatus(http.StatusNotFound)
  50. }
  51. return
  52. }
  53. c.Next()
  54. }
  55. // initRouter sets up the API routes for inbounds, server, and other endpoints.
  56. func (a *APIController) initRouter(g *gin.RouterGroup, customGeo *integration.CustomGeoService) {
  57. // Main API group
  58. api := g.Group("/panel/api")
  59. api.Use(a.checkAPIAuth)
  60. api.Use(middleware.CSRFMiddleware())
  61. // Inbounds API
  62. inbounds := api.Group("/inbounds")
  63. a.inboundController = NewInboundController(inbounds)
  64. clients := api.Group("/clients")
  65. NewClientController(clients)
  66. NewGroupController(clients)
  67. // Server API
  68. server := api.Group("/server")
  69. a.serverController = NewServerController(server)
  70. // Nodes API — multi-panel management
  71. nodes := api.Group("/nodes")
  72. a.nodeController = NewNodeController(nodes)
  73. NewCustomGeoController(api.Group("/custom-geo"), customGeo)
  74. // Settings + Xray config management live under the API surface too, so the
  75. // same API token drives them. Paths are /panel/api/setting/* and
  76. // /panel/api/xray/*.
  77. a.settingController = NewSettingController(api)
  78. a.xraySettingController = NewXraySettingController(api)
  79. // Extra routes
  80. api.POST("/backuptotgbot", a.BackuptoTgbot)
  81. }
  82. // BackuptoTgbot sends a backup of the panel data to Telegram bot admins.
  83. func (a *APIController) BackuptoTgbot(c *gin.Context) {
  84. a.Tgbot.SendBackupToAdmins()
  85. }