* 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).
95 lines
4.2 KiB
HTML
95 lines
4.2 KiB
HTML
{{define "pgcreds_form"}}
|
|
<div id="pgcreds-section">
|
|
{{if .PGCred}}
|
|
<dl style="display:grid;grid-template-columns:140px 1fr;gap:.5rem .75rem;font-size:.9rem;margin-bottom:1rem">
|
|
<dt class="text-muted">Host</dt><dd>{{.PGCred.PGHost}}:{{.PGCred.PGPort}}</dd>
|
|
<dt class="text-muted">Database</dt><dd>{{.PGCred.PGDatabase}}</dd>
|
|
<dt class="text-muted">Username</dt><dd>{{.PGCred.PGUsername}}</dd>
|
|
<dt class="text-muted">Password</dt><dd><em class="text-muted">stored (not shown)</em></dd>
|
|
<dt class="text-muted">Updated</dt><dd class="text-small">{{formatTime .PGCred.UpdatedAt}}</dd>
|
|
</dl>
|
|
{{else}}
|
|
<p class="text-muted text-small" style="margin-bottom:1rem">No credentials stored.</p>
|
|
{{end}}
|
|
|
|
{{/* 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}}
|