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