gitea源码

service.go 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. // Copyright 2019 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package setting
  4. import (
  5. "regexp"
  6. "runtime"
  7. "strings"
  8. "time"
  9. "code.gitea.io/gitea/modules/glob"
  10. "code.gitea.io/gitea/modules/log"
  11. "code.gitea.io/gitea/modules/structs"
  12. )
  13. // enumerates all the types of captchas
  14. const (
  15. ImageCaptcha = "image"
  16. ReCaptcha = "recaptcha"
  17. HCaptcha = "hcaptcha"
  18. MCaptcha = "mcaptcha"
  19. CfTurnstile = "cfturnstile"
  20. )
  21. // Service settings
  22. var Service = struct {
  23. DefaultUserVisibility string
  24. DefaultUserVisibilityMode structs.VisibleType
  25. AllowedUserVisibilityModes []string
  26. AllowedUserVisibilityModesSlice AllowedVisibility `ini:"-"`
  27. DefaultOrgVisibility string
  28. DefaultOrgVisibilityMode structs.VisibleType
  29. ActiveCodeLives int
  30. ResetPwdCodeLives int
  31. RegisterEmailConfirm bool
  32. RegisterManualConfirm bool
  33. EmailDomainAllowList []glob.Glob
  34. EmailDomainBlockList []glob.Glob
  35. DisableRegistration bool
  36. AllowOnlyInternalRegistration bool
  37. AllowOnlyExternalRegistration bool
  38. ShowRegistrationButton bool
  39. EnablePasswordSignInForm bool
  40. ShowMilestonesDashboardPage bool
  41. RequireSignInViewStrict bool
  42. BlockAnonymousAccessExpensive bool
  43. EnableNotifyMail bool
  44. EnableBasicAuth bool
  45. EnablePasskeyAuth bool
  46. EnableReverseProxyAuth bool
  47. EnableReverseProxyAuthAPI bool
  48. EnableReverseProxyAutoRegister bool
  49. EnableReverseProxyEmail bool
  50. EnableReverseProxyFullName bool
  51. EnableCaptcha bool
  52. RequireCaptchaForLogin bool
  53. RequireExternalRegistrationCaptcha bool
  54. RequireExternalRegistrationPassword bool
  55. CaptchaType string
  56. RecaptchaSecret string
  57. RecaptchaSitekey string
  58. RecaptchaURL string
  59. CfTurnstileSecret string
  60. CfTurnstileSitekey string
  61. HcaptchaSecret string
  62. HcaptchaSitekey string
  63. McaptchaSecret string
  64. McaptchaSitekey string
  65. McaptchaURL string
  66. DefaultKeepEmailPrivate bool
  67. DefaultAllowCreateOrganization bool
  68. DefaultUserIsRestricted bool
  69. EnableTimetracking bool
  70. DefaultEnableTimetracking bool
  71. DefaultEnableDependencies bool
  72. AllowCrossRepositoryDependencies bool
  73. DefaultAllowOnlyContributorsToTrackTime bool
  74. NoReplyAddress string
  75. UserLocationMapURL string
  76. EnableUserHeatmap bool
  77. AutoWatchNewRepos bool
  78. AutoWatchOnChanges bool
  79. DefaultOrgMemberVisible bool
  80. UserDeleteWithCommentsMaxTime time.Duration
  81. ValidSiteURLSchemes []string
  82. // OpenID settings
  83. EnableOpenIDSignIn bool
  84. EnableOpenIDSignUp bool
  85. OpenIDWhitelist []*regexp.Regexp
  86. OpenIDBlacklist []*regexp.Regexp
  87. // Explore page settings
  88. Explore struct {
  89. RequireSigninView bool `ini:"REQUIRE_SIGNIN_VIEW"`
  90. DisableUsersPage bool `ini:"DISABLE_USERS_PAGE"`
  91. DisableOrganizationsPage bool `ini:"DISABLE_ORGANIZATIONS_PAGE"`
  92. DisableCodePage bool `ini:"DISABLE_CODE_PAGE"`
  93. } `ini:"service.explore"`
  94. QoS struct {
  95. Enabled bool
  96. MaxInFlightRequests int
  97. MaxWaitingRequests int
  98. TargetWaitTime time.Duration
  99. }
  100. }{
  101. AllowedUserVisibilityModesSlice: []bool{true, true, true},
  102. }
  103. // AllowedVisibility store in a 3 item bool array what is allowed
  104. type AllowedVisibility []bool
  105. // IsAllowedVisibility check if a AllowedVisibility allow a specific VisibleType
  106. func (a AllowedVisibility) IsAllowedVisibility(t structs.VisibleType) bool {
  107. if int(t) >= len(a) {
  108. return false
  109. }
  110. return a[t]
  111. }
  112. // ToVisibleTypeSlice convert a AllowedVisibility into a VisibleType slice
  113. func (a AllowedVisibility) ToVisibleTypeSlice() (result []structs.VisibleType) {
  114. for i, v := range a {
  115. if v {
  116. result = append(result, structs.VisibleType(i))
  117. }
  118. }
  119. return result
  120. }
  121. func CompileEmailGlobList(sec ConfigSection, keys ...string) (globs []glob.Glob) {
  122. for _, key := range keys {
  123. list := sec.Key(key).Strings(",")
  124. for _, s := range list {
  125. if g, err := glob.Compile(s); err == nil {
  126. globs = append(globs, g)
  127. } else {
  128. log.Error("Skip invalid email allow/block list expression %q: %v", s, err)
  129. }
  130. }
  131. }
  132. return globs
  133. }
  134. func loadServiceFrom(rootCfg ConfigProvider) {
  135. sec := rootCfg.Section("service")
  136. Service.ActiveCodeLives = sec.Key("ACTIVE_CODE_LIVE_MINUTES").MustInt(180)
  137. Service.ResetPwdCodeLives = sec.Key("RESET_PASSWD_CODE_LIVE_MINUTES").MustInt(180)
  138. Service.DisableRegistration = sec.Key("DISABLE_REGISTRATION").MustBool()
  139. Service.AllowOnlyInternalRegistration = sec.Key("ALLOW_ONLY_INTERNAL_REGISTRATION").MustBool()
  140. Service.AllowOnlyExternalRegistration = sec.Key("ALLOW_ONLY_EXTERNAL_REGISTRATION").MustBool()
  141. if Service.AllowOnlyExternalRegistration && Service.AllowOnlyInternalRegistration {
  142. log.Warn("ALLOW_ONLY_INTERNAL_REGISTRATION and ALLOW_ONLY_EXTERNAL_REGISTRATION are true - disabling registration")
  143. Service.DisableRegistration = true
  144. }
  145. if !sec.Key("REGISTER_EMAIL_CONFIRM").MustBool() {
  146. Service.RegisterManualConfirm = sec.Key("REGISTER_MANUAL_CONFIRM").MustBool(false)
  147. } else {
  148. Service.RegisterManualConfirm = false
  149. }
  150. if sec.HasKey("EMAIL_DOMAIN_WHITELIST") {
  151. deprecatedSetting(rootCfg, "service", "EMAIL_DOMAIN_WHITELIST", "service", "EMAIL_DOMAIN_ALLOWLIST", "1.21")
  152. }
  153. Service.EmailDomainAllowList = CompileEmailGlobList(sec, "EMAIL_DOMAIN_WHITELIST", "EMAIL_DOMAIN_ALLOWLIST")
  154. Service.EmailDomainBlockList = CompileEmailGlobList(sec, "EMAIL_DOMAIN_BLOCKLIST")
  155. Service.ShowRegistrationButton = sec.Key("SHOW_REGISTRATION_BUTTON").MustBool(!(Service.DisableRegistration || Service.AllowOnlyExternalRegistration))
  156. Service.ShowMilestonesDashboardPage = sec.Key("SHOW_MILESTONES_DASHBOARD_PAGE").MustBool(true)
  157. // boolean values are considered as "strict"
  158. var err error
  159. Service.RequireSignInViewStrict, err = sec.Key("REQUIRE_SIGNIN_VIEW").Bool()
  160. if s := sec.Key("REQUIRE_SIGNIN_VIEW").String(); err != nil && s != "" {
  161. // non-boolean value only supports "expensive" at the moment
  162. Service.BlockAnonymousAccessExpensive = s == "expensive"
  163. if !Service.BlockAnonymousAccessExpensive {
  164. log.Fatal("Invalid config option: REQUIRE_SIGNIN_VIEW = %s", s)
  165. }
  166. }
  167. Service.EnableBasicAuth = sec.Key("ENABLE_BASIC_AUTHENTICATION").MustBool(true)
  168. Service.EnablePasswordSignInForm = sec.Key("ENABLE_PASSWORD_SIGNIN_FORM").MustBool(true)
  169. Service.EnablePasskeyAuth = sec.Key("ENABLE_PASSKEY_AUTHENTICATION").MustBool(true)
  170. Service.EnableReverseProxyAuth = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool()
  171. Service.EnableReverseProxyAuthAPI = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION_API").MustBool()
  172. Service.EnableReverseProxyAutoRegister = sec.Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool()
  173. Service.EnableReverseProxyEmail = sec.Key("ENABLE_REVERSE_PROXY_EMAIL").MustBool()
  174. Service.EnableReverseProxyFullName = sec.Key("ENABLE_REVERSE_PROXY_FULL_NAME").MustBool()
  175. Service.EnableCaptcha = sec.Key("ENABLE_CAPTCHA").MustBool(false)
  176. Service.RequireCaptchaForLogin = sec.Key("REQUIRE_CAPTCHA_FOR_LOGIN").MustBool(false)
  177. Service.RequireExternalRegistrationCaptcha = sec.Key("REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA").MustBool(Service.EnableCaptcha)
  178. Service.RequireExternalRegistrationPassword = sec.Key("REQUIRE_EXTERNAL_REGISTRATION_PASSWORD").MustBool()
  179. Service.CaptchaType = sec.Key("CAPTCHA_TYPE").MustString(ImageCaptcha)
  180. Service.RecaptchaSecret = sec.Key("RECAPTCHA_SECRET").MustString("")
  181. Service.RecaptchaSitekey = sec.Key("RECAPTCHA_SITEKEY").MustString("")
  182. Service.RecaptchaURL = sec.Key("RECAPTCHA_URL").MustString("https://www.google.com/recaptcha/")
  183. Service.CfTurnstileSecret = sec.Key("CF_TURNSTILE_SECRET").MustString("")
  184. Service.CfTurnstileSitekey = sec.Key("CF_TURNSTILE_SITEKEY").MustString("")
  185. Service.HcaptchaSecret = sec.Key("HCAPTCHA_SECRET").MustString("")
  186. Service.HcaptchaSitekey = sec.Key("HCAPTCHA_SITEKEY").MustString("")
  187. Service.McaptchaURL = sec.Key("MCAPTCHA_URL").MustString("https://demo.mcaptcha.org/")
  188. Service.McaptchaSecret = sec.Key("MCAPTCHA_SECRET").MustString("")
  189. Service.McaptchaSitekey = sec.Key("MCAPTCHA_SITEKEY").MustString("")
  190. Service.DefaultKeepEmailPrivate = sec.Key("DEFAULT_KEEP_EMAIL_PRIVATE").MustBool()
  191. Service.DefaultAllowCreateOrganization = sec.Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").MustBool(true)
  192. Service.DefaultUserIsRestricted = sec.Key("DEFAULT_USER_IS_RESTRICTED").MustBool(false)
  193. Service.EnableTimetracking = sec.Key("ENABLE_TIMETRACKING").MustBool(true)
  194. if Service.EnableTimetracking {
  195. Service.DefaultEnableTimetracking = sec.Key("DEFAULT_ENABLE_TIMETRACKING").MustBool(true)
  196. }
  197. Service.DefaultEnableDependencies = sec.Key("DEFAULT_ENABLE_DEPENDENCIES").MustBool(true)
  198. Service.AllowCrossRepositoryDependencies = sec.Key("ALLOW_CROSS_REPOSITORY_DEPENDENCIES").MustBool(true)
  199. Service.DefaultAllowOnlyContributorsToTrackTime = sec.Key("DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME").MustBool(true)
  200. Service.NoReplyAddress = sec.Key("NO_REPLY_ADDRESS").MustString("noreply." + Domain)
  201. Service.UserLocationMapURL = sec.Key("USER_LOCATION_MAP_URL").String()
  202. Service.EnableUserHeatmap = sec.Key("ENABLE_USER_HEATMAP").MustBool(true)
  203. Service.AutoWatchNewRepos = sec.Key("AUTO_WATCH_NEW_REPOS").MustBool(true)
  204. Service.AutoWatchOnChanges = sec.Key("AUTO_WATCH_ON_CHANGES").MustBool(false)
  205. modes := sec.Key("ALLOWED_USER_VISIBILITY_MODES").Strings(",")
  206. if len(modes) != 0 {
  207. Service.AllowedUserVisibilityModes = []string{}
  208. Service.AllowedUserVisibilityModesSlice = []bool{false, false, false}
  209. for _, sMode := range modes {
  210. if tp, ok := structs.VisibilityModes[sMode]; ok { // remove unsupported modes
  211. Service.AllowedUserVisibilityModes = append(Service.AllowedUserVisibilityModes, sMode)
  212. Service.AllowedUserVisibilityModesSlice[tp] = true
  213. } else {
  214. log.Warn("ALLOWED_USER_VISIBILITY_MODES %s is unsupported", sMode)
  215. }
  216. }
  217. }
  218. if len(Service.AllowedUserVisibilityModes) == 0 {
  219. Service.AllowedUserVisibilityModes = []string{"public", "limited", "private"}
  220. Service.AllowedUserVisibilityModesSlice = []bool{true, true, true}
  221. }
  222. Service.DefaultUserVisibility = sec.Key("DEFAULT_USER_VISIBILITY").String()
  223. if Service.DefaultUserVisibility == "" {
  224. Service.DefaultUserVisibility = Service.AllowedUserVisibilityModes[0]
  225. } else if !Service.AllowedUserVisibilityModesSlice[structs.VisibilityModes[Service.DefaultUserVisibility]] {
  226. log.Warn("DEFAULT_USER_VISIBILITY %s is wrong or not in ALLOWED_USER_VISIBILITY_MODES, using first allowed", Service.DefaultUserVisibility)
  227. Service.DefaultUserVisibility = Service.AllowedUserVisibilityModes[0]
  228. }
  229. Service.DefaultUserVisibilityMode = structs.VisibilityModes[Service.DefaultUserVisibility]
  230. Service.DefaultOrgVisibility = sec.Key("DEFAULT_ORG_VISIBILITY").In("public", structs.ExtractKeysFromMapString(structs.VisibilityModes))
  231. Service.DefaultOrgVisibilityMode = structs.VisibilityModes[Service.DefaultOrgVisibility]
  232. Service.DefaultOrgMemberVisible = sec.Key("DEFAULT_ORG_MEMBER_VISIBLE").MustBool()
  233. Service.UserDeleteWithCommentsMaxTime = sec.Key("USER_DELETE_WITH_COMMENTS_MAX_TIME").MustDuration(0)
  234. sec.Key("VALID_SITE_URL_SCHEMES").MustString("http,https")
  235. Service.ValidSiteURLSchemes = sec.Key("VALID_SITE_URL_SCHEMES").Strings(",")
  236. schemes := make([]string, 0, len(Service.ValidSiteURLSchemes))
  237. for _, scheme := range Service.ValidSiteURLSchemes {
  238. scheme = strings.ToLower(strings.TrimSpace(scheme))
  239. if scheme != "" {
  240. schemes = append(schemes, scheme)
  241. }
  242. }
  243. Service.ValidSiteURLSchemes = schemes
  244. mustMapSetting(rootCfg, "service.explore", &Service.Explore)
  245. loadOpenIDSetting(rootCfg)
  246. loadQosSetting(rootCfg)
  247. }
  248. func loadOpenIDSetting(rootCfg ConfigProvider) {
  249. sec := rootCfg.Section("openid")
  250. Service.EnableOpenIDSignIn = sec.Key("ENABLE_OPENID_SIGNIN").MustBool(!InstallLock)
  251. Service.EnableOpenIDSignUp = sec.Key("ENABLE_OPENID_SIGNUP").MustBool(!Service.DisableRegistration && Service.EnableOpenIDSignIn)
  252. pats := sec.Key("WHITELISTED_URIS").Strings(" ")
  253. if len(pats) != 0 {
  254. Service.OpenIDWhitelist = make([]*regexp.Regexp, len(pats))
  255. for i, p := range pats {
  256. Service.OpenIDWhitelist[i] = regexp.MustCompilePOSIX(p)
  257. }
  258. }
  259. pats = sec.Key("BLACKLISTED_URIS").Strings(" ")
  260. if len(pats) != 0 {
  261. Service.OpenIDBlacklist = make([]*regexp.Regexp, len(pats))
  262. for i, p := range pats {
  263. Service.OpenIDBlacklist[i] = regexp.MustCompilePOSIX(p)
  264. }
  265. }
  266. }
  267. func loadQosSetting(rootCfg ConfigProvider) {
  268. sec := rootCfg.Section("qos")
  269. Service.QoS.Enabled = sec.Key("ENABLED").MustBool(false)
  270. Service.QoS.MaxInFlightRequests = sec.Key("MAX_INFLIGHT").MustInt(4 * runtime.NumCPU())
  271. Service.QoS.MaxWaitingRequests = sec.Key("MAX_WAITING").MustInt(100)
  272. Service.QoS.TargetWaitTime = sec.Key("TARGET_WAIT_TIME").MustDuration(250 * time.Millisecond)
  273. }