feat(webui): open a currated version of the user accounts section to non admin users
This commit is contained in:
parent
2bf1731343
commit
0aaf93d4ba
8 changed files with 46 additions and 23 deletions
|
@ -2,9 +2,12 @@
|
|||
<h1>User Accounts</h1>
|
||||
<div class="flex-row" style="justify-content:space-between;">
|
||||
<div style="min-width:240px;">
|
||||
<p>There are <span class="button">{{ len .Accounts }}</span> user accounts.</p>
|
||||
<p>Use this page to inspect user accounts or create a new one.</p>
|
||||
<p>
|
||||
There are <strong>{{ len .Accounts }}</strong> user accounts.
|
||||
Use this page to inspect user accounts.
|
||||
</p>
|
||||
</div>
|
||||
{{ if .Page.IsAdmin }}
|
||||
<form action="/accounts" enctype="multipart/form-data" method="post">
|
||||
<fieldset>
|
||||
<legend>New User Account</legend>
|
||||
|
@ -39,6 +42,7 @@
|
|||
<button class="primary" type="submit" value="submit">Create User Account</button>
|
||||
</fieldset>
|
||||
</form>
|
||||
{{ end }}
|
||||
</div>
|
||||
<article>
|
||||
<table style="width:100%;">
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
{{ if ne .Account.PasswordReset nil }}
|
||||
<h2>Password Reset</h2>
|
||||
<article>
|
||||
Direct the user to <a href="/account/{{ .Account.Id }}/reset/{{ .Account.PasswordReset }}">/account/{{ .Account.Id }}/reset/{{ .Account.PasswordReset }}</a> so that they can create their password.
|
||||
Direct the user to <a href="/account/{{ .Account.Id }}/reset/{{ .Account.PasswordReset }}">/account/{{ .Account.Id }}/reset/{{ .Account.PasswordReset }}</a> so that they can create their password.
|
||||
</article>
|
||||
{{ end }}
|
||||
<h2>Status</h2>
|
||||
|
@ -24,6 +24,7 @@ Direct the user to <a href="/account/{{ .Account.Id }}/reset/{{ .Account.Passwor
|
|||
{{ if .Account.IsAdmin }}
|
||||
<p>This accounts has <strong>admin</strong> privileges on TfStated.</p>
|
||||
{{ end }}
|
||||
{{ if .Page.IsAdmin }}
|
||||
<h2>Operations</h2>
|
||||
<form action="/accounts/{{ .Account.Id }}" enctype="multipart/form-data" method="post">
|
||||
<div class="flex-row">
|
||||
|
@ -37,7 +38,8 @@ Direct the user to <a href="/account/{{ .Account.Id }}/reset/{{ .Account.Passwor
|
|||
type="text"
|
||||
value="{{ .Username }}">
|
||||
<label for="is-admin">Is Admin</label>
|
||||
<input {{ if .Account.IsAdmin }} checked{{ end }}
|
||||
<input {{ if .Account.IsAdmin }}checked{{ end }}
|
||||
{{ if eq .Page.AccountId.String .Account.Id.String }}disabled{{ end }}
|
||||
id="is-admin"
|
||||
name="is-admin"
|
||||
type="checkbox"
|
||||
|
@ -61,12 +63,21 @@ Direct the user to <a href="/account/{{ .Account.Id }}/reset/{{ .Account.Passwor
|
|||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>Danger Zone</legend>
|
||||
<button type="submit" value="delete">Delete User Account</button>
|
||||
<button {{ if eq .Page.AccountId.String .Account.Id.String }}disabled{{ end }}
|
||||
type="submit"
|
||||
value="delete">
|
||||
Delete User Account
|
||||
</button>
|
||||
<!--<button type="submit" value="lock">Lock User Account</button>-->
|
||||
<button type="submit" value="reset-password">Reset Password</button>
|
||||
<button {{ if eq .Page.AccountId.String .Account.Id.String }}disabled{{ end }}
|
||||
type="submit"
|
||||
value="reset-password">
|
||||
Reset Password
|
||||
</button>
|
||||
</fieldset>
|
||||
</div>
|
||||
</form>
|
||||
{{ end }}
|
||||
{{ if gt (len .Versions) 0 }}
|
||||
<h2>Activity</h2>
|
||||
<article>
|
||||
|
|
|
@ -28,12 +28,10 @@
|
|||
<i class="material-symbols-outlined">settings</i>
|
||||
<span>Settings</span>
|
||||
</a>
|
||||
{{ if .Page.IsAdmin }}
|
||||
<a href="/accounts"{{ if eq .Page.Section "accounts" }} class="primary"{{ end}}>
|
||||
<i class="material-symbols-outlined">person</i>
|
||||
<span>User Accounts</span>
|
||||
</a>
|
||||
{{ end }}
|
||||
<hr>
|
||||
<a href="/logout">
|
||||
<i class="material-symbols-outlined">logout</i>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<h1>States</h1>
|
||||
<div class="flex-row" style="justify-content:space-between;">
|
||||
<div style="min-width:240px;">
|
||||
<p>TfStated is currently managing <span class="button">{{ len .States }}</span> states.</p>
|
||||
<p>TfStated is currently managing <strong>{{ len .States }}</strong> states.</p>
|
||||
<p>Use this page to inspect the existing states.</p>
|
||||
<p>You also have the option to upload a JSON state file in order to create a new state in TfStated. This is equivalent to using the <code>state push</code> command of OpenTofu/Terraform on a brand new state.</p>
|
||||
</div>
|
||||
|
|
|
@ -2,23 +2,22 @@
|
|||
<h1>State</h1>
|
||||
<p>
|
||||
The state at path
|
||||
<span class="button">{{ .State.Path }}</span>
|
||||
<strong>{{ .State.Path }}</strong>
|
||||
has
|
||||
<span class="button">{{ len .Versions }}</span>
|
||||
<strong>{{ len .Versions }}</strong>
|
||||
versions and is currently
|
||||
<span class="button">
|
||||
<strong>
|
||||
{{ if eq .State.Lock nil }}
|
||||
unlocked
|
||||
unlocked.
|
||||
{{ else }}
|
||||
<span class="tooltip">
|
||||
locked
|
||||
locked.
|
||||
<span class="tooltip-text">
|
||||
{{ .State.Lock }}
|
||||
</span>
|
||||
</span>
|
||||
{{ end }}
|
||||
</span>
|
||||
.
|
||||
</strong>
|
||||
</p>
|
||||
<p>Use this page to inspect the existing versions.</p>
|
||||
<article>
|
||||
|
|
|
@ -5,9 +5,11 @@ import (
|
|||
"net/http"
|
||||
|
||||
"git.adyxax.org/adyxax/tfstated/pkg/model"
|
||||
"go.n16f.net/uuid"
|
||||
)
|
||||
|
||||
type Page struct {
|
||||
AccountId uuid.UUID
|
||||
IsAdmin bool
|
||||
LightMode bool
|
||||
Section string
|
||||
|
@ -16,6 +18,7 @@ type Page struct {
|
|||
|
||||
func makePage(r *http.Request, page *Page) *Page {
|
||||
account := r.Context().Value(model.AccountContextKey{}).(*model.Account)
|
||||
page.AccountId = account.Id
|
||||
page.IsAdmin = account.IsAdmin
|
||||
settings := r.Context().Value(model.SettingsContextKey{}).(*model.Settings)
|
||||
page.LightMode = settings.LightMode
|
||||
|
|
|
@ -13,8 +13,8 @@ func addRoutes(
|
|||
requireSession := sessionsMiddleware(db)
|
||||
requireLogin := loginMiddleware(db, requireSession)
|
||||
requireAdmin := adminMiddleware(db, requireLogin)
|
||||
mux.Handle("GET /accounts", requireAdmin(handleAccountsGET(db)))
|
||||
mux.Handle("GET /accounts/{id}", requireAdmin(handleAccountsIdGET(db)))
|
||||
mux.Handle("GET /accounts", requireLogin(handleAccountsGET(db)))
|
||||
mux.Handle("GET /accounts/{id}", requireLogin(handleAccountsIdGET(db)))
|
||||
mux.Handle("POST /accounts", requireAdmin(handleAccountsPOST(db)))
|
||||
mux.Handle("GET /healthz", handleHealthz())
|
||||
mux.Handle("GET /login", requireSession(handleLoginGET()))
|
||||
|
|
|
@ -82,8 +82,13 @@ textarea {
|
|||
text-overflow: ellipsis;
|
||||
}
|
||||
input:not([type=image i], [type=range i], [type=checkbox i], [type=radio i]) {
|
||||
overflow: clip !important;
|
||||
overflow-clip-margin: 0 !important;
|
||||
overflow: clip !important;
|
||||
overflow-clip-margin: 0 !important;
|
||||
}
|
||||
button:disabled, button:disabled:hover {
|
||||
background-color: var(--bg-2);
|
||||
border: 1px solid var(--fg-1);
|
||||
color:var(--dim) !important;
|
||||
}
|
||||
|
||||
html {
|
||||
|
@ -248,12 +253,11 @@ fieldset {
|
|||
padding: 8px;
|
||||
}
|
||||
button, .button {
|
||||
background-color: var(--bg-2);
|
||||
border: 1px solid var(--orange);
|
||||
color: var(--orange);
|
||||
align-items: center;
|
||||
background-color: var(--bg-2);
|
||||
border: 1px solid var(--fg-1);
|
||||
border-radius: 8px;
|
||||
color: var(--orange);
|
||||
display: inline-flex;
|
||||
font-size: 16px;
|
||||
gap: 8px;
|
||||
|
@ -329,6 +333,10 @@ footer p {
|
|||
footer a {
|
||||
color: var(--green);
|
||||
}
|
||||
strong {
|
||||
color: var(--orange);
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
@media only screen and (640px <= width < 968px) { /*856*/
|
||||
header {
|
||||
|
|
Loading…
Add table
Reference in a new issue