internal/web/templates/account.html
202 lines · 11200 bytes
1{{define "width"}}wide{{end}}
2{{define "title"}}account settings{{end}}
3{{define "content"}}
4<h1>Account settings</h1>
5{{if .Notice}}<p class="error" role="alert">{{.Notice}}</p>{{end}}
6{{if .Message}}<p class="notice" role="status">{{.Message}}</p>{{end}}
7
8<div class="withcol narrow">
9<nav class="sidecol" aria-label="Sections">
10<details class="sidedrop">
11<summary><span class="sideword">Sections</span></summary>
12 <div class="grp"><h2 class="colhead">Sections</h2>
13 <ul>
14 <li><a href="#profile">Profile</a></li>
15 <li><a href="#keys">SSH keys</a></li>
16 <li><a href="#emails">Email addresses</a></li>
17 <li><a href="#pgp">OpenPGP keys</a></li>
18 <li><a href="#notifications">Notifications</a></li>
19 <li><a href="#appearance">Appearance</a></li>
20 <li><a href="#export">Export</a></li>
21 <li><a href="#cli">On the command line</a></li>
22 </ul></div>
23</details>
24</nav>
25<div class="colmain">
26<section id="profile"><h2>Profile</h2>
27<p class="meta">Shown on your profile page, <a href="/{{.Viewer}}">/{{.Viewer}}</a>.</p>
28<form method="post" action="/settings" class="setform stack">
29 <input type="hidden" name="field" value="profile">
30 <label for="p-description">Description</label>
31 <input type="text" id="p-description" name="description" value="{{.Profile.Description}}" placeholder="one line, shown in listings">
32 <label for="p-website">Website</label>
33 <input type="text" id="p-website" name="website" value="{{.Profile.Website}}" placeholder="https://example.org">
34 <label for="p-links">Links</label>
35 <textarea id="p-links" name="links" rows="3" placeholder="one per line: label|https://... or a bare https://... (at most 5)">{{.LinksText}}</textarea>
36 <span class="btngroup"><button type="submit" class="btn">Save profile</button></span>
37</form>
38<h3>About</h3>
39<p class="meta">The longer text below your repositories is a file:
40<code>profile/README.md</code> in <a href="/{{.AboutRepo}}">{{.AboutRepo}}</a>.
41Write it with a push, or edit it here.</p>
42{{if .AboutEdit}}<p><a class="btn" href="{{.AboutEdit}}">Edit {{.Profile.AboutPath}}</a></p>
43{{else}}<form method="post" action="/settings" class="setform">
44 <input type="hidden" name="field" value="profile-repo">
45 <button type="submit" class="btn">Create {{.AboutRepo}}</button>
46</form>{{end}}
47</section>
48
49<section id="keys"><h2>SSH keys</h2>
50<p class="meta">Your keys are your identity here. A <code>full</code> key can run
51commands and push; a <code>git</code> key can only move git data (e.g., CI).</p>
52{{if .Keys}}<div class="tablewrap"><table class="keys nowrap">
53<tr class="cols"><th scope="col">label</th><th scope="col">fingerprint</th><th scope="col">type</th><th scope="col">scope</th><th scope="col"><span class="vh">actions</span></th></tr>
54{{range .Keys}}<tr>
55 <td>{{.Label}}</td>
56 <td class="mono">{{.Fingerprint}}</td>
57 <td>{{.Algo}}</td>
58 <td>{{.Scope}}</td>
59 <td class="act"><form method="post" action="/settings"><input type="hidden" name="field" value="key-remove"><input type="hidden" name="fingerprint" value="{{.Fingerprint}}">{{template "confirmfield" .Confirm}} <button type="submit" class="danger">Remove</button></form></td>
60</tr>
61{{end}}</table></div>
62{{else}}<p class="none">No SSH keys? Which cannot be right, since you signed in.</p>{{end}}
63<details class="editbox">
64 <summary>Add an SSH key</summary>
65 <form method="post" action="/settings" class="setform stack">
66 <input type="hidden" name="field" value="key-add">
67 <label for="key">Public key</label>
68 <textarea id="key" name="key" rows="3" required placeholder="ssh-ed25519 AAAA... you@machine"></textarea>
69 <label for="key-label">Label</label>
70 <input id="key-label" name="label" maxlength="64" placeholder="defaults to the key's comment">
71 <label for="scope">Scope</label>
72 <select id="scope" name="scope">
73 <option value="full">full: commands and git</option>
74 <option value="git">git: git transport only</option>
75 </select>
76 <button type="submit" class="btn">Add key</button>
77 </form>
78</details>
79</section>
80
81<section id="emails"><h2>Email addresses</h2>
82<p class="meta">A verified address ties signed commits to this
83account and where notifications go.</p>
84{{if .Emails}}<ul class="plain">
85{{range .Emails}}<li>{{.Address}}
86 {{if .Primary}}<span class="chip">primary</span>{{end}}
87 {{if .Verified}}<span class="badge badge-verified">verified{{with .VerifiedBy}} · {{.}}{{end}}</span>
88 {{else}}<span class="badge badge-unsigned">unverified</span>{{end}}
89 {{if not .Primary}}{{if .Verified}}<form method="post" action="/settings" class="inline"><input type="hidden" name="field" value="email-primary"><input type="hidden" name="address" value="{{.Address}}"><button type="submit" class="linklike">Make primary</button></form>{{end}}
90 <form method="post" action="/settings" class="inline"><input type="hidden" name="field" value="email-remove"><input type="hidden" name="address" value="{{.Address}}">{{template "confirmfield" .Address}} <button type="submit" class="danger">Remove</button></form>{{end}}</li>
91{{end}}</ul>{{end}}
92<details class="editbox">
93 <summary>Add an address</summary>
94 <form method="post" action="/settings" class="setform">
95 <input type="hidden" name="field" value="email-add">
96 <label for="address">Address</label>
97 <input type="email" id="address" name="address" required placeholder="you@example.org">
98 <button type="submit" class="btn">Send code</button>
99 </form>
100 <form method="post" action="/settings" class="setform">
101 <input type="hidden" name="field" value="email-verify">
102 <label for="code">Verification code</label>
103 <input type="text" id="code" name="code" required placeholder="from the mail">
104 <button type="submit" class="btn">Verify</button>
105 </form>
106</details>
107</section>
108
109<section id="pgp"><h2>OpenPGP keys</h2>
110<p class="meta">Only needed if you sign commits with GPG. SSH signing
111(<code>gpg.format = ssh</code>) uses the keys above.</p>
112{{if .PGP}}<div class="tablewrap"><table class="keys">
113<tr class="cols"><th scope="col">fingerprint</th><th scope="col">identities</th><th scope="col"><span class="vh">actions</span></th></tr>
114{{range .PGP}}<tr>
115 <td class="mono">{{.Fingerprint}}</td>
116 <td>{{range .UIDs}}{{.}}<br>{{end}}{{if .Revoked}}<span class="badge badge-bad_signature">revoked</span>{{else if .Expired}}<span class="badge badge-signed_key_expired">expired</span>{{end}}</td>
117 <td class="act"><form method="post" action="/settings"><input type="hidden" name="field" value="pgp-remove"><input type="hidden" name="fingerprint" value="{{.Fingerprint}}">{{template "confirmfield" .Confirm}} <button type="submit" class="danger">Remove</button></form></td>
118</tr>
119{{end}}</table></div>
120{{else}}<p class="none">No OpenPGP keys.</p>{{end}}
121<details class="editbox">
122 <summary>Add a PGP key</summary>
123 <form method="post" action="/settings" class="setform stack">
124 <input type="hidden" name="field" value="pgp-add">
125 <label for="pgpkey">Armored public key</label>
126 <textarea id="pgpkey" name="key" rows="6" required placeholder="-----BEGIN PGP PUBLIC KEY BLOCK-----"></textarea>
127 <button type="submit" class="btn">Add key</button>
128 </form>
129</details>
130</section>
131
132<section id="notifications"><h2>Notifications</h2>
133<form method="post" action="/settings" class="setform">
134 <input type="hidden" name="field" value="notify-mail">
135 <label for="notify-mail">Activity by mail</label>
136 <input type="checkbox" id="notify-mail" name="mail" value="on"{{if .MailOn}} checked{{end}}>
137 <button type="submit" class="btn">Save</button>
138</form>
139<p class="meta">Enable to receive activity alerts by email. Login links will arrive regardless of this setting.</p>
140<form method="post" action="/settings" class="setform">
141 <input type="hidden" name="field" value="notify-watch">
142 <label for="notify-watch">Watch repositories you can write to</label>
143 <input type="checkbox" id="notify-watch" name="watch" value="on"{{if .WatchOn}} checked{{end}}>
144 <button type="submit" class="btn">Save</button>
145</form>
146<p class="meta">Alerts for every issue and merge request on those repositories. A watch or mute on a repository has priority over this setting.</p>
147<form method="post" action="/settings" class="setform">
148 <input type="hidden" name="field" value="notify-push">
149 <label for="notify-push">Activity on your registered devices</label>
150 <input type="checkbox" id="notify-push" name="push" value="on"{{if .PushOn}} checked{{end}}>
151 <button type="submit" class="btn">Save</button>
152</form>
153<p class="meta">Notification text is sent in full, including for private repositories, so a repository name and item number reach Apple and appear on a lock screen.</p>
154<h3>Devices</h3>
155{{if .Devices}}<div class="tablewrap"><table class="keys nowrap">
156<tr class="cols"><th scope="col">id</th><th scope="col">label</th><th scope="col">token</th><th scope="col">last seen</th><th scope="col"><span class="vh">actions</span></th></tr>
157{{range .Devices}}<tr>
158 <td class="mono">{{.ID}}</td>
159 <td>{{.Label}}</td>
160 <td class="mono">{{.Token}}</td>
161 <td>{{if .LastSeenAt}}{{when .LastSeenAt}}{{else}}never{{end}}</td>
162 <td class="act"><form method="post" action="/settings"><input type="hidden" name="field" value="device-remove"><input type="hidden" name="id" value="{{.ID}}">{{template "confirmfield" .Confirm}} <button type="submit" class="danger">Remove</button></form></td>
163</tr>
164{{end}}</table></div>
165{{else}}<p class="none">No registered devices.</p>{{end}}
166<p class="meta">Devices register themselves from the iOS app; there is no
167form here to add one, since a browser cannot produce an APNs token.</p>
168</section>
169
170<section id="appearance"><h2>Appearance</h2>
171<form method="post" action="/settings" class="setform">
172 <input type="hidden" name="field" value="theme">
173 <label for="theme">Colour scheme</label>
174 <select id="theme" name="theme">
175 <option value="system"{{if eq .ThemeSetting "system"}} selected{{end}}>follow the browser</option>
176 <option value="light"{{if eq .ThemeSetting "light"}} selected{{end}}>light</option>
177 <option value="dark"{{if eq .ThemeSetting "dark"}} selected{{end}}>dark</option>
178 </select>
179 <button type="submit" class="btn">Save</button>
180</form>
181<p class="meta">The same setting as <code>gitbay web theme set</code>. Following the browser takes its light or dark preference.</p>
182</section>
183
184<section id="export"><h2>Export</h2>
185<p class="meta">Your profile, repositories, issues and merge requests as one
186JSON bundle, the same one <code>gitbay account export</code> writes. Keys are
187never included; a replayed bundle's emails arrive unverified.</p>
188<p><a href="/settings/export">Download bundle</a></p>
189</section>
190
191<section id="cli"><h2>On the command line</h2>
192<p class="meta">No page here yet, and nothing refusing one: a credential is
193easier to pipe than to paste, and a minted token is shown once.</p>
194<pre class="message" tabindex="0">gitbay auth token create --name laptop # API tokens
195gitbay web sessions list # browser sessions
196gitbay admin ... # instance administration</pre>
197<p class="meta">All of it works from stock OpenSSH too:
198<code>ssh git@{{.Host}} auth whoami</code>.</p>
199</section>
200</div>
201</div>
202{{end}}