refactor: convert force_password_change to standalone layout (no sidebar)

This commit is contained in:
2026-04-05 19:03:32 +02:00
parent 5bd77de32d
commit ea3e7e71ca
2 changed files with 129 additions and 61 deletions

View File

@@ -1,65 +1,123 @@
{{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>
</div>
<div class="card-body">
<div class="alert alert-warning">
<div class="d-flex">
<div><i class="ti ti-alert-triangle icon alert-icon"></i></div>
<div>
<h4 class="alert-title">You must change your password</h4>
<div class="text-secondary">Your administrator has set an initial password for your account. Please choose a new personal password to continue.</div>
</div>
</div>
<!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>
{{if .PasswordPolicy}}
<div class="alert alert-info">
<div class="d-flex">
<div><i class="ti ti-info-circle icon alert-icon"></i></div>
<div>
<h4 class="alert-title">Password Requirements</h4>
<ul class="mb-0">
<li>Minimum <strong>{{.PasswordPolicy.MinLength}}</strong> characters</li>
{{if .PasswordPolicy.RequireUpper}}<li>At least one <strong>uppercase letter</strong> (A-Z)</li>{{end}}
{{if .PasswordPolicy.RequireLower}}<li>At least one <strong>lowercase letter</strong> (a-z)</li>{{end}}
{{if .PasswordPolicy.RequireDigit}}<li>At least one <strong>digit</strong> (0-9)</li>{{end}}
{{if .PasswordPolicy.RequireSpecial}}<li>At least one <strong>special character</strong> (!@#$...)</li>{{end}}
</ul>
<div class="alert alert-warning">
<div class="d-flex">
<div><i class="ti ti-alert-triangle icon alert-icon"></i></div>
<div>
<h4 class="alert-title">You must change your password</h4>
<div class="text-secondary">Your administrator has set an initial password for your account. Please choose a new personal password to continue.</div>
</div>
</div>
</div>
</div>
</div>
{{end}}
<form action="/password/change" method="post" autocomplete="off">
<div class="mb-3">
<label class="form-label required">New Password</label>
<div class="input-icon">
<span class="input-icon-addon"><i class="ti ti-lock"></i></span>
<input type="password" name="new_password" class="form-control" placeholder="New password" required minlength="{{if .PasswordPolicy}}{{.PasswordPolicy.MinLength}}{{else}}8{{end}}">
{{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">
<div><i class="ti ti-info-circle icon alert-icon"></i></div>
<div>
<h4 class="alert-title">Password Requirements</h4>
<ul class="mb-0">
<li>Minimum <strong>{{.PasswordPolicy.MinLength}}</strong> characters</li>
{{if .PasswordPolicy.RequireUpper}}<li>At least one <strong>uppercase letter</strong> (A-Z)</li>{{end}}
{{if .PasswordPolicy.RequireLower}}<li>At least one <strong>lowercase letter</strong> (a-z)</li>{{end}}
{{if .PasswordPolicy.RequireDigit}}<li>At least one <strong>digit</strong> (0-9)</li>{{end}}
{{if .PasswordPolicy.RequireSpecial}}<li>At least one <strong>special character</strong> (!@#$...)</li>{{end}}
</ul>
</div>
</div>
</div>
{{end}}
<form action="/password/change" method="post" autocomplete="off">
<div class="mb-3">
<label class="form-label required">New Password</label>
<div class="input-icon">
<span class="input-icon-addon"><i class="ti ti-lock"></i></span>
<input type="password" name="new_password" class="form-control" placeholder="New password" required minlength="{{if .PasswordPolicy}}{{.PasswordPolicy.MinLength}}{{else}}8{{end}}">
</div>
</div>
<div class="mb-3">
<label class="form-label required">Confirm New Password</label>
<div class="input-icon">
<span class="input-icon-addon"><i class="ti ti-lock-check"></i></span>
<input type="password" name="confirm_password" class="form-control" placeholder="Confirm new password" required minlength="{{if .PasswordPolicy}}{{.PasswordPolicy.MinLength}}{{else}}8{{end}}">
</div>
</div>
<div class="form-footer">
<button type="submit" class="btn btn-primary w-100">
<i class="ti ti-lock-check"></i> Set New Password
</button>
</div>
</form>
<div class="text-center mt-3">
<a href="/logout" class="text-secondary"><i class="ti ti-logout"></i> Logout</a>
</div>
</div>
<div class="mb-3">
<label class="form-label required">Confirm New Password</label>
<div class="input-icon">
<span class="input-icon-addon"><i class="ti ti-lock-check"></i></span>
<input type="password" name="confirm_password" class="form-control" placeholder="Confirm new password" required minlength="{{if .PasswordPolicy}}{{.PasswordPolicy.MinLength}}{{else}}8{{end}}">
</div>
</div>
<div class="form-footer">
<button type="submit" class="btn btn-primary w-100">
<i class="ti ti-lock-check"></i> Set New Password
</button>
</div>
</form>
<div class="text-center mt-3">
<a href="/logout" class="text-secondary"><i class="ti ti-logout"></i> Logout</a>
</div>
</div>
</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>