mailwolt/app/Livewire/Ui/Security/AccountSecurityForm.php

195 lines
6.6 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<?php
namespace App\Livewire\Ui\Security;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Password;
use Illuminate\Validation\Rule;
use Livewire\Component;
class AccountSecurityForm extends Component
{
// “Company Policy” hier nur Platzhalter; speicherst du später global
public bool $require2fa = false;
public bool $allowTotp = true;
public bool $allowMail = true;
public string $name = '';
public string $username = '';
public string $maskedEmail = ''; // nur Anzeige links
public string $emailInput = ''; // editierbar rechts
// aktueller Benutzer
public bool $userHas2fa = false;
public bool $totpActive = false;
public bool $email2faActive = false;
// Profil
public string $email = '';
// Passwort
public string $current_password = '';
public string $new_password = '';
public string $new_password_confirmation = '';
// E-Mail-2FA
public string $email_current = '';
public string $email_new = '';
protected $listeners = [
'totp-enabled' => 'onTotpEnabled',
'totp-disabled' => 'onTotpDisabled',
'email2fa-enabled' => 'onEmail2faEnabled',
'email2fa-disabled' => 'onEmail2faDisabled',
];
public function mount(): void
{
$u = Auth::user();
$this->name = (string)($u->name ?? '');
$this->username = (string)($u->username ?? '');
$this->email = (string)($u->email ?? '');
$this->maskedEmail = $this->maskEmail($u->email ?? '');
$this->emailInput = (string)($u->email ?? '');
$this->totpActive = (bool) optional($u->twoFactorMethod('totp'))->enabled;
$this->email2faActive = (bool) optional($u->twoFactorMethod('email'))->enabled;
$this->userHas2fa = $u->twoFactorEnabled();
}
protected function rules(): array
{
$userId = Auth::id();
return [
'require2fa' => ['boolean'],
'allowTotp' => ['boolean'],
'allowMail' => ['boolean'],
'username' => ['required','string','min:3','max:80'],
'email' => [
'required','email', Rule::unique('users','email')->ignore($userId)
],
'current_password' => ['nullable','string'],
'new_password' => ['nullable', Password::min(10)->mixedCase()->numbers()],
'new_password_confirmation' => ['same:new_password'],
'email_current' => ['required','email','in:'.(auth()->user()->email ?? '')],
'email_new' => ['required','email','different:email_current','max:255','unique:users,email'],
];
}
/* ===== Aktionen ===== */
public function save2faPolicy(): void
{
$this->validate([
'require2fa' => ['boolean'],
'allowTotp' => ['boolean'],
'allowMail' => ['boolean'],
]);
// TODO: In einer Settings-Tabelle persistieren
$this->dispatch('toast', body: '2FA-Richtlinie gespeichert.');
}
// public function toggleUser2fa(): void
// {
// // “Globaler” Toggle wenn nichts aktiv, öffnet der Nutzer die Modals.
// // Hier nur eine UX-Rückmeldung:
// if (! $this->userHas2fa) {
// $this->dispatch('toast', body: 'Wähle und richte zuerst eine Methode ein (TOTP oder E-Mail).');
// return;
// }
//
// // Wenn mindestens 1 Methode aktiv ist → komplett aus
// $u = Auth::user();
// $u->twoFactorMethods()->update(['enabled' => false, 'confirmed_at' => null, 'secret' => null]);
// $this->totpActive = $this->email2faActive = $this->userHas2fa = false;
//
// $this->dispatch('toast', body: '2FA deaktiviert.');
// }
protected function maskEmail(string $email): string {
if (!str_contains($email, '@')) return $email;
[$l, $d] = explode('@', $email, 2);
$l = strlen($l) <= 2 ? substr($l, 0, 1).'…' : substr($l,0,1).str_repeat('•', max(1, strlen($l)-3)).substr($l,-2);
$d = preg_replace('/(^.).*(\..{1,4}$)/', '$1…$2', $d);
return "{$l}@{$d}";
}
public function saveProfile(): void
{
$this->validate([
'username' => ['required','string','min:3','max:80'],
'email' => ['required','email', Rule::unique('users','email')->ignore(Auth::id())],
]);
$u = Auth::user();
$u->name = $this->username;
$u->email = $this->email;
$u->save();
$this->dispatch('toast', body: 'Profil gespeichert.');
}
public function changePassword(): void
{
if ($this->new_password === '') {
$this->dispatch('toast', body: 'Kein neues Passwort eingegeben.');
return;
}
$this->validate([
'current_password' => ['required','string'],
'new_password' => ['required', Password::min(10)->mixedCase()->numbers()],
'new_password_confirmation' => ['required','same:new_password'],
]);
$u = Auth::user();
if (! Hash::check($this->current_password, $u->password)) {
$this->addError('current_password','Aktuelles Passwort ist falsch.');
return;
}
$u->password = Hash::make($this->new_password);
$u->save();
$this->reset(['current_password','new_password','new_password_confirmation']);
$this->dispatch('toast', body: 'Passwort aktualisiert.');
}
public function changeEmail(): void
{
$this->validate(['email_current','email_new']);
$user = auth()->user();
$old = $user->email;
// 1) neue E-Mail in „pending“ Tabelle/Spalte ablegen (z. B. users.email_pending + token)
// 2) Verifizierungs-Mail an $this->email_new senden (mit Token)
// 3) Anzeigen/Toast
$this->dispatch('toast', body: 'Bestätigungslink an die neue E-Mail gesendet.');
// Felder leeren
$this->reset(['email_current', 'email_new', 'email_new_confirmation']);
}
public function onTotpEnabled() { $this->totpActive = true; $this->userHas2fa = true; }
public function onTotpDisabled() { $this->totpActive = false; $this->userHas2fa = $this->email2faActive; }
public function onEmail2faEnabled() { $this->email2faActive = true; $this->userHas2fa = true; }
public function onEmail2faDisabled(){ $this->email2faActive = false; $this->userHas2fa = $this->totpActive; }
public function render()
{
return view('livewire.ui.security.account-security-form');
}
}