diff --git a/pkg/webui/html/accounts.html b/pkg/webui/html/accounts.html index b6253ec..da13bca 100644 --- a/pkg/webui/html/accounts.html +++ b/pkg/webui/html/accounts.html @@ -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%;"> diff --git a/pkg/webui/html/accountsId.html b/pkg/webui/html/accountsId.html index 8ecf70d..9bfe95c 100644 --- a/pkg/webui/html/accountsId.html +++ b/pkg/webui/html/accountsId.html @@ -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,14 +63,23 @@ 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 or (ne .Account.PasswordReset nil) (eq .Page.AccountId.String .Account.Id.String) }}disabled{{ end }} + type="submit" + value="reset-password"> + Reset Password + </button> </fieldset> </div> </form> -{{ if gt (len .Versions) 0 }} +{{ end }} <h2>Activity</h2> +{{ if gt (len .Versions) 0 }} <article> <table style="width:100%;"> <thead> @@ -87,6 +98,8 @@ Direct the user to <a href="/account/{{ .Account.Id }}/reset/{{ .Account.Passwor </tbody> </table> </article> +{{ else }} +<p>This user account has not authored any change currently tracked by TfStated.</p> {{ end }} <a href="/accounts">Go back to the user accounts list</a> {{ end }} diff --git a/pkg/webui/html/base.html b/pkg/webui/html/base.html index 1bbc2a2..c8732c7 100644 --- a/pkg/webui/html/base.html +++ b/pkg/webui/html/base.html @@ -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> diff --git a/pkg/webui/html/states.html b/pkg/webui/html/states.html index 493b74d..10eaf33 100644 --- a/pkg/webui/html/states.html +++ b/pkg/webui/html/states.html @@ -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> diff --git a/pkg/webui/html/statesId.html b/pkg/webui/html/statesId.html index 8dd159e..9139c91 100644 --- a/pkg/webui/html/statesId.html +++ b/pkg/webui/html/statesId.html @@ -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> diff --git a/pkg/webui/index.go b/pkg/webui/index.go index d88a7fa..580d5a8 100644 --- a/pkg/webui/index.go +++ b/pkg/webui/index.go @@ -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 diff --git a/pkg/webui/routes.go b/pkg/webui/routes.go index 772489b..ee52fa6 100644 --- a/pkg/webui/routes.go +++ b/pkg/webui/routes.go @@ -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())) diff --git a/pkg/webui/static/main.css b/pkg/webui/static/main.css index 6956316..4658d65 100644 --- a/pkg/webui/static/main.css +++ b/pkg/webui/static/main.css @@ -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 {