diff options
Diffstat (limited to '')
-rw-r--r-- | modules/setting/service.go | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/modules/setting/service.go b/modules/setting/service.go new file mode 100644 index 0000000..afaee18 --- /dev/null +++ b/modules/setting/service.go @@ -0,0 +1,262 @@ +// Copyright 2019 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package setting + +import ( + "regexp" + "strings" + "time" + + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/structs" + + "github.com/gobwas/glob" +) + +// enumerates all the types of captchas +const ( + ImageCaptcha = "image" + ReCaptcha = "recaptcha" + HCaptcha = "hcaptcha" + MCaptcha = "mcaptcha" + CfTurnstile = "cfturnstile" +) + +// Service settings +var Service = struct { + DefaultUserVisibility string + DefaultUserVisibilityMode structs.VisibleType + AllowedUserVisibilityModes []string + AllowedUserVisibilityModesSlice AllowedVisibility `ini:"-"` + DefaultOrgVisibility string + DefaultOrgVisibilityMode structs.VisibleType + ActiveCodeLives int + ResetPwdCodeLives int + RegisterEmailConfirm bool + RegisterManualConfirm bool + EmailDomainAllowList []glob.Glob + EmailDomainBlockList []glob.Glob + DisableRegistration bool + AllowOnlyInternalRegistration bool + AllowOnlyExternalRegistration bool + ShowRegistrationButton bool + ShowMilestonesDashboardPage bool + RequireSignInView bool + EnableNotifyMail bool + EnableBasicAuth bool + EnableReverseProxyAuth bool + EnableReverseProxyAuthAPI bool + EnableReverseProxyAutoRegister bool + EnableReverseProxyEmail bool + EnableReverseProxyFullName bool + EnableCaptcha bool + RequireCaptchaForLogin bool + RequireExternalRegistrationCaptcha bool + RequireExternalRegistrationPassword bool + CaptchaType string + RecaptchaSecret string + RecaptchaSitekey string + RecaptchaURL string + CfTurnstileSecret string + CfTurnstileSitekey string + HcaptchaSecret string + HcaptchaSitekey string + McaptchaSecret string + McaptchaSitekey string + McaptchaURL string + DefaultKeepEmailPrivate bool + DefaultAllowCreateOrganization bool + DefaultUserIsRestricted bool + AllowDotsInUsernames bool + EnableTimetracking bool + DefaultEnableTimetracking bool + DefaultEnableDependencies bool + AllowCrossRepositoryDependencies bool + DefaultAllowOnlyContributorsToTrackTime bool + NoReplyAddress string + UserLocationMapURL string + EnableUserHeatmap bool + AutoWatchNewRepos bool + AutoWatchOnChanges bool + DefaultOrgMemberVisible bool + UserDeleteWithCommentsMaxTime time.Duration + ValidSiteURLSchemes []string + + // OpenID settings + EnableOpenIDSignIn bool + EnableOpenIDSignUp bool + OpenIDWhitelist []*regexp.Regexp + OpenIDBlacklist []*regexp.Regexp + + // Explore page settings + Explore struct { + RequireSigninView bool `ini:"REQUIRE_SIGNIN_VIEW"` + DisableUsersPage bool `ini:"DISABLE_USERS_PAGE"` + } `ini:"service.explore"` +}{ + AllowedUserVisibilityModesSlice: []bool{true, true, true}, +} + +// AllowedVisibility store in a 3 item bool array what is allowed +type AllowedVisibility []bool + +// IsAllowedVisibility check if a AllowedVisibility allow a specific VisibleType +func (a AllowedVisibility) IsAllowedVisibility(t structs.VisibleType) bool { + if int(t) >= len(a) { + return false + } + return a[t] +} + +// ToVisibleTypeSlice convert a AllowedVisibility into a VisibleType slice +func (a AllowedVisibility) ToVisibleTypeSlice() (result []structs.VisibleType) { + for i, v := range a { + if v { + result = append(result, structs.VisibleType(i)) + } + } + return result +} + +func CompileEmailGlobList(sec ConfigSection, keys ...string) (globs []glob.Glob) { + for _, key := range keys { + list := sec.Key(key).Strings(",") + for _, s := range list { + if g, err := glob.Compile(s); err == nil { + globs = append(globs, g) + } else { + log.Error("Skip invalid email allow/block list expression %q: %v", s, err) + } + } + } + return globs +} + +func loadServiceFrom(rootCfg ConfigProvider) { + sec := rootCfg.Section("service") + Service.ActiveCodeLives = sec.Key("ACTIVE_CODE_LIVE_MINUTES").MustInt(180) + Service.ResetPwdCodeLives = sec.Key("RESET_PASSWD_CODE_LIVE_MINUTES").MustInt(180) + Service.DisableRegistration = sec.Key("DISABLE_REGISTRATION").MustBool() + Service.AllowOnlyInternalRegistration = sec.Key("ALLOW_ONLY_INTERNAL_REGISTRATION").MustBool() + Service.AllowOnlyExternalRegistration = sec.Key("ALLOW_ONLY_EXTERNAL_REGISTRATION").MustBool() + if Service.AllowOnlyExternalRegistration && Service.AllowOnlyInternalRegistration { + log.Warn("ALLOW_ONLY_INTERNAL_REGISTRATION and ALLOW_ONLY_EXTERNAL_REGISTRATION are true - disabling registration") + Service.DisableRegistration = true + } + if !sec.Key("REGISTER_EMAIL_CONFIRM").MustBool() { + Service.RegisterManualConfirm = sec.Key("REGISTER_MANUAL_CONFIRM").MustBool(false) + } else { + Service.RegisterManualConfirm = false + } + if sec.HasKey("EMAIL_DOMAIN_WHITELIST") { + deprecatedSetting(rootCfg, "service", "EMAIL_DOMAIN_WHITELIST", "service", "EMAIL_DOMAIN_ALLOWLIST", "1.21") + } + Service.EmailDomainAllowList = CompileEmailGlobList(sec, "EMAIL_DOMAIN_WHITELIST", "EMAIL_DOMAIN_ALLOWLIST") + Service.EmailDomainBlockList = CompileEmailGlobList(sec, "EMAIL_DOMAIN_BLOCKLIST") + Service.ShowRegistrationButton = sec.Key("SHOW_REGISTRATION_BUTTON").MustBool(!(Service.DisableRegistration || Service.AllowOnlyExternalRegistration)) + Service.ShowMilestonesDashboardPage = sec.Key("SHOW_MILESTONES_DASHBOARD_PAGE").MustBool(true) + Service.RequireSignInView = sec.Key("REQUIRE_SIGNIN_VIEW").MustBool() + Service.EnableBasicAuth = sec.Key("ENABLE_BASIC_AUTHENTICATION").MustBool(true) + Service.EnableReverseProxyAuth = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION").MustBool() + Service.EnableReverseProxyAuthAPI = sec.Key("ENABLE_REVERSE_PROXY_AUTHENTICATION_API").MustBool() + Service.EnableReverseProxyAutoRegister = sec.Key("ENABLE_REVERSE_PROXY_AUTO_REGISTRATION").MustBool() + Service.EnableReverseProxyEmail = sec.Key("ENABLE_REVERSE_PROXY_EMAIL").MustBool() + Service.EnableReverseProxyFullName = sec.Key("ENABLE_REVERSE_PROXY_FULL_NAME").MustBool() + Service.EnableCaptcha = sec.Key("ENABLE_CAPTCHA").MustBool(false) + Service.RequireCaptchaForLogin = sec.Key("REQUIRE_CAPTCHA_FOR_LOGIN").MustBool(false) + Service.RequireExternalRegistrationCaptcha = sec.Key("REQUIRE_EXTERNAL_REGISTRATION_CAPTCHA").MustBool(Service.EnableCaptcha) + Service.RequireExternalRegistrationPassword = sec.Key("REQUIRE_EXTERNAL_REGISTRATION_PASSWORD").MustBool() + Service.CaptchaType = sec.Key("CAPTCHA_TYPE").MustString(ImageCaptcha) + Service.RecaptchaSecret = sec.Key("RECAPTCHA_SECRET").MustString("") + Service.RecaptchaSitekey = sec.Key("RECAPTCHA_SITEKEY").MustString("") + Service.RecaptchaURL = sec.Key("RECAPTCHA_URL").MustString("https://www.google.com/recaptcha/") + Service.CfTurnstileSecret = sec.Key("CF_TURNSTILE_SECRET").MustString("") + Service.CfTurnstileSitekey = sec.Key("CF_TURNSTILE_SITEKEY").MustString("") + Service.HcaptchaSecret = sec.Key("HCAPTCHA_SECRET").MustString("") + Service.HcaptchaSitekey = sec.Key("HCAPTCHA_SITEKEY").MustString("") + Service.McaptchaURL = sec.Key("MCAPTCHA_URL").MustString("https://demo.mcaptcha.org/") + Service.McaptchaSecret = sec.Key("MCAPTCHA_SECRET").MustString("") + Service.McaptchaSitekey = sec.Key("MCAPTCHA_SITEKEY").MustString("") + Service.DefaultKeepEmailPrivate = sec.Key("DEFAULT_KEEP_EMAIL_PRIVATE").MustBool() + Service.DefaultAllowCreateOrganization = sec.Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").MustBool(true) + Service.DefaultUserIsRestricted = sec.Key("DEFAULT_USER_IS_RESTRICTED").MustBool(false) + Service.AllowDotsInUsernames = sec.Key("ALLOW_DOTS_IN_USERNAMES").MustBool(true) + Service.EnableTimetracking = sec.Key("ENABLE_TIMETRACKING").MustBool(true) + if Service.EnableTimetracking { + Service.DefaultEnableTimetracking = sec.Key("DEFAULT_ENABLE_TIMETRACKING").MustBool(true) + } + Service.DefaultEnableDependencies = sec.Key("DEFAULT_ENABLE_DEPENDENCIES").MustBool(true) + Service.AllowCrossRepositoryDependencies = sec.Key("ALLOW_CROSS_REPOSITORY_DEPENDENCIES").MustBool(true) + Service.DefaultAllowOnlyContributorsToTrackTime = sec.Key("DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME").MustBool(true) + Service.NoReplyAddress = sec.Key("NO_REPLY_ADDRESS").MustString("noreply." + Domain) + Service.UserLocationMapURL = sec.Key("USER_LOCATION_MAP_URL").MustString("https://www.openstreetmap.org/search?query=") + Service.EnableUserHeatmap = sec.Key("ENABLE_USER_HEATMAP").MustBool(true) + Service.AutoWatchNewRepos = sec.Key("AUTO_WATCH_NEW_REPOS").MustBool(true) + Service.AutoWatchOnChanges = sec.Key("AUTO_WATCH_ON_CHANGES").MustBool(false) + modes := sec.Key("ALLOWED_USER_VISIBILITY_MODES").Strings(",") + if len(modes) != 0 { + Service.AllowedUserVisibilityModes = []string{} + Service.AllowedUserVisibilityModesSlice = []bool{false, false, false} + for _, sMode := range modes { + if tp, ok := structs.VisibilityModes[sMode]; ok { // remove unsupported modes + Service.AllowedUserVisibilityModes = append(Service.AllowedUserVisibilityModes, sMode) + Service.AllowedUserVisibilityModesSlice[tp] = true + } else { + log.Warn("ALLOWED_USER_VISIBILITY_MODES %s is unsupported", sMode) + } + } + } + + if len(Service.AllowedUserVisibilityModes) == 0 { + Service.AllowedUserVisibilityModes = []string{"public", "limited", "private"} + Service.AllowedUserVisibilityModesSlice = []bool{true, true, true} + } + + Service.DefaultUserVisibility = sec.Key("DEFAULT_USER_VISIBILITY").String() + if Service.DefaultUserVisibility == "" { + Service.DefaultUserVisibility = Service.AllowedUserVisibilityModes[0] + } else if !Service.AllowedUserVisibilityModesSlice[structs.VisibilityModes[Service.DefaultUserVisibility]] { + log.Warn("DEFAULT_USER_VISIBILITY %s is wrong or not in ALLOWED_USER_VISIBILITY_MODES, using first allowed", Service.DefaultUserVisibility) + Service.DefaultUserVisibility = Service.AllowedUserVisibilityModes[0] + } + Service.DefaultUserVisibilityMode = structs.VisibilityModes[Service.DefaultUserVisibility] + Service.DefaultOrgVisibility = sec.Key("DEFAULT_ORG_VISIBILITY").In("public", structs.ExtractKeysFromMapString(structs.VisibilityModes)) + Service.DefaultOrgVisibilityMode = structs.VisibilityModes[Service.DefaultOrgVisibility] + Service.DefaultOrgMemberVisible = sec.Key("DEFAULT_ORG_MEMBER_VISIBLE").MustBool() + Service.UserDeleteWithCommentsMaxTime = sec.Key("USER_DELETE_WITH_COMMENTS_MAX_TIME").MustDuration(0) + sec.Key("VALID_SITE_URL_SCHEMES").MustString("http,https") + Service.ValidSiteURLSchemes = sec.Key("VALID_SITE_URL_SCHEMES").Strings(",") + schemes := make([]string, 0, len(Service.ValidSiteURLSchemes)) + for _, scheme := range Service.ValidSiteURLSchemes { + scheme = strings.ToLower(strings.TrimSpace(scheme)) + if scheme != "" { + schemes = append(schemes, scheme) + } + } + Service.ValidSiteURLSchemes = schemes + + mustMapSetting(rootCfg, "service.explore", &Service.Explore) + + loadOpenIDSetting(rootCfg) +} + +func loadOpenIDSetting(rootCfg ConfigProvider) { + sec := rootCfg.Section("openid") + Service.EnableOpenIDSignIn = sec.Key("ENABLE_OPENID_SIGNIN").MustBool(!InstallLock) + Service.EnableOpenIDSignUp = sec.Key("ENABLE_OPENID_SIGNUP").MustBool(!Service.DisableRegistration && Service.EnableOpenIDSignIn) + pats := sec.Key("WHITELISTED_URIS").Strings(" ") + if len(pats) != 0 { + Service.OpenIDWhitelist = make([]*regexp.Regexp, len(pats)) + for i, p := range pats { + Service.OpenIDWhitelist[i] = regexp.MustCompilePOSIX(p) + } + } + pats = sec.Key("BLACKLISTED_URIS").Strings(" ") + if len(pats) != 0 { + Service.OpenIDBlacklist = make([]*regexp.Regexp, len(pats)) + for i, p := range pats { + Service.OpenIDBlacklist[i] = regexp.MustCompilePOSIX(p) + } + } +} |