Merge remote-tracking branch 'upstream/main' into limit-repo-size

Resolved Conflicts:
	models/migrations/migrations.go
This commit is contained in:
DmitryFrolovTri
2023-10-25 09:59:00 +00:00
557 changed files with 6757 additions and 6624 deletions
+55
View File
@@ -0,0 +1,55 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package setting
import (
"sync"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting/config"
)
type PictureStruct struct {
DisableGravatar *config.Value[bool]
EnableFederatedAvatar *config.Value[bool]
}
type ConfigStruct struct {
Picture *PictureStruct
}
var (
defaultConfig *ConfigStruct
defaultConfigOnce sync.Once
)
func initDefaultConfig() {
config.SetCfgSecKeyGetter(&cfgSecKeyGetter{})
defaultConfig = &ConfigStruct{
Picture: &PictureStruct{
DisableGravatar: config.Bool(false, config.CfgSecKey{Sec: "picture", Key: "DISABLE_GRAVATAR"}, "picture.disable_gravatar"),
EnableFederatedAvatar: config.Bool(false, config.CfgSecKey{Sec: "picture", Key: "ENABLE_FEDERATED_AVATAR"}, "picture.enable_federated_avatar"),
},
}
}
func Config() *ConfigStruct {
defaultConfigOnce.Do(initDefaultConfig)
return defaultConfig
}
type cfgSecKeyGetter struct{}
func (c cfgSecKeyGetter) GetValue(sec, key string) (v string, has bool) {
cfgSec, err := CfgProvider.GetSection(sec)
if err != nil {
log.Error("Unable to get config section: %q", sec)
return "", false
}
cfgKey := ConfigSectionKey(cfgSec, key)
if cfgKey == nil {
return "", false
}
return cfgKey.Value(), true
}
+49
View File
@@ -0,0 +1,49 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package config
import (
"context"
"sync"
)
var getterMu sync.RWMutex
type CfgSecKeyGetter interface {
GetValue(sec, key string) (v string, has bool)
}
var cfgSecKeyGetterInternal CfgSecKeyGetter
func SetCfgSecKeyGetter(p CfgSecKeyGetter) {
getterMu.Lock()
cfgSecKeyGetterInternal = p
getterMu.Unlock()
}
func GetCfgSecKeyGetter() CfgSecKeyGetter {
getterMu.RLock()
defer getterMu.RUnlock()
return cfgSecKeyGetterInternal
}
type DynKeyGetter interface {
GetValue(ctx context.Context, key string) (v string, has bool)
GetRevision(ctx context.Context) int
InvalidateCache()
}
var dynKeyGetterInternal DynKeyGetter
func SetDynGetter(p DynKeyGetter) {
getterMu.Lock()
dynKeyGetterInternal = p
getterMu.Unlock()
}
func GetDynGetter() DynKeyGetter {
getterMu.RLock()
defer getterMu.RUnlock()
return dynKeyGetterInternal
}
+81
View File
@@ -0,0 +1,81 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package config
import (
"context"
"strconv"
"sync"
)
type CfgSecKey struct {
Sec, Key string
}
type Value[T any] struct {
mu sync.RWMutex
cfgSecKey CfgSecKey
dynKey string
def, value T
revision int
}
func (value *Value[T]) parse(s string) (v T) {
switch any(v).(type) {
case bool:
b, _ := strconv.ParseBool(s)
return any(b).(T)
default:
panic("unsupported config type, please complete the code")
}
}
func (value *Value[T]) Value(ctx context.Context) (v T) {
dg := GetDynGetter()
if dg == nil {
// this is an edge case: the database is not initialized but the system setting is going to be used
// it should panic to avoid inconsistent config values (from config / system setting) and fix the code
panic("no config dyn value getter")
}
rev := dg.GetRevision(ctx)
// if the revision in database doesn't change, use the last value
value.mu.RLock()
if rev == value.revision {
v = value.value
value.mu.RUnlock()
return v
}
value.mu.RUnlock()
// try to parse the config and cache it
var valStr *string
if dynVal, has := dg.GetValue(ctx, value.dynKey); has {
valStr = &dynVal
} else if cfgVal, has := GetCfgSecKeyGetter().GetValue(value.cfgSecKey.Sec, value.cfgSecKey.Key); has {
valStr = &cfgVal
}
if valStr == nil {
v = value.def
} else {
v = value.parse(*valStr)
}
value.mu.Lock()
value.value = v
value.revision = rev
value.mu.Unlock()
return v
}
func (value *Value[T]) DynKey() string {
return value.dynKey
}
func Bool(def bool, cfgSecKey CfgSecKey, dynKey string) *Value[bool] {
return &Value[bool]{def: def, cfgSecKey: cfgSecKey, dynKey: dynKey}
}
+2 -1
View File
@@ -149,8 +149,9 @@ func EnvironmentToConfig(cfg ConfigProvider, envs []string) (changed bool) {
continue
}
}
key := section.Key(keyName)
key := ConfigSectionKey(section, keyName)
if key == nil {
changed = true
key, err = section.NewKey(keyName, keyValue)
if err != nil {
log.Error("Error creating key: %s in section: %s with value: %s : %v", keyName, sectionName, keyValue, err)
+26
View File
@@ -115,3 +115,29 @@ key = old
EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile})
assert.Equal(t, "value-from-file\n", cfg.Section("sec").Key("key").String())
}
func TestEnvironmentToConfigSubSecKey(t *testing.T) {
// the INI package has a quirk: by default, the keys are inherited.
// when maintaining the keys, the newly added sub key should not be affected by the parent key.
cfg, err := NewConfigProviderFromData(`
[sec]
key = some
`)
assert.NoError(t, err)
changed := EnvironmentToConfig(cfg, []string{"GITEA__sec_0X2E_sub__key=some"})
assert.True(t, changed)
tmpFile := t.TempDir() + "/test-sub-sec-key.ini"
defer os.Remove(tmpFile)
err = cfg.SaveTo(tmpFile)
assert.NoError(t, err)
bs, err := os.ReadFile(tmpFile)
assert.NoError(t, err)
assert.Equal(t, `[sec]
key = some
[sec.sub]
key = some
`, string(bs))
}
+3 -5
View File
@@ -213,11 +213,9 @@ func NewConfigProviderFromFile(file string, extraConfigs ...string) (ConfigProvi
}
}
if len(extraConfigs) > 0 {
for _, s := range extraConfigs {
if err := cfg.Append([]byte(s)); err != nil {
return nil, fmt.Errorf("unable to append more config: %v", err)
}
for _, s := range extraConfigs {
if err := cfg.Append([]byte(s)); err != nil {
return nil, fmt.Errorf("unable to append more config: %v", err)
}
}
+1 -1
View File
@@ -110,7 +110,7 @@ var OAuth2 = struct {
JWTSigningAlgorithm: "RS256",
JWTSigningPrivateKeyFile: "jwt/private.pem",
MaxTokenLength: math.MaxInt16,
DefaultApplications: []string{"git-credential-oauth", "git-credential-manager"},
DefaultApplications: []string{"git-credential-oauth", "git-credential-manager", "tea"},
}
func loadOAuth2From(rootCfg ConfigProvider) {
+1 -1
View File
@@ -30,7 +30,7 @@ func GetQueueSettings(rootCfg ConfigProvider, name string) (QueueSettings, error
queueSettingsDefault := QueueSettings{
Type: "level", // dummy, channel, level, redis
Datadir: "queues/common", // relative to AppDataPath
Length: 100, // queue length before a channel queue will block
Length: 100000, // queue length before a channel queue will block
QueueName: "_queue",
SetName: "_unique",
-2
View File
@@ -19,7 +19,6 @@ var (
SecretKey string
InternalToken string // internal access token
LogInRememberDays int
CookieUserName string
CookieRememberName string
ReverseProxyAuthUser string
ReverseProxyAuthEmail string
@@ -104,7 +103,6 @@ func loadSecurityFrom(rootCfg ConfigProvider) {
sec := rootCfg.Section("security")
InstallLock = HasInstallLock(rootCfg)
LogInRememberDays = sec.Key("LOGIN_REMEMBER_DAYS").MustInt(7)
CookieUserName = sec.Key("COOKIE_USERNAME").MustString("gitea_awesome")
SecretKey = loadSecret(sec, "SECRET_KEY_URI", "SECRET_KEY")
if SecretKey == "" {
// FIXME: https://github.com/go-gitea/gitea/issues/16832
+2 -2
View File
@@ -76,8 +76,8 @@ var UI = struct {
CodeCommentLines: 4,
ReactionMaxUserNum: 10,
MaxDisplayFileSize: 8388608,
DefaultTheme: `auto`,
Themes: []string{`auto`, `gitea`, `arc-green`},
DefaultTheme: `gitea-auto`,
Themes: []string{`gitea-auto`, `gitea-light`, `gitea-dark`},
Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`},
CustomEmojis: []string{`git`, `gitea`, `codeberg`, `gitlab`, `github`, `gogs`},
CustomEmojisMap: map[string]string{"git": ":git:", "gitea": ":gitea:", "codeberg": ":codeberg:", "gitlab": ":gitlab:", "github": ":github:", "gogs": ":gogs:"},