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.

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/templates/admin_users.html +25−5

@@ -3,7 +3,7 @@
3 3 <div class="page-head">
4 4 <div class="page-head-main">
5 5 <h1>Accounts</h1>
6 <p class="page-sub">Enrollment links, keys, sessions, and instance roles. New accounts start with an enrollment link, never a pasted SSH key.</p>
6 <p class="page-sub">Invite people, set their role, and set up automation accounts.</p>
7 7 </div>
8 8 </div>
9 9
@@ -16,7 +16,7 @@
16 16 {{range .Users}}
17 17 <tr>
18 18 <td>
19 <a href="/users/{{.Account.Name}}">{{.Account.Name}}</a>
19 <a href="/users/{{.Account.Name}}">{{.Account.Name}}</a>{{if .Account.Bot}} <span class="state">bot</span>{{end}}
20 20 </td>
21 21 <td><span class="state {{.Account.Status}}">{{.Account.Status}}</span></td>
22 22 <td>{{if .Account.Admin}}<span class="label">instance admin</span>{{else}}<span class="muted">{{.Account.Role}}</span>{{end}}</td>
@@ -29,7 +29,8 @@
29 29 </table>
30 30 </div>
31 31
32 <h2>Create an account</h2>
32 <h2>Invite a person</h2>
33 <p class="muted">Send them a one-time link: they choose a passkey, then can add an SSH key.</p>
33 34 <form method="post" action="/users" class="form-block">
34 35 <input type="hidden" name="csrf" value="{{.CSRF}}">
35 36 <div class="card form-card">
@@ -40,6 +41,21 @@
40 41 </div>
41 42 <div class="form-actions"><button type="submit">{{icon "user"}}Create account</button></div>
42 43 </form>
44
45 <h2>Create a bot account</h2>
46 <p class="muted">For a runner or another automation. It acts with the SSH key you paste here and cannot sign in to the browser or become an instance admin.</p>
47 <form method="post" action="/users/bots" class="form-block">
48 <input type="hidden" name="csrf" value="{{.CSRF}}">
49 <div class="card form-card">
50 <label>Account name
51 <input type="text" name="name" required maxlength="63" autocomplete="off" placeholder="lowercase-name">
52 </label>
53 <label for="bot-public-key">SSH public key</label>
54 <textarea id="bot-public-key" name="key" rows="3" placeholder="ssh-ed25519 AAAA... you@example.com" required></textarea>
55 {{template "role-picker" (rolePicker "role" "none" "Instance role" "Instance roles apply to public repositories. A bot cannot be an instance admin." "bot" false)}}
56 </div>
57 <div class="form-actions"><button type="submit">{{icon "terminal"}}Create bot</button></div>
58 </form>
43 59 {{template "footer" .}}
44 60 {{end}}
45 61
@@ -47,19 +63,21 @@
47 63 {{template "header" .}}
48 64 <div class="page-head">
49 65 <div class="page-head-main">
50 <h1>{{.Account.Name}}</h1>
66 <h1>{{.Account.Name}}{{if .Account.Bot}} <span class="state">bot</span>{{end}}</h1>
51 67 <p class="page-sub">
52 68 <span class="state {{.Account.Status}}">{{.Account.Status}}</span>
53 69 · instance role {{.Account.Role}}
54 70 · created {{since .Account.Created.Unix}}
55 71 </p>
56 72 </div>
73 {{if not .Account.Bot}}
57 74 <div class="page-head-actions">
58 75 <form class="inline" method="post" action="/users/{{.Account.Name}}/invite">
59 76 <input type="hidden" name="csrf" value="{{.CSRF}}">
60 77 <button type="submit" class="secondary">{{icon "external-link"}}New enrollment link</button>
61 78 </form>
62 79 </div>
80 {{end}}
63 81 </div>
64 82
65 83 {{if .Error}}<div class="flash bad">{{.Error}}</div>{{end}}
@@ -69,7 +87,7 @@
69 87 <form method="post" action="/users/{{.Account.Name}}/role" class="form-block">
70 88 <input type="hidden" name="csrf" value="{{.CSRF}}">
71 89 <div class="card form-card">
72 {{template "role-picker" (rolePicker "role" $role (printf "Role for %s" .Account.Name) "Instance roles apply to public repositories. A repository-specific role can grant more on one repository. admin is the exception: it applies to every repository, private ones included." "instance" false)}}
90 {{template "role-picker" (rolePicker "role" $role (printf "Role for %s" .Account.Name) .RoleHelp .RoleScope false)}}
73 91 </div>
74 92 <div class="form-actions">
75 93 <button type="submit">{{icon "check"}}Save role</button>
@@ -99,6 +117,8 @@
99 117 </tbody>
100 118 </table>
101 119 </div>
120 {{else if .Account.Bot}}
121 <p class="muted">No SSH keys. This bot cannot act until a key is added.</p>
102 122 {{else}}
103 123 <p class="muted">No SSH keys. This account can sign in with a passkey only.</p>
104 124 {{end}}