internal/web/templates/account.html

ba0a7d33f3a65ce53aafb074fda1682cf1cecfdf
gitbay/internal/web/templates/account.html history · blame · raw

202 lines · 11416 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 spellcheck="false" 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 autocomplete="email" 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 autocomplete="one-time-code" autocapitalize="none" spellcheck="false" 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  <div class="check"><input type="checkbox" id="notify-mail" name="mail" value="on"{{if .MailOn}} checked{{end}}></div>
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  <div class="check"><input type="checkbox" id="notify-watch" name="watch" value="on"{{if .WatchOn}} checked{{end}}></div>
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  <div class="check"><input type="checkbox" id="notify-push" name="push" value="on"{{if .PushOn}} checked{{end}}></div>
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, read-only unless --scope full
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}}