From 3b7094965139e2cf35e4f99a4ae8faa8f04e734c Mon Sep 17 00:00:00 2001 From: Gergely Nagy Date: Mon, 26 Aug 2024 13:25:34 +0200 Subject: [PATCH] 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 --- models/quota/default.go | 25 ++++++++++++++ models/quota/group.go | 4 +-- modules/setting/quota.go | 9 +++++ tests/integration/quota_use_test.go | 52 +++++++++++++++++++++++++++-- 4 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 models/quota/default.go diff --git a/models/quota/default.go b/models/quota/default.go new file mode 100644 index 000000000..6b553d6f7 --- /dev/null +++ b/models/quota/default.go @@ -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) +} diff --git a/models/quota/group.go b/models/quota/group.go index 045a98ec2..0acb5b255 100644 --- a/models/quota/group.go +++ b/models/quota/group.go @@ -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 { diff --git a/modules/setting/quota.go b/modules/setting/quota.go index 6dfadb59f..05e14baa9 100644 --- a/modules/setting/quota.go +++ b/modules/setting/quota.go @@ -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) { diff --git a/tests/integration/quota_use_test.go b/tests/integration/quota_use_test.go index 06f23c9c2..39c5c1ae5 100644 --- a/tests/integration/quota_use_test.go +++ b/tests/integration/quota_use_test.go @@ -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 }