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:
		
					parent
					
						
							
								190b5a3859
							
						
					
				
			
			
				commit
				
					
						3b70949651
					
				
			
		
					 4 changed files with 86 additions and 4 deletions
				
			
		
							
								
								
									
										25
									
								
								models/quota/default.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								models/quota/default.go
									
										
									
									
									
										Normal 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)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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 {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue