From d9b3849454e04c1f498c12e29b8c19660cbae328 Mon Sep 17 00:00:00 2001
From: wackbyte <wackbyte@pm.me>
Date: Sun, 28 Jan 2024 07:36:44 -0500
Subject: [PATCH] Fix inconsistent naming of OAuth 2.0 `ENABLE` setting
 (#28951)

Renames it to `ENABLED` to be consistent with other settings and
deprecates it.

I believe this change is necessary because other setting groups such as
`attachment`, `cors`, `mailer`, etc. have an `ENABLED` setting, but
`oauth2` is the only one with an `ENABLE` setting, which could cause
confusion for users.

This is no longer a breaking change because `ENABLE` has been set as
deprecated and as an alias to `ENABLED`.
---
 custom/conf/app.example.ini                   |  2 +-
 .../config-cheat-sheet.en-us.md               |  2 +-
 .../config-cheat-sheet.zh-cn.md               |  2 +-
 modules/setting/oauth2.go                     | 19 +++++++++++++------
 routers/web/user/setting/applications.go      |  4 ++--
 routers/web/web.go                            | 10 +++++-----
 6 files changed, 23 insertions(+), 16 deletions(-)

diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini
index b0875123b7..7032e709db 100644
--- a/custom/conf/app.example.ini
+++ b/custom/conf/app.example.ini
@@ -524,7 +524,7 @@ INTERNAL_TOKEN=
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;
 ;; Enables OAuth2 provider
-ENABLE = true
+ENABLED = true
 ;;
 ;; Algorithm used to sign OAuth2 tokens. Valid values: HS256, HS384, HS512, RS256, RS384, RS512, ES256, ES384, ES512, EdDSA
 ;JWT_SIGNING_ALGORITHM = RS256
diff --git a/docs/content/administration/config-cheat-sheet.en-us.md b/docs/content/administration/config-cheat-sheet.en-us.md
index eb9b8d1ae9..33732d080b 100644
--- a/docs/content/administration/config-cheat-sheet.en-us.md
+++ b/docs/content/administration/config-cheat-sheet.en-us.md
@@ -1107,7 +1107,7 @@ This section only does "set" config, a removed config key from this section won'
 
 ## OAuth2 (`oauth2`)
 
-- `ENABLE`: **true**: Enables OAuth2 provider.
+- `ENABLED`: **true**: Enables OAuth2 provider.
 - `ACCESS_TOKEN_EXPIRATION_TIME`: **3600**: Lifetime of an OAuth2 access token in seconds
 - `REFRESH_TOKEN_EXPIRATION_TIME`: **730**: Lifetime of an OAuth2 refresh token in hours
 - `INVALIDATE_REFRESH_TOKENS`: **false**: Check if refresh token has already been used
diff --git a/docs/content/administration/config-cheat-sheet.zh-cn.md b/docs/content/administration/config-cheat-sheet.zh-cn.md
index 415cba14ed..2cee70daab 100644
--- a/docs/content/administration/config-cheat-sheet.zh-cn.md
+++ b/docs/content/administration/config-cheat-sheet.zh-cn.md
@@ -1043,7 +1043,7 @@ Gitea 创建以下非唯一队列:
 
 ## OAuth2 (`oauth2`)
 
-- `ENABLE`: **true**:启用OAuth2提供者。
+- `ENABLED`: **true**:启用OAuth2提供者。
 - `ACCESS_TOKEN_EXPIRATION_TIME`:**3600**:OAuth2访问令牌的生命周期,以秒为单位。
 - `REFRESH_TOKEN_EXPIRATION_TIME`:**730**:OAuth2刷新令牌的生命周期,以小时为单位。
 - `INVALIDATE_REFRESH_TOKENS`:**false**:检查刷新令牌是否已被使用。
diff --git a/modules/setting/oauth2.go b/modules/setting/oauth2.go
index 10cadf03dd..0d15e91ef0 100644
--- a/modules/setting/oauth2.go
+++ b/modules/setting/oauth2.go
@@ -93,7 +93,7 @@ func parseScopes(sec ConfigSection, name string) []string {
 }
 
 var OAuth2 = struct {
-	Enable                     bool
+	Enabled                    bool
 	AccessTokenExpirationTime  int64
 	RefreshTokenExpirationTime int64
 	InvalidateRefreshTokens    bool
@@ -103,7 +103,7 @@ var OAuth2 = struct {
 	MaxTokenLength             int
 	DefaultApplications        []string
 }{
-	Enable:                     true,
+	Enabled:                    true,
 	AccessTokenExpirationTime:  3600,
 	RefreshTokenExpirationTime: 730,
 	InvalidateRefreshTokens:    false,
@@ -114,16 +114,23 @@ var OAuth2 = struct {
 }
 
 func loadOAuth2From(rootCfg ConfigProvider) {
-	if err := rootCfg.Section("oauth2").MapTo(&OAuth2); err != nil {
-		log.Fatal("Failed to OAuth2 settings: %v", err)
+	sec := rootCfg.Section("oauth2")
+	if err := sec.MapTo(&OAuth2); err != nil {
+		log.Fatal("Failed to map OAuth2 settings: %v", err)
 		return
 	}
 
-	if !OAuth2.Enable {
+	// Handle the rename of ENABLE to ENABLED
+	deprecatedSetting(rootCfg, "oauth2", "ENABLE", "oauth2", "ENABLED", "v1.23.0")
+	if sec.HasKey("ENABLE") && !sec.HasKey("ENABLED") {
+		OAuth2.Enabled = sec.Key("ENABLE").MustBool(OAuth2.Enabled)
+	}
+
+	if !OAuth2.Enabled {
 		return
 	}
 
-	OAuth2.JWTSecretBase64 = loadSecret(rootCfg.Section("oauth2"), "JWT_SECRET_URI", "JWT_SECRET")
+	OAuth2.JWTSecretBase64 = loadSecret(sec, "JWT_SECRET_URI", "JWT_SECRET")
 
 	if !filepath.IsAbs(OAuth2.JWTSigningPrivateKeyFile) {
 		OAuth2.JWTSigningPrivateKeyFile = filepath.Join(AppDataPath, OAuth2.JWTSigningPrivateKeyFile)
diff --git a/routers/web/user/setting/applications.go b/routers/web/user/setting/applications.go
index 69a93dbf03..a7e31fd505 100644
--- a/routers/web/user/setting/applications.go
+++ b/routers/web/user/setting/applications.go
@@ -95,9 +95,9 @@ func loadApplicationsData(ctx *context.Context) {
 		return
 	}
 	ctx.Data["Tokens"] = tokens
-	ctx.Data["EnableOAuth2"] = setting.OAuth2.Enable
+	ctx.Data["EnableOAuth2"] = setting.OAuth2.Enabled
 	ctx.Data["IsAdmin"] = ctx.Doer.IsAdmin
-	if setting.OAuth2.Enable {
+	if setting.OAuth2.Enabled {
 		ctx.Data["Applications"], err = db.Find[auth_model.OAuth2Application](ctx, auth_model.FindOAuth2ApplicationsOptions{
 			OwnerID: ctx.Doer.ID,
 		})
diff --git a/routers/web/web.go b/routers/web/web.go
index ff0ce0c258..92cf5132b4 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -304,7 +304,7 @@ func registerRoutes(m *web.Route) {
 	validation.AddBindingRules()
 
 	linkAccountEnabled := func(ctx *context.Context) {
-		if !setting.Service.EnableOpenIDSignIn && !setting.Service.EnableOpenIDSignUp && !setting.OAuth2.Enable {
+		if !setting.Service.EnableOpenIDSignIn && !setting.Service.EnableOpenIDSignUp && !setting.OAuth2.Enabled {
 			ctx.Error(http.StatusForbidden)
 			return
 		}
@@ -768,7 +768,7 @@ func registerRoutes(m *web.Route) {
 				m.Post("/delete", admin.DeleteApplication)
 			})
 		}, func(ctx *context.Context) {
-			if !setting.OAuth2.Enable {
+			if !setting.OAuth2.Enabled {
 				ctx.Error(http.StatusForbidden)
 				return
 			}
@@ -779,7 +779,7 @@ func registerRoutes(m *web.Route) {
 			addSettingsRunnersRoutes()
 			addSettingsVariablesRoutes()
 		})
-	}, adminReq, ctxDataSet("EnableOAuth2", setting.OAuth2.Enable, "EnablePackages", setting.Packages.Enabled))
+	}, adminReq, ctxDataSet("EnableOAuth2", setting.OAuth2.Enabled, "EnablePackages", setting.Packages.Enabled))
 	// ***** END: Admin *****
 
 	m.Group("", func() {
@@ -891,7 +891,7 @@ func registerRoutes(m *web.Route) {
 						m.Post("/delete", org.DeleteOAuth2Application)
 					})
 				}, func(ctx *context.Context) {
-					if !setting.OAuth2.Enable {
+					if !setting.OAuth2.Enabled {
 						ctx.Error(http.StatusForbidden)
 						return
 					}
@@ -943,7 +943,7 @@ func registerRoutes(m *web.Route) {
 						m.Post("/rebuild", org.RebuildCargoIndex)
 					})
 				}, packagesEnabled)
-			}, ctxDataSet("EnableOAuth2", setting.OAuth2.Enable, "EnablePackages", setting.Packages.Enabled, "PageIsOrgSettings", true))
+			}, ctxDataSet("EnableOAuth2", setting.OAuth2.Enabled, "EnablePackages", setting.Packages.Enabled, "PageIsOrgSettings", true))
 		}, context.OrgAssignment(true, true))
 	}, reqSignIn)
 	// ***** END: Organization *****