feat: set preferred MFA method from account settings

Adds the ability for users to change their preferred/primary MFA method
when both TOTP and email are available.

Backend:
- Add PUT /auth/mfa/preferred-method endpoint with validation
  (method must be totp/email, MFA must be enabled, TOTP must be
  configured if selecting totp)
- Add totp_configured and email_configured fields to MFA status
  endpoint (totp = has secret + enabled, email = always when enabled)
- Fix setupEmail() to preserve mfa_secret so TOTP config survives
  when email is set up as a second method

Frontend (organizer + portal):
- Add useSetPreferredMethod() composable to useMfa.ts
- Add totp_configured/email_configured to MfaStatus type
- SecurityTab method cards now show "Primaire methode" chip on the
  preferred method and "Als primair instellen" button on the other
- Portal security section shows per-method rows with status chips
  and primary switching

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-15 22:47:34 +02:00
parent a77986334c
commit d5fb15e5fe
9 changed files with 225 additions and 43 deletions

View File

@@ -90,14 +90,16 @@ final class MfaService
/**
* Setup email as MFA method (simpler than TOTP no QR code).
* Sends a verification code to confirm.
* Preserves the TOTP secret so both methods can coexist.
*/
public function setupEmail(User $user): void
{
$user->update([
'mfa_method' => MfaMethod::EMAIL->value,
'mfa_secret' => null,
'mfa_confirmed_at' => null,
]);
if (! $user->mfa_enabled) {
$user->update([
'mfa_method' => MfaMethod::EMAIL->value,
'mfa_confirmed_at' => null,
]);
}
$this->sendEmailCode($user);
}