feat: Trivial default quota configuration

This adds a new configuration setting: `[quota.default].TOTAL`, which
will be used if no groups are configured for a particular user. The new
option makes it possible to entirely skip configuring quotas via the API
if all that one wants is a total size.

Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
This commit is contained in:
Gergely Nagy 2024-08-26 13:25:34 +02:00
parent 190b5a3859
commit 3b70949651
No known key found for this signature in database
4 changed files with 86 additions and 4 deletions

25
models/quota/default.go Normal file
View file

@ -0,0 +1,25 @@
// Copyright 2024 The Forgejo Authors. All rights reserved.
// SPDX-License-Identifier: MIT
package quota
import (
"code.gitea.io/gitea/modules/setting"
)
func EvaluateDefault(used Used, forSubject LimitSubject) bool {
groups := GroupList{
&Group{
Name: "builtin-default-group",
Rules: []Rule{
{
Name: "builtin-default-rule",
Limit: setting.Quota.Default.Total,
Subjects: LimitSubjects{LimitSubjectSizeAll},
},
},
},
}
return groups.Evaluate(used, forSubject)
}

View file

@ -230,9 +230,9 @@ func (g *Group) Evaluate(used Used, forSubject LimitSubject) (bool, bool) {
}
func (gl *GroupList) Evaluate(used Used, forSubject LimitSubject) bool {
// If there are no groups, default to success:
// If there are no groups, use the configured defaults:
if gl == nil || len(*gl) == 0 {
return true
return EvaluateDefault(used, forSubject)
}
for _, group := range *gl {

View file

@ -7,9 +7,18 @@ package setting
var Quota = struct {
Enabled bool `ini:"ENABLED"`
DefaultGroups []string `ini:"DEFAULT_GROUPS"`
Default struct {
Total int64
} `ini:"quota.default"`
}{
Enabled: false,
DefaultGroups: []string{},
Default: struct {
Total int64
}{
Total: -1,
},
}
func loadQuotaFrom(rootCfg ConfigProvider) {

View file

@ -548,6 +548,42 @@ func TestGitQuotaEnforcement(t *testing.T) {
})
}
func TestQuotaConfigDefault(t *testing.T) {
onGiteaRun(t, func(t *testing.T, u *url.URL) {
env := createQuotaWebEnv(t)
defer env.Cleanup()
t.Run("with config-based default", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
defer test.MockVariableValue(&setting.Quota.Default.Total, 0)()
env.As(t, env.Users.Ungrouped).
With(Context{
Payload: &Payload{
"uid": env.Users.Ungrouped.ID().AsString(),
"repo_name": "quota-config-default",
},
}).
PostToPage("/repo/create").
ExpectStatus(http.StatusRequestEntityTooLarge)
})
t.Run("without config-based default", func(t *testing.T) {
defer tests.PrintCurrentTest(t)()
env.As(t, env.Users.Ungrouped).
With(Context{
Payload: &Payload{
"uid": env.Users.Ungrouped.ID().AsString(),
"repo_name": "quota-config-default",
},
}).
PostToPage("/repo/create").
ExpectStatus(http.StatusSeeOther)
})
})
}
/**********************
* Here be dragons! *
* *
@ -568,6 +604,7 @@ type quotaWebEnv struct {
type quotaWebEnvUsers struct {
Limited quotaWebEnvUser
Contributor quotaWebEnvUser
Ungrouped quotaWebEnvUser
}
type quotaWebEnvOrgs struct {
@ -1005,8 +1042,7 @@ func createQuotaWebEnv(t *testing.T) *quotaWebEnv {
// *** helpers ***
// Create a user, its quota group & rule
makeUser := func(t *testing.T, limit int64) quotaWebEnvUser {
makeUngroupedUser := func(t *testing.T) quotaWebEnvUser {
t.Helper()
user := quotaWebEnvUser{}
@ -1021,6 +1057,16 @@ func createQuotaWebEnv(t *testing.T) *quotaWebEnv {
repo, _, _ := tests.CreateDeclarativeRepoWithOptions(t, user.User, tests.DeclarativeRepoOptions{})
user.Repo = repo
return user
}
// Create a user, its quota group & rule
makeUser := func(t *testing.T, limit int64) quotaWebEnvUser {
t.Helper()
user := makeUngroupedUser(t)
userName := user.User.Name
// Create a quota group for them
group, err := quota_model.CreateGroup(db.DefaultContext, userName)
require.NoError(t, err)
@ -1095,5 +1141,7 @@ func createQuotaWebEnv(t *testing.T) *quotaWebEnv {
env.Orgs.Limited = makeOrg(t, env.Users.Limited.User, int64(0))
env.Orgs.Unlimited = makeOrg(t, env.Users.Limited.User, int64(-1))
env.Users.Ungrouped = makeUngroupedUser(t)
return &env
}