auth/mail: Magic-Link-2FA (M1) + Mailversand über die Queue
- Magic-Link-Login übergibt bei aktiviertem 2FA an die 2FA-Challenge, statt sie zu umgehen (M1). - Bestätigungs-/Benachrichtigungs-Mails (Kontakt, Recht, Kündigung, Widerruf, Magic-Link) laufen als ShouldQueue+afterCommit über die Queue, damit die Response nicht am SMTP-Roundtrip hängt. Hinweis: Der Queue-Worker muss im Betrieb laufen und überwacht werden, da fristrelevante Bestätigungen darüber zugestellt werden (siehe Betriebsüberwachung). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
6764fb9bc2
commit
ea8d017445
20 changed files with 135 additions and 60 deletions
|
|
@ -45,18 +45,35 @@ class MagicLinkConsumeController extends Controller
|
|||
return redirect()->route('login')->with('status', __('The magic login link has expired or was already used.'));
|
||||
}
|
||||
|
||||
$magicLink->user->update([
|
||||
$user = $magicLink->user;
|
||||
|
||||
// 2FA aktiv: nicht direkt einloggen, sondern – wie der Passwort-Login –
|
||||
// in Fortifys Challenge übergeben. Der Magic-Link (Besitz des Postfachs)
|
||||
// ersetzt nur das Passwort, nicht den zweiten Faktor. Der Link ist bereits
|
||||
// atomar verbraucht; bricht der Nutzer die Challenge ab, fordert er einen
|
||||
// neuen an.
|
||||
if ($user->hasEnabledTwoFactorAuthentication()) {
|
||||
$request->session()->put([
|
||||
'login.id' => $user->getKey(),
|
||||
'login.remember' => false,
|
||||
]);
|
||||
|
||||
$request->session()->regenerate();
|
||||
|
||||
return redirect()->route('two-factor.challenge');
|
||||
}
|
||||
|
||||
$user->update([
|
||||
'last_login_at' => now(),
|
||||
'last_login_ip' => $request->ip(),
|
||||
]);
|
||||
|
||||
Auth::guard('web')->login($magicLink->user);
|
||||
Auth::guard('web')->login($user);
|
||||
$request->session()->regenerate();
|
||||
|
||||
// Rollensicherer Redirect ohne intended(): eine als Gast besuchte
|
||||
// Admin-URL (z. B. /dashboard) darf einen Customer nach dem
|
||||
// Magic-Link-Login nicht in den 403-Admin-Bereich schicken.
|
||||
$user = $magicLink->user;
|
||||
|
||||
$home = $user->canAccessAdmin()
|
||||
? route('dashboard', absolute: false)
|
||||
|
|
|
|||
|
|
@ -95,9 +95,13 @@ class LegalRequestController extends Controller
|
|||
// Vorgangsnummer (sofern eine E-Mail-Adresse angegeben wurde) +
|
||||
// interner Hinweis ans Melde-Postfach.
|
||||
if ($legalRequest->requester_email) {
|
||||
Mail::to($legalRequest->requester_email)->send(new LegalRequestReceived($legalRequest));
|
||||
Mail::to($legalRequest->requester_email)->queue(
|
||||
(new LegalRequestReceived($legalRequest))->afterCommit()
|
||||
);
|
||||
}
|
||||
Mail::to($this->operatorRecipient())->send(new LegalRequestSubmitted($legalRequest));
|
||||
Mail::to($this->operatorRecipient())->queue(
|
||||
(new LegalRequestSubmitted($legalRequest))->afterCommit()
|
||||
);
|
||||
|
||||
return redirect()
|
||||
->route('release.detail', ['slug' => $release->slug])
|
||||
|
|
|
|||
|
|
@ -77,10 +77,17 @@ class ReportFormController extends Controller
|
|||
'requester_ip' => $request->ip(),
|
||||
]);
|
||||
|
||||
// Unverzügliche Eingangsbestätigung (DSA Art. 16 Abs. 4) + interner
|
||||
// Hinweis ans Melde-Postfach, damit Fristen nicht an der Queue hängen.
|
||||
Mail::to($legalRequest->requester_email)->send(new LegalRequestReceived($legalRequest));
|
||||
Mail::to($this->operatorRecipient($request))->send(new LegalRequestSubmitted($legalRequest));
|
||||
// Eingangsbestätigung (DSA Art. 16 Abs. 4) + interner Hinweis ans
|
||||
// Melde-Postfach. Versand über die Queue (afterCommit), damit die
|
||||
// Response nicht am SMTP-Roundtrip hängt — setzt einen laufenden
|
||||
// Queue-Worker voraus (Ops-Monitoring erforderlich, da die Zustellung
|
||||
// fristrelevant ist).
|
||||
Mail::to($legalRequest->requester_email)->queue(
|
||||
(new LegalRequestReceived($legalRequest))->afterCommit()
|
||||
);
|
||||
Mail::to($this->operatorRecipient($request))->queue(
|
||||
(new LegalRequestSubmitted($legalRequest))->afterCommit()
|
||||
);
|
||||
|
||||
return back()->with('report-status', __('static.report_form.flash_received', [
|
||||
'reference' => $legalRequest->reference(),
|
||||
|
|
|
|||
|
|
@ -71,8 +71,12 @@ class TerminationController extends Controller
|
|||
|
||||
// § 312k Abs. 4 BGB: Zugang der Kündigungserklärung sofort auf
|
||||
// elektronischem Wege bestätigen (Inhalt, Datum, Uhrzeit).
|
||||
Mail::to($terminationRequest->email)->send(new TerminationRequestReceived($terminationRequest));
|
||||
Mail::to($this->operatorRecipient())->send(new TerminationRequestSubmitted($terminationRequest));
|
||||
Mail::to($terminationRequest->email)->queue(
|
||||
(new TerminationRequestReceived($terminationRequest))->afterCommit()
|
||||
);
|
||||
Mail::to($this->operatorRecipient())->queue(
|
||||
(new TerminationRequestSubmitted($terminationRequest))->afterCommit()
|
||||
);
|
||||
|
||||
return $this->done();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,8 +49,12 @@ class WithdrawalController extends Controller
|
|||
]);
|
||||
|
||||
// Gesetzlich vorgeschrieben: sofortige automatische Eingangsbestätigung.
|
||||
Mail::to($withdrawalRequest->email)->send(new WithdrawalRequestReceived($withdrawalRequest));
|
||||
Mail::to($this->operatorRecipient())->send(new WithdrawalRequestSubmitted($withdrawalRequest));
|
||||
Mail::to($withdrawalRequest->email)->queue(
|
||||
(new WithdrawalRequestReceived($withdrawalRequest))->afterCommit()
|
||||
);
|
||||
Mail::to($this->operatorRecipient())->queue(
|
||||
(new WithdrawalRequestSubmitted($withdrawalRequest))->afterCommit()
|
||||
);
|
||||
|
||||
return $this->done();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,13 +3,14 @@
|
|||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Address;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class ContactRequestSubmitted extends Mailable
|
||||
class ContactRequestSubmitted extends Mailable implements ShouldQueue
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace App\Mail;
|
|||
|
||||
use App\Models\LegalRequest;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
@ -14,7 +15,7 @@ use Illuminate\Queue\SerializesModels;
|
|||
* meldende Person (T10, DSA Art. 16 Abs. 4) — mit Vorgangsnummer sowie Datum
|
||||
* und Uhrzeit des Eingangs.
|
||||
*/
|
||||
class LegalRequestReceived extends Mailable
|
||||
class LegalRequestReceived extends Mailable implements ShouldQueue
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace App\Mail;
|
|||
|
||||
use App\Models\LegalRequest;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
@ -14,7 +15,7 @@ use Illuminate\Queue\SerializesModels;
|
|||
* der Admin-Queue (DSA-Fristen — Meldungen sollen nicht erst beim nächsten
|
||||
* Blick in den Admin auffallen).
|
||||
*/
|
||||
class LegalRequestSubmitted extends Mailable
|
||||
class LegalRequestSubmitted extends Mailable implements ShouldQueue
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,13 @@ namespace App\Mail;
|
|||
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class MagicLoginLink extends Mailable
|
||||
class MagicLoginLink extends Mailable implements ShouldQueue
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace App\Mail;
|
|||
|
||||
use App\Models\TerminationRequest;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
@ -14,7 +15,7 @@ use Illuminate\Queue\SerializesModels;
|
|||
* vorgeschrieben beim Kündigungsbutton (§ 312k Abs. 4 BGB): Inhalt sowie
|
||||
* Datum und Uhrzeit des Zugangs der Kündigungserklärung.
|
||||
*/
|
||||
class TerminationRequestReceived extends Mailable
|
||||
class TerminationRequestReceived extends Mailable implements ShouldQueue
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace App\Mail;
|
|||
|
||||
use App\Models\TerminationRequest;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
@ -13,7 +14,7 @@ use Illuminate\Queue\SerializesModels;
|
|||
* Interne Benachrichtigung an den Betreiber über eine neue Online-Kündigung
|
||||
* (Kündigungsbutton § 312k BGB) — Bearbeitung über die Admin-Queue.
|
||||
*/
|
||||
class TerminationRequestSubmitted extends Mailable
|
||||
class TerminationRequestSubmitted extends Mailable implements ShouldQueue
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace App\Mail;
|
|||
|
||||
use App\Models\WithdrawalRequest;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
@ -13,7 +14,7 @@ use Illuminate\Queue\SerializesModels;
|
|||
* Sofortige automatische Eingangsbestätigung an den Verbraucher — gesetzlich
|
||||
* vorgeschrieben beim Online-Widerruf (Widerrufsbutton).
|
||||
*/
|
||||
class WithdrawalRequestReceived extends Mailable
|
||||
class WithdrawalRequestReceived extends Mailable implements ShouldQueue
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ namespace App\Mail;
|
|||
|
||||
use App\Models\WithdrawalRequest;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
|
|
@ -12,7 +13,7 @@ use Illuminate\Queue\SerializesModels;
|
|||
/**
|
||||
* Interne Benachrichtigung an den Betreiber über einen neuen Online-Widerruf.
|
||||
*/
|
||||
class WithdrawalRequestSubmitted extends Mailable
|
||||
class WithdrawalRequestSubmitted extends Mailable implements ShouldQueue
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
|
|
|
|||
|
|
@ -203,11 +203,11 @@ class ContactAccessService
|
|||
{
|
||||
$generated = $this->magicLinks->createLoginLink($user, $ip);
|
||||
|
||||
Mail::to($user->email)->send(new MagicLoginLink(
|
||||
Mail::to($user->email)->queue((new MagicLoginLink(
|
||||
user: $user,
|
||||
loginUrl: route('magic-links.consume', ['token' => $generated['plain_token']]),
|
||||
expiresAt: $generated['expires_at']->format('d.m.Y H:i'),
|
||||
));
|
||||
))->afterCommit());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue