diff --git a/app/Http/Middleware/EnsureSecurityOnboarded.php b/app/Http/Middleware/EnsureSecurityOnboarded.php index f50ba5f..0ffc3dd 100644 --- a/app/Http/Middleware/EnsureSecurityOnboarded.php +++ b/app/Http/Middleware/EnsureSecurityOnboarded.php @@ -7,8 +7,10 @@ use Illuminate\Http\Request; use Symfony\Component\HttpFoundation\Response; /** - * After login, force the seeded-password rotation before the panel is reachable. - * 2FA is optional (offered in Settings), so it is NOT forced here. + * After login, NUDGE the operator to rotate the seeded password — but do not force it. The prompt + * shows once per session and can be skipped (PasswordChange::skip sets `onboarding.password_skipped`); + * a persistent banner keeps warning while the default password is still in use. 2FA is optional too, + * so it is never forced here. */ class EnsureSecurityOnboarded { @@ -16,7 +18,9 @@ class EnsureSecurityOnboarded { $user = $request->user(); - if ($user && $user->must_change_password && ! $request->routeIs('password.change', 'logout')) { + if ($user && $user->must_change_password + && ! $request->session()->get('onboarding.password_skipped') + && ! $request->routeIs('password.change', 'logout')) { return redirect()->route('password.change'); } diff --git a/app/Livewire/Auth/PasswordChange.php b/app/Livewire/Auth/PasswordChange.php index c3b5198..7478a92 100644 --- a/app/Livewire/Auth/PasswordChange.php +++ b/app/Livewire/Auth/PasswordChange.php @@ -57,6 +57,18 @@ class PasswordChange extends Component return $this->redirect(route('dashboard'), navigate: true); } + /** + * Keep the current password for now — rotation is not forced. Remember the choice for this session + * so the prompt does not reappear; `must_change_password` stays true, so the persistent default- + * password banner keeps warning until the password is actually changed. + */ + public function skip() + { + session()->put('onboarding.password_skipped', true); + + return $this->redirect(route('dashboard'), navigate: true); + } + public function render() { return view('livewire.auth.password-change')->title(__('auth.title_password_change')); diff --git a/lang/de/auth.php b/lang/de/auth.php index 12076c7..6ac0a8d 100644 --- a/lang/de/auth.php +++ b/lang/de/auth.php @@ -15,7 +15,7 @@ return [ 'login_submit' => 'Anmelden', 'checking' => 'Prüfe…', 'secured' => 'Gesichert', - 'security_note' => 'Verbindung über SSH · 2FA erforderlich · jede Aktion landet im Audit-Log.', + 'security_note' => 'Verbindung über SSH · 2FA empfohlen · jede Aktion landet im Audit-Log.', // ── Password change ────────────────────────────────────────────────── 'security' => 'Sicherheit', @@ -26,6 +26,9 @@ return [ 'confirm_new_password' => 'Neues Passwort bestätigen', 'save_and_continue' => 'Speichern & weiter', 'saving' => 'Speichere…', + 'skip_for_now' => 'Vorerst überspringen', + 'default_pw_warning' => 'Standard-Passwort aktiv. Aus Sicherheitsgründen solltest du es ändern.', + 'default_pw_change' => 'Ändern', // ── Two-factor (shared label) ──────────────────────────────────────── 'two_factor' => 'Zwei-Faktor', @@ -55,7 +58,7 @@ return [ 'terminal_title' => 'clusev · sicherheitsmodell', 'terminal_ssh' => 'agentenlos · exec + SFTP über phpseclib', 'terminal_key' => 'Host-Keys via TOFU gepinnt', - 'terminal_2fa' => 'erzwungen für jeden Login', + 'terminal_2fa' => 'optional, aber empfohlen', 'terminal_log' => 'jede Aktion im Audit-Log', 'terminal_core' => 'Open Core · AGPL-lizenziert', 'footer_copyright' => '© :year Clusev · Fleet Control', diff --git a/lang/en/auth.php b/lang/en/auth.php index a6bb7aa..5e0772a 100644 --- a/lang/en/auth.php +++ b/lang/en/auth.php @@ -15,7 +15,7 @@ return [ 'login_submit' => 'Sign in', 'checking' => 'Checking…', 'secured' => 'Secured', - 'security_note' => 'Connection over SSH · 2FA required · every action lands in the audit log.', + 'security_note' => 'Connection over SSH · 2FA recommended · every action lands in the audit log.', // ── Password change ────────────────────────────────────────────────── 'security' => 'Security', @@ -26,6 +26,9 @@ return [ 'confirm_new_password' => 'Confirm new password', 'save_and_continue' => 'Save & continue', 'saving' => 'Saving…', + 'skip_for_now' => 'Skip for now', + 'default_pw_warning' => 'Default password in use. For security, you should change it.', + 'default_pw_change' => 'Change', // ── Two-factor (shared label) ──────────────────────────────────────── 'two_factor' => 'Two-factor', @@ -55,7 +58,7 @@ return [ 'terminal_title' => 'clusev · security model', 'terminal_ssh' => 'agentless · exec + SFTP over phpseclib', 'terminal_key' => 'host keys pinned via TOFU', - 'terminal_2fa' => 'enforced on every login', + 'terminal_2fa' => 'optional, but recommended', 'terminal_log' => 'every action in the audit log', 'terminal_core' => 'Open Core · AGPL-licensed', 'footer_copyright' => '© :year Clusev · Fleet Control', diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php index 7a88119..d2351ce 100644 --- a/resources/views/layouts/app.blade.php +++ b/resources/views/layouts/app.blade.php @@ -37,6 +37,16 @@