vole
Clone
Read only, no credentials:
https://rodent.software/git/vole.git
Write over SSH with a registered key:
git clone ssh://git@0.0.0.0:2222/vole.git
A free and open-source forge that lives in your Git repo.
Budget only the untrusted write role
e5542ac6b64fa3ebaf62af4831e55996dba45e7e · Keenan Nemetz · 12d 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/ratelimit.go +9−8
| @@ -41,10 +41,11 @@ const ( | |||
| 41 | 41 | registrationsPerAddress = 5 | |
| 42 | 42 | // authLimitWindow is the window every budget above is counted in. | |
| 43 | 43 | authLimitWindow = time.Minute | |
| 44 | // defaultWritesPerHour bounds one account's browser writes (issues, comments, | ||
| 45 | // requests, labels, state changes). A person discussing never comes near it; a | ||
| 46 | // script posting in a loop does. | ||
| 47 | defaultWritesPerHour = 300 | ||
| 44 | // defaultContributorWritesPerHour bounds an untrusted account's browser writes | ||
| 45 | // (issues, comments, requests, labels, state changes). A person discussing never | ||
| 46 | // comes near it; a script posting in a loop does. Trusted roles are not | ||
| 47 | // budgeted at all; see writeBudgeted. | ||
| 48 | defaultContributorWritesPerHour = 300 | ||
| 48 | 49 | // maxLimitKeys bounds the table. Keys are addresses and account names; the | |
| 49 | 50 | // sweep drops the ones whose window has passed, and a table past this size is | |
| 50 | 51 | // cleared rather than grown, because the alternative is memory an anonymous | |
| @@ -114,15 +115,15 @@ type authLimits struct { | |||
| 114 | 115 | beginAccount *rateLimiter | |
| 115 | 116 | finish *rateLimiter | |
| 116 | 117 | register *rateLimiter | |
| 117 | // write bounds one account's repository writes for an hour. It is keyed by the | ||
| 118 | // account rather than the address, because the account is what a write is | ||
| 119 | // attributed to and because one person may use two browsers. | ||
| 118 | // write bounds an untrusted account's repository writes for an hour. It is | ||
| 119 | // keyed by the account rather than the address, because the account is what a | ||
| 120 | // write is attributed to and because one person may use two browsers. | ||
| 120 | 121 | write *rateLimiter | |
| 121 | 122 | } | |
| 122 | 123 | ||
| 123 | 124 | func newAuthLimits(writesPerHour int) authLimits { | |
| 124 | 125 | if writesPerHour <= 0 { | |
| 125 | writesPerHour = defaultWritesPerHour | ||
| 126 | writesPerHour = defaultContributorWritesPerHour | ||
| 126 | 127 | } | |
| 127 | 128 | return authLimits{ | |
| 128 | 129 | beginAddress: newRateLimiter(authBeginsPerAddress, authLimitWindow), | |