From 9f8d59858af581a2c278a4896a301339991ece5b Mon Sep 17 00:00:00 2001
From: wxiaoguang <wxiaoguang@gmail.com>
Date: Thu, 5 Oct 2023 09:08:19 +0800
Subject: Refactor system setting (#27000)

This PR reduces the complexity of the system setting system.

It only needs one line to introduce a new option, and the option can be
used anywhere out-of-box.

It is still high-performant (and more performant) because the config
values are cached in the config system.
---
 routers/web/admin/config.go | 67 +++++++++------------------------------------
 routers/web/admin/users.go  | 22 ++++++---------
 2 files changed, 21 insertions(+), 68 deletions(-)

(limited to 'routers/web/admin')

diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go
index c70a2d1c95..c827f2a4f5 100644
--- a/routers/web/admin/config.go
+++ b/routers/web/admin/config.go
@@ -5,19 +5,19 @@
 package admin
 
 import (
-	"fmt"
 	"net/http"
 	"net/url"
-	"strconv"
 	"strings"
 
 	system_model "code.gitea.io/gitea/models/system"
 	"code.gitea.io/gitea/modules/base"
+	"code.gitea.io/gitea/modules/container"
 	"code.gitea.io/gitea/modules/context"
 	"code.gitea.io/gitea/modules/git"
 	"code.gitea.io/gitea/modules/json"
 	"code.gitea.io/gitea/modules/log"
 	"code.gitea.io/gitea/modules/setting"
+	"code.gitea.io/gitea/modules/setting/config"
 	"code.gitea.io/gitea/modules/util"
 	"code.gitea.io/gitea/services/mailer"
 
@@ -101,16 +101,6 @@ func Config(ctx *context.Context) {
 	ctx.Data["Title"] = ctx.Tr("admin.config")
 	ctx.Data["PageIsAdminConfig"] = true
 
-	systemSettings, err := system_model.GetAllSettings(ctx)
-	if err != nil {
-		ctx.ServerError("system_model.GetAllSettings", err)
-		return
-	}
-
-	// All editable settings from UI
-	ctx.Data["SystemSettings"] = systemSettings
-	ctx.PageData["adminConfigPage"] = true
-
 	ctx.Data["CustomConf"] = setting.CustomConf
 	ctx.Data["AppUrl"] = setting.AppURL
 	ctx.Data["AppBuiltWith"] = setting.AppBuiltWith
@@ -170,7 +160,8 @@ func Config(ctx *context.Context) {
 	ctx.Data["LogSQL"] = setting.Database.LogSQL
 
 	ctx.Data["Loggers"] = log.GetManager().DumpLoggers()
-
+	config.GetDynGetter().InvalidateCache()
+	ctx.Data["SystemConfig"] = setting.Config()
 	prepareDeprecatedWarningsAlert(ctx)
 
 	ctx.HTML(http.StatusOK, tplConfig)
@@ -178,51 +169,19 @@ func Config(ctx *context.Context) {
 
 func ChangeConfig(ctx *context.Context) {
 	key := strings.TrimSpace(ctx.FormString("key"))
-	if key == "" {
-		ctx.JSONRedirect(ctx.Req.URL.String())
-		return
-	}
 	value := ctx.FormString("value")
-	version := ctx.FormInt("version")
-
-	if check, ok := changeConfigChecks[key]; ok {
-		if err := check(ctx, value); err != nil {
-			log.Warn("refused to set setting: %v", err)
-			ctx.JSON(http.StatusOK, map[string]string{
-				"err": ctx.Tr("admin.config.set_setting_failed", key),
-			})
-			return
-		}
+	cfg := setting.Config()
+	allowedKeys := container.SetOf(cfg.Picture.DisableGravatar.DynKey(), cfg.Picture.EnableFederatedAvatar.DynKey())
+	if !allowedKeys.Contains(key) {
+		ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key))
+		return
 	}
-
-	if err := system_model.SetSetting(ctx, &system_model.Setting{
-		SettingKey:   key,
-		SettingValue: value,
-		Version:      version,
-	}); err != nil {
+	if err := system_model.SetSettings(ctx, map[string]string{key: value}); err != nil {
 		log.Error("set setting failed: %v", err)
-		ctx.JSON(http.StatusOK, map[string]string{
-			"err": ctx.Tr("admin.config.set_setting_failed", key),
-		})
+		ctx.JSONError(ctx.Tr("admin.config.set_setting_failed", key))
 		return
 	}
 
-	ctx.JSON(http.StatusOK, map[string]any{
-		"version": version + 1,
-	})
-}
-
-var changeConfigChecks = map[string]func(ctx *context.Context, newValue string) error{
-	system_model.KeyPictureDisableGravatar: func(_ *context.Context, newValue string) error {
-		if v, _ := strconv.ParseBool(newValue); setting.OfflineMode && !v {
-			return fmt.Errorf("%q should be true when OFFLINE_MODE is true", system_model.KeyPictureDisableGravatar)
-		}
-		return nil
-	},
-	system_model.KeyPictureEnableFederatedAvatar: func(_ *context.Context, newValue string) error {
-		if v, _ := strconv.ParseBool(newValue); setting.OfflineMode && v {
-			return fmt.Errorf("%q cannot be false when OFFLINE_MODE is true", system_model.KeyPictureEnableFederatedAvatar)
-		}
-		return nil
-	},
+	config.GetDynGetter().InvalidateCache()
+	ctx.JSONOK()
 }
diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go
index 4c6551501e..18d7313e72 100644
--- a/routers/web/admin/users.go
+++ b/routers/web/admin/users.go
@@ -15,7 +15,6 @@ import (
 	"code.gitea.io/gitea/models/db"
 	org_model "code.gitea.io/gitea/models/organization"
 	repo_model "code.gitea.io/gitea/models/repo"
-	system_model "code.gitea.io/gitea/models/system"
 	user_model "code.gitea.io/gitea/models/user"
 	"code.gitea.io/gitea/modules/auth/password"
 	"code.gitea.io/gitea/modules/base"
@@ -308,17 +307,18 @@ func ViewUser(ctx *context.Context) {
 	ctx.HTML(http.StatusOK, tplUserView)
 }
 
-// EditUser show editing user page
-func EditUser(ctx *context.Context) {
+func editUserCommon(ctx *context.Context) {
 	ctx.Data["Title"] = ctx.Tr("admin.users.edit_account")
 	ctx.Data["PageIsAdminUsers"] = true
 	ctx.Data["DisableRegularOrgCreation"] = setting.Admin.DisableRegularOrgCreation
 	ctx.Data["DisableMigrations"] = setting.Repository.DisableMigrations
 	ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
-	ctx.Data["DisableGravatar"] = system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureDisableGravatar,
-		setting.GetDefaultDisableGravatar(),
-	)
+	ctx.Data["DisableGravatar"] = setting.Config().Picture.DisableGravatar.Value(ctx)
+}
 
+// EditUser show editing user page
+func EditUser(ctx *context.Context) {
+	editUserCommon(ctx)
 	prepareUserInfo(ctx)
 	if ctx.Written() {
 		return
@@ -329,19 +329,13 @@ func EditUser(ctx *context.Context) {
 
 // EditUserPost response for editing user
 func EditUserPost(ctx *context.Context) {
-	form := web.GetForm(ctx).(*forms.AdminEditUserForm)
-	ctx.Data["Title"] = ctx.Tr("admin.users.edit_account")
-	ctx.Data["PageIsAdminUsers"] = true
-	ctx.Data["DisableMigrations"] = setting.Repository.DisableMigrations
-	ctx.Data["AllowedUserVisibilityModes"] = setting.Service.AllowedUserVisibilityModesSlice.ToVisibleTypeSlice()
-	ctx.Data["DisableGravatar"] = system_model.GetSettingWithCacheBool(ctx, system_model.KeyPictureDisableGravatar,
-		setting.GetDefaultDisableGravatar())
-
+	editUserCommon(ctx)
 	u := prepareUserInfo(ctx)
 	if ctx.Written() {
 		return
 	}
 
+	form := web.GetForm(ctx).(*forms.AdminEditUserForm)
 	if ctx.HasError() {
 		ctx.HTML(http.StatusOK, tplUserEdit)
 		return
-- 
cgit v1.2.3