You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

config.go 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // Copyright 2019 The Gitea Authors. All rights reserved.
  3. // SPDX-License-Identifier: MIT
  4. package admin
  5. import (
  6. "fmt"
  7. "net/http"
  8. "net/url"
  9. "strconv"
  10. "strings"
  11. system_model "code.gitea.io/gitea/models/system"
  12. "code.gitea.io/gitea/modules/base"
  13. "code.gitea.io/gitea/modules/context"
  14. "code.gitea.io/gitea/modules/git"
  15. "code.gitea.io/gitea/modules/json"
  16. "code.gitea.io/gitea/modules/log"
  17. "code.gitea.io/gitea/modules/setting"
  18. "code.gitea.io/gitea/modules/util"
  19. "code.gitea.io/gitea/services/mailer"
  20. "gitea.com/go-chi/session"
  21. )
  22. const tplConfig base.TplName = "admin/config"
  23. // SendTestMail send test mail to confirm mail service is OK
  24. func SendTestMail(ctx *context.Context) {
  25. email := ctx.FormString("email")
  26. // Send a test email to the user's email address and redirect back to Config
  27. if err := mailer.SendTestMail(email); err != nil {
  28. ctx.Flash.Error(ctx.Tr("admin.config.test_mail_failed", email, err))
  29. } else {
  30. ctx.Flash.Info(ctx.Tr("admin.config.test_mail_sent", email))
  31. }
  32. ctx.Redirect(setting.AppSubURL + "/admin/config")
  33. }
  34. func shadowPasswordKV(cfgItem, splitter string) string {
  35. fields := strings.Split(cfgItem, splitter)
  36. for i := 0; i < len(fields); i++ {
  37. if strings.HasPrefix(fields[i], "password=") {
  38. fields[i] = "password=******"
  39. break
  40. }
  41. }
  42. return strings.Join(fields, splitter)
  43. }
  44. func shadowURL(provider, cfgItem string) string {
  45. u, err := url.Parse(cfgItem)
  46. if err != nil {
  47. log.Error("Shadowing Password for %v failed: %v", provider, err)
  48. return cfgItem
  49. }
  50. if u.User != nil {
  51. atIdx := strings.Index(cfgItem, "@")
  52. if atIdx > 0 {
  53. colonIdx := strings.LastIndex(cfgItem[:atIdx], ":")
  54. if colonIdx > 0 {
  55. return cfgItem[:colonIdx+1] + "******" + cfgItem[atIdx:]
  56. }
  57. }
  58. }
  59. return cfgItem
  60. }
  61. func shadowPassword(provider, cfgItem string) string {
  62. switch provider {
  63. case "redis":
  64. return shadowPasswordKV(cfgItem, ",")
  65. case "mysql":
  66. // root:@tcp(localhost:3306)/macaron?charset=utf8
  67. atIdx := strings.Index(cfgItem, "@")
  68. if atIdx > 0 {
  69. colonIdx := strings.Index(cfgItem[:atIdx], ":")
  70. if colonIdx > 0 {
  71. return cfgItem[:colonIdx+1] + "******" + cfgItem[atIdx:]
  72. }
  73. }
  74. return cfgItem
  75. case "postgres":
  76. // user=jiahuachen dbname=macaron port=5432 sslmode=disable
  77. if !strings.HasPrefix(cfgItem, "postgres://") {
  78. return shadowPasswordKV(cfgItem, " ")
  79. }
  80. fallthrough
  81. case "couchbase":
  82. return shadowURL(provider, cfgItem)
  83. // postgres://pqgotest:password@localhost/pqgotest?sslmode=verify-full
  84. // Notice: use shadowURL
  85. }
  86. return cfgItem
  87. }
  88. // Config show admin config page
  89. func Config(ctx *context.Context) {
  90. ctx.Data["Title"] = ctx.Tr("admin.config")
  91. ctx.Data["PageIsAdminConfig"] = true
  92. systemSettings, err := system_model.GetAllSettings(ctx)
  93. if err != nil {
  94. ctx.ServerError("system_model.GetAllSettings", err)
  95. return
  96. }
  97. // All editable settings from UI
  98. ctx.Data["SystemSettings"] = systemSettings
  99. ctx.PageData["adminConfigPage"] = true
  100. ctx.Data["CustomConf"] = setting.CustomConf
  101. ctx.Data["AppUrl"] = setting.AppURL
  102. ctx.Data["AppBuiltWith"] = setting.AppBuiltWith
  103. ctx.Data["Domain"] = setting.Domain
  104. ctx.Data["OfflineMode"] = setting.OfflineMode
  105. ctx.Data["RunUser"] = setting.RunUser
  106. ctx.Data["RunMode"] = util.ToTitleCase(setting.RunMode)
  107. ctx.Data["GitVersion"] = git.VersionInfo()
  108. ctx.Data["AppDataPath"] = setting.AppDataPath
  109. ctx.Data["RepoRootPath"] = setting.RepoRootPath
  110. ctx.Data["CustomRootPath"] = setting.CustomPath
  111. ctx.Data["LogRootPath"] = setting.Log.RootPath
  112. ctx.Data["ScriptType"] = setting.ScriptType
  113. ctx.Data["ReverseProxyAuthUser"] = setting.ReverseProxyAuthUser
  114. ctx.Data["ReverseProxyAuthEmail"] = setting.ReverseProxyAuthEmail
  115. ctx.Data["SSH"] = setting.SSH
  116. ctx.Data["LFS"] = setting.LFS
  117. ctx.Data["Service"] = setting.Service
  118. ctx.Data["DbCfg"] = setting.Database
  119. ctx.Data["Webhook"] = setting.Webhook
  120. ctx.Data["MailerEnabled"] = false
  121. if setting.MailService != nil {
  122. ctx.Data["MailerEnabled"] = true
  123. ctx.Data["Mailer"] = setting.MailService
  124. }
  125. ctx.Data["CacheAdapter"] = setting.CacheService.Adapter
  126. ctx.Data["CacheInterval"] = setting.CacheService.Interval
  127. ctx.Data["CacheConn"] = shadowPassword(setting.CacheService.Adapter, setting.CacheService.Conn)
  128. ctx.Data["CacheItemTTL"] = setting.CacheService.TTL
  129. sessionCfg := setting.SessionConfig
  130. if sessionCfg.Provider == "VirtualSession" {
  131. var realSession session.Options
  132. if err := json.Unmarshal([]byte(sessionCfg.ProviderConfig), &realSession); err != nil {
  133. log.Error("Unable to unmarshall session config for virtual provider config: %s\nError: %v", sessionCfg.ProviderConfig, err)
  134. }
  135. sessionCfg.Provider = realSession.Provider
  136. sessionCfg.ProviderConfig = realSession.ProviderConfig
  137. sessionCfg.CookieName = realSession.CookieName
  138. sessionCfg.CookiePath = realSession.CookiePath
  139. sessionCfg.Gclifetime = realSession.Gclifetime
  140. sessionCfg.Maxlifetime = realSession.Maxlifetime
  141. sessionCfg.Secure = realSession.Secure
  142. sessionCfg.Domain = realSession.Domain
  143. }
  144. sessionCfg.ProviderConfig = shadowPassword(sessionCfg.Provider, sessionCfg.ProviderConfig)
  145. ctx.Data["SessionConfig"] = sessionCfg
  146. ctx.Data["Git"] = setting.Git
  147. ctx.Data["AccessLogTemplate"] = setting.Log.AccessLogTemplate
  148. ctx.Data["LogSQL"] = setting.Database.LogSQL
  149. ctx.Data["Loggers"] = log.GetManager().DumpLoggers()
  150. prepareDeprecatedWarningsAlert(ctx)
  151. ctx.HTML(http.StatusOK, tplConfig)
  152. }
  153. func ChangeConfig(ctx *context.Context) {
  154. key := strings.TrimSpace(ctx.FormString("key"))
  155. if key == "" {
  156. ctx.JSON(http.StatusOK, map[string]string{
  157. "redirect": ctx.Req.URL.String(),
  158. })
  159. return
  160. }
  161. value := ctx.FormString("value")
  162. version := ctx.FormInt("version")
  163. if check, ok := changeConfigChecks[key]; ok {
  164. if err := check(ctx, value); err != nil {
  165. log.Warn("refused to set setting: %v", err)
  166. ctx.JSON(http.StatusOK, map[string]string{
  167. "err": ctx.Tr("admin.config.set_setting_failed", key),
  168. })
  169. return
  170. }
  171. }
  172. if err := system_model.SetSetting(ctx, &system_model.Setting{
  173. SettingKey: key,
  174. SettingValue: value,
  175. Version: version,
  176. }); err != nil {
  177. log.Error("set setting failed: %v", err)
  178. ctx.JSON(http.StatusOK, map[string]string{
  179. "err": ctx.Tr("admin.config.set_setting_failed", key),
  180. })
  181. return
  182. }
  183. ctx.JSON(http.StatusOK, map[string]any{
  184. "version": version + 1,
  185. })
  186. }
  187. var changeConfigChecks = map[string]func(ctx *context.Context, newValue string) error{
  188. system_model.KeyPictureDisableGravatar: func(_ *context.Context, newValue string) error {
  189. if v, _ := strconv.ParseBool(newValue); setting.OfflineMode && !v {
  190. return fmt.Errorf("%q should be true when OFFLINE_MODE is true", system_model.KeyPictureDisableGravatar)
  191. }
  192. return nil
  193. },
  194. system_model.KeyPictureEnableFederatedAvatar: func(_ *context.Context, newValue string) error {
  195. if v, _ := strconv.ParseBool(newValue); setting.OfflineMode && v {
  196. return fmt.Errorf("%q cannot be false when OFFLINE_MODE is true", system_model.KeyPictureEnableFederatedAvatar)
  197. }
  198. return nil
  199. },
  200. }