Commit 92e025a4f6
92e025a4f688baf87e197921b1f99c3bb76659b4
parent: f3f7422f62
Verified · cmc ci/build: success ci/test: success
cmc <hello@cleberg.net> · 2026-09-12 02:20 UTC
config: refuse a negative max_snippets_per_user
The load-time check that rejects a negative max_repos_per_user or
max_bytes_per_user now covers max_snippets_per_user, which otherwise
read as unlimited. gofmt realigns the two fields after it.
Closes #214
internal/config/config.go
+4 −4
| @@ -180,8 +180,8 @@ type Limits struct { |
| 180 | 180 | // MaxSnippetsPerUser caps snippets an account may own. 0 means |
| 181 | 181 | // unlimited, like MaxReposPerUser. |
| 182 | 182 | MaxSnippetsPerUser int `toml:"max_snippets_per_user"` |
| 183 | | CloneTimeoutSec int `toml:"clone_timeout"` |
| 184 | | SSHAuthRate int `toml:"ssh_auth_rate"` |
| 183 | CloneTimeoutSec int `toml:"clone_timeout"` |
| 184 | SSHAuthRate int `toml:"ssh_auth_rate"` |
| 185 | 185 | // APIRate is sustained JSON-API requests per minute per caller; writes |
| 186 | 186 | // draw on a tenth of it. 0 uses the default. |
| 187 | 187 | APIRate int `toml:"api_rate"` |
| @@ -277,8 +277,8 @@ func (c Config) Validate() error { |
| 277 | 277 | errs = append(errs, fmt.Errorf("registration.pending_expiry %q must be a positive duration such as 168h", c.Registration.PendingExpiry)) |
| 278 | 278 | } |
| 279 | 279 | } |
| 280 | | if c.Limits.MaxReposPerUser < 0 || c.Limits.MaxBytesPerUser < 0 { |
| 281 | | errs = append(errs, errors.New("limits.max_repos_per_user and max_bytes_per_user must not be negative")) |
| 280 | if c.Limits.MaxReposPerUser < 0 || c.Limits.MaxBytesPerUser < 0 || c.Limits.MaxSnippetsPerUser < 0 { |
| 281 | errs = append(errs, errors.New("limits.max_repos_per_user, max_bytes_per_user and max_snippets_per_user must not be negative")) |
| 282 | 282 | } |
| 283 | 283 | if c.SSH.Port < 1 || c.SSH.Port > 65535 { |
| 284 | 284 | errs = append(errs, fmt.Errorf("ssh.port %d out of range", c.SSH.Port)) |
internal/config/config_test.go
+10
| @@ -80,6 +80,16 @@ func TestContradictions(t *testing.T) { |
| 80 | 80 | "[server]\nroot = \"/var/lib/gitbay\"\n", |
| 81 | 81 | "site_url", |
| 82 | 82 | }, |
| 83 | { |
| 84 | "negative repo limit", |
| 85 | minimal + "\n[limits]\nmax_repos_per_user = -1\n", |
| 86 | "must not be negative", |
| 87 | }, |
| 88 | { |
| 89 | "negative snippet limit", |
| 90 | minimal + "\n[limits]\nmax_snippets_per_user = -1\n", |
| 91 | "max_snippets_per_user", |
| 92 | }, |
| 83 | 93 | } |
| 84 | 94 | for _, tc := range cases { |
| 85 | 95 | t.Run(tc.name, func(t *testing.T) { |