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.
Fold admin work into repository settings and a Users page
9579c1f976254fdeb2ec73d4016db5b25c7921c1 · Keenan Nemetz · 14d ago · parent 381d6aac
Fold admin work into repository settings and a Users page Remove the combined /admin tabs. Per-repository access rules now live on the repository's Settings page, visible to instance admins while repository details and the danger zone stay with repository admins. User management moves to /users, linked from the top navigation only for instance admins, and repository creation moves to /repos/new. Align the invite, danger-zone, and settings forms with the shared card-and-actions layout, and make settings section headings consistent.
server/web/templates/admin.html −96
| @@ -1,96 +0,0 @@ | |||
| 1 | {{define "admin"}} | ||
| 2 | {{template "header" .}} | ||
| 3 | {{template "adminhead" .}} | ||
| 4 | <div class="toolbar"> | ||
| 5 | <span class="muted">{{len .Repos}} repositories</span> | ||
| 6 | <a class="button secondary" href="/admin/repos/new">{{icon "plus"}}New repository</a> | ||
| 7 | </div> | ||
| 8 | |||
| 9 | {{if .Repos}} | ||
| 10 | <div class="panel"> | ||
| 11 | <table> | ||
| 12 | <thead><tr><th>Repository</th><th>Visibility</th><th>Default role</th><th>Accounts</th><th>Runners</th><th></th></tr></thead> | ||
| 13 | <tbody> | ||
| 14 | {{range .Repos}} | ||
| 15 | <tr> | ||
| 16 | <td> | ||
| 17 | <a href="/r/{{.Name}}">{{.Name}}</a> | ||
| 18 | {{if .Description}}<div class="muted">{{.Description}}</div>{{end}} | ||
| 19 | </td> | ||
| 20 | <td>{{if .Public}}Public{{else}}Private{{end}}</td> | ||
| 21 | <td><code>{{.Default}}</code></td> | ||
| 22 | <td>{{.Principals}}</td> | ||
| 23 | <td>{{.Runners}}</td> | ||
| 24 | <td><a href="/admin/repos/{{.Name}}/access">Access</a></td> | ||
| 25 | </tr> | ||
| 26 | {{end}} | ||
| 27 | </tbody> | ||
| 28 | </table> | ||
| 29 | </div> | ||
| 30 | {{else}} | ||
| 31 | <p class="muted">No repositories.</p> | ||
| 32 | {{end}} | ||
| 33 | {{template "footer" .}} | ||
| 34 | {{end}} | ||
| 35 | |||
| 36 | {{define "admin_access"}} | ||
| 37 | {{template "header" .}} | ||
| 38 | {{template "adminhead" .}} | ||
| 39 | <div class="page-head subhead"> | ||
| 40 | <div class="page-head-main"> | ||
| 41 | <h1>{{.Name}} access</h1> | ||
| 42 | <p class="page-sub">{{if .Description}}{{.Description}} · {{end}}{{if .Public}}public{{else}}private{{end}} · instance-admin rules</p> | ||
| 43 | </div> | ||
| 44 | </div> | ||
| 45 | |||
| 46 | {{if .Error}}<div class="flash bad">{{.Error}}</div>{{end}} | ||
| 47 | {{if .Saved}}<div class="flash good">Access rules saved.</div>{{end}} | ||
| 48 | |||
| 49 | <form method="post" action="/admin/repos/{{.Name}}/access" class="form-block"> | ||
| 50 | <input type="hidden" name="csrf" value="{{.CSRF}}"> | ||
| 51 | <div class="card form-card"> | ||
| 52 | <label>Default role | ||
| 53 | <select name="default"> | ||
| 54 | {{range .Roles}}<option value="{{.}}"{{if eq . $.Default}} selected{{end}}>{{.}}</option>{{end}} | ||
| 55 | </select> | ||
| 56 | </label> | ||
| 57 | <label>Approvals required | ||
| 58 | <input type="number" name="approvals" min="0" value="{{.Approvals}}"> | ||
| 59 | </label> | ||
| 60 | <label class="acl-check"><input type="checkbox" name="checks"{{if .Checks}} checked{{end}}> Require CI checks before landing a protected branch</label> | ||
| 61 | <label>Protected branches | ||
| 62 | <textarea name="protected" placeholder="refs/heads/main refs/heads/release/*">{{.Protected}}</textarea> | ||
| 63 | </label> | ||
| 64 | </div> | ||
| 65 | |||
| 66 | <h2>Accounts</h2> | ||
| 67 | <p class="muted">Admins can report CI even when they are not listed. A runner's result counts as a check, and naming one also lets them lease jobs for this repository.</p> | ||
| 68 | <div class="panel"> | ||
| 69 | <table class="acl"> | ||
| 70 | <thead><tr><th>Account</th><th>Role</th><th>Runner</th></tr></thead> | ||
| 71 | <tbody> | ||
| 72 | {{range .Rows}}{{$row := .}} | ||
| 73 | <tr> | ||
| 74 | <td> | ||
| 75 | <span>{{.Name}}</span> | ||
| 76 | {{if ne .Status "active"}}<span class="label">{{.Status}}</span>{{end}} | ||
| 77 | </td> | ||
| 78 | <td> | ||
| 79 | <select name="role:{{.Name}}" aria-label="Role for {{.Name}}"> | ||
| 80 | {{range $.Roles}}<option value="{{.}}"{{if eq . $row.Role}} selected{{end}}>{{.}}</option>{{end}} | ||
| 81 | </select> | ||
| 82 | </td> | ||
| 83 | <td><input type="checkbox" name="runner:{{.Name}}" aria-label="Runner for {{.Name}}"{{if .Runner}} checked{{end}}></td> | ||
| 84 | </tr> | ||
| 85 | {{end}} | ||
| 86 | </tbody> | ||
| 87 | </table> | ||
| 88 | </div> | ||
| 89 | |||
| 90 | <div class="form-actions"> | ||
| 91 | <a class="button secondary" href="/admin">Cancel</a> | ||
| 92 | <button type="submit">{{icon "check"}}Save access</button> | ||
| 93 | </div> | ||
| 94 | </form> | ||
| 95 | {{template "footer" .}} | ||
| 96 | {{end}} | ||