191 lines
5.9 KiB
PHP
191 lines
5.9 KiB
PHP
<?php
|
||
// src/auth/login.php
|
||
// wird durch public/auth/login.php aufgerufen
|
||
|
||
// Basis-Setup: Session, $pdo, flash_*, Sprachlogik etc.
|
||
require_once $_SERVER['DOCUMENT_ROOT']. '/../config/fileload.php';
|
||
|
||
// Sprache aus der zentralen Sprachlogik holen
|
||
// (fileload.php sollte $GLOBALS['lang'] anhand von URL, Session, Browser etc. setzen)
|
||
$lang = $GLOBALS['lang'] ?? 'en';
|
||
|
||
// Nur POST zulassen – alles andere zurück zur Login-Seite
|
||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||
$target = '/login/?lang=' . urlencode($lang) . '&view=login#auth';
|
||
header('Location: ' . $target);
|
||
exit;
|
||
}
|
||
|
||
// ---------------------------------------------------------
|
||
// Form-Daten einsammeln
|
||
// ---------------------------------------------------------
|
||
$email = trim((string)($_POST['email'] ?? ''));
|
||
$password = (string)($_POST['password'] ?? '');
|
||
$redirect = $_POST['redirect'] ?? '/';
|
||
|
||
// (Optional) Falls das Formular noch ein <input name="lang"> hat,
|
||
// kannst du das nutzen, falls kein $GLOBALS['lang'] gesetzt ist:
|
||
if (empty($lang) && !empty($_POST['lang'])) {
|
||
$lang = substr((string)$_POST['lang'], 0, 2);
|
||
}
|
||
|
||
// Minimal-Validierung
|
||
if (
|
||
$email === '' ||
|
||
!filter_var($email, FILTER_VALIDATE_EMAIL) ||
|
||
$password === ''
|
||
) {
|
||
flash_set('error', 'Bitte E-Mail-Adresse und Passwort eingeben.', 'login');
|
||
header('Location: /login/?lang=' . urlencode($lang) . '&view=login#auth');
|
||
exit;
|
||
}
|
||
|
||
/* ---------------------------------------------------------
|
||
USER LADEN
|
||
--------------------------------------------------------- */
|
||
|
||
try {
|
||
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email LIMIT 1');
|
||
$stmt->execute([':email' => $email]);
|
||
$user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||
} catch (Throwable $e) {
|
||
// DB-Fehler → generische Meldung
|
||
flash_set('error', 'Es ist ein Fehler beim Login aufgetreten. Bitte versuche es später erneut.', 'login');
|
||
header('Location: /login/?lang=' . urlencode($lang) . '&view=login#auth');
|
||
exit;
|
||
}
|
||
|
||
if (!$user) {
|
||
flash_set('error', 'E-Mail oder Passwort ist falsch.', 'login');
|
||
header('Location: /login/?lang=' . urlencode($lang) . '&view=login#auth');
|
||
exit;
|
||
}
|
||
|
||
/* ---------------------------------------------------------
|
||
ACCOUNT GESPERRT?
|
||
--------------------------------------------------------- */
|
||
|
||
if (!empty($user['is_locked'])) {
|
||
flash_set('error', 'Dein Konto ist gesperrt. Bitte kontaktiere den Support.', 'login');
|
||
header('Location: /login/?lang=' . urlencode($lang) . '&view=login#auth');
|
||
exit;
|
||
}
|
||
|
||
/* ---------------------------------------------------------
|
||
PASSWORT PRÜFEN
|
||
--------------------------------------------------------- */
|
||
|
||
if (!password_verify($password, $user['password_hash'])) {
|
||
|
||
// Fehlversuche hochzählen
|
||
try {
|
||
$failed = (int)($user['failed_logins'] ?? 0) + 1;
|
||
$lock = 0;
|
||
|
||
if ($failed >= 5) {
|
||
$lock = 1;
|
||
}
|
||
|
||
$upd = $pdo->prepare('UPDATE users SET failed_logins = :failed, is_locked = :locked WHERE id = :id');
|
||
$upd->execute([
|
||
':failed' => $failed,
|
||
':locked' => $lock,
|
||
':id' => $user['id'],
|
||
]);
|
||
} catch (Throwable $e) {
|
||
// Nicht kritisch, Meldung reicht
|
||
}
|
||
|
||
$msg = 'E-Mail oder Passwort ist falsch.';
|
||
if (($user['failed_logins'] ?? 0) + 1 >= 5) {
|
||
$msg = 'Zu viele Fehlversuche. Dein Konto wurde vorübergehend gesperrt.';
|
||
}
|
||
|
||
flash_set('error', $msg, 'login');
|
||
header('Location: /login/?lang=' . urlencode($lang) . '&view=login#auth');
|
||
exit;
|
||
}
|
||
|
||
/* ---------------------------------------------------------
|
||
PASSWORT KORREKT → FAILED_LOGINS RESET + LAST_LOGIN
|
||
--------------------------------------------------------- */
|
||
|
||
try {
|
||
$upd = $pdo->prepare('UPDATE users SET failed_logins = 0, last_login_at = NOW() WHERE id = :id');
|
||
$upd->execute([':id' => $user['id']]);
|
||
} catch (Throwable $e) {
|
||
// Nicht kritisch für den Nutzer
|
||
}
|
||
|
||
/* ---------------------------------------------------------
|
||
SESSION FÜLLEN
|
||
--------------------------------------------------------- */
|
||
|
||
$firstName = $user['first_name'] ?? '';
|
||
$lastName = $user['last_name'] ?? '';
|
||
$initials = '';
|
||
|
||
if ($firstName !== '') {
|
||
$initials .= mb_substr($firstName, 0, 1);
|
||
}
|
||
if ($lastName !== '') {
|
||
$initials .= mb_substr($lastName, 0, 1);
|
||
}
|
||
if ($initials === '') {
|
||
$initials = mb_substr($user['username'] ?? $user['email'], 0, 2);
|
||
}
|
||
$initials = mb_strtoupper($initials);
|
||
|
||
$_SESSION['user'] = [
|
||
'id' => $user['id'],
|
||
'email' => $user['email'],
|
||
'username' => $user['username'],
|
||
'first_name' => $user['first_name'],
|
||
'last_name' => $user['last_name'],
|
||
'plan' => $user['plan'] ?? 'free',
|
||
'initials' => $initials,
|
||
];
|
||
|
||
/* ---------------------------------------------------------
|
||
FLASH & SMART REDIRECT
|
||
--------------------------------------------------------- */
|
||
|
||
flash_set('success', 'Willkommen zurück, ' . ($user['first_name'] ?: 'User') . '!', 'login');
|
||
|
||
// redirect normalisieren
|
||
$redirect = trim((string)($redirect ?? ''));
|
||
|
||
// Flag: sollen wir stattdessen aufs Dashboard?
|
||
$goDashboard = false;
|
||
|
||
// 1) redirect leer → Dashboard
|
||
if ($redirect === '') {
|
||
$goDashboard = true;
|
||
}
|
||
|
||
// 2) redirect zeigt auf /login → Dashboard (Endlosschleife vermeiden)
|
||
if (!$goDashboard && preg_match('#^/login(/|\?|$)#i', $redirect)) {
|
||
$goDashboard = true;
|
||
}
|
||
|
||
// 3) redirect ist keine interne URL → Dashboard (Sicherheit!)
|
||
if (!$goDashboard && strpos($redirect, '/') !== 0) {
|
||
$goDashboard = true;
|
||
}
|
||
|
||
// 4) Finales Ziel bestimmen
|
||
if ($goDashboard) {
|
||
// Immer Dashboard-Seite
|
||
$target = '/dashboard/?lang=' . urlencode($lang);
|
||
} else {
|
||
// Internes Ziel, Sprache anhängen falls noch nicht vorhanden
|
||
if (strpos($redirect, 'lang=') === false) {
|
||
$sep = (strpos($redirect, '?') === false) ? '?' : '&';
|
||
$redirect = $redirect . $sep . 'lang=' . urlencode($lang);
|
||
}
|
||
$target = $redirect;
|
||
}
|
||
|
||
header('Location: ' . $target);
|
||
exit;
|