@
hub v0.54.0: change operator login password from the Configuration UI Adds a "Login password" card on /configuration. The password was previously settable only via the hub-config ConfigMap (auth.password_hash) + redeploy. - store: hub_settings key operator_password_hash + Get/SetOperatorPasswordHash - server: passwordHash field -> configPasswordHash (seed); new effectivePasswordHash() (DB override wins, else seed) is now the single source for the CSRF gate, RequireAuth, and handleLogin - POST /configuration/password (handleChangePassword): requires current password, 8-72 byte new + confirm, bcrypt cost 10, persists DB override; existing sessions kept valid; ConfigMap stays the break-glass reset path - UI: current/new/confirm form + inline mismatch pre-check + 6 flashes - tests + red-proofs: override precedence, happy-path via handleLogin, wrong-current rejection, mismatch/too-short/no-op, template render - docs: CHANGELOG, README (auth+config), REUSE, REPORT Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LbMm4T7Ayzs1unB9pN6Uqd @
This commit is contained in:
@@ -47,6 +47,24 @@
|
||||
{{if eq .Flash "artifact_sha_invalid"}}
|
||||
<div class="flash flash-error">Couldn't set the checksum — the Gitea sha lookup failed (version missing / Gitea unreachable) or the manually-entered sha is invalid. Manifest unchanged.</div>
|
||||
{{end}}
|
||||
{{if eq .Flash "pw_changed"}}
|
||||
<div class="flash flash-success">Login password changed. It is already in effect — use it next time you sign in. Existing sessions stay logged in.</div>
|
||||
{{end}}
|
||||
{{if eq .Flash "pw_current_wrong"}}
|
||||
<div class="flash flash-error">Current password is incorrect — password unchanged.</div>
|
||||
{{end}}
|
||||
{{if eq .Flash "pw_too_short"}}
|
||||
<div class="flash flash-error">New password is too short (minimum 8 characters) — password unchanged.</div>
|
||||
{{end}}
|
||||
{{if eq .Flash "pw_too_long"}}
|
||||
<div class="flash flash-error">New password is too long (maximum 72 characters) — password unchanged.</div>
|
||||
{{end}}
|
||||
{{if eq .Flash "pw_mismatch"}}
|
||||
<div class="flash flash-error">New password and confirmation don't match — password unchanged.</div>
|
||||
{{end}}
|
||||
{{if eq .Flash "pw_unchanged"}}
|
||||
<div class="flash flash-error">New password is the same as the current one — nothing changed.</div>
|
||||
{{end}}
|
||||
|
||||
<!-- Phase 2 managed updates: global controller-version floor. ITS OWN card, separate from the
|
||||
Day-0 artifact manifest below (a manifest save must NEVER touch the live floor — the
|
||||
@@ -178,6 +196,47 @@
|
||||
</script>
|
||||
</section>
|
||||
|
||||
<!-- Operator login password (v0.54.0). Changing it here writes a hub_settings DB override that
|
||||
WINS over the hub.yaml ConfigMap seed (auth.password_hash); the ConfigMap stays the
|
||||
break-glass fallback (blank the DB row / edit the manifest to reset a lost password).
|
||||
Requires the current password. Existing sessions are intentionally kept valid. -->
|
||||
<section class="card">
|
||||
<h3 style="margin-top: 0;">Login password</h3>
|
||||
<p class="text-muted" style="margin: 0 0 0.75rem; font-size: 0.85em;">
|
||||
The password for signing in to this hub UI. <strong>Changing it takes effect immediately</strong>
|
||||
for the next sign-in — your current session stays logged in. Enter your current password to confirm.
|
||||
If you ever lose it, the deployment ConfigMap (<code>auth.password_hash</code>) remains the reset path.
|
||||
</p>
|
||||
<form method="POST" action="/configuration/password" style="display: grid; grid-template-columns: auto 20em; gap: 0.5rem; align-items: center; max-width: 40em;"
|
||||
onsubmit="return felhomCheckNewPw(this);">
|
||||
{{.CSRFField}}
|
||||
<label style="font-size: 0.9em; color: #cbd5e1;">Current password</label>
|
||||
<input type="password" name="current_password" autocomplete="current-password" required style="padding: 0.3em 0.5em;">
|
||||
<label style="font-size: 0.9em; color: #cbd5e1;">New password</label>
|
||||
<input type="password" id="new_password" name="new_password" autocomplete="new-password" minlength="8" maxlength="72" required style="padding: 0.3em 0.5em;">
|
||||
<label style="font-size: 0.9em; color: #cbd5e1;">Confirm new password</label>
|
||||
<input type="password" id="confirm_password" name="confirm_password" autocomplete="new-password" minlength="8" maxlength="72" required style="padding: 0.3em 0.5em;">
|
||||
<span></span>
|
||||
<span>
|
||||
<button class="btn btn-sm" type="submit">Change password</button>
|
||||
<span id="pw-client-err" style="margin-left: 0.6em; font-size: 0.8em; color: #f87171;"></span>
|
||||
</span>
|
||||
</form>
|
||||
<script>
|
||||
// Client-side pre-check only (the server re-validates authoritatively): catch the
|
||||
// mismatch before a round-trip so the operator sees it inline.
|
||||
function felhomCheckNewPw(form) {
|
||||
var a = form.new_password.value;
|
||||
var b = form.confirm_password.value;
|
||||
var err = document.getElementById('pw-client-err');
|
||||
err.textContent = '';
|
||||
if (a.length < 8) { err.textContent = 'New password must be at least 8 characters.'; return false; }
|
||||
if (a !== b) { err.textContent = 'New password and confirmation do not match.'; return false; }
|
||||
return true;
|
||||
}
|
||||
</script>
|
||||
</section>
|
||||
|
||||
<!-- Assets section -->
|
||||
<section class="card">
|
||||
<h3 style="margin-top: 0;">Assets</h3>
|
||||
|
||||
Reference in New Issue
Block a user