From 82067ba731173662eb81974901d3ba6cb76afb29 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 8 Oct 2025 14:20:54 -0700 Subject: [PATCH 1/4] Move some service configuration from app.ini to database --- custom/conf/app.example.ini | 12 ++ models/issues/issue_list_test.go | 8 +- models/issues/issue_test.go | 7 +- models/migrations/v1_6/v70.go | 3 +- models/organization/org.go | 4 +- models/organization/org_user_test.go | 13 +- models/repo/issue.go | 19 +-- models/repo/watch.go | 2 +- models/repo/watch_test.go | 12 +- models/user/user.go | 6 +- modules/eventsource/manager_run.go | 2 +- modules/setting/config.go | 30 +++++ modules/setting/service.go | 121 +++++++----------- modules/templates/helper.go | 5 +- options/locale/locale_en-US.ini | 24 +++- routers/api/v1/api.go | 2 +- routers/api/v1/repo/issue_dependency.go | 2 +- routers/api/v1/settings/settings.go | 2 +- routers/install/install.go | 6 +- routers/web/admin/config.go | 14 ++ routers/web/auth/oauth.go | 2 +- routers/web/repo/issue_dependency.go | 2 +- routers/web/repo/issue_view.go | 2 +- routers/web/user/home.go | 2 +- routers/web/user/profile.go | 2 +- services/org/team.go | 2 +- services/repository/create.go | 8 +- services/repository/repo_team.go | 2 +- services/user/user_test.go | 7 +- .../config_settings/config_settings.tmpl | 2 + templates/admin/config_settings/service.tmpl | 90 +++++++++++++ templates/base/head_script.tmpl | 2 +- templates/org/menu.tmpl | 2 +- tests/integration/repo_watch_test.go | 10 +- tests/integration/signup_test.go | 7 +- 35 files changed, 311 insertions(+), 125 deletions(-) create mode 100644 templates/admin/config_settings/service.tmpl diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index aa2fcee765507..a12770238c772 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -844,13 +844,16 @@ LEVEL = Info ;; ;; Default value for KeepEmailPrivate ;; Each new user will get the value of this setting copied into their profile +;; Deprecated: Moved to database based configuration which can be set from UI ;DEFAULT_KEEP_EMAIL_PRIVATE = false ;; ;; Default value for AllowCreateOrganization ;; Every new user will have rights set to create organizations depending on this setting +;; Deprecated: Moved to database based configuration which can be set from UI ;DEFAULT_ALLOW_CREATE_ORGANIZATION = true ;; Default value for IsRestricted ;; Every new user will have restricted permissions depending on this setting +;; Deprecated: Moved to database based configuration which can be set from UI ;DEFAULT_USER_IS_RESTRICTED = false ;; ;; Either "public", "limited" or "private", default is "public" @@ -870,13 +873,16 @@ LEVEL = Info ;; ;; Default value for DefaultOrgMemberVisible ;; True will make the membership of the users visible when added to the organisation +;; Deprecated: Moved to database based configuration which can be set from UI ;DEFAULT_ORG_MEMBER_VISIBLE = false ;; ;; Default value for EnableDependencies ;; Repositories will use dependencies by default depending on this setting +;; Deprecated: Moved to database based configuration which can be set from UI ;DEFAULT_ENABLE_DEPENDENCIES = true ;; ;; Dependencies can be added from any repository where the user is granted access or only from the current repository depending on this setting. +;; Deprecated: Moved to database based configuration which can be set from UI ;ALLOW_CROSS_REPOSITORY_DEPENDENCIES = true ;; ;; Default map service. No external API support has been included. A service has to allow @@ -889,17 +895,21 @@ LEVEL = Info ; USER_LOCATION_MAP_URL = ;; ;; Enable heatmap on users profiles. +;; Deprecated: Moved to database based configuration which can be set from UI ;ENABLE_USER_HEATMAP = true ;; ;; Enable Timetracking +;; Deprecated: Moved to database based configuration which can be set from UI ;ENABLE_TIMETRACKING = true ;; ;; Default value for EnableTimetracking ;; Repositories will use timetracking by default depending on this setting +;; Deprecated: Moved to database based configuration which can be set from UI ;DEFAULT_ENABLE_TIMETRACKING = true ;; ;; Default value for AllowOnlyContributorsToTrackTime ;; Only users with write permissions can track time if this is true +;; Deprecated: Moved to database based configuration which can be set from UI ;DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME = true ;; ;; Value for the domain part of the user's email address in the git log if user @@ -918,10 +928,12 @@ LEVEL = Info ;; Default value for AutoWatchNewRepos ;; When adding a repo to a team or creating a new repo all team members will watch the ;; repo automatically if enabled +;; Deprecated: Moved to database based configuration which can be set from UI ;AUTO_WATCH_NEW_REPOS = true ;; ;; Default value for AutoWatchOnChanges ;; Make the user watch a repository When they commit for the first time +;; Deprecated: Moved to database based configuration which can be set from UI ;AUTO_WATCH_ON_CHANGES = false ;; ;; Minimum amount of time a user must exist before comments are kept when the user is deleted. diff --git a/models/issues/issue_list_test.go b/models/issues/issue_list_test.go index e9dc412331db1..16e75ef56ee8c 100644 --- a/models/issues/issue_list_test.go +++ b/models/issues/issue_list_test.go @@ -7,8 +7,10 @@ import ( "testing" issues_model "code.gitea.io/gitea/models/issues" + "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/setting/config" "github.com/stretchr/testify/assert" ) @@ -32,7 +34,11 @@ func TestIssueList_LoadRepositories(t *testing.T) { func TestIssueList_LoadAttributes(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - setting.Service.EnableTimetracking = true + system.SetSettings(t.Context(), map[string]string{ + setting.Config().Service.EnableTimeTracking.DynKey(): "true", + }) + config.GetDynGetter().InvalidateCache() + issueList := issues_model.IssueList{ unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}), unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 4}), diff --git a/models/issues/issue_test.go b/models/issues/issue_test.go index 09fd492667389..92c9bdfa399d9 100644 --- a/models/issues/issue_test.go +++ b/models/issues/issue_test.go @@ -14,9 +14,11 @@ import ( "code.gitea.io/gitea/models/db" issues_model "code.gitea.io/gitea/models/issues" repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/setting/config" "github.com/stretchr/testify/assert" "xorm.io/builder" @@ -384,7 +386,10 @@ func TestCountIssues(t *testing.T) { func TestIssueLoadAttributes(t *testing.T) { assert.NoError(t, unittest.PrepareTestDatabase()) - setting.Service.EnableTimetracking = true + system.SetSettings(t.Context(), map[string]string{ + setting.Config().Service.EnableTimeTracking.DynKey(): "true", + }) + config.GetDynGetter().InvalidateCache() issueList := issues_model.IssueList{ unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}), diff --git a/models/migrations/v1_6/v70.go b/models/migrations/v1_6/v70.go index 41f096694234c..0c423ba44ff1a 100644 --- a/models/migrations/v1_6/v70.go +++ b/models/migrations/v1_6/v70.go @@ -4,6 +4,7 @@ package v1_6 import ( + "context" "fmt" "time" @@ -99,7 +100,7 @@ func AddIssueDependencies(x *xorm.Engine) (err error) { unit.Config = make(map[string]any) } if _, ok := unit.Config["EnableDependencies"]; !ok { - unit.Config["EnableDependencies"] = setting.Service.DefaultEnableDependencies + unit.Config["EnableDependencies"] = setting.Config().Service.DefaultEnableDependencies.Value(context.Background()) } if _, err := x.ID(unit.ID).Cols("config").Update(unit); err != nil { return err diff --git a/models/organization/org.go b/models/organization/org.go index 9ece044d6c0ef..fe32204fc0798 100644 --- a/models/organization/org.go +++ b/models/organization/org.go @@ -326,7 +326,7 @@ func CreateOrganization(ctx context.Context, org *Organization, owner *user_mode if err = db.Insert(ctx, &OrgUser{ UID: owner.ID, OrgID: org.ID, - IsPublic: setting.Service.DefaultOrgMemberVisible, + IsPublic: setting.Config().Service.DefaultOrgMemberVisible.Value(ctx), }); err != nil { return fmt.Errorf("insert org-user relation: %w", err) } @@ -504,7 +504,7 @@ func AddOrgUser(ctx context.Context, orgID, uid int64) error { ou := &OrgUser{ UID: uid, OrgID: orgID, - IsPublic: setting.Service.DefaultOrgMemberVisible, + IsPublic: setting.Config().Service.DefaultOrgMemberVisible.Value(ctx), } if err := db.Insert(ctx, ou); err != nil { diff --git a/models/organization/org_user_test.go b/models/organization/org_user_test.go index d21df4b474c1f..45dd397502d9c 100644 --- a/models/organization/org_user_test.go +++ b/models/organization/org_user_test.go @@ -8,9 +8,11 @@ import ( "testing" "code.gitea.io/gitea/models/organization" + "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/setting/config" "github.com/stretchr/testify/assert" ) @@ -141,12 +143,19 @@ func TestAddOrgUser(t *testing.T) { assert.Equal(t, expectedNumMembers, org.NumMembers) } - setting.Service.DefaultOrgMemberVisible = false + system.SetSettings(t.Context(), map[string]string{ + setting.Config().Service.DefaultOrgMemberVisible.DynKey(): "false", + }) + config.GetDynGetter().InvalidateCache() + testSuccess(3, 5, false) testSuccess(3, 5, false) testSuccess(6, 2, false) - setting.Service.DefaultOrgMemberVisible = true + system.SetSettings(t.Context(), map[string]string{ + setting.Config().Service.DefaultOrgMemberVisible.DynKey(): "true", + }) + config.GetDynGetter().InvalidateCache() testSuccess(6, 3, true) unittest.CheckConsistencyFor(t, &user_model.User{}, &organization.Team{}) diff --git a/models/repo/issue.go b/models/repo/issue.go index 0dd4fd5ed480e..fb3337b60faa7 100644 --- a/models/repo/issue.go +++ b/models/repo/issue.go @@ -11,29 +11,22 @@ import ( "code.gitea.io/gitea/modules/setting" ) -// ___________.__ ___________ __ -// \__ ___/|__| _____ ___\__ ___/___________ ____ | | __ ___________ -// | | | |/ \_/ __ \| | \_ __ \__ \ _/ ___\| |/ // __ \_ __ \ -// | | | | Y Y \ ___/| | | | \// __ \\ \___| <\ ___/| | \/ -// |____| |__|__|_| /\___ >____| |__| (____ /\___ >__|_ \\___ >__| -// \/ \/ \/ \/ \/ \/ - // CanEnableTimetracker returns true when the server admin enabled time tracking // This overrules IsTimetrackerEnabled -func (repo *Repository) CanEnableTimetracker() bool { - return setting.Service.EnableTimetracking +func (repo *Repository) CanEnableTimetracker(ctx context.Context) bool { + return setting.Config().Service.EnableTimeTracking.Value(ctx) } // IsTimetrackerEnabled returns whether or not the timetracker is enabled. It returns the default value from config if an error occurs. func (repo *Repository) IsTimetrackerEnabled(ctx context.Context) bool { - if !setting.Service.EnableTimetracking { + if !setting.Config().Service.EnableTimeTracking.Value(ctx) { return false } var u *RepoUnit var err error if u, err = repo.GetUnit(ctx, unit.TypeIssues); err != nil { - return setting.Service.DefaultEnableTimetracking + return setting.Config().Service.DefaultEnableTimeTracking.Value(ctx) } return u.IssuesConfig().EnableTimetracker } @@ -43,7 +36,7 @@ func (repo *Repository) AllowOnlyContributorsToTrackTime(ctx context.Context) bo var u *RepoUnit var err error if u, err = repo.GetUnit(ctx, unit.TypeIssues); err != nil { - return setting.Service.DefaultAllowOnlyContributorsToTrackTime + return setting.Config().Service.DefaultAllowOnlyContributorsToTrackTime.Value(ctx) } return u.IssuesConfig().AllowOnlyContributorsToTrackTime } @@ -54,7 +47,7 @@ func (repo *Repository) IsDependenciesEnabled(ctx context.Context) bool { var err error if u, err = repo.GetUnit(ctx, unit.TypeIssues); err != nil { log.Trace("IsDependenciesEnabled: %v", err) - return setting.Service.DefaultEnableDependencies + return setting.Config().Service.DefaultEnableDependencies.Value(ctx) } return u.IssuesConfig().EnableDependencies } diff --git a/models/repo/watch.go b/models/repo/watch.go index a616544cae314..298c7898b3e97 100644 --- a/models/repo/watch.go +++ b/models/repo/watch.go @@ -164,7 +164,7 @@ func GetRepoWatchers(ctx context.Context, repoID int64, opts db.ListOptions) ([] // WatchIfAuto subscribes to repo if AutoWatchOnChanges is set func WatchIfAuto(ctx context.Context, userID, repoID int64, isWrite bool) error { - if !isWrite || !setting.Service.AutoWatchOnChanges { + if !isWrite || !setting.Config().Service.AutoWatchOnChanges.Value(ctx) { return nil } watch, err := GetWatch(ctx, userID, repoID) diff --git a/models/repo/watch_test.go b/models/repo/watch_test.go index 19e363f6b08d5..eaa827e583dee 100644 --- a/models/repo/watch_test.go +++ b/models/repo/watch_test.go @@ -8,9 +8,11 @@ import ( "code.gitea.io/gitea/models/db" repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/setting/config" "github.com/stretchr/testify/assert" ) @@ -71,7 +73,10 @@ func TestWatchIfAuto(t *testing.T) { assert.NoError(t, err) assert.Len(t, watchers, repo.NumWatches) - setting.Service.AutoWatchOnChanges = false + assert.NoError(t, system.SetSettings(t.Context(), map[string]string{ + setting.Config().Service.AutoWatchOnChanges.DynKey(): "false", + })) + config.GetDynGetter().InvalidateCache() prevCount := repo.NumWatches @@ -87,7 +92,10 @@ func TestWatchIfAuto(t *testing.T) { assert.NoError(t, err) assert.Len(t, watchers, prevCount) - setting.Service.AutoWatchOnChanges = true + assert.NoError(t, system.SetSettings(t.Context(), map[string]string{ + setting.Config().Service.AutoWatchOnChanges.DynKey(): "true", + })) + config.GetDynGetter().InvalidateCache() // Must not add watch assert.NoError(t, repo_model.WatchIfAuto(t.Context(), 8, 1, true)) diff --git a/models/user/user.go b/models/user/user.go index 80d5eb5ec4e40..20f8788eb3cc2 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -658,13 +658,13 @@ func createUser(ctx context.Context, u *User, meta *Meta, createdByAdmin bool, o } // set system defaults - u.KeepEmailPrivate = setting.Service.DefaultKeepEmailPrivate + u.KeepEmailPrivate = setting.Config().Service.DefaultKeepEmailPrivate.Value(ctx) u.Visibility = setting.Service.DefaultUserVisibilityMode - u.AllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization && !setting.Admin.DisableRegularOrgCreation + u.AllowCreateOrganization = setting.Config().Service.DefaultAllowCreateOrganization.Value(ctx) && !setting.Admin.DisableRegularOrgCreation u.EmailNotificationsPreference = setting.Admin.DefaultEmailNotification u.MaxRepoCreation = -1 u.Theme = setting.UI.DefaultTheme - u.IsRestricted = setting.Service.DefaultUserIsRestricted + u.IsRestricted = setting.Config().Service.DefaultUserIsRestricted.Value(ctx) u.IsActive = !(setting.Service.RegisterEmailConfirm || setting.Service.RegisterManualConfirm) // Ensure consistency of the dates. diff --git a/modules/eventsource/manager_run.go b/modules/eventsource/manager_run.go index f66dc78c7e493..db6481716ad5f 100644 --- a/modules/eventsource/manager_run.go +++ b/modules/eventsource/manager_run.go @@ -83,7 +83,7 @@ loop: } then = now - if setting.Service.EnableTimetracking { + if setting.Config().Service.EnableTimeTracking.Value(ctx) { usersStopwatches, err := issues_model.GetUIDsAndStopwatch(ctx) if err != nil { log.Error("Unable to get GetUIDsAndStopwatch: %v", err) diff --git a/modules/setting/config.go b/modules/setting/config.go index 4c5d2df7d8a01..2bfe7f0b40587 100644 --- a/modules/setting/config.go +++ b/modules/setting/config.go @@ -52,9 +52,25 @@ type RepositoryStruct struct { GitGuideRemoteName *config.Value[string] } +type ServiceStruct struct { + DefaultKeepEmailPrivate *config.Value[bool] + DefaultAllowCreateOrganization *config.Value[bool] + DefaultUserIsRestricted *config.Value[bool] + EnableTimeTracking *config.Value[bool] + DefaultEnableTimeTracking *config.Value[bool] + DefaultEnableDependencies *config.Value[bool] + AllowCrossRepositoryDependencies *config.Value[bool] + DefaultAllowOnlyContributorsToTrackTime *config.Value[bool] + EnableUserHeatmap *config.Value[bool] + AutoWatchNewRepos *config.Value[bool] + AutoWatchOnChanges *config.Value[bool] + DefaultOrgMemberVisible *config.Value[bool] +} + type ConfigStruct struct { Picture *PictureStruct Repository *RepositoryStruct + Service *ServiceStruct } var ( @@ -73,6 +89,20 @@ func initDefaultConfig() { OpenWithEditorApps: config.ValueJSON[OpenWithEditorAppsType]("repository.open-with.editor-apps"), GitGuideRemoteName: config.ValueJSON[string]("repository.git-guide-remote-name").WithDefault("origin"), }, + Service: &ServiceStruct{ + DefaultKeepEmailPrivate: config.ValueJSON[bool]("service.default_keep_email_private").WithFileConfig(config.CfgSecKey{Sec: "service", Key: "DEFAULT_KEEP_EMAIL_PRIVATE"}).WithDefault(false), + DefaultAllowCreateOrganization: config.ValueJSON[bool]("service.default_allow_create_organization").WithFileConfig(config.CfgSecKey{Sec: "service", Key: "DEFAULT_ALLOW_CREATE_ORGANIZATION"}).WithDefault(true), + DefaultUserIsRestricted: config.ValueJSON[bool]("service.default_user_is_restricted").WithFileConfig(config.CfgSecKey{Sec: "service", Key: "DEFAULT_USER_IS_RESTRICTED"}).WithDefault(false), + EnableTimeTracking: config.ValueJSON[bool]("service.enable_time_tracking").WithFileConfig(config.CfgSecKey{Sec: "service", Key: "ENABLE_TIMETRACKING"}).WithDefault(true), + DefaultEnableTimeTracking: config.ValueJSON[bool]("service.default_enable_time_tracking").WithFileConfig(config.CfgSecKey{Sec: "service", Key: "DEFAULT_ENABLE_TIMETRACKING"}).WithDefault(true), + DefaultEnableDependencies: config.ValueJSON[bool]("service.default_enable_dependencies").WithFileConfig(config.CfgSecKey{Sec: "service", Key: "DEFAULT_ENABLE_DEPENDENCIES"}).WithDefault(true), + AllowCrossRepositoryDependencies: config.ValueJSON[bool]("service.allow_cross_repository_dependencies").WithFileConfig(config.CfgSecKey{Sec: "service", Key: "ALLOW_CROSS_REPOSITORY_DEPENDENCIES"}).WithDefault(true), + DefaultAllowOnlyContributorsToTrackTime: config.ValueJSON[bool]("service.default_allow_only_contributors_to_track_time").WithFileConfig(config.CfgSecKey{Sec: "service", Key: "DEFAULT_ALLOW_ONLY_CONTRIBUTORS_TO_TRACK_TIME"}).WithDefault(true), + EnableUserHeatmap: config.ValueJSON[bool]("service.enable_user_heatmap").WithFileConfig(config.CfgSecKey{Sec: "service", Key: "ENABLE_USER_HEATMAP"}).WithDefault(true), + AutoWatchNewRepos: config.ValueJSON[bool]("service.auto_watch_new_repos").WithFileConfig(config.CfgSecKey{Sec: "service", Key: "AUTO_WATCH_NEW_REPOS"}).WithDefault(true), + AutoWatchOnChanges: config.ValueJSON[bool]("service.auto_watch_on_changes").WithFileConfig(config.CfgSecKey{Sec: "service", Key: "AUTO_WATCH_ON_CHANGES"}).WithDefault(false), + DefaultOrgMemberVisible: config.ValueJSON[bool]("service.default_org_member_visible").WithFileConfig(config.CfgSecKey{Sec: "service", Key: "DEFAULT_ORG_MEMBER_VISIBLE"}).WithDefault(false), + }, } } diff --git a/modules/setting/service.go b/modules/setting/service.go index e652c13c9c9e3..01ad11ab502ec 100644 --- a/modules/setting/service.go +++ b/modules/setting/service.go @@ -25,65 +25,53 @@ const ( // 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 - EnablePasswordSignInForm bool - ShowMilestonesDashboardPage bool - RequireSignInViewStrict bool - BlockAnonymousAccessExpensive bool - EnableNotifyMail bool - EnableBasicAuth bool - EnablePasskeyAuth 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 - 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 + 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 + EnablePasswordSignInForm bool + ShowMilestonesDashboardPage bool + RequireSignInViewStrict bool + BlockAnonymousAccessExpensive bool + EnableNotifyMail bool + EnableBasicAuth bool + EnablePasskeyAuth 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 + NoReplyAddress string + UserLocationMapURL string + UserDeleteWithCommentsMaxTime time.Duration + ValidSiteURLSchemes []string // OpenID settings EnableOpenIDSignIn bool @@ -202,21 +190,9 @@ func loadServiceFrom(rootCfg ConfigProvider) { 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.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").String() - 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{} @@ -246,7 +222,6 @@ func loadServiceFrom(rootCfg ConfigProvider) { 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(",") diff --git a/modules/templates/helper.go b/modules/templates/helper.go index e454bce4bd3c2..0056f054fb559 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -5,6 +5,7 @@ package templates import ( + "context" "fmt" "html/template" "net/url" @@ -124,8 +125,8 @@ func NewFuncMap() template.FuncMap { "MetaKeywords": func() string { return setting.UI.Meta.Keywords }, - "EnableTimetracking": func() bool { - return setting.Service.EnableTimetracking + "EnableTimeTracking": func(ctx context.Context) bool { + return setting.Config().Service.EnableTimeTracking.Value(ctx) }, "DisableWebhooks": func() bool { return setting.DisableWebhooks diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 03017ce6746df..c403270d4a136 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -3383,7 +3383,29 @@ config.default_enable_timetracking = Enable Time Tracking by Default config.default_allow_only_contributors_to_track_time = Let Only Contributors Track Time config.no_reply_address = Hidden Email Domain config.default_visibility_organization = Default visibility for new Organizations -config.default_enable_dependencies = Enable Issue Dependencies by Default +config.service_default_keep_email_private = Default value for KeepEmailPrivate +config.service_default_keep_email_private_desc = Each new user will get the value of this setting copied into their profile +config.service_default_allow_create_organization = Default value for AllowCreateOrganization +config.service_default_allow_create_organization_desc = Every new user will have rights set to create organizations depending on this setting +config.service_default_user_is_restricted = Default value for IsRestricted +config.service_default_user_is_restricted_desc = Every new user will have restricted permissions depending on this setting +config.service_enable_time_tracking = Enable Time Tracking +config.service_default_enable_time_tracking = Default value for EnableTimetracking +config.service_default_enable_time_tracking_desc = Repositories will use timetracking by default depending on this setting +config.service_default_enable_dependencies = Enable Issue Dependencies by Default +config.service_default_enable_dependencies_desc = Repositories will use dependencies by default depending on this setting +config.service_allow_cross_repository_dependencies = Allow Cross Repository Issue Dependencies +config.service_allow_cross_repository_dependencies_desc = Dependencies can be added from any repository where the user is granted access or only from the current repository depending on this setting. +config.service_default_allow_only_contributors_to_track_time = Default value for AllowOnlyContributorsToTrackTime +config.service_default_allow_only_contributors_to_track_time_desc = Only users with write permissions can track time if this is true +config.service_enable_user_heatmap = Enable User Heatmap +config.service_enable_user_heatmap_desc = Show a heatmap of user activity on user profiles +config.service_auto_watch_new_repos = Enable Auto Watch for New Repositories +config.service_auto_watch_new_repos_desc = When adding a repo to a team or creating a new repo all team members will watch the repo automatically if enabled +config.service_auto_watch_on_changes = Enable Auto Watch for Repositories Push +config.service_auto_watch_on_changes_desc = Make the user watch a repository When they commit for the first time +config.service_default_org_member_visible = Default value for DefaultOrgMemberVisible +config.service_default_org_member_visible_desc = True will make the membership of the users visible when added to the organisation config.webhook_config = Webhook Configuration config.queue_length = Queue Length diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index 66afede218c65..b1f287f2c3a79 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -1010,7 +1010,7 @@ func Routes() *web.Router { m.Group("/{username}", func() { m.Get("", reqExploreSignIn(), user.GetInfo) - if setting.Service.EnableUserHeatmap { + if setting.Config().Service.EnableUserHeatmap.Value(gocontext.Background()) { m.Get("/heatmap", user.GetUserHeatmapData) } diff --git a/routers/api/v1/repo/issue_dependency.go b/routers/api/v1/repo/issue_dependency.go index 1b58beb7b6e92..8bb14c697a4de 100644 --- a/routers/api/v1/repo/issue_dependency.go +++ b/routers/api/v1/repo/issue_dependency.go @@ -509,7 +509,7 @@ func getParamsIssue(ctx *context.APIContext) *issues_model.Issue { func getFormIssue(ctx *context.APIContext, form *api.IssueMeta) *issues_model.Issue { var repo *repo_model.Repository if form.Owner != ctx.Repo.Repository.OwnerName || form.Name != ctx.Repo.Repository.Name { - if !setting.Service.AllowCrossRepositoryDependencies { + if !setting.Config().Service.AllowCrossRepositoryDependencies.Value(ctx) { ctx.JSON(http.StatusBadRequest, "CrossRepositoryDependencies not enabled") return nil } diff --git a/routers/api/v1/settings/settings.go b/routers/api/v1/settings/settings.go index 94fbadeab0188..049adbe876e6b 100644 --- a/routers/api/v1/settings/settings.go +++ b/routers/api/v1/settings/settings.go @@ -62,7 +62,7 @@ func GetGeneralRepoSettings(ctx *context.APIContext) { HTTPGitDisabled: setting.Repository.DisableHTTPGit, MigrationsDisabled: setting.Repository.DisableMigrations, StarsDisabled: setting.Repository.DisableStars, - TimeTrackingDisabled: !setting.Service.EnableTimetracking, + TimeTrackingDisabled: !setting.Config().Service.EnableTimeTracking.Value(ctx), LFSDisabled: !setting.LFS.StartServer, }) } diff --git a/routers/install/install.go b/routers/install/install.go index 4a9dabac6fe87..c06b6dee255c3 100644 --- a/routers/install/install.go +++ b/routers/install/install.go @@ -145,9 +145,9 @@ func Install(ctx *context.Context) { form.AllowOnlyExternalRegistration = setting.Service.AllowOnlyExternalRegistration form.EnableCaptcha = setting.Service.EnableCaptcha form.RequireSignInView = setting.Service.RequireSignInViewStrict - form.DefaultKeepEmailPrivate = setting.Service.DefaultKeepEmailPrivate - form.DefaultAllowCreateOrganization = setting.Service.DefaultAllowCreateOrganization - form.DefaultEnableTimetracking = setting.Service.DefaultEnableTimetracking + form.DefaultKeepEmailPrivate = setting.Config().Service.DefaultKeepEmailPrivate.Value(ctx) + form.DefaultAllowCreateOrganization = setting.Config().Service.DefaultAllowCreateOrganization.Value(ctx) + form.DefaultEnableTimetracking = setting.Config().Service.DefaultEnableTimeTracking.Value(ctx) form.NoReplyAddress = setting.Service.NoReplyAddress form.PasswordAlgorithm = hash.ConfigHashAlgorithm(setting.PasswordHashAlgo) diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go index 774b31ab9842a..a2305f8598bcb 100644 --- a/routers/web/admin/config.go +++ b/routers/web/admin/config.go @@ -233,6 +233,20 @@ func ChangeConfig(ctx *context.Context) { marshallers := map[string]func(string) ([]byte, error){ cfg.Picture.DisableGravatar.DynKey(): marshalBool, cfg.Picture.EnableFederatedAvatar.DynKey(): marshalBool, + + cfg.Service.DefaultKeepEmailPrivate.DynKey(): marshalBool, + cfg.Service.DefaultAllowCreateOrganization.DynKey(): marshalBool, + cfg.Service.DefaultUserIsRestricted.DynKey(): marshalBool, + cfg.Service.EnableTimeTracking.DynKey(): marshalBool, + cfg.Service.DefaultEnableTimeTracking.DynKey(): marshalBool, + cfg.Service.DefaultEnableDependencies.DynKey(): marshalBool, + cfg.Service.AllowCrossRepositoryDependencies.DynKey(): marshalBool, + cfg.Service.DefaultAllowOnlyContributorsToTrackTime.DynKey(): marshalBool, + cfg.Service.EnableUserHeatmap.DynKey(): marshalBool, + cfg.Service.AutoWatchNewRepos.DynKey(): marshalBool, + cfg.Service.AutoWatchOnChanges.DynKey(): marshalBool, + cfg.Service.DefaultOrgMemberVisible.DynKey(): marshalBool, + cfg.Repository.OpenWithEditorApps.DynKey(): marshalOpenWithApps, cfg.Repository.GitGuideRemoteName.DynKey(): marshalString(cfg.Repository.GitGuideRemoteName.DefaultValue()), } diff --git a/routers/web/auth/oauth.go b/routers/web/auth/oauth.go index f1c155e78f52c..49e0f2579a11c 100644 --- a/routers/web/auth/oauth.go +++ b/routers/web/auth/oauth.go @@ -191,7 +191,7 @@ func SignInOAuthCallback(ctx *context.Context) { isAdmin, isRestricted := getUserAdminAndRestrictedFromGroupClaims(source, &gothUser) u.IsAdmin = isAdmin.ValueOrDefault(user_service.UpdateOptionField[bool]{FieldValue: false}).FieldValue - u.IsRestricted = isRestricted.ValueOrDefault(setting.Service.DefaultUserIsRestricted) + u.IsRestricted = isRestricted.ValueOrDefault(setting.Config().Service.DefaultUserIsRestricted.Value(ctx)) linkAccountData := &LinkAccountData{authSource.ID, gothUser} if setting.OAuth2Client.AccountLinking == setting.OAuth2AccountLinkingDisabled { diff --git a/routers/web/repo/issue_dependency.go b/routers/web/repo/issue_dependency.go index 73298958c0559..9e76ba7062408 100644 --- a/routers/web/repo/issue_dependency.go +++ b/routers/web/repo/issue_dependency.go @@ -46,7 +46,7 @@ func AddDependency(ctx *context.Context) { // Check if both issues are in the same repo if cross repository dependencies is not enabled if issue.RepoID != dep.RepoID { - if !setting.Service.AllowCrossRepositoryDependencies { + if !setting.Config().Service.AllowCrossRepositoryDependencies.Value(ctx) { ctx.Flash.Error(ctx.Tr("repo.issues.dependency.add_error_dep_not_same_repo")) return } diff --git a/routers/web/repo/issue_view.go b/routers/web/repo/issue_view.go index d9f6c33e3fbc5..e5a86fde3fb24 100644 --- a/routers/web/repo/issue_view.go +++ b/routers/web/repo/issue_view.go @@ -464,7 +464,7 @@ func prepareIssueViewSidebarDependency(ctx *context.Context, issue *issues_model ctx.Data["CanCreateIssueDependencies"] = ctx.Repo.CanCreateIssueDependencies(ctx, ctx.Doer, issue.IsPull) // check if dependencies can be created across repositories - ctx.Data["AllowCrossRepositoryDependencies"] = setting.Service.AllowCrossRepositoryDependencies + ctx.Data["AllowCrossRepositoryDependencies"] = setting.Config().Service.AllowCrossRepositoryDependencies.Value(ctx) // Get Dependencies blockedBy, err := issue.BlockedByDependencies(ctx, db.ListOptions{}) diff --git a/routers/web/user/home.go b/routers/web/user/home.go index b53a3daedb5ea..4f579cfb0e59e 100644 --- a/routers/web/user/home.go +++ b/routers/web/user/home.go @@ -109,7 +109,7 @@ func Dashboard(ctx *context.Context) { "uid": uid, } - if setting.Service.EnableUserHeatmap { + if setting.Config().Service.EnableUserHeatmap.Value(ctx) { data, err := activities_model.GetUserHeatmapDataByUserTeam(ctx, ctxUser, ctx.Org.Team, ctx.Doer) if err != nil { ctx.ServerError("GetUserHeatmapDataByUserTeam", err) diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go index d7052914b6865..826c37dcf3f56 100644 --- a/routers/web/user/profile.go +++ b/routers/web/user/profile.go @@ -162,7 +162,7 @@ func prepareUserProfileTabData(ctx *context.Context, profileDbRepo *repo_model.R total = int(numFollowing) case "activity": // prepare heatmap data - if setting.Service.EnableUserHeatmap { + if setting.Config().Service.EnableUserHeatmap.Value(ctx) { data, err := activities_model.GetUserHeatmapDataByUser(ctx, ctx.ContextUser, ctx.Doer) if err != nil { ctx.ServerError("GetUserHeatmapDataByUser", err) diff --git a/services/org/team.go b/services/org/team.go index 633056cf95ff6..6f5c816ace49e 100644 --- a/services/org/team.go +++ b/services/org/team.go @@ -251,7 +251,7 @@ func AddTeamMember(ctx context.Context, team *organization.Team, user *user_mode // this behaviour may spend much time so run it in a goroutine // FIXME: Update watch repos batchly - if setting.Service.AutoWatchNewRepos { + if setting.Config().Service.AutoWatchNewRepos.Value(ctx) { // Get team and its repositories. repos, err := repo_model.GetTeamRepositories(ctx, &repo_model.SearchTeamRepoOptions{ TeamID: team.ID, diff --git a/services/repository/create.go b/services/repository/create.go index 0b57db988b73b..15a28b7561f5c 100644 --- a/services/repository/create.go +++ b/services/repository/create.go @@ -376,9 +376,9 @@ func createRepositoryInDB(ctx context.Context, doer, u *user_model.User, repo *r RepoID: repo.ID, Type: tp, Config: &repo_model.IssuesConfig{ - EnableTimetracker: setting.Service.DefaultEnableTimetracking, - AllowOnlyContributorsToTrackTime: setting.Service.DefaultAllowOnlyContributorsToTrackTime, - EnableDependencies: setting.Service.DefaultEnableDependencies, + EnableTimetracker: setting.Config().Service.DefaultEnableTimeTracking.Value(ctx), + AllowOnlyContributorsToTrackTime: setting.Config().Service.DefaultAllowOnlyContributorsToTrackTime.Value(ctx), + EnableDependencies: setting.Config().Service.DefaultEnableDependencies.Value(ctx), }, }) case unit.TypePullRequests: @@ -447,7 +447,7 @@ func createRepositoryInDB(ctx context.Context, doer, u *user_model.User, repo *r return fmt.Errorf("RecalculateAccesses: %w", err) } - if setting.Service.AutoWatchNewRepos { + if setting.Config().Service.AutoWatchNewRepos.Value(ctx) { if err = repo_model.WatchRepo(ctx, doer, repo, true); err != nil { return fmt.Errorf("WatchRepo: %w", err) } diff --git a/services/repository/repo_team.go b/services/repository/repo_team.go index 8ea186f8cc65c..9e98d4ea0be2f 100644 --- a/services/repository/repo_team.go +++ b/services/repository/repo_team.go @@ -45,7 +45,7 @@ func addRepositoryToTeam(ctx context.Context, t *organization.Team, repo *repo_m } // Make all team members watch this repo if enabled in global settings - if setting.Service.AutoWatchNewRepos { + if setting.Config().Service.AutoWatchNewRepos.Value(ctx) { if err = t.LoadMembers(ctx); err != nil { return fmt.Errorf("getMembers: %w", err) } diff --git a/services/user/user_test.go b/services/user/user_test.go index 48852b4cb9a39..b41aba45ea70d 100644 --- a/services/user/user_test.go +++ b/services/user/user_test.go @@ -13,9 +13,11 @@ import ( "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/organization" repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/setting/config" "code.gitea.io/gitea/modules/timeutil" org_service "code.gitea.io/gitea/services/org" @@ -170,7 +172,10 @@ func TestCreateUser_Issue5882(t *testing.T) { {&user_model.User{Name: "GiteaBot2", Email: "GiteaBot2@gitea.io", Passwd: passwd, MustChangePassword: false}, true}, } - setting.Service.DefaultAllowCreateOrganization = true + system.SetSettings(t.Context(), map[string]string{ + setting.Config().Service.DefaultAllowCreateOrganization.DynKey(): "true", + }) + config.GetDynGetter().InvalidateCache() for _, v := range tt { setting.Admin.DisableRegularOrgCreation = v.disableOrgCreation diff --git a/templates/admin/config_settings/config_settings.tmpl b/templates/admin/config_settings/config_settings.tmpl index 1ef764a58bac5..eaaedfe1d0b72 100644 --- a/templates/admin/config_settings/config_settings.tmpl +++ b/templates/admin/config_settings/config_settings.tmpl @@ -4,4 +4,6 @@ {{template "admin/config_settings/repository" .}} +{{template "admin/config_settings/service" .}} + {{template "admin/layout_footer" .}} diff --git a/templates/admin/config_settings/service.tmpl b/templates/admin/config_settings/service.tmpl new file mode 100644 index 0000000000000..7a04ffd5059f7 --- /dev/null +++ b/templates/admin/config_settings/service.tmpl @@ -0,0 +1,90 @@ +

+ {{ctx.Locale.Tr "admin.config.service_config"}} +

+
+
+
{{ctx.Locale.Tr "admin.config.service_default_keep_email_private"}}
+
+
+ +
+
+
+
{{ctx.Locale.Tr "admin.config.service_default_allow_create_organization"}}
+
+
+ +
+
+
+
{{ctx.Locale.Tr "admin.config.service_default_user_is_restricted"}}
+
+
+ +
+
+
+
{{ctx.Locale.Tr "admin.config.service_enable_time_tracking"}}
+
+
+ +
+
+
+
{{ctx.Locale.Tr "admin.config.service_default_enable_time_tracking"}}
+
+
+ +
+
+
+
{{ctx.Locale.Tr "admin.config.service_default_enable_dependencies"}}
+
+
+ +
+
+
+
{{ctx.Locale.Tr "admin.config.service_allow_cross_repository_dependencies"}}
+
+
+ +
+
+
+
{{ctx.Locale.Tr "admin.config.service_default_allow_only_contributors_to_track_time"}}
+
+
+ +
+
+
+
{{ctx.Locale.Tr "admin.config.service_enable_user_heatmap"}}
+
+
+ +
+
+
+
{{ctx.Locale.Tr "admin.config.service_auto_watch_new_repos"}}
+
+
+ +
+
+
+
{{ctx.Locale.Tr "admin.config.service_auto_watch_on_changes"}}
+
+
+ +
+
+
+
{{ctx.Locale.Tr "admin.config.service_default_org_member_visible"}}
+
+
+ +
+
+
+
diff --git a/templates/base/head_script.tmpl b/templates/base/head_script.tmpl index f6648b59d8c53..205b7ba0426d2 100644 --- a/templates/base/head_script.tmpl +++ b/templates/base/head_script.tmpl @@ -16,7 +16,7 @@ If you introduce mistakes in it, Gitea JavaScript code wouldn't run correctly. csrfToken: '{{.CsrfToken}}', pageData: {{.PageData}}, notificationSettings: {{NotificationSettings}}, {{/*a map provided by NewFuncMap in helper.go*/}} - enableTimeTracking: {{EnableTimetracking}}, + enableTimeTracking: {{EnableTimeTracking ctx}}, {{if or .Participants .Assignees .MentionableTeams}} mentionValues: Array.from(new Map([ {{- range .Participants -}} diff --git a/templates/org/menu.tmpl b/templates/org/menu.tmpl index d876dabb4435a..ba4e3edf5b497 100644 --- a/templates/org/menu.tmpl +++ b/templates/org/menu.tmpl @@ -44,7 +44,7 @@ {{end}} {{end}} - {{if and EnableTimetracking .IsOrganizationOwner}} + {{if and (EnableTimeTracking ctx) .IsOrganizationOwner}} {{svg "octicon-clock"}} {{ctx.Locale.Tr "org.worktime"}} diff --git a/tests/integration/repo_watch_test.go b/tests/integration/repo_watch_test.go index ef3028f2936cc..beef94e271cd2 100644 --- a/tests/integration/repo_watch_test.go +++ b/tests/integration/repo_watch_test.go @@ -8,14 +8,22 @@ import ( "testing" repo_model "code.gitea.io/gitea/models/repo" + "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/setting/config" + "github.com/stretchr/testify/assert" ) func TestRepoWatch(t *testing.T) { onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { // Test round-trip auto-watch - setting.Service.AutoWatchOnChanges = true + + assert.NoError(t, system.SetSettings(t.Context(), map[string]string{ + setting.Config().Service.AutoWatchOnChanges.DynKey(): "true", + })) + config.GetDynGetter().InvalidateCache() + session := loginUser(t, "user2") unittest.AssertNotExistsBean(t, &repo_model.Watch{UserID: 2, RepoID: 3}) testEditFile(t, session, "org3", "repo3", "master", "README.md", "Hello, World (Edited for watch)\n") diff --git a/tests/integration/signup_test.go b/tests/integration/signup_test.go index 06c513f61675c..9fce0f7a50704 100644 --- a/tests/integration/signup_test.go +++ b/tests/integration/signup_test.go @@ -10,9 +10,11 @@ import ( "testing" "code.gitea.io/gitea/models/db" + "code.gitea.io/gitea/models/system" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/setting/config" "code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/translation" "code.gitea.io/gitea/tests" @@ -40,7 +42,10 @@ func TestSignup(t *testing.T) { func TestSignupAsRestricted(t *testing.T) { defer tests.PrepareTestEnv(t)() defer test.MockVariableValue(&setting.Service.EnableCaptcha, false)() - defer test.MockVariableValue(&setting.Service.DefaultUserIsRestricted, true)() + system.SetSettings(t.Context(), map[string]string{ + setting.Config().Service.DefaultUserIsRestricted.DynKey(): "true", + }) + config.GetDynGetter().InvalidateCache() req := NewRequestWithValues(t, "POST", "/user/sign_up", map[string]string{ "user_name": "restrictedUser", From 313856357e9bfbdf47fff02f42777cf718ad0e1c Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 8 Oct 2025 17:12:58 -0700 Subject: [PATCH 2/4] Fix lint --- tests/integration/repo_watch_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/integration/repo_watch_test.go b/tests/integration/repo_watch_test.go index beef94e271cd2..222bfabb43a3e 100644 --- a/tests/integration/repo_watch_test.go +++ b/tests/integration/repo_watch_test.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/setting/config" + "github.com/stretchr/testify/assert" ) From 8e273ce093eba2214a8982600736cd04b68cc545 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 8 Oct 2025 20:31:22 -0700 Subject: [PATCH 3/4] fix --- options/locale/locale_en-US.ini | 52 ++++++++----------- routers/install/install.go | 3 -- templates/admin/config.tmpl | 15 ------ templates/admin/config_settings/service.tmpl | 54 ++++++++++---------- templates/install.tmpl | 18 ------- tests/mssql.ini.tmpl | 2 - tests/mysql.ini.tmpl | 2 - tests/pgsql.ini.tmpl | 2 - tests/sqlite.ini.tmpl | 2 - 9 files changed, 47 insertions(+), 103 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index c403270d4a136..5ca90358d4868 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -350,12 +350,6 @@ secret_key_failed = Failed to generate secret key: %v save_config_failed = Failed to save configuration: %v invalid_admin_setting = Administrator account setting is invalid: %v invalid_log_root_path = The log path is invalid: %v -default_keep_email_private = Hide Email Addresses by Default -default_keep_email_private_popup = Hide email addresses of new user accounts by default. -default_allow_create_organization = Allow Creation of Organizations by Default -default_allow_create_organization_popup = Allow new user accounts to create organizations by default. -default_enable_timetracking = Enable Time Tracking by Default -default_enable_timetracking_popup = Enable time tracking for new repositories by default. no_reply_address = Hidden Email Domain no_reply_address_helper = Domain name for users with a hidden email address. For example, the username 'joe' will be logged in Git as 'joe@noreply.example.org' if the hidden email domain is set to 'noreply.example.org'. password_algorithm = Password Hash Algorithm @@ -3377,36 +3371,30 @@ config.enable_captcha = Enable CAPTCHA config.active_code_lives = Active Code Lives config.reset_password_code_lives = Recover Account Code Expiry Time config.default_keep_email_private = Hide Email Addresses by Default +config.default_keep_email_private_desc = Each new user will get the value of this setting copied into their profile config.default_allow_create_organization = Allow Creation of Organizations by Default -config.enable_timetracking = Enable Time Tracking -config.default_enable_timetracking = Enable Time Tracking by Default +config.default_allow_create_organization_desc = Every new user will have rights set to create organizations depending on this setting +config.default_user_is_restricted = New user will be restricted by default +config.default_user_is_restricted_desc = Every new user will have restricted permissions depending on this setting +config.enable_time_tracking = Enable Time Tracking +config.default_enable_time_tracking = Enable Time Tracking by Default +config.default_enable_time_tracking_desc = Repositories will use time tracking by default depending on this setting config.default_allow_only_contributors_to_track_time = Let Only Contributors Track Time +config.default_allow_only_contributors_to_track_time_desc = Only users with write permissions can track time if this is true +config.default_enable_dependencies = Enable Issue Dependencies by Default +config.default_enable_dependencies_desc = Repositories will use dependencies by default depending on this setting +config.allow_cross_repository_dependencies = Allow Cross Repository Issue Dependencies +config.allow_cross_repository_dependencies_desc = Dependencies can be added from any repository where the user is granted access or only from the current repository depending on this setting. +config.enable_user_heatmap = Enable User Heatmap +config.enable_user_heatmap_desc = Show a heatmap of user activity on user profiles +config.auto_watch_new_repos = Enable Auto Watch for New Repositories +config.auto_watch_new_repos_desc = When adding a repo to a team or creating a new repo all team members will watch the repo automatically if enabled +config.auto_watch_on_changes = Enable Auto Watch for Repositories Push +config.auto_watch_on_changes_desc = Make the user watch a repository When they commit for the first time +config.default_org_member_visible = Default Organization Member Visibility +config.default_org_member_visible_desc = True will make the membership of the users visible when added to the organisation config.no_reply_address = Hidden Email Domain config.default_visibility_organization = Default visibility for new Organizations -config.service_default_keep_email_private = Default value for KeepEmailPrivate -config.service_default_keep_email_private_desc = Each new user will get the value of this setting copied into their profile -config.service_default_allow_create_organization = Default value for AllowCreateOrganization -config.service_default_allow_create_organization_desc = Every new user will have rights set to create organizations depending on this setting -config.service_default_user_is_restricted = Default value for IsRestricted -config.service_default_user_is_restricted_desc = Every new user will have restricted permissions depending on this setting -config.service_enable_time_tracking = Enable Time Tracking -config.service_default_enable_time_tracking = Default value for EnableTimetracking -config.service_default_enable_time_tracking_desc = Repositories will use timetracking by default depending on this setting -config.service_default_enable_dependencies = Enable Issue Dependencies by Default -config.service_default_enable_dependencies_desc = Repositories will use dependencies by default depending on this setting -config.service_allow_cross_repository_dependencies = Allow Cross Repository Issue Dependencies -config.service_allow_cross_repository_dependencies_desc = Dependencies can be added from any repository where the user is granted access or only from the current repository depending on this setting. -config.service_default_allow_only_contributors_to_track_time = Default value for AllowOnlyContributorsToTrackTime -config.service_default_allow_only_contributors_to_track_time_desc = Only users with write permissions can track time if this is true -config.service_enable_user_heatmap = Enable User Heatmap -config.service_enable_user_heatmap_desc = Show a heatmap of user activity on user profiles -config.service_auto_watch_new_repos = Enable Auto Watch for New Repositories -config.service_auto_watch_new_repos_desc = When adding a repo to a team or creating a new repo all team members will watch the repo automatically if enabled -config.service_auto_watch_on_changes = Enable Auto Watch for Repositories Push -config.service_auto_watch_on_changes_desc = Make the user watch a repository When they commit for the first time -config.service_default_org_member_visible = Default value for DefaultOrgMemberVisible -config.service_default_org_member_visible_desc = True will make the membership of the users visible when added to the organisation - config.webhook_config = Webhook Configuration config.queue_length = Queue Length config.deliver_timeout = Deliver Timeout diff --git a/routers/install/install.go b/routers/install/install.go index c06b6dee255c3..c68b278641a6d 100644 --- a/routers/install/install.go +++ b/routers/install/install.go @@ -440,9 +440,6 @@ func SubmitInstall(ctx *context.Context) { cfg.Section("service").Key("ALLOW_ONLY_EXTERNAL_REGISTRATION").SetValue(strconv.FormatBool(form.AllowOnlyExternalRegistration)) cfg.Section("service").Key("ENABLE_CAPTCHA").SetValue(strconv.FormatBool(form.EnableCaptcha)) cfg.Section("service").Key("REQUIRE_SIGNIN_VIEW").SetValue(strconv.FormatBool(form.RequireSignInView)) - cfg.Section("service").Key("DEFAULT_KEEP_EMAIL_PRIVATE").SetValue(strconv.FormatBool(form.DefaultKeepEmailPrivate)) - cfg.Section("service").Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").SetValue(strconv.FormatBool(form.DefaultAllowCreateOrganization)) - cfg.Section("service").Key("DEFAULT_ENABLE_TIMETRACKING").SetValue(strconv.FormatBool(form.DefaultEnableTimetracking)) cfg.Section("service").Key("NO_REPLY_ADDRESS").SetValue(form.NoReplyAddress) cfg.Section("cron.update_checker").Key("ENABLED").SetValue(strconv.FormatBool(form.EnableUpdateChecker)) diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl index 806347c72049d..f3f7c40eb9483 100644 --- a/templates/admin/config.tmpl +++ b/templates/admin/config.tmpl @@ -149,25 +149,10 @@
{{svg (Iif .Service.EnableNotifyMail "octicon-check" "octicon-x")}}
{{ctx.Locale.Tr "admin.config.enable_captcha"}}
{{svg (Iif .Service.EnableCaptcha "octicon-check" "octicon-x")}}
-
{{ctx.Locale.Tr "admin.config.default_keep_email_private"}}
-
{{svg (Iif .Service.DefaultKeepEmailPrivate "octicon-check" "octicon-x")}}
-
{{ctx.Locale.Tr "admin.config.default_allow_create_organization"}}
-
{{svg (Iif .Service.DefaultAllowCreateOrganization "octicon-check" "octicon-x")}}
-
{{ctx.Locale.Tr "admin.config.enable_timetracking"}}
-
{{svg (Iif .Service.EnableTimetracking "octicon-check" "octicon-x")}}
- {{if .Service.EnableTimetracking}} -
{{ctx.Locale.Tr "admin.config.default_enable_timetracking"}}
-
{{svg (Iif .Service.DefaultEnableTimetracking "octicon-check" "octicon-x")}}
-
{{ctx.Locale.Tr "admin.config.default_allow_only_contributors_to_track_time"}}
-
{{svg (Iif .Service.DefaultAllowOnlyContributorsToTrackTime "octicon-check" "octicon-x")}}
- {{end}}
{{ctx.Locale.Tr "admin.config.default_visibility_organization"}}
{{.Service.DefaultOrgVisibility}}
-
{{ctx.Locale.Tr "admin.config.no_reply_address"}}
{{if .Service.NoReplyAddress}}{{.Service.NoReplyAddress}}{{else}}-{{end}}
-
{{ctx.Locale.Tr "admin.config.default_enable_dependencies"}}
-
{{svg (Iif .Service.DefaultEnableDependencies "octicon-check" "octicon-x")}}
{{ctx.Locale.Tr "admin.config.active_code_lives"}}
{{.Service.ActiveCodeLives}} {{ctx.Locale.Tr "tool.raw_minutes"}}
diff --git a/templates/admin/config_settings/service.tmpl b/templates/admin/config_settings/service.tmpl index 7a04ffd5059f7..53c10d6ca41ff 100644 --- a/templates/admin/config_settings/service.tmpl +++ b/templates/admin/config_settings/service.tmpl @@ -3,86 +3,86 @@
-
{{ctx.Locale.Tr "admin.config.service_default_keep_email_private"}}
+
{{ctx.Locale.Tr "admin.config.default_keep_email_private"}}
-
+
-
{{ctx.Locale.Tr "admin.config.service_default_allow_create_organization"}}
+
{{ctx.Locale.Tr "admin.config.default_allow_create_organization"}}
-
+
-
{{ctx.Locale.Tr "admin.config.service_default_user_is_restricted"}}
+
{{ctx.Locale.Tr "admin.config.default_user_is_restricted"}}
-
+
-
{{ctx.Locale.Tr "admin.config.service_enable_time_tracking"}}
+
{{ctx.Locale.Tr "admin.config.enable_time_tracking"}}
-
+
-
{{ctx.Locale.Tr "admin.config.service_default_enable_time_tracking"}}
+
{{ctx.Locale.Tr "admin.config.default_enable_time_tracking"}}
-
+
-
{{ctx.Locale.Tr "admin.config.service_default_enable_dependencies"}}
+
{{ctx.Locale.Tr "admin.config.default_allow_only_contributors_to_track_time"}}
-
- +
+
-
{{ctx.Locale.Tr "admin.config.service_allow_cross_repository_dependencies"}}
+
{{ctx.Locale.Tr "admin.config.default_enable_dependencies"}}
-
- +
+
-
{{ctx.Locale.Tr "admin.config.service_default_allow_only_contributors_to_track_time"}}
+
{{ctx.Locale.Tr "admin.config.allow_cross_repository_dependencies"}}
-
- +
+
-
{{ctx.Locale.Tr "admin.config.service_enable_user_heatmap"}}
+
{{ctx.Locale.Tr "admin.config.enable_user_heatmap"}}
-
+
-
{{ctx.Locale.Tr "admin.config.service_auto_watch_new_repos"}}
+
{{ctx.Locale.Tr "admin.config.auto_watch_new_repos"}}
-
+
-
{{ctx.Locale.Tr "admin.config.service_auto_watch_on_changes"}}
+
{{ctx.Locale.Tr "admin.config.auto_watch_on_changes"}}
-
+
-
{{ctx.Locale.Tr "admin.config.service_default_org_member_visible"}}
+
{{ctx.Locale.Tr "admin.config.default_org_member_visible"}}
-
+
diff --git a/templates/install.tmpl b/templates/install.tmpl index 0aec52f27baa9..99b19291862ac 100644 --- a/templates/install.tmpl +++ b/templates/install.tmpl @@ -257,24 +257,6 @@
-
-
- - -
-
-
-
- - -
-
-
-
- - -
-
diff --git a/tests/mssql.ini.tmpl b/tests/mssql.ini.tmpl index 42bf683a079f1..2fdd14062d3f1 100644 --- a/tests/mssql.ini.tmpl +++ b/tests/mssql.ini.tmpl @@ -68,8 +68,6 @@ REGISTER_MANUAL_CONFIRM = false DISABLE_REGISTRATION = false ENABLE_CAPTCHA = false REQUIRE_SIGNIN_VIEW = false -DEFAULT_KEEP_EMAIL_PRIVATE = false -DEFAULT_ALLOW_CREATE_ORGANIZATION = true NO_REPLY_ADDRESS = noreply.example.org ENABLE_NOTIFY_MAIL = true diff --git a/tests/mysql.ini.tmpl b/tests/mysql.ini.tmpl index 7cef540d1d139..e95d5f03f49e3 100644 --- a/tests/mysql.ini.tmpl +++ b/tests/mysql.ini.tmpl @@ -71,8 +71,6 @@ REGISTER_MANUAL_CONFIRM = false DISABLE_REGISTRATION = false ENABLE_CAPTCHA = false REQUIRE_SIGNIN_VIEW = false -DEFAULT_KEEP_EMAIL_PRIVATE = false -DEFAULT_ALLOW_CREATE_ORGANIZATION = true NO_REPLY_ADDRESS = noreply.example.org ENABLE_NOTIFY_MAIL = true diff --git a/tests/pgsql.ini.tmpl b/tests/pgsql.ini.tmpl index 13a5932608c1d..b4978df9a516a 100644 --- a/tests/pgsql.ini.tmpl +++ b/tests/pgsql.ini.tmpl @@ -69,8 +69,6 @@ REGISTER_MANUAL_CONFIRM = false DISABLE_REGISTRATION = false ENABLE_CAPTCHA = false REQUIRE_SIGNIN_VIEW = false -DEFAULT_KEEP_EMAIL_PRIVATE = false -DEFAULT_ALLOW_CREATE_ORGANIZATION = true NO_REPLY_ADDRESS = noreply.example.org ENABLE_NOTIFY_MAIL = true diff --git a/tests/sqlite.ini.tmpl b/tests/sqlite.ini.tmpl index 938f203633528..2d72268eb9770 100644 --- a/tests/sqlite.ini.tmpl +++ b/tests/sqlite.ini.tmpl @@ -69,8 +69,6 @@ ENABLE_NOTIFY_MAIL = true DISABLE_REGISTRATION = false ENABLE_CAPTCHA = false REQUIRE_SIGNIN_VIEW = false -DEFAULT_KEEP_EMAIL_PRIVATE = false -DEFAULT_ALLOW_CREATE_ORGANIZATION = true NO_REPLY_ADDRESS = noreply.example.org [picture] From 65d051eedb6c507176a2f8a783312afaa7333de7 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Wed, 8 Oct 2025 20:43:35 -0700 Subject: [PATCH 4/4] improvements --- options/locale/locale_en-US.ini | 1 + templates/admin/config_settings/service.tmpl | 38 +++++++++++++------- templates/repo/settings/options.tmpl | 2 +- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index 5ca90358d4868..283b6a5927bdd 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -3377,6 +3377,7 @@ config.default_allow_create_organization_desc = Every new user will have rights config.default_user_is_restricted = New user will be restricted by default config.default_user_is_restricted_desc = Every new user will have restricted permissions depending on this setting config.enable_time_tracking = Enable Time Tracking +config.enable_time_tracking_desc = Allow users to track time on issues and pull requests config.default_enable_time_tracking = Enable Time Tracking by Default config.default_enable_time_tracking_desc = Repositories will use time tracking by default depending on this setting config.default_allow_only_contributors_to_track_time = Let Only Contributors Track Time diff --git a/templates/admin/config_settings/service.tmpl b/templates/admin/config_settings/service.tmpl index 53c10d6ca41ff..0dbe81561cf0e 100644 --- a/templates/admin/config_settings/service.tmpl +++ b/templates/admin/config_settings/service.tmpl @@ -2,89 +2,103 @@ {{ctx.Locale.Tr "admin.config.service_config"}}
+
{{ctx.Locale.Tr "admin.config.default_keep_email_private"}}
-
+
+

{{ctx.Locale.Tr "admin.config.default_keep_email_private_desc"}}

{{ctx.Locale.Tr "admin.config.default_allow_create_organization"}}
-
+
+

{{ctx.Locale.Tr "admin.config.default_allow_create_organization_desc"}}

{{ctx.Locale.Tr "admin.config.default_user_is_restricted"}}
-
+
+

{{ctx.Locale.Tr "admin.config.default_user_is_restricted_desc"}}

{{ctx.Locale.Tr "admin.config.enable_time_tracking"}}
-
+
+

{{ctx.Locale.Tr "admin.config.enable_time_tracking_desc"}}

{{ctx.Locale.Tr "admin.config.default_enable_time_tracking"}}
-
+
+

{{ctx.Locale.Tr "admin.config.default_enable_time_tracking_desc"}}

{{ctx.Locale.Tr "admin.config.default_allow_only_contributors_to_track_time"}}
-
+
+

{{ctx.Locale.Tr "admin.config.default_allow_only_contributors_to_track_time_desc"}}

{{ctx.Locale.Tr "admin.config.default_enable_dependencies"}}
-
+
+

{{ctx.Locale.Tr "admin.config.default_enable_dependencies_desc"}}

{{ctx.Locale.Tr "admin.config.allow_cross_repository_dependencies"}}
-
+
+

{{ctx.Locale.Tr "admin.config.allow_cross_repository_dependencies_desc"}}

{{ctx.Locale.Tr "admin.config.enable_user_heatmap"}}
-
+
+

{{ctx.Locale.Tr "admin.config.enable_user_heatmap_desc"}}

{{ctx.Locale.Tr "admin.config.auto_watch_new_repos"}}
-
+
+

{{ctx.Locale.Tr "admin.config.auto_watch_new_repos_desc"}}

{{ctx.Locale.Tr "admin.config.auto_watch_on_changes"}}
-
+
+

{{ctx.Locale.Tr "admin.config.auto_watch_on_changes_desc"}}

{{ctx.Locale.Tr "admin.config.default_org_member_visible"}}
-
+
+

{{ctx.Locale.Tr "admin.config.default_org_member_visible_desc"}}

+
diff --git a/templates/repo/settings/options.tmpl b/templates/repo/settings/options.tmpl index fc42056e0a2bb..11f9b82f2af9b 100644 --- a/templates/repo/settings/options.tmpl +++ b/templates/repo/settings/options.tmpl @@ -372,7 +372,7 @@
- {{if .Repository.CanEnableTimetracker}} + {{if .Repository.CanEnableTimetracker ctx}}