setting.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. package controller
  2. import (
  3. "errors"
  4. "strconv"
  5. "time"
  6. "github.com/mhsanaei/3x-ui/v3/internal/logger"
  7. "github.com/mhsanaei/3x-ui/v3/internal/util/crypto"
  8. "github.com/mhsanaei/3x-ui/v3/internal/web/entity"
  9. "github.com/mhsanaei/3x-ui/v3/internal/web/middleware"
  10. "github.com/mhsanaei/3x-ui/v3/internal/web/service"
  11. "github.com/mhsanaei/3x-ui/v3/internal/web/service/panel"
  12. "github.com/mhsanaei/3x-ui/v3/internal/web/session"
  13. "github.com/gin-gonic/gin"
  14. )
  15. // updateUserForm represents the form for updating user credentials.
  16. type updateUserForm struct {
  17. OldUsername string `json:"oldUsername" form:"oldUsername"`
  18. OldPassword string `json:"oldPassword" form:"oldPassword"`
  19. NewUsername string `json:"newUsername" form:"newUsername"`
  20. NewPassword string `json:"newPassword" form:"newPassword"`
  21. }
  22. // SettingController handles settings and user management operations.
  23. type SettingController struct {
  24. settingService service.SettingService
  25. userService panel.UserService
  26. panelService panel.PanelService
  27. apiTokenService panel.ApiTokenService
  28. xrayService service.XrayService
  29. }
  30. // NewSettingController creates a new SettingController and initializes its routes.
  31. func NewSettingController(g *gin.RouterGroup) *SettingController {
  32. a := &SettingController{}
  33. a.initRouter(g)
  34. return a
  35. }
  36. // initRouter sets up the routes for settings management.
  37. func (a *SettingController) initRouter(g *gin.RouterGroup) {
  38. g = g.Group("/setting")
  39. g.POST("/all", a.getAllSetting)
  40. g.POST("/defaultSettings", a.getDefaultSettings)
  41. g.POST("/update", a.updateSetting)
  42. g.POST("/updateUser", a.updateUser)
  43. g.POST("/restartPanel", a.restartPanel)
  44. g.GET("/getDefaultJsonConfig", a.getDefaultXrayConfig)
  45. g.GET("/apiTokens", a.listApiTokens)
  46. g.POST("/apiTokens/create", a.createApiToken)
  47. g.POST("/apiTokens/delete/:id", a.deleteApiToken)
  48. g.POST("/apiTokens/setEnabled/:id", a.setApiTokenEnabled)
  49. }
  50. // getAllSetting retrieves all current settings.
  51. func (a *SettingController) getAllSetting(c *gin.Context) {
  52. allSetting, err := a.settingService.GetAllSetting()
  53. if err != nil {
  54. jsonMsg(c, I18nWeb(c, "pages.settings.toasts.getSettings"), err)
  55. return
  56. }
  57. jsonObj(c, allSetting, nil)
  58. }
  59. // getDefaultSettings retrieves the default settings based on the host.
  60. func (a *SettingController) getDefaultSettings(c *gin.Context) {
  61. result, err := a.settingService.GetDefaultSettings(c.Request.Host)
  62. if err != nil {
  63. jsonMsg(c, I18nWeb(c, "pages.settings.toasts.getSettings"), err)
  64. return
  65. }
  66. jsonObj(c, result, nil)
  67. }
  68. // updateSetting updates all settings with the provided data.
  69. func (a *SettingController) updateSetting(c *gin.Context) {
  70. allSetting, ok := middleware.BindAndValidate[entity.AllSetting](c)
  71. if !ok {
  72. return
  73. }
  74. oldTwoFactor, twoFactorErr := a.settingService.GetTwoFactorEnable()
  75. oldPanelOutbound, _ := a.settingService.GetPanelOutbound()
  76. err := a.settingService.UpdateAllSetting(allSetting)
  77. if err == nil && twoFactorErr == nil && !oldTwoFactor && allSetting.TwoFactorEnable {
  78. if bumpErr := a.userService.BumpLoginEpoch(); bumpErr != nil {
  79. err = bumpErr
  80. }
  81. }
  82. if err == nil && allSetting.PanelOutbound != oldPanelOutbound {
  83. // The egress bridge lives in the generated config; reconcile the
  84. // running core. One SOCKS inbound plus one routing rule — both
  85. // hot-appliable, so this normally does not restart Xray.
  86. if applyErr := a.xrayService.RestartXray(false); applyErr != nil {
  87. logger.Warning("apply panel outbound change failed:", applyErr)
  88. }
  89. }
  90. jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifySettings"), err)
  91. }
  92. // updateUser updates the current user's username and password.
  93. func (a *SettingController) updateUser(c *gin.Context) {
  94. form := &updateUserForm{}
  95. err := c.ShouldBind(form)
  96. if err != nil {
  97. jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifySettings"), err)
  98. return
  99. }
  100. user := session.GetLoginUser(c)
  101. if user.Username != form.OldUsername || !crypto.CheckPasswordHash(user.Password, form.OldPassword) {
  102. jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifyUserError"), errors.New(I18nWeb(c, "pages.settings.toasts.originalUserPassIncorrect")))
  103. return
  104. }
  105. if form.NewUsername == "" || form.NewPassword == "" {
  106. jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifyUserError"), errors.New(I18nWeb(c, "pages.settings.toasts.userPassMustBeNotEmpty")))
  107. return
  108. }
  109. err = a.userService.UpdateUser(user.Id, form.NewUsername, form.NewPassword)
  110. if err == nil {
  111. user.Username = form.NewUsername
  112. user.Password, _ = crypto.HashPasswordAsBcrypt(form.NewPassword)
  113. if saveErr := session.SetLoginUser(c, user); saveErr != nil {
  114. err = saveErr
  115. }
  116. }
  117. jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifyUser"), err)
  118. }
  119. // restartPanel restarts the panel service after a delay.
  120. func (a *SettingController) restartPanel(c *gin.Context) {
  121. err := a.panelService.RestartPanel(time.Second * 3)
  122. jsonMsg(c, I18nWeb(c, "pages.settings.restartPanelSuccess"), err)
  123. }
  124. // getDefaultXrayConfig retrieves the default Xray configuration.
  125. func (a *SettingController) getDefaultXrayConfig(c *gin.Context) {
  126. defaultJsonConfig, err := a.settingService.GetDefaultXrayConfig()
  127. if err != nil {
  128. jsonMsg(c, I18nWeb(c, "pages.settings.toasts.getSettings"), err)
  129. return
  130. }
  131. jsonObj(c, defaultJsonConfig, nil)
  132. }
  133. type apiTokenCreateForm struct {
  134. Name string `json:"name" form:"name"`
  135. }
  136. type apiTokenEnabledForm struct {
  137. Enabled bool `json:"enabled" form:"enabled"`
  138. }
  139. func (a *SettingController) listApiTokens(c *gin.Context) {
  140. rows, err := a.apiTokenService.List()
  141. if err != nil {
  142. jsonMsg(c, I18nWeb(c, "pages.settings.toasts.getSettings"), err)
  143. return
  144. }
  145. jsonObj(c, rows, nil)
  146. }
  147. func (a *SettingController) createApiToken(c *gin.Context) {
  148. form := &apiTokenCreateForm{}
  149. if err := c.ShouldBind(form); err != nil {
  150. jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifySettings"), err)
  151. return
  152. }
  153. row, err := a.apiTokenService.Create(form.Name)
  154. if err != nil {
  155. jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifySettings"), err)
  156. return
  157. }
  158. jsonObj(c, row, nil)
  159. }
  160. func (a *SettingController) deleteApiToken(c *gin.Context) {
  161. id, err := strconv.Atoi(c.Param("id"))
  162. if err != nil {
  163. jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifySettings"), err)
  164. return
  165. }
  166. jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifySettings"), a.apiTokenService.Delete(id))
  167. }
  168. func (a *SettingController) setApiTokenEnabled(c *gin.Context) {
  169. id, err := strconv.Atoi(c.Param("id"))
  170. if err != nil {
  171. jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifySettings"), err)
  172. return
  173. }
  174. form := &apiTokenEnabledForm{}
  175. if bindErr := c.ShouldBind(form); bindErr != nil {
  176. jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifySettings"), bindErr)
  177. return
  178. }
  179. jsonMsg(c, I18nWeb(c, "pages.settings.toasts.modifySettings"), a.apiTokenService.SetEnabled(id, form.Enabled))
  180. }