203 lines
8.2 KiB
PHP
Executable file
203 lines
8.2 KiB
PHP
Executable file
<?php
|
|
|
|
namespace App\Http\Controllers\Portal\Auth;
|
|
|
|
use Carbon\Carbon;
|
|
use App\Services\Util;
|
|
use Illuminate\Support\Str;
|
|
use App\Models\ShoppingUser;
|
|
use Illuminate\Http\Request;
|
|
use App\Mail\MailOTPCustomer;
|
|
use Illuminate\Support\Facades\DB;
|
|
use App\Http\Controllers\Controller;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Mail;
|
|
use Illuminate\Validation\ValidationException;
|
|
use App\Models\Customer; // Oder User, je nach Setup
|
|
use App\Models\OtpToken; // Zum Speichern/Prüfen des OTP
|
|
use Illuminate\Support\Facades\Hash; // Zum Hashen des Tokens
|
|
|
|
class LoginController extends Controller
|
|
{
|
|
// Zeigt das Formular zur Eingabe der E-Mail an
|
|
public function showLoginForm()
|
|
{
|
|
//wenn als Berater eingeloggt, dann zum Login wechseln
|
|
if (Auth::guard('user')->check()) {
|
|
return redirect()->route('portal.change_login');
|
|
}
|
|
//wenn als Kunde eingeloggt, dann direkt zum Dashboard
|
|
if (Auth::guard('customers')->check()) {
|
|
return redirect()->route('portal.dashboard');
|
|
}
|
|
return view('portal.auth.login'); // Erstelle diese View
|
|
}
|
|
|
|
// Sendet das OTP
|
|
public function sendOtp(Request $request)
|
|
{
|
|
$request->validate(['email' => 'required|email']);
|
|
$email = $request->input('email');
|
|
|
|
// 1. Prüfen, ob die E-Mail im System bekannt ist über Kunden-Tabelle)
|
|
$customer = Customer::firstOrCreate(['email' => $email]); // Erstellt Kunden, wenn nicht vorhanden
|
|
if ($customer && $customer->language) {
|
|
\App::setLocale($customer->language);
|
|
}
|
|
|
|
// if (!$customerExists && !$orderExists) { // Oder nur eine Prüfung, je nach Logik
|
|
if (!$customer) { // Prüfung anhand des Customer-Models
|
|
throw ValidationException::withMessages([
|
|
'email' => __('auth.failed_customer'), // Generische Fehlermeldung
|
|
]);
|
|
}
|
|
// 2. Alten Token löschen (optional, aber empfohlen)
|
|
DB::table('otp_tokens')->where('email', $email)->delete();
|
|
|
|
// 3. OTP generieren (z.B. 6-stellige Zahl)
|
|
$otp = random_int(100000, 999999);
|
|
$expiresAt = Carbon::now()->addMinutes(10); // Gültigkeit z.B. 10 Minuten
|
|
|
|
// 4. OTP (gehasht!) speichern
|
|
DB::table('otp_tokens')->insert([
|
|
'email' => $email,
|
|
'token' => Hash::make((string)$otp), // WICHTIG: Token hashen!
|
|
'expires_at' => $expiresAt,
|
|
'created_at' => Carbon::now(),
|
|
]);
|
|
|
|
// 5. OTP per E-Mail senden (Notification oder Mailable verwenden)
|
|
try {
|
|
Mail::to($email)->locale(\App::getLocale())->send(new MailOTPCustomer($otp, $email));
|
|
} catch (\Exception $e) {
|
|
// Logge den Fehler
|
|
\Log::error('OTP Send Error: ' . $e->getMessage());
|
|
// Gib eine Fehlermeldung zurück, ohne Details preiszugeben
|
|
return back()->withErrors(['email' => 'Konnte E-Mail nicht senden. Bitte versuchen Sie es später erneut.'])->withInput();
|
|
}
|
|
|
|
|
|
// 6. Zum OTP-Eingabeformular weiterleiten (E-Mail in Session speichern oder als Parameter übergeben)
|
|
session(['otp_email' => $email]); // Explizit in Session speichern
|
|
return redirect()->route('portal.login.otp.form', ['email' => $email]); // E-Mail auch als Parameter übergeben
|
|
}
|
|
|
|
// Zeigt das Formular zur Eingabe des OTP an
|
|
public function showOtpForm(Request $request, $email = null, $otp = null)
|
|
{
|
|
//wenn als Berater eingeloggt, dann zum Login wechseln
|
|
if (Auth::guard('user')->check()) {
|
|
return redirect()->route('portal.change_login');
|
|
}
|
|
//wenn als Kunde eingeloggt, dann zum Dashboard wechseln
|
|
if (Auth::guard('customers')->check()) {
|
|
return redirect()->route('portal.dashboard');
|
|
}
|
|
// E-Mail aus der Session holen (oder als Request-Parameter erwarten)
|
|
if ($email) {
|
|
$email = $email;
|
|
} else {
|
|
$email = session('otp_email', $request->query('email'));
|
|
}
|
|
if (!$email) {
|
|
return redirect()->route('portal.login.form')->withErrors(['message' => 'Sitzung abgelaufen oder E-Mail fehlt.']);
|
|
}
|
|
|
|
// CSRF-Token regenerieren für neue Session
|
|
$request->session()->regenerateToken();
|
|
|
|
// Übergebe sowohl 'email' als auch 'otp' an die View
|
|
return view('portal.auth.verify-otp', ['email' => $email, 'otp_value' => $otp]); // Variable umbenannt zu otp_value für Klarheit
|
|
}
|
|
|
|
// Validiert das OTP und loggt den Kunden ein
|
|
public function verifyOtpAndLogin(Request $request)
|
|
{
|
|
$request->validate([
|
|
'email' => 'required|email',
|
|
'otp' => 'required|numeric|digits:6', // An die Länge deines OTPs anpassen
|
|
]);
|
|
|
|
$email = $request->input('email');
|
|
$otpInput = $request->input('otp');
|
|
|
|
// 1. Gespeicherten OTP-Eintrag finden
|
|
$otpRecord = DB::table('otp_tokens')->where('email', $email)->first();
|
|
|
|
// 2. Prüfen ob Eintrag existiert, nicht abgelaufen ist und das OTP (Hash) übereinstimmt
|
|
if (!$otpRecord || Carbon::now()->gt($otpRecord->expires_at) || !Hash::check($otpInput, $otpRecord->token)) {
|
|
// Ungültiges oder abgelaufenes OTP
|
|
DB::table('otp_tokens')->where('email', $email)->delete(); // Ungültigen Token löschen
|
|
return back()->withErrors(['otp' => 'Ungültiges oder abgelaufenes Einmalpasswort.'])->withInput(['email' => $email]);
|
|
}
|
|
// 3. Kunden-Objekt finden (basierend auf dem Provider-Model)
|
|
$customer = Customer::where('email', $email)->first(); // Oder User::where('email', $email)->where('role','customer')->first();
|
|
|
|
if (!$customer) {
|
|
// Sollte eigentlich nicht passieren, wenn sendOtp korrekt funktioniert hat
|
|
DB::table('otp_tokens')->where('email', $email)->delete();
|
|
return back()->withErrors(['otp' => __('auth.failed')])->withInput(['email' => $email]);
|
|
}
|
|
// 4. Kunden einloggen über den 'customers'-Guard
|
|
Auth::guard('customers')->login($customer); // Loggt den gefundenen Kunden ein
|
|
|
|
// 5. Explizite Session-Speicherung
|
|
$request->session()->save();
|
|
|
|
// 6. OTP-Eintrag löschen
|
|
DB::table('otp_tokens')->where('email', $email)->delete();
|
|
|
|
// 7. Session Token regenerieren (statt komplette Session)
|
|
$request->session()->regenerate();
|
|
|
|
// 8. customer DB aktualisieren
|
|
$shopping_user = ShoppingUser::where('billing_email', $email)->latest()->first();
|
|
if ($shopping_user) {
|
|
$data = [
|
|
'name' => $shopping_user->billing_firstname . ' ' . $shopping_user->billing_lastname,
|
|
'shopping_user_id' => $shopping_user->id,
|
|
'member_id' => $shopping_user->member_id,
|
|
'number' => $shopping_user->number,
|
|
'language' => session('locale') ?? 'de',
|
|
];
|
|
$customer->update($data);
|
|
} else {
|
|
$data = [
|
|
'name' => __('portal.guest'),
|
|
'shopping_user_id' => null,
|
|
'member_id' => null,
|
|
'number' => null,
|
|
'language' => session('locale') ?? 'de',
|
|
];
|
|
$customer->update($data);
|
|
}
|
|
|
|
|
|
// 10. Zum Kunden-Dashboard weiterleiten
|
|
return redirect()->intended(route('portal.dashboard')); // intended() leitet zur ursprünglich angefragten Seite weiter
|
|
}
|
|
|
|
// Logout für Kunden
|
|
public function logout(Request $request)
|
|
{
|
|
$url = Util::getMyMivitaShopUrl();
|
|
Auth::guard('customers')->logout();
|
|
$request->session()->invalidate();
|
|
$request->session()->regenerateToken();
|
|
return redirect($url);
|
|
}
|
|
|
|
// Logout für Berater
|
|
public function logoutChange(Request $request)
|
|
{
|
|
//$url = Util::getMyMivitaShopUrl();
|
|
$user_shop_domain = session('user_shop_domain');
|
|
$locale = session('locale');
|
|
Auth::guard('user')->logout();
|
|
$request->session()->invalidate();
|
|
$request->session()->regenerateToken();
|
|
session(['user_shop_domain' => $user_shop_domain]);
|
|
session(['locale' => $locale]);
|
|
return redirect()->route('portal.login.form');
|
|
}
|
|
}
|