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

This commit is contained in:
DmitryFrolovTri
2023-08-23 10:10:22 +00:00
710 changed files with 13439 additions and 12772 deletions
+6
View File
@@ -4,6 +4,7 @@
package setting
import (
"bytes"
"os"
"regexp"
"strconv"
@@ -131,6 +132,11 @@ func EnvironmentToConfig(cfg ConfigProvider, envs []string) (changed bool) {
log.Error("Error reading file for %s : %v", envKey, envValue, err)
continue
}
if bytes.HasSuffix(fileContent, []byte("\r\n")) {
fileContent = fileContent[:len(fileContent)-2]
} else if bytes.HasSuffix(fileContent, []byte("\n")) {
fileContent = fileContent[:len(fileContent)-1]
}
keyValue = string(fileContent)
}
+15
View File
@@ -99,4 +99,19 @@ key = old
changed = EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile})
assert.True(t, changed)
assert.Equal(t, "value-from-file", cfg.Section("sec").Key("key").String())
cfg, _ = NewConfigProviderFromData("")
_ = os.WriteFile(tmpFile, []byte("value-from-file\n"), 0o644)
EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile})
assert.Equal(t, "value-from-file", cfg.Section("sec").Key("key").String())
cfg, _ = NewConfigProviderFromData("")
_ = os.WriteFile(tmpFile, []byte("value-from-file\r\n"), 0o644)
EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile})
assert.Equal(t, "value-from-file", cfg.Section("sec").Key("key").String())
cfg, _ = NewConfigProviderFromData("")
_ = os.WriteFile(tmpFile, []byte("value-from-file\n\n"), 0o644)
EnvironmentToConfig(cfg, []string{"GITEA__sec__key__FILE=" + tmpFile})
assert.Equal(t, "value-from-file\n", cfg.Section("sec").Key("key").String())
}
+5 -7
View File
@@ -9,6 +9,7 @@ import (
"time"
"code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/util"
)
// LFS represents the configuration for Git LFS
@@ -56,17 +57,14 @@ func loadLFSFrom(rootCfg ConfigProvider) error {
LFS.HTTPAuthExpiry = sec.Key("LFS_HTTP_AUTH_EXPIRY").MustDuration(24 * time.Hour)
if !LFS.StartServer {
if !LFS.StartServer || !InstallLock {
return nil
}
LFS.JWTSecretBase64 = loadSecret(rootCfg.Section("server"), "LFS_JWT_SECRET_URI", "LFS_JWT_SECRET")
LFS.JWTSecretBytes = make([]byte, 32)
n, err := base64.RawURLEncoding.Decode(LFS.JWTSecretBytes, []byte(LFS.JWTSecretBase64))
if (err != nil || n != 32) && InstallLock {
LFS.JWTSecretBase64, err = generate.NewJwtSecretBase64()
LFS.JWTSecretBytes, err = util.Base64FixedDecode(base64.RawURLEncoding, []byte(LFS.JWTSecretBase64), 32)
if err != nil {
LFS.JWTSecretBytes, LFS.JWTSecretBase64, err = generate.NewJwtSecretBase64()
if err != nil {
return fmt.Errorf("error generating JWT Secret for custom config: %v", err)
}
+1 -1
View File
@@ -165,7 +165,7 @@ func loadLogModeByName(rootCfg ConfigProvider, loggerName, modeName string) (wri
writerMode.WriterOption = writerOption
default:
if !log.HasEventWriter(writerType) {
return "", "", writerMode, fmt.Errorf("invalid log writer type (mode): %s", writerType)
return "", "", writerMode, fmt.Errorf("invalid log writer type (mode): %s, maybe it needs something like 'MODE=file' in [log.%s] section", writerType, modeName)
}
}
+8 -7
View File
@@ -10,6 +10,7 @@ import (
"code.gitea.io/gitea/modules/generate"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util"
)
// OAuth2UsernameType is enum describing the way gitea 'name' should be generated from oauth2 data
@@ -100,6 +101,7 @@ var OAuth2 = struct {
JWTSecretBase64 string `ini:"JWT_SECRET"`
JWTSigningPrivateKeyFile string `ini:"JWT_SIGNING_PRIVATE_KEY_FILE"`
MaxTokenLength int
DefaultApplications []string
}{
Enable: true,
AccessTokenExpirationTime: 3600,
@@ -108,6 +110,7 @@ var OAuth2 = struct {
JWTSigningAlgorithm: "RS256",
JWTSigningPrivateKeyFile: "jwt/private.pem",
MaxTokenLength: math.MaxInt16,
DefaultApplications: []string{"git-credential-oauth", "git-credential-manager"},
}
func loadOAuth2From(rootCfg ConfigProvider) {
@@ -127,21 +130,19 @@ func loadOAuth2From(rootCfg ConfigProvider) {
}
if InstallLock {
key := make([]byte, 32)
n, err := base64.RawURLEncoding.Decode(key, []byte(OAuth2.JWTSecretBase64))
if err != nil || n != 32 {
key, err = generate.NewJwtSecret()
if _, err := util.Base64FixedDecode(base64.RawURLEncoding, []byte(OAuth2.JWTSecretBase64), 32); err != nil {
key, err := generate.NewJwtSecret()
if err != nil {
log.Fatal("error generating JWT secret: %v", err)
}
secretBase64 := base64.RawURLEncoding.EncodeToString(key)
OAuth2.JWTSecretBase64 = base64.RawURLEncoding.EncodeToString(key)
saveCfg, err := rootCfg.PrepareSaving()
if err != nil {
log.Fatal("save oauth2.JWT_SECRET failed: %v", err)
}
rootCfg.Section("oauth2").Key("JWT_SECRET").SetValue(secretBase64)
saveCfg.Section("oauth2").Key("JWT_SECRET").SetValue(secretBase64)
rootCfg.Section("oauth2").Key("JWT_SECRET").SetValue(OAuth2.JWTSecretBase64)
saveCfg.Section("oauth2").Key("JWT_SECRET").SetValue(OAuth2.JWTSecretBase64)
if err := saveCfg.Save(); err != nil {
log.Fatal("save oauth2.JWT_SECRET failed: %v", err)
}
+1 -1
View File
@@ -124,7 +124,7 @@ func loadSecurityFrom(rootCfg ConfigProvider) {
ReverseProxyTrustedProxies = []string{"127.0.0.0/8", "::1/128"}
}
MinPasswordLength = sec.Key("MIN_PASSWORD_LENGTH").MustInt(6)
MinPasswordLength = sec.Key("MIN_PASSWORD_LENGTH").MustInt(8)
ImportLocalPaths = sec.Key("IMPORT_LOCAL_PATHS").MustBool(false)
DisableGitHooks = sec.Key("DISABLE_GIT_HOOKS").MustBool(true)
DisableWebhooks = sec.Key("DISABLE_WEBHOOKS").MustBool(false)
+26 -6
View File
@@ -73,6 +73,7 @@ var Service = struct {
AllowCrossRepositoryDependencies bool
DefaultAllowOnlyContributorsToTrackTime bool
NoReplyAddress string
UserLocationMapURL string
EnableUserHeatmap bool
AutoWatchNewRepos bool
AutoWatchOnChanges bool
@@ -185,18 +186,37 @@ func loadServiceFrom(rootCfg ConfigProvider) {
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)
Service.DefaultUserVisibility = sec.Key("DEFAULT_USER_VISIBILITY").In("public", structs.ExtractKeysFromMapString(structs.VisibilityModes))
Service.DefaultUserVisibilityMode = structs.VisibilityModes[Service.DefaultUserVisibility]
Service.AllowedUserVisibilityModes = sec.Key("ALLOWED_USER_VISIBILITY_MODES").Strings(",")
if len(Service.AllowedUserVisibilityModes) != 0 {
modes := sec.Key("ALLOWED_USER_VISIBILITY_MODES").Strings(",")
if len(modes) != 0 {
Service.AllowedUserVisibilityModes = []string{}
Service.AllowedUserVisibilityModesSlice = []bool{false, false, false}
for _, sMode := range Service.AllowedUserVisibilityModes {
Service.AllowedUserVisibilityModesSlice[structs.VisibilityModes[sMode]] = true
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()
+86
View File
@@ -6,6 +6,8 @@ package setting
import (
"testing"
"code.gitea.io/gitea/modules/structs"
"github.com/gobwas/glob"
"github.com/stretchr/testify/assert"
)
@@ -44,3 +46,87 @@ EMAIL_DOMAIN_BLOCKLIST = d3, *.b
assert.True(t, match(Service.EmailDomainBlockList, "foo.b"))
assert.False(t, match(Service.EmailDomainBlockList, "d1"))
}
func TestLoadServiceVisibilityModes(t *testing.T) {
oldService := Service
defer func() {
Service = oldService
}()
kases := map[string]func(){
`
[service]
DEFAULT_USER_VISIBILITY = public
ALLOWED_USER_VISIBILITY_MODES = public,limited,private
`: func() {
assert.Equal(t, "public", Service.DefaultUserVisibility)
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
assert.Equal(t, []string{"public", "limited", "private"}, Service.AllowedUserVisibilityModes)
},
`
[service]
DEFAULT_USER_VISIBILITY = public
`: func() {
assert.Equal(t, "public", Service.DefaultUserVisibility)
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
assert.Equal(t, []string{"public", "limited", "private"}, Service.AllowedUserVisibilityModes)
},
`
[service]
DEFAULT_USER_VISIBILITY = limited
`: func() {
assert.Equal(t, "limited", Service.DefaultUserVisibility)
assert.Equal(t, structs.VisibleTypeLimited, Service.DefaultUserVisibilityMode)
assert.Equal(t, []string{"public", "limited", "private"}, Service.AllowedUserVisibilityModes)
},
`
[service]
ALLOWED_USER_VISIBILITY_MODES = public,limited,private
`: func() {
assert.Equal(t, "public", Service.DefaultUserVisibility)
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
assert.Equal(t, []string{"public", "limited", "private"}, Service.AllowedUserVisibilityModes)
},
`
[service]
DEFAULT_USER_VISIBILITY = public
ALLOWED_USER_VISIBILITY_MODES = limited,private
`: func() {
assert.Equal(t, "limited", Service.DefaultUserVisibility)
assert.Equal(t, structs.VisibleTypeLimited, Service.DefaultUserVisibilityMode)
assert.Equal(t, []string{"limited", "private"}, Service.AllowedUserVisibilityModes)
},
`
[service]
DEFAULT_USER_VISIBILITY = my_type
ALLOWED_USER_VISIBILITY_MODES = limited,private
`: func() {
assert.Equal(t, "limited", Service.DefaultUserVisibility)
assert.Equal(t, structs.VisibleTypeLimited, Service.DefaultUserVisibilityMode)
assert.Equal(t, []string{"limited", "private"}, Service.AllowedUserVisibilityModes)
},
`
[service]
DEFAULT_USER_VISIBILITY = public
ALLOWED_USER_VISIBILITY_MODES = public, limit, privated
`: func() {
assert.Equal(t, "public", Service.DefaultUserVisibility)
assert.Equal(t, structs.VisibleTypePublic, Service.DefaultUserVisibilityMode)
assert.Equal(t, []string{"public"}, Service.AllowedUserVisibilityModes)
},
}
for kase, fun := range kases {
t.Run(kase, func(t *testing.T) {
cfg, err := NewConfigProviderFromData(kase)
assert.NoError(t, err)
loadServiceFrom(cfg)
fun()
// reset
Service.AllowedUserVisibilityModesSlice = []bool{true, true, true}
Service.AllowedUserVisibilityModes = []string{}
Service.DefaultUserVisibility = ""
Service.DefaultUserVisibilityMode = structs.VisibleTypePublic
})
}
}
+150 -73
View File
@@ -84,102 +84,179 @@ func getDefaultStorageSection(rootCfg ConfigProvider) ConfigSection {
return storageSec
}
// getStorage will find target section and extra special section first and then read override
// items from extra section
func getStorage(rootCfg ConfigProvider, name, typ string, sec ConfigSection) (*Storage, error) {
if name == "" {
return nil, errors.New("no name for storage")
}
var targetSec ConfigSection
if typ != "" {
var err error
targetSec, err = rootCfg.GetSection(storageSectionName + "." + typ)
if err != nil {
if !IsValidStorageType(StorageType(typ)) {
return nil, fmt.Errorf("get section via storage type %q failed: %v", typ, err)
}
}
if targetSec != nil {
targetType := targetSec.Key("STORAGE_TYPE").String()
if targetType == "" {
if !IsValidStorageType(StorageType(typ)) {
return nil, fmt.Errorf("unknow storage type %q", typ)
}
targetSec.Key("STORAGE_TYPE").SetValue(typ)
} else if !IsValidStorageType(StorageType(targetType)) {
return nil, fmt.Errorf("unknow storage type %q for section storage.%v", targetType, typ)
}
}
targetSec, tp, err := getStorageTargetSection(rootCfg, name, typ, sec)
if err != nil {
return nil, err
}
storageNameSec, _ := rootCfg.GetSection(storageSectionName + "." + name)
overrideSec := getStorageOverrideSection(rootCfg, targetSec, sec, tp, name)
if targetSec == nil {
targetSec = sec
targetType := targetSec.Key("STORAGE_TYPE").String()
switch targetType {
case string(LocalStorageType):
return getStorageForLocal(targetSec, overrideSec, tp, name)
case string(MinioStorageType):
return getStorageForMinio(targetSec, overrideSec, tp, name)
default:
return nil, fmt.Errorf("unsupported storage type %q", targetType)
}
if targetSec == nil {
targetSec = storageNameSec
}
if targetSec == nil {
targetSec = getDefaultStorageSection(rootCfg)
} else {
targetType := targetSec.Key("STORAGE_TYPE").String()
switch {
case targetType == "":
if targetSec.Key("PATH").String() == "" {
targetSec = getDefaultStorageSection(rootCfg)
} else {
targetSec.Key("STORAGE_TYPE").SetValue("local")
}
default:
newTargetSec, _ := rootCfg.GetSection(storageSectionName + "." + targetType)
if newTargetSec == nil {
if !IsValidStorageType(StorageType(targetType)) {
return nil, fmt.Errorf("invalid storage section %s.%q", storageSectionName, targetType)
}
} else {
targetSec = newTargetSec
if IsValidStorageType(StorageType(targetType)) {
tp := targetSec.Key("STORAGE_TYPE").String()
if tp == "" {
targetSec.Key("STORAGE_TYPE").SetValue(targetType)
}
}
}
}
type targetSecType int
const (
targetSecIsTyp targetSecType = iota // target section is [storage.type] which the type from parameter
targetSecIsStorage // target section is [storage]
targetSecIsDefault // target section is the default value
targetSecIsStorageWithName // target section is [storage.name]
targetSecIsSec // target section is from the name seciont [name]
)
func getStorageSectionByType(rootCfg ConfigProvider, typ string) (ConfigSection, targetSecType, error) {
targetSec, err := rootCfg.GetSection(storageSectionName + "." + typ)
if err != nil {
if !IsValidStorageType(StorageType(typ)) {
return nil, 0, fmt.Errorf("get section via storage type %q failed: %v", typ, err)
}
// if typ is a valid storage type, but there is no [storage.local] or [storage.minio] section
// it's not an error
return nil, 0, nil
}
targetType := targetSec.Key("STORAGE_TYPE").String()
if !IsValidStorageType(StorageType(targetType)) {
return nil, fmt.Errorf("invalid storage type %q", targetType)
if targetType == "" {
if !IsValidStorageType(StorageType(typ)) {
return nil, 0, fmt.Errorf("unknow storage type %q", typ)
}
targetSec.Key("STORAGE_TYPE").SetValue(typ)
} else if !IsValidStorageType(StorageType(targetType)) {
return nil, 0, fmt.Errorf("unknow storage type %q for section storage.%v", targetType, typ)
}
var storage Storage
storage.Type = StorageType(targetType)
return targetSec, targetSecIsTyp, nil
}
switch targetType {
case string(LocalStorageType):
storage.Path = ConfigSectionKeyString(targetSec, "PATH", filepath.Join(AppDataPath, name))
if !filepath.IsAbs(storage.Path) {
storage.Path = filepath.Join(AppWorkPath, storage.Path)
func getStorageTargetSection(rootCfg ConfigProvider, name, typ string, sec ConfigSection) (ConfigSection, targetSecType, error) {
// check typ first
if typ == "" {
if sec != nil { // check sec's type secondly
typ = sec.Key("STORAGE_TYPE").String()
if IsValidStorageType(StorageType(typ)) {
if targetSec, _ := rootCfg.GetSection(storageSectionName + "." + typ); targetSec == nil {
return sec, targetSecIsSec, nil
}
}
}
case string(MinioStorageType):
storage.MinioConfig.BasePath = name + "/"
}
if err := targetSec.MapTo(&storage.MinioConfig); err != nil {
return nil, fmt.Errorf("map minio config failed: %v", err)
if typ != "" {
targetSec, tp, err := getStorageSectionByType(rootCfg, typ)
if targetSec != nil || err != nil {
return targetSec, tp, err
}
// extra config section will be read SERVE_DIRECT, PATH, MINIO_BASE_PATH to override the targetsec
extraConfigSec := sec
if extraConfigSec == nil {
extraConfigSec = storageNameSec
}
// check stoarge name thirdly
targetSec, _ := rootCfg.GetSection(storageSectionName + "." + name)
if targetSec != nil {
targetType := targetSec.Key("STORAGE_TYPE").String()
switch {
case targetType == "":
if targetSec.Key("PATH").String() == "" { // both storage type and path are empty, use default
return getDefaultStorageSection(rootCfg), targetSecIsDefault, nil
}
targetSec.Key("STORAGE_TYPE").SetValue("local")
default:
targetSec, tp, err := getStorageSectionByType(rootCfg, targetType)
if targetSec != nil || err != nil {
return targetSec, tp, err
}
}
if extraConfigSec != nil {
storage.MinioConfig.ServeDirect = ConfigSectionKeyBool(extraConfigSec, "SERVE_DIRECT", storage.MinioConfig.ServeDirect)
storage.MinioConfig.BasePath = ConfigSectionKeyString(extraConfigSec, "MINIO_BASE_PATH", storage.MinioConfig.BasePath)
storage.MinioConfig.Bucket = ConfigSectionKeyString(extraConfigSec, "MINIO_BUCKET", storage.MinioConfig.Bucket)
return targetSec, targetSecIsStorageWithName, nil
}
return getDefaultStorageSection(rootCfg), targetSecIsDefault, nil
}
// getStorageOverrideSection override section will be read SERVE_DIRECT, PATH, MINIO_BASE_PATH, MINIO_BUCKET to override the targetsec when possible
func getStorageOverrideSection(rootConfig ConfigProvider, targetSec, sec ConfigSection, targetSecType targetSecType, name string) ConfigSection {
if targetSecType == targetSecIsSec {
return nil
}
if sec != nil {
return sec
}
if targetSecType != targetSecIsStorageWithName {
nameSec, _ := rootConfig.GetSection(storageSectionName + "." + name)
return nameSec
}
return nil
}
func getStorageForLocal(targetSec, overrideSec ConfigSection, tp targetSecType, name string) (*Storage, error) {
storage := Storage{
Type: StorageType(targetSec.Key("STORAGE_TYPE").String()),
}
targetPath := ConfigSectionKeyString(targetSec, "PATH", "")
var fallbackPath string
if targetPath == "" { // no path
fallbackPath = filepath.Join(AppDataPath, name)
} else {
if tp == targetSecIsStorage || tp == targetSecIsDefault {
fallbackPath = filepath.Join(targetPath, name)
} else {
fallbackPath = targetPath
}
if !filepath.IsAbs(fallbackPath) {
fallbackPath = filepath.Join(AppDataPath, fallbackPath)
}
}
if overrideSec == nil { // no override section
storage.Path = fallbackPath
} else {
storage.Path = ConfigSectionKeyString(overrideSec, "PATH", "")
if storage.Path == "" { // overrideSec has no path
storage.Path = fallbackPath
} else if !filepath.IsAbs(storage.Path) {
if targetPath == "" {
storage.Path = filepath.Join(AppDataPath, storage.Path)
} else {
storage.Path = filepath.Join(targetPath, storage.Path)
}
}
}
return &storage, nil
}
func getStorageForMinio(targetSec, overrideSec ConfigSection, tp targetSecType, name string) (*Storage, error) {
var storage Storage
storage.Type = StorageType(targetSec.Key("STORAGE_TYPE").String())
if err := targetSec.MapTo(&storage.MinioConfig); err != nil {
return nil, fmt.Errorf("map minio config failed: %v", err)
}
if storage.MinioConfig.BasePath == "" {
storage.MinioConfig.BasePath = name + "/"
}
if overrideSec != nil {
storage.MinioConfig.ServeDirect = ConfigSectionKeyBool(overrideSec, "SERVE_DIRECT", storage.MinioConfig.ServeDirect)
storage.MinioConfig.BasePath = ConfigSectionKeyString(overrideSec, "MINIO_BASE_PATH", storage.MinioConfig.BasePath)
storage.MinioConfig.Bucket = ConfigSectionKeyString(overrideSec, "MINIO_BUCKET", storage.MinioConfig.Bucket)
}
return &storage, nil
}
+322
View File
@@ -4,6 +4,7 @@
package setting
import (
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
@@ -26,12 +27,15 @@ MINIO_BUCKET = gitea-storage
assert.NoError(t, loadAttachmentFrom(cfg))
assert.EqualValues(t, "gitea-attachment", Attachment.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "attachments/", Attachment.Storage.MinioConfig.BasePath)
assert.NoError(t, loadLFSFrom(cfg))
assert.EqualValues(t, "gitea-lfs", LFS.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "lfs/", LFS.Storage.MinioConfig.BasePath)
assert.NoError(t, loadAvatarsFrom(cfg))
assert.EqualValues(t, "gitea-storage", Avatar.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "avatars/", Avatar.Storage.MinioConfig.BasePath)
}
func Test_getStorageUseOtherNameAsType(t *testing.T) {
@@ -48,9 +52,11 @@ MINIO_BUCKET = gitea-storage
assert.NoError(t, loadAttachmentFrom(cfg))
assert.EqualValues(t, "gitea-storage", Attachment.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "attachments/", Attachment.Storage.MinioConfig.BasePath)
assert.NoError(t, loadLFSFrom(cfg))
assert.EqualValues(t, "gitea-storage", LFS.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "lfs/", LFS.Storage.MinioConfig.BasePath)
}
func Test_getStorageInheritStorageType(t *testing.T) {
@@ -90,3 +96,319 @@ STORAGE_TYPE = minio
assert.EqualValues(t, "gitea", RepoAvatar.Storage.MinioConfig.Bucket)
assert.EqualValues(t, "repo-avatars/", RepoAvatar.Storage.MinioConfig.BasePath)
}
type testLocalStoragePathCase struct {
loader func(rootCfg ConfigProvider) error
storagePtr **Storage
expectedPath string
}
func testLocalStoragePath(t *testing.T, appDataPath, iniStr string, cases []testLocalStoragePathCase) {
cfg, err := NewConfigProviderFromData(iniStr)
assert.NoError(t, err)
AppDataPath = appDataPath
for _, c := range cases {
assert.NoError(t, c.loader(cfg))
storage := *c.storagePtr
assert.EqualValues(t, "local", storage.Type)
assert.True(t, filepath.IsAbs(storage.Path))
assert.EqualValues(t, filepath.Clean(c.expectedPath), filepath.Clean(storage.Path))
}
}
func Test_getStorageInheritStorageTypeLocal(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage]
STORAGE_TYPE = local
`, []testLocalStoragePathCase{
{loadAttachmentFrom, &Attachment.Storage, "/appdata/attachments"},
{loadLFSFrom, &LFS.Storage, "/appdata/lfs"},
{loadActionsFrom, &Actions.ArtifactStorage, "/appdata/actions_artifacts"},
{loadPackagesFrom, &Packages.Storage, "/appdata/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/repo-archive"},
{loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/appdata/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalPath(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage]
STORAGE_TYPE = local
PATH = /data/gitea
`, []testLocalStoragePathCase{
{loadAttachmentFrom, &Attachment.Storage, "/data/gitea/attachments"},
{loadLFSFrom, &LFS.Storage, "/data/gitea/lfs"},
{loadActionsFrom, &Actions.ArtifactStorage, "/data/gitea/actions_artifacts"},
{loadPackagesFrom, &Packages.Storage, "/data/gitea/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/repo-archive"},
{loadActionsFrom, &Actions.LogStorage, "/data/gitea/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/data/gitea/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/data/gitea/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalRelativePath(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage]
STORAGE_TYPE = local
PATH = storages
`, []testLocalStoragePathCase{
{loadAttachmentFrom, &Attachment.Storage, "/appdata/storages/attachments"},
{loadLFSFrom, &LFS.Storage, "/appdata/storages/lfs"},
{loadActionsFrom, &Actions.ArtifactStorage, "/appdata/storages/actions_artifacts"},
{loadPackagesFrom, &Packages.Storage, "/appdata/storages/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/storages/repo-archive"},
{loadActionsFrom, &Actions.LogStorage, "/appdata/storages/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/appdata/storages/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/storages/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalPathOverride(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage]
STORAGE_TYPE = local
PATH = /data/gitea
[repo-archive]
PATH = /data/gitea/the-archives-dir
`, []testLocalStoragePathCase{
{loadAttachmentFrom, &Attachment.Storage, "/data/gitea/attachments"},
{loadLFSFrom, &LFS.Storage, "/data/gitea/lfs"},
{loadActionsFrom, &Actions.ArtifactStorage, "/data/gitea/actions_artifacts"},
{loadPackagesFrom, &Packages.Storage, "/data/gitea/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/the-archives-dir"},
{loadActionsFrom, &Actions.LogStorage, "/data/gitea/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/data/gitea/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/data/gitea/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalPathOverrideEmpty(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage]
STORAGE_TYPE = local
PATH = /data/gitea
[repo-archive]
`, []testLocalStoragePathCase{
{loadAttachmentFrom, &Attachment.Storage, "/data/gitea/attachments"},
{loadLFSFrom, &LFS.Storage, "/data/gitea/lfs"},
{loadActionsFrom, &Actions.ArtifactStorage, "/data/gitea/actions_artifacts"},
{loadPackagesFrom, &Packages.Storage, "/data/gitea/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/repo-archive"},
{loadActionsFrom, &Actions.LogStorage, "/data/gitea/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/data/gitea/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/data/gitea/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalRelativePathOverride(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage]
STORAGE_TYPE = local
PATH = /data/gitea
[repo-archive]
PATH = the-archives-dir
`, []testLocalStoragePathCase{
{loadAttachmentFrom, &Attachment.Storage, "/data/gitea/attachments"},
{loadLFSFrom, &LFS.Storage, "/data/gitea/lfs"},
{loadActionsFrom, &Actions.ArtifactStorage, "/data/gitea/actions_artifacts"},
{loadPackagesFrom, &Packages.Storage, "/data/gitea/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/the-archives-dir"},
{loadActionsFrom, &Actions.LogStorage, "/data/gitea/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/data/gitea/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/data/gitea/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalPathOverride3(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage.repo-archive]
STORAGE_TYPE = local
PATH = /data/gitea/archives
`, []testLocalStoragePathCase{
{loadAttachmentFrom, &Attachment.Storage, "/appdata/attachments"},
{loadLFSFrom, &LFS.Storage, "/appdata/lfs"},
{loadActionsFrom, &Actions.ArtifactStorage, "/appdata/actions_artifacts"},
{loadPackagesFrom, &Packages.Storage, "/appdata/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/archives"},
{loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/appdata/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalPathOverride3_5(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage.repo-archive]
STORAGE_TYPE = local
PATH = a-relative-path
`, []testLocalStoragePathCase{
{loadAttachmentFrom, &Attachment.Storage, "/appdata/attachments"},
{loadLFSFrom, &LFS.Storage, "/appdata/lfs"},
{loadActionsFrom, &Actions.ArtifactStorage, "/appdata/actions_artifacts"},
{loadPackagesFrom, &Packages.Storage, "/appdata/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/a-relative-path"},
{loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/appdata/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalPathOverride4(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage.repo-archive]
STORAGE_TYPE = local
PATH = /data/gitea/archives
[repo-archive]
PATH = /tmp/gitea/archives
`, []testLocalStoragePathCase{
{loadAttachmentFrom, &Attachment.Storage, "/appdata/attachments"},
{loadLFSFrom, &LFS.Storage, "/appdata/lfs"},
{loadActionsFrom, &Actions.ArtifactStorage, "/appdata/actions_artifacts"},
{loadPackagesFrom, &Packages.Storage, "/appdata/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/tmp/gitea/archives"},
{loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/appdata/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalPathOverride5(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage.repo-archive]
STORAGE_TYPE = local
PATH = /data/gitea/archives
[repo-archive]
`, []testLocalStoragePathCase{
{loadAttachmentFrom, &Attachment.Storage, "/appdata/attachments"},
{loadLFSFrom, &LFS.Storage, "/appdata/lfs"},
{loadActionsFrom, &Actions.ArtifactStorage, "/appdata/actions_artifacts"},
{loadPackagesFrom, &Packages.Storage, "/appdata/packages"},
{loadRepoArchiveFrom, &RepoArchive.Storage, "/data/gitea/archives"},
{loadActionsFrom, &Actions.LogStorage, "/appdata/actions_log"},
{loadAvatarsFrom, &Avatar.Storage, "/appdata/avatars"},
{loadRepoAvatarFrom, &RepoAvatar.Storage, "/appdata/repo-avatars"},
})
}
func Test_getStorageInheritStorageTypeLocalPathOverride72(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[repo-archive]
STORAGE_TYPE = local
PATH = archives
`, []testLocalStoragePathCase{
{loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/archives"},
})
}
func Test_getStorageConfiguration20(t *testing.T) {
cfg, err := NewConfigProviderFromData(`
[repo-archive]
STORAGE_TYPE = my_storage
PATH = archives
`)
assert.NoError(t, err)
assert.Error(t, loadRepoArchiveFrom(cfg))
}
func Test_getStorageConfiguration21(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage.repo-archive]
`, []testLocalStoragePathCase{
{loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/repo-archive"},
})
}
func Test_getStorageConfiguration22(t *testing.T) {
testLocalStoragePath(t, "/appdata", `
[storage.repo-archive]
PATH = archives
`, []testLocalStoragePathCase{
{loadRepoArchiveFrom, &RepoArchive.Storage, "/appdata/archives"},
})
}
func Test_getStorageConfiguration23(t *testing.T) {
cfg, err := NewConfigProviderFromData(`
[repo-archive]
STORAGE_TYPE = minio
MINIO_ACCESS_KEY_ID = my_access_key
MINIO_SECRET_ACCESS_KEY = my_secret_key
`)
assert.NoError(t, err)
_, err = getStorage(cfg, "", "", nil)
assert.Error(t, err)
assert.NoError(t, loadRepoArchiveFrom(cfg))
cp := RepoArchive.Storage.ToShadowCopy()
assert.EqualValues(t, "******", cp.MinioConfig.AccessKeyID)
assert.EqualValues(t, "******", cp.MinioConfig.SecretAccessKey)
}
func Test_getStorageConfiguration24(t *testing.T) {
cfg, err := NewConfigProviderFromData(`
[repo-archive]
STORAGE_TYPE = my_archive
[storage.my_archive]
; unsupported, storage type should be defined explicitly
PATH = archives
`)
assert.NoError(t, err)
assert.Error(t, loadRepoArchiveFrom(cfg))
}
func Test_getStorageConfiguration25(t *testing.T) {
cfg, err := NewConfigProviderFromData(`
[repo-archive]
STORAGE_TYPE = my_archive
[storage.my_archive]
; unsupported, storage type should be known type
STORAGE_TYPE = unknown // should be local or minio
PATH = archives
`)
assert.NoError(t, err)
assert.Error(t, loadRepoArchiveFrom(cfg))
}
func Test_getStorageConfiguration26(t *testing.T) {
cfg, err := NewConfigProviderFromData(`
[repo-archive]
STORAGE_TYPE = minio
MINIO_ACCESS_KEY_ID = my_access_key
MINIO_SECRET_ACCESS_KEY = my_secret_key
; wrong configuration
MINIO_USE_SSL = abc
`)
assert.NoError(t, err)
// assert.Error(t, loadRepoArchiveFrom(cfg))
// FIXME: this should return error but now ini package's MapTo() doesn't check type
assert.NoError(t, loadRepoArchiveFrom(cfg))
}
func Test_getStorageConfiguration27(t *testing.T) {
cfg, err := NewConfigProviderFromData(`
[storage.repo-archive]
STORAGE_TYPE = minio
MINIO_ACCESS_KEY_ID = my_access_key
MINIO_SECRET_ACCESS_KEY = my_secret_key
MINIO_USE_SSL = true
`)
assert.NoError(t, err)
assert.NoError(t, loadRepoArchiveFrom(cfg))
assert.EqualValues(t, "my_access_key", RepoArchive.Storage.MinioConfig.AccessKeyID)
assert.EqualValues(t, "my_secret_key", RepoArchive.Storage.MinioConfig.SecretAccessKey)
assert.EqualValues(t, true, RepoArchive.Storage.MinioConfig.UseSSL)
assert.EqualValues(t, "repo-archive/", RepoArchive.Storage.MinioConfig.BasePath)
}