refactor: convert force_password_change to standalone layout (no sidebar)
This commit is contained in:
@@ -306,7 +306,6 @@ func (h *Handler) loadTemplates(templateFS embed.FS) {
|
||||
"admin_settings", "system_info",
|
||||
"cron", "cron_add", "cron_edit",
|
||||
"assignments", "assignments_add", "assignments_edit",
|
||||
"force_password_change",
|
||||
}
|
||||
for _, page := range pages {
|
||||
pageContent, err := fs.ReadFile(templateFS, "templates/"+page+".html")
|
||||
@@ -335,6 +334,17 @@ func (h *Handler) loadTemplates(templateFS embed.FS) {
|
||||
}
|
||||
h.templates["login"] = loginTmpl
|
||||
|
||||
// Force password change page has its own layout (standalone, no sidebar)
|
||||
fpcContent, err := fs.ReadFile(templateFS, "templates/force_password_change.html")
|
||||
if err != nil {
|
||||
logging.Fatal("Failed to read force_password_change template: %v", err)
|
||||
}
|
||||
fpcTmpl, err := template.New("force_password_change").Funcs(funcMap).Parse(string(fpcContent))
|
||||
if err != nil {
|
||||
logging.Fatal("Failed to parse force_password_change: %v", err)
|
||||
}
|
||||
h.templates["force_password_change"] = fpcTmpl
|
||||
|
||||
// MFA required page has its own layout (standalone, no sidebar)
|
||||
mfaReqContent, err := fs.ReadFile(templateFS, "templates/mfa_required.html")
|
||||
if err != nil {
|
||||
@@ -2225,7 +2235,7 @@ func (h *Handler) handleForcePasswordChange(w http.ResponseWriter, r *http.Reque
|
||||
User: user,
|
||||
PasswordPolicy: &policy,
|
||||
}
|
||||
h.templates["force_password_change"].ExecuteTemplate(w, "base", data)
|
||||
h.templates["force_password_change"].Execute(w, data)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2239,7 +2249,7 @@ func (h *Handler) handleForcePasswordChange(w http.ResponseWriter, r *http.Reque
|
||||
PasswordPolicy: &policy,
|
||||
Flash: &Flash{Type: "danger", Message: "Passwords do not match."},
|
||||
}
|
||||
h.templates["force_password_change"].ExecuteTemplate(w, "base", data)
|
||||
h.templates["force_password_change"].Execute(w, data)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2250,7 +2260,7 @@ func (h *Handler) handleForcePasswordChange(w http.ResponseWriter, r *http.Reque
|
||||
PasswordPolicy: &policy,
|
||||
Flash: &Flash{Type: "danger", Message: err.Error()},
|
||||
}
|
||||
h.templates["force_password_change"].ExecuteTemplate(w, "base", data)
|
||||
h.templates["force_password_change"].Execute(w, data)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -2261,7 +2271,7 @@ func (h *Handler) handleForcePasswordChange(w http.ResponseWriter, r *http.Reque
|
||||
PasswordPolicy: &policy,
|
||||
Flash: &Flash{Type: "danger", Message: "Failed to change password: " + err.Error()},
|
||||
}
|
||||
h.templates["force_password_change"].ExecuteTemplate(w, "base", data)
|
||||
h.templates["force_password_change"].Execute(w, data)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,44 @@
|
||||
{{define "content"}}
|
||||
<div class="row row-deck row-cards justify-content-center">
|
||||
<div class="col-lg-6">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><i class="ti ti-lock-exclamation"></i> Password Change Required</h3>
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"/>
|
||||
<title>Password Change Required - {{appName}}</title>
|
||||
<link rel="icon" type="image/svg+xml" href="/static/favicon.svg">
|
||||
<link rel="preload" href="/static/css/fonts/tabler-icons.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<script>
|
||||
(function() {
|
||||
var resolved = (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) ? 'dark' : 'light';
|
||||
document.documentElement.setAttribute('data-bs-theme', resolved);
|
||||
document.documentElement.style.colorScheme = resolved;
|
||||
})();
|
||||
</script>
|
||||
<style>
|
||||
html[data-bs-theme="dark"],
|
||||
html[data-bs-theme="dark"] body { background-color: #1a2234; color-scheme: dark; }
|
||||
html[data-bs-theme="light"],
|
||||
html[data-bs-theme="light"] body { background-color: #f1f5f9; color-scheme: light; }
|
||||
[data-bs-theme="dark"] ::selection { background: #3d6098; color: #f0f4f8; }
|
||||
[data-bs-theme="dark"] ::-moz-selection { background: #3d6098; color: #f0f4f8; }
|
||||
[data-bs-theme="light"] ::selection { background: #b3d4fc; color: #1a1a1a; }
|
||||
[data-bs-theme="light"] ::-moz-selection { background: #b3d4fc; color: #1a1a1a; }
|
||||
</style>
|
||||
<link rel="stylesheet" href="/static/css/tabler.min.css">
|
||||
<link rel="stylesheet" href="/static/css/tabler-icons.min.css">
|
||||
</head>
|
||||
<body class="d-flex flex-column">
|
||||
<div class="page page-center">
|
||||
<div class="container container-tight py-4">
|
||||
<div class="text-center mb-4">
|
||||
<h1><i class="ti ti-key"></i> {{appName}}</h1>
|
||||
<p class="text-secondary">Centralized SSH Key Management and Deployment</p>
|
||||
</div>
|
||||
<div class="card card-md">
|
||||
<div class="card-body">
|
||||
<h2 class="h2 text-center mb-4">
|
||||
<i class="ti ti-lock-exclamation"></i> Password Change Required
|
||||
</h2>
|
||||
|
||||
<div class="alert alert-warning">
|
||||
<div class="d-flex">
|
||||
<div><i class="ti ti-alert-triangle icon alert-icon"></i></div>
|
||||
@@ -16,6 +49,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{if .Flash}}
|
||||
<div class="alert alert-{{.Flash.Type}}">
|
||||
<i class="ti ti-alert-circle"></i> {{.Flash.Message}}
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
{{if .PasswordPolicy}}
|
||||
<div class="alert alert-info">
|
||||
<div class="d-flex">
|
||||
@@ -55,6 +94,7 @@
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="text-center mt-3">
|
||||
<a href="/logout" class="text-secondary"><i class="ti ti-logout"></i> Logout</a>
|
||||
</div>
|
||||
@@ -62,4 +102,22 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{end}}
|
||||
|
||||
<!-- CSRF Protection -->
|
||||
<script>
|
||||
(function() {
|
||||
var m = document.cookie.match(/(?:^|;\s*)_csrf=([^;]*)/);
|
||||
var token = m ? decodeURIComponent(m[1]) : '';
|
||||
document.querySelectorAll('form').forEach(function(form) {
|
||||
if ((form.method || 'get').toLowerCase() === 'post' && !form.querySelector('input[name="_csrf"]')) {
|
||||
var input = document.createElement('input');
|
||||
input.type = 'hidden';
|
||||
input.name = '_csrf';
|
||||
input.value = token;
|
||||
form.prepend(input);
|
||||
}
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user