feat(auth): support API tokens and bearer token authentication
- 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.
This commit is contained in:
@@ -42,6 +42,61 @@
|
||||
<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>
|
||||
|
||||
Reference in New Issue
Block a user