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.
Let instance admins create bot accounts from the web UI
8c72543b9ef4ac728740a6f0b3a649f9c3102e7a · Keenan Nemetz · 5d ago · parent f422c24f
Let instance admins create bot accounts from the web UI The Accounts page could only invite a person with an enrollment link. A bot has no browser sign-in, so it needs an SSH key at creation instead. Add a bot form that reuses identity.CreateBot, keep admin out of its role picker, and hide the enrollment action on a bot's account page.
server/web/rolepicker.go +22−3
| @@ -20,6 +20,20 @@ var instanceRoleOptions = []roleOption{ | |||
| 20 | 20 | {"admin", "admin", "full admin on every repository, including private ones"}, | |
| 21 | 21 | } | |
| 22 | 22 | ||
| 23 | // botRoleOptions is the instance-role list without admin. It is derived so a | ||
| 24 | // wording change to an instance role reaches both pickers. | ||
| 25 | var botRoleOptions = withoutAdminRole(instanceRoleOptions) | ||
| 26 | |||
| 27 | func withoutAdminRole(options []roleOption) []roleOption { | ||
| 28 | kept := make([]roleOption, 0, len(options)) | ||
| 29 | for _, opt := range options { | ||
| 30 | if opt.Value != "admin" { | ||
| 31 | kept = append(kept, opt) | ||
| 32 | } | ||
| 33 | } | ||
| 34 | return kept | ||
| 35 | } | ||
| 36 | |||
| 23 | 37 | var repoRoleOptions = []roleOption{ | |
| 24 | 38 | {"none", "none", "no repository-specific entry"}, | |
| 25 | 39 | {"read", "read", "clone, fetch, and browse"}, | |
| @@ -39,12 +53,17 @@ type rolePickerData struct { | |||
| 39 | 53 | ||
| 40 | 54 | // newRolePicker is the one role-selection control. scope chooses the wording: | |
| 41 | 55 | // instance roles apply to public repositories, while repository roles describe | |
| 42 | // what the entry grants in one repository. compact is for table rows, where the | ||
| 43 | // descriptions live in the radio's accessible label rather than on screen. | ||
| 56 | // what the entry grants in one repository. A bot may hold an instance role but | ||
| 57 | // cannot be an instance admin, so its scope leaves that option out. compact is | ||
| 58 | // for table rows, where the descriptions live in the radio's accessible label | ||
| 59 | // rather than on screen. | ||
| 44 | 60 | func newRolePicker(name, selected, legend, help, scope string, compact bool) rolePickerData { | |
| 45 | 61 | options := instanceRoleOptions | |
| 46 | if scope == "repo" { | ||
| 62 | switch scope { | ||
| 63 | case "repo": | ||
| 47 | 64 | options = repoRoleOptions | |
| 65 | case "bot": | ||
| 66 | options = botRoleOptions | ||
| 48 | 67 | } | |
| 49 | 68 | return rolePickerData{ | |
| 50 | 69 | Name: name, Selected: selected, Legend: legend, Help: help, | |