Sign in

Search issue titles and bodies, change requests and comments. Private repositories you cannot read are not included.

vole
Clone

Read only, no credentials:

https://rodent.software/vole.git

Write over SSH with a registered key:

git clone ssh://git@rodent.software:2222/vole.git

A free and open-source forge that lives in your Git repo.

Budget only the untrusted write role

e5542ac6b64fa3ebaf62af4831e55996dba45e7e · Keenan Nemetz · 13d ago · parent 9e8cc155

Budget only the untrusted write role

Maintainers and admins are trusted roles: they can already change the
rules, push shared branches and run the instance, so a write budget would
slow their work without bounding anybody who could not do worse. The
budget now applies only below maintain, which is the contribute role and
the read-only accounts that cannot write at all.

The setting is named for what it does: contributor_writes_per_hour. The
role is the effective one on the repository, so an instance-wide
maintainer on a public repository is exempt for the same reason a
repository maintainer is.

server/web/auth_hardening_test.go +24−6

@@ -14,6 +14,7 @@ import (
14 14 "testing"
15 15 "time"
16 16
17 "github.com/rodent-software/vole/forge/access"
17 18 "github.com/rodent-software/vole/forge/config"
18 19 "github.com/rodent-software/vole/forge/identity"
19 20 )
@@ -279,17 +280,16 @@ func TestInviteTokensAreRedactedFromLogs(t *testing.T) {
279 280 }
280 281 }
281 282
282 // TestAccountWritesAreBudgeted: one account's browser writes are budgeted per hour,
283 // and the budget comes from the instance config. A person discussing never reaches
284 // it; a script posting in a loop does.
285 func TestAccountWritesAreBudgeted(t *testing.T) {
283 // TestContributorWritesAreBudgeted: an untrusted account's browser writes are
284 // budgeted per hour, and the budget comes from the instance config.
285 func TestContributorWritesAreBudgeted(t *testing.T) {
286 286 t.Parallel()
287 287 limits := newAuthLimits(2)
288 288 if limits.write.limit != 2 {
289 289 t.Fatalf("write limit = %d, want 2", limits.write.limit)
290 290 }
291 if got := newAuthLimits(0).write.limit; got != defaultWritesPerHour {
292 t.Fatalf("default write limit = %d, want %d", got, defaultWritesPerHour)
291 if got := newAuthLimits(0).write.limit; got != defaultContributorWritesPerHour {
292 t.Fatalf("default write limit = %d, want %d", got, defaultContributorWritesPerHour)
293 293 }
294 294 w := &Web{limits: limits}
295 295 req := httptest.NewRequest("POST", "/r/demo/issues", nil)
@@ -310,3 +310,21 @@ func TestAccountWritesAreBudgeted(t *testing.T) {
310 310 t.Fatal("one account's budget limited another")
311 311 }
312 312 }
313
314 // TestOnlyUntrustedWritesAreBudgeted: maintainers and admins are trusted roles in
315 // the instance's threat model — they can change rules, push shared branches and run
316 // the instance — so the contributor budget does not apply to them.
317 func TestOnlyUntrustedWritesAreBudgeted(t *testing.T) {
318 t.Parallel()
319 for role, want := range map[access.Role]bool{
320 access.None: true,
321 access.Read: true,
322 access.Contribute: true,
323 access.Maintain: false,
324 access.Admin: false,
325 } {
326 if got := writeBudgeted(role); got != want {
327 t.Fatalf("writeBudgeted(%s) = %v, want %v", role, got, want)
328 }
329 }
330 }