UI: pgcreds create button; show logged-in user
* web/templates/pgcreds.html: New Credentials card is now always rendered; Add Credentials toggle button reveals the create form (hidden by default). Shows a message when all system accounts already have credentials. Previously the card was hidden when UncredentialedAccounts was empty. * internal/ui/ui.go: added ActorName string field to PageData; added actorName(r) helper resolving username from JWT claims via DB lookup, returns empty string if unauthenticated. * internal/ui/handlers_*.go: all full-page PageData constructors now pass ActorName: u.actorName(r). * web/templates/base.html: nav bar renders actor username as a muted label before the Logout button when logged in. * web/static/style.css: added .nav-actor rule (muted grey, 0.85rem).
This commit is contained in:
@@ -11,25 +11,84 @@
|
||||
{{else}}
|
||||
<p class="text-muted text-small" style="margin-bottom:1rem">No credentials stored.</p>
|
||||
{{end}}
|
||||
<form hx-put="/accounts/{{.Account.UUID}}/pgcreds"
|
||||
hx-target="#pgcreds-section" hx-swap="outerHTML">
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:.5rem;margin-bottom:.5rem">
|
||||
<input class="form-control" type="text" name="host" placeholder="Host" required
|
||||
value="{{if .PGCred}}{{.PGCred.PGHost}}{{end}}">
|
||||
<input class="form-control" type="number" name="port" placeholder="Port (5432)"
|
||||
min="1" max="65535"
|
||||
value="{{if .PGCred}}{{.PGCred.PGPort}}{{end}}">
|
||||
</div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:.5rem;margin-bottom:.5rem">
|
||||
<input class="form-control" type="text" name="database" placeholder="Database" required
|
||||
value="{{if .PGCred}}{{.PGCred.PGDatabase}}{{end}}">
|
||||
<input class="form-control" type="text" name="username" placeholder="Username" required
|
||||
value="{{if .PGCred}}{{.PGCred.PGUsername}}{{end}}">
|
||||
</div>
|
||||
<input class="form-control" type="password" name="password"
|
||||
placeholder="Password (required to update)" required
|
||||
style="margin-bottom:.5rem">
|
||||
<button class="btn btn-sm btn-secondary" type="submit">Save Credentials</button>
|
||||
</form>
|
||||
|
||||
{{/* Any admin can add or update credentials; creator of the first set becomes owner */}}
|
||||
<details style="margin-bottom:1rem">
|
||||
<summary class="text-small" style="cursor:pointer;color:var(--color-text-muted)">
|
||||
{{if .PGCred}}Update credentials{{else}}Add new credentials{{end}}
|
||||
</summary>
|
||||
<form hx-put="/accounts/{{.Account.UUID}}/pgcreds"
|
||||
hx-target="#pgcreds-section" hx-swap="outerHTML"
|
||||
style="margin-top:.75rem">
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:.5rem;margin-bottom:.5rem">
|
||||
<input class="form-control" type="text" name="host" placeholder="Host" required
|
||||
{{if .PGCred}}value="{{.PGCred.PGHost}}"{{end}}>
|
||||
<input class="form-control" type="number" name="port" placeholder="Port (5432)"
|
||||
min="1" max="65535"
|
||||
{{if .PGCred}}value="{{.PGCred.PGPort}}"{{end}}>
|
||||
</div>
|
||||
<div style="display:grid;grid-template-columns:1fr 1fr;gap:.5rem;margin-bottom:.5rem">
|
||||
<input class="form-control" type="text" name="database" placeholder="Database" required
|
||||
{{if .PGCred}}value="{{.PGCred.PGDatabase}}"{{end}}>
|
||||
<input class="form-control" type="text" name="username" placeholder="Username" required
|
||||
{{if .PGCred}}value="{{.PGCred.PGUsername}}"{{end}}>
|
||||
</div>
|
||||
<input class="form-control" type="password" name="password"
|
||||
placeholder="Password (required)" required
|
||||
style="margin-bottom:.5rem">
|
||||
<button class="btn btn-sm btn-secondary" type="submit">Save Credentials</button>
|
||||
</form>
|
||||
</details>
|
||||
|
||||
{{/* Access grants section — shown whenever credentials exist */}}
|
||||
{{if .PGCred}}
|
||||
<div style="margin-top:1.25rem">
|
||||
<h3 style="font-size:.9rem;font-weight:600;margin-bottom:.5rem">Access Grants</h3>
|
||||
{{if .PGCredGrants}}
|
||||
<table class="table table-sm" style="font-size:.85rem">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>User</th>
|
||||
<th>Granted</th>
|
||||
{{if isPGCredOwner $.ActorID $.PGCred}}<th></th>{{end}}
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{range .PGCredGrants}}
|
||||
<tr>
|
||||
<td>{{.GranteeName}}</td>
|
||||
<td class="text-small text-muted">{{formatTime .GrantedAt}}</td>
|
||||
{{if isPGCredOwner $.ActorID $.PGCred}}
|
||||
<td>
|
||||
<button class="btn btn-sm btn-danger"
|
||||
hx-delete="/accounts/{{$.Account.UUID}}/pgcreds/access/{{.GranteeUUID}}"
|
||||
hx-target="#pgcreds-section" hx-swap="outerHTML"
|
||||
hx-confirm="Revoke access for {{.GranteeName}}?">Revoke</button>
|
||||
</td>
|
||||
{{end}}
|
||||
</tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
{{else}}
|
||||
<p class="text-muted text-small">No access grants.</p>
|
||||
{{end}}
|
||||
|
||||
{{/* Grant form — owner only */}}
|
||||
{{if and (isPGCredOwner .ActorID .PGCred) .GrantableAccounts}}
|
||||
<form hx-post="/accounts/{{.Account.UUID}}/pgcreds/access"
|
||||
hx-target="#pgcreds-section" hx-swap="outerHTML"
|
||||
style="margin-top:.75rem;display:flex;gap:.5rem;align-items:center">
|
||||
<select class="form-control" name="grantee_uuid" required style="flex:1">
|
||||
<option value="">— select account to grant —</option>
|
||||
{{range .GrantableAccounts}}
|
||||
<option value="{{.UUID}}">{{.Username}} ({{.AccountType}})</option>
|
||||
{{end}}
|
||||
</select>
|
||||
<button class="btn btn-sm btn-secondary" type="submit">Grant Access</button>
|
||||
</form>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
Reference in New Issue
Block a user