with('user') ->where('token_hash', hash('sha256', $token)) ->where('purpose', 'login') ->first(); if (! $magicLink || ! $magicLink->user) { return redirect()->route('login')->with('status', __('The magic login link is invalid.')); } if ($magicLink->consumed_at !== null || $magicLink->expires_at->isPast()) { return redirect()->route('login')->with('status', __('The magic login link has expired or was already used.')); } if (! $magicLink->user->is_active) { return redirect()->route('login')->with('status', __('Your account is not active.')); } // Atomar beanspruchen: nur EIN paralleler Request darf den Link // verbrauchen. Das konditionale UPDATE greift dank Zeilen-Atomarität // genau einmal; verliert ein Race, ist consumed_at bereits gesetzt. $claimed = MagicLink::query() ->whereKey($magicLink->id) ->whereNull('consumed_at') ->update([ 'consumed_at' => now(), 'ip_consumed' => $request->ip(), ]); if ($claimed === 0) { return redirect()->route('login')->with('status', __('The magic login link has expired or was already used.')); } $magicLink->user->update([ 'last_login_at' => now(), 'last_login_ip' => $request->ip(), ]); Auth::guard('web')->login($magicLink->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) : ($user->canAccessCustomer() ? route('me.dashboard', absolute: false) : '/'); return redirect($home); } }