- Add backend services to create, list, and delete API tokens. - Implement Bearer token authentication to resolve tokens to users. - Register HTTP routes for managing user tokens under `/account/tokens`. - Add tests to verify that uploads with valid Bearer tokens associate the upload with the correct user, while invalid tokens fall back to anonymous uploads.
104 lines
4.6 KiB
HTML
104 lines
4.6 KiB
HTML
{{define "account.html"}}{{template "base" .}}{{end}}
|
|
|
|
{{define "content"}}
|
|
<section class="app-shell" aria-labelledby="account-title">
|
|
<aside class="app-sidebar">
|
|
<nav class="sidebar-nav">
|
|
<a class="sidebar-link" href="/app">{{template "icon-home-simple" .}}<span>My Files</span></a>
|
|
<a class="sidebar-link is-active" href="/account/settings">{{template "icon-user-circle" .}}<span>Account</span></a>
|
|
{{if eq .Data.Role "admin"}}<a class="sidebar-link" href="/admin">{{template "icon-dashboard" .}}<span>Admin panel</span></a>{{end}}
|
|
</nav>
|
|
<hr class="sidebar-sep">
|
|
<form class="sidebar-logout" action="/logout" method="post">
|
|
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
|
|
<button class="button button-outline" type="submit">{{template "icon-log-out" .}}<span>Sign out</span></button>
|
|
</form>
|
|
</aside>
|
|
|
|
<div class="app-main">
|
|
<div class="admin-header">
|
|
<div>
|
|
<p class="kicker">Account</p>
|
|
<h1 id="account-title">Settings</h1>
|
|
<p class="muted-copy">{{.Data.Email}} · {{.Data.Role}}</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="settings-stack">
|
|
<div class="card settings-panel">
|
|
<div class="card-content">
|
|
<div class="table-header">
|
|
<div>
|
|
<h2>Password</h2>
|
|
<p>Update the password for your account.</p>
|
|
</div>
|
|
</div>
|
|
<form class="settings-form settings-form-narrow" action="/account/password" method="post">
|
|
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
|
|
<label><span>Current password</span><input type="password" name="current_password" autocomplete="current-password" required></label>
|
|
<label><span>New password</span><input type="password" name="new_password" autocomplete="new-password" minlength="8" required></label>
|
|
<button class="button button-primary" type="submit">Update password</button>
|
|
</form>
|
|
<p class="muted-copy">Public forgot-password is deferred until SMTP support is added. Admins can generate reset links.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="card settings-panel">
|
|
<div class="card-content">
|
|
<div class="table-header">
|
|
<div>
|
|
<h2>Access tokens</h2>
|
|
<p>Personal tokens act as your account for the API and CLI. They never expire until you delete them.</p>
|
|
</div>
|
|
</div>
|
|
|
|
{{if .Data.Error}}<p class="form-error">{{.Data.Error}}</p>{{end}}
|
|
|
|
{{if .Data.NewToken}}
|
|
<div class="token-reveal">
|
|
<p class="token-reveal-title">Copy your new token now — it won't be shown again.</p>
|
|
<div class="token-reveal-row">
|
|
<code class="token-reveal-value" data-token-value>{{.Data.NewToken}}</code>
|
|
<button class="button button-outline button-sm" type="button" data-token-copy>Copy</button>
|
|
</div>
|
|
<p class="muted-copy">Use it as a bearer token: <code>Authorization: Bearer {{.Data.NewToken}}</code></p>
|
|
</div>
|
|
{{end}}
|
|
|
|
<form class="token-create-form" action="/account/tokens" method="post">
|
|
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
|
|
<label><span>Token name</span><input name="name" placeholder="e.g. CLI on laptop" maxlength="80" required></label>
|
|
<button class="button button-primary button-sm" type="submit">Generate token</button>
|
|
</form>
|
|
|
|
{{if .Data.Tokens}}
|
|
<div class="admin-table-wrap">
|
|
<table class="admin-table">
|
|
<thead><tr><th>Name</th><th>Created</th><th>Last used</th><th></th></tr></thead>
|
|
<tbody>
|
|
{{range .Data.Tokens}}
|
|
<tr>
|
|
<td>{{.Name}}</td>
|
|
<td>{{.CreatedAt}}</td>
|
|
<td>{{.LastUsedAt}}</td>
|
|
<td class="table-actions">
|
|
<form action="/account/tokens/{{.ID}}/delete" method="post" onsubmit="return confirm('Delete this token? Any client using it will stop working.');">
|
|
<input type="hidden" name="csrf_token" value="{{$.CSRFToken}}">
|
|
<button class="button button-danger button-sm" type="submit">Delete</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{{else}}
|
|
<p class="muted-copy">No tokens yet. Generate one above to use the API or CLI.</p>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
{{end}}
|