login change
This commit is contained in:
@@ -1,5 +1,26 @@
|
|||||||
<?php
|
<?php
|
||||||
|
ini_set('display_errors', 0);
|
||||||
|
ini_set('display_startup_errors', 0);
|
||||||
|
error_reporting(E_ALL); // aber in ein Log schreiben lassen
|
||||||
|
if (php_sapi_name() !== 'cli') {
|
||||||
|
// Session nur starten, wenn noch keine läuft
|
||||||
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
|
|
||||||
|
// Optional: Session-Konfiguration vor session_start
|
||||||
|
session_name('usbcheck_session');
|
||||||
|
|
||||||
|
session_set_cookie_params([
|
||||||
|
'lifetime' => 0, // Session-Cookie
|
||||||
|
'path' => '/',
|
||||||
|
'domain' => '', // leer = aktuelle Domain
|
||||||
|
'secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'),
|
||||||
|
'httponly' => true,
|
||||||
|
'samesite' => 'Lax', // oder 'Strict' falls du sehr streng sein willst
|
||||||
|
]);
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
}
|
||||||
|
}
|
||||||
require __DIR__ . "/config.php";
|
require __DIR__ . "/config.php";
|
||||||
require __DIR__ . "/db.php";
|
require __DIR__ . "/db.php";
|
||||||
require __DIR__ . '/../src/functions.php';
|
require __DIR__ . '/../src/functions.php';
|
||||||
|
|||||||
@@ -2,6 +2,26 @@
|
|||||||
ini_set('display_errors', 1);
|
ini_set('display_errors', 1);
|
||||||
ini_set('display_startup_errors', 1);
|
ini_set('display_startup_errors', 1);
|
||||||
error_reporting(E_ALL);
|
error_reporting(E_ALL);
|
||||||
|
// Nur im Web-Kontext (nicht in CLI-Skripten)
|
||||||
|
if (php_sapi_name() !== 'cli') {
|
||||||
|
// Session nur starten, wenn noch keine läuft
|
||||||
|
if (session_status() === PHP_SESSION_NONE) {
|
||||||
|
|
||||||
|
// Optional: Session-Konfiguration vor session_start
|
||||||
|
session_name('usbcheck_session');
|
||||||
|
|
||||||
|
session_set_cookie_params([
|
||||||
|
'lifetime' => 0, // Session-Cookie
|
||||||
|
'path' => '/',
|
||||||
|
'domain' => '', // leer = aktuelle Domain
|
||||||
|
'secure' => (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off'),
|
||||||
|
'httponly' => true,
|
||||||
|
'samesite' => 'Lax', // oder 'Strict' falls du sehr streng sein willst
|
||||||
|
]);
|
||||||
|
|
||||||
|
session_start();
|
||||||
|
}
|
||||||
|
}
|
||||||
require __DIR__ . "/config.php";
|
require __DIR__ . "/config.php";
|
||||||
require __DIR__ . "/db.php";
|
require __DIR__ . "/db.php";
|
||||||
require __DIR__ . '/../src/functions.php';
|
require __DIR__ . '/../src/functions.php';
|
||||||
|
|||||||
@@ -1,6 +1,19 @@
|
|||||||
<?php
|
<?php
|
||||||
// Fallback falls $authView nicht gesetzt ist
|
// Fallback falls $authView nicht gesetzt ist
|
||||||
$authView = $authView ?? 'login';
|
$authView = $authView ?? 'login';
|
||||||
|
|
||||||
|
// Optional: View über GET-Parameter überschreiben (?view=login|register)
|
||||||
|
if (isset($_GET['view']) && in_array($_GET['view'], ['login', 'register'], true)) {
|
||||||
|
$authView = $_GET['view'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flash-Meldung holen (falls flash_get() existiert)
|
||||||
|
$flash = function_exists('flash_get') ? flash_get() : null;
|
||||||
|
|
||||||
|
// Wenn eine Flash-Message mit Kontext kommt, Tabs entsprechend umschalten
|
||||||
|
if ($flash && !empty($flash['context']) && in_array($flash['context'], ['login', 'register'], true)) {
|
||||||
|
$authView = $flash['context'];
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
<section id="auth" class="border-t border-brand-border/70 bg-brand-primarySoft/20">
|
<section id="auth" class="border-t border-brand-border/70 bg-brand-primarySoft/20">
|
||||||
<div class="mx-auto max-w-xl px-4 sm:px-6 lg:px-8 py-16 sm:py-20">
|
<div class="mx-auto max-w-xl px-4 sm:px-6 lg:px-8 py-16 sm:py-20">
|
||||||
@@ -16,6 +29,20 @@ $authView = $authView ?? 'login';
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<?php if ($flash): ?>
|
||||||
|
<div class="mb-6 rounded-xl px-4 py-3 text-sm border
|
||||||
|
<?php if ($flash['type'] === 'error'): ?>
|
||||||
|
border-red-500/60 bg-red-500/10 text-red-300
|
||||||
|
<?php elseif ($flash['type'] === 'success'): ?>
|
||||||
|
border-emerald-500/60 bg-emerald-500/10 text-emerald-300
|
||||||
|
<?php else: ?>
|
||||||
|
border-brand-border bg-brand-bg/60 text-brand-muted
|
||||||
|
<?php endif; ?>
|
||||||
|
">
|
||||||
|
<?= htmlspecialchars($flash['message']) ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<!-- Tabs -->
|
<!-- Tabs -->
|
||||||
<div class="mb-6 rounded-full border border-brand-border bg-brand-surface/80 p-1 flex text-xs font-semibold uppercase tracking-[0.18em] text-brand-muted">
|
<div class="mb-6 rounded-full border border-brand-border bg-brand-surface/80 p-1 flex text-xs font-semibold uppercase tracking-[0.18em] text-brand-muted">
|
||||||
<button
|
<button
|
||||||
@@ -47,8 +74,10 @@ $authView = $authView ?? 'login';
|
|||||||
Melde dich mit deiner E-Mail-Adresse und deinem Passwort an.
|
Melde dich mit deiner E-Mail-Adresse und deinem Passwort an.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<form method="post" action="/login/?lang=<?= htmlspecialchars($lang) ?>" class="space-y-4" autocomplete="on">
|
<form method="post" action="/auth/login" class="space-y-4" autocomplete="on">
|
||||||
<input type="hidden" name="action" value="login">
|
<input type="hidden" name="lang" value="<?= htmlspecialchars($lang ?? 'de') ?>">
|
||||||
|
<input type="hidden" name="redirect" value="<?= htmlspecialchars($_GET['redirect'] ?? '/') ?>">
|
||||||
|
<input type="hidden" name="authView" value="login">
|
||||||
|
|
||||||
<div class="space-y-1">
|
<div class="space-y-1">
|
||||||
<label for="login_email" class="block text-xs font-semibold tracking-wide uppercase text-brand-muted" data-i18n="auth_login_email_label">
|
<label for="login_email" class="block text-xs font-semibold tracking-wide uppercase text-brand-muted" data-i18n="auth_login_email_label">
|
||||||
@@ -108,8 +137,10 @@ $authView = $authView ?? 'login';
|
|||||||
Erstelle einen kostenlosen Account, um Tests zu speichern, Berichte zu exportieren und den Pro-Modus später freizuschalten.
|
Erstelle einen kostenlosen Account, um Tests zu speichern, Berichte zu exportieren und den Pro-Modus später freizuschalten.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<form method="post" action="/login/?lang=<?= htmlspecialchars($lang) ?>" class="space-y-4" autocomplete="on">
|
<form method="post" action="/auth/register" class="space-y-4" autocomplete="on">
|
||||||
<input type="hidden" name="action" value="register">
|
<input type="hidden" name="lang" value="<?= htmlspecialchars($lang ?? 'de') ?>">
|
||||||
|
<input type="hidden" name="redirect" value="<?= htmlspecialchars($_GET['redirect'] ?? '/') ?>">
|
||||||
|
<input type="hidden" name="authView" value="register">
|
||||||
|
|
||||||
<div class="space-y-1">
|
<div class="space-y-1">
|
||||||
<label for="reg_name" class="block text-xs font-semibold tracking-wide uppercase text-brand-muted" data-i18n="auth_register_name_label">
|
<label for="reg_name" class="block text-xs font-semibold tracking-wide uppercase text-brand-muted" data-i18n="auth_register_name_label">
|
||||||
|
|||||||
@@ -10,6 +10,40 @@ $baseUrl = $scheme . '://' . $host;
|
|||||||
if (!isset($navAnchors) || !is_array($navAnchors)) {
|
if (!isset($navAnchors) || !is_array($navAnchors)) {
|
||||||
$navAnchors = [];
|
$navAnchors = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Session sollte in config/fileload.php bereits gestartet sein.
|
||||||
|
// Falls nicht, hier Fallback:
|
||||||
|
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||||
|
@session_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// aktuellen User aus der Session holen (wenn vorhanden)
|
||||||
|
$currentUser = $_SESSION['user'] ?? null;
|
||||||
|
$isLoggedIn = is_array($currentUser) && !empty($currentUser['id']);
|
||||||
|
|
||||||
|
// Initialen für Avatar bestimmen
|
||||||
|
$userInitials = null;
|
||||||
|
if ($isLoggedIn) {
|
||||||
|
if (!empty($currentUser['initials'])) {
|
||||||
|
$userInitials = $currentUser['initials'];
|
||||||
|
} else {
|
||||||
|
$firstName = $currentUser['first_name'] ?? '';
|
||||||
|
$lastName = $currentUser['last_name'] ?? '';
|
||||||
|
$username = $currentUser['username'] ?? ($currentUser['email'] ?? 'U');
|
||||||
|
|
||||||
|
$initials = '';
|
||||||
|
if ($firstName !== '') {
|
||||||
|
$initials .= mb_substr($firstName, 0, 1);
|
||||||
|
}
|
||||||
|
if ($lastName !== '') {
|
||||||
|
$initials .= mb_substr($lastName, 0, 1);
|
||||||
|
}
|
||||||
|
if ($initials === '') {
|
||||||
|
$initials = mb_substr($username, 0, 2);
|
||||||
|
}
|
||||||
|
$userInitials = mb_strtoupper($initials);
|
||||||
|
}
|
||||||
|
}
|
||||||
?>
|
?>
|
||||||
<header class="sticky top-0 z-40 border-b border-brand-border/70 backdrop-blur bg-brand-bg/85">
|
<header class="sticky top-0 z-40 border-b border-brand-border/70 backdrop-blur bg-brand-bg/85">
|
||||||
<div class="mx-auto max-w-6xl px-4 sm:px-6 lg:px-8 flex items-center justify-between h-16">
|
<div class="mx-auto max-w-6xl px-4 sm:px-6 lg:px-8 flex items-center justify-between h-16">
|
||||||
@@ -44,6 +78,7 @@ if (!isset($navAnchors) || !is_array($navAnchors)) {
|
|||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
<!-- Language Switcher -->
|
||||||
<div class="relative">
|
<div class="relative">
|
||||||
<button id="langCurrent"
|
<button id="langCurrent"
|
||||||
type="button"
|
type="button"
|
||||||
@@ -84,19 +119,22 @@ if (!isset($navAnchors) || !is_array($navAnchors)) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Login Button / Avatar -->
|
<!-- Login Button / Avatar -->
|
||||||
<a href="/login/?lang=<?= htmlspecialchars($lang) ?>"
|
<?php if (!$isLoggedIn): ?>
|
||||||
id="loginButton"
|
<!-- Nicht eingeloggt: Login-Button anzeigen -->
|
||||||
class="relative inline-flex items-center justify-center rounded-full bg-brand-primary px-4 py-1.5 text-xs font-semibold uppercase tracking-[0.18em] text-brand-bg shadow-soft hover:bg-cyan-400 transition-colors"
|
<button id="loginButton"
|
||||||
data-i18n="header_btn_login">
|
class="relative inline-flex items-center justify-center rounded-full bg-brand-primary px-4 py-1.5 text-xs font-semibold uppercase tracking-[0.18em] text-brand-bg shadow-soft hover:bg-cyan-400 transition-colors"
|
||||||
Login
|
data-i18n="header_btn_login">
|
||||||
</a>
|
Login
|
||||||
<button id="userAvatar"
|
</button>
|
||||||
class="hidden h-9 w-9 rounded-full border border-brand-border bg-brand-surface flex items-center justify-center text-xs font-semibold text-brand-text shadow-soft hover:border-brand-primary transition"
|
<?php else: ?>
|
||||||
aria-label="Mein Konto">
|
<!-- Eingeloggt: Avatar anzeigen -->
|
||||||
<span><?= strtoupper(substr($userInitials ?? 'U', 0, 2)) ?></span>
|
<button id="userAvatar"
|
||||||
</button>
|
class="h-9 w-9 rounded-full border border-brand-border bg-brand-surface flex items-center justify-center text-xs font-semibold text-brand-text shadow-soft hover:border-brand-primary transition"
|
||||||
|
aria-label="Mein Konto">
|
||||||
|
<span><?= htmlspecialchars($userInitials) ?></span>
|
||||||
|
</button>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@@ -4,6 +4,14 @@ RewriteEngine On
|
|||||||
RewriteCond %{HTTP_HOST} (^|\.)ismyusbfake\.com$ [NC]
|
RewriteCond %{HTTP_HOST} (^|\.)ismyusbfake\.com$ [NC]
|
||||||
RewriteRule ^$ /fakecheck/ [L,R=301]
|
RewriteRule ^$ /fakecheck/ [L,R=301]
|
||||||
|
|
||||||
|
# 1b) Auth-Routen auf Backend-Handler außerhalb von /public/ mappen
|
||||||
|
# /auth/login -> ../src/auth/login.php
|
||||||
|
# /auth/register -> ../src/auth/register.php
|
||||||
|
# /auth/logout -> ../src/auth/logout.php
|
||||||
|
RewriteRule ^auth/login/?$ ../src/auth/login.php [L]
|
||||||
|
RewriteRule ^auth/register/?$ ../src/auth/register.php [L]
|
||||||
|
RewriteRule ^auth/logout/?$ ../src/auth/logout.php [L]
|
||||||
|
|
||||||
# 2) Deine bisherigen Regeln
|
# 2) Deine bisherigen Regeln
|
||||||
RewriteCond %{REQUEST_FILENAME} -f [OR]
|
RewriteCond %{REQUEST_FILENAME} -f [OR]
|
||||||
RewriteCond %{REQUEST_FILENAME} -d
|
RewriteCond %{REQUEST_FILENAME} -d
|
||||||
|
|||||||
136
src/auth/login.php
Normal file
136
src/auth/login.php
Normal file
@@ -0,0 +1,136 @@
|
|||||||
|
<?php
|
||||||
|
// public/auth/login.php
|
||||||
|
|
||||||
|
// Gemeinsame Bootstrap-/Config-Datei laden
|
||||||
|
require __DIR__ . '/../../config/fileload.php'; // Pfad ggf. anpassen
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
|
// Direktzugriff per GET → einfach zurück zur Login-Seite
|
||||||
|
$lang = $_GET['lang'] ?? 'de';
|
||||||
|
header('Location: /login/?lang=' . urlencode($lang) . '&view=login#auth');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Daten einsammeln
|
||||||
|
$lang = $_POST['lang'] ?? 'de';
|
||||||
|
$email = trim((string)($_POST['email'] ?? ''));
|
||||||
|
$password = (string)($_POST['password'] ?? '');
|
||||||
|
$redirect = $_POST['redirect'] ?? '/';
|
||||||
|
|
||||||
|
// Minimale 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Annahme: $pdo ist in fileload.php / db.php gesetzt (PDO-Instanz)
|
||||||
|
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 (optional)
|
||||||
|
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) {
|
||||||
|
// Ignorieren, Login-Fehler 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 → Fehlversuche zurücksetzen & letztes Login speichern
|
||||||
|
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
|
||||||
|
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||||
|
@session_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialen bauen
|
||||||
|
$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 für „Willkommen“
|
||||||
|
flash_set('success', 'Willkommen zurück, ' . ($user['first_name'] ?: 'User') . '!', 'login');
|
||||||
|
|
||||||
|
// Redirect-Ziel prüfen (nur interne Pfade erlauben)
|
||||||
|
$target = is_string($redirect) ? trim($redirect) : '/';
|
||||||
|
if ($target === '' || $target[0] !== '/') {
|
||||||
|
$target = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sprache ggf. anfügen, wenn noch nicht als Parameter vorhanden
|
||||||
|
$sep = (strpos($target, '?') === false) ? '?' : '&';
|
||||||
|
$target = $target . $sep . 'lang=' . urlencode($lang);
|
||||||
|
|
||||||
|
header('Location: ' . $target);
|
||||||
|
exit;
|
||||||
22
src/auth/logout.php
Normal file
22
src/auth/logout.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
// public/auth/logout.php
|
||||||
|
|
||||||
|
require __DIR__ . '/../../config/fileload.php'; // Pfad ggf. anpassen
|
||||||
|
|
||||||
|
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||||
|
@session_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Session leeren, aber NICHT komplett zerstören,
|
||||||
|
// damit flash_set noch funktionieren kann.
|
||||||
|
$_SESSION = [];
|
||||||
|
session_regenerate_id(true);
|
||||||
|
|
||||||
|
// Sprache aus GET, falls vorhanden
|
||||||
|
$lang = $_GET['lang'] ?? 'de';
|
||||||
|
|
||||||
|
flash_set('success', 'Du wurdest erfolgreich ausgeloggt.', 'login');
|
||||||
|
|
||||||
|
// Zur Startseite zurück
|
||||||
|
header('Location: /?lang=' . urlencode($lang));
|
||||||
|
exit;
|
||||||
124
src/auth/register.php
Normal file
124
src/auth/register.php
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
<?php
|
||||||
|
// public/auth/register.php
|
||||||
|
|
||||||
|
require __DIR__ . '/../../config/fileload.php'; // Pfad ggf. anpassen
|
||||||
|
|
||||||
|
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||||
|
$lang = $_GET['lang'] ?? 'de';
|
||||||
|
header('Location: /login/?lang=' . urlencode($lang) . '&view=register#auth');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
$lang = $_POST['lang'] ?? 'de';
|
||||||
|
$name = trim((string)($_POST['name'] ?? ''));
|
||||||
|
$email = trim((string)($_POST['email'] ?? ''));
|
||||||
|
$password = (string)($_POST['password'] ?? '');
|
||||||
|
$redirect = $_POST['redirect'] ?? '/';
|
||||||
|
|
||||||
|
if ($name === '' || $email === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) {
|
||||||
|
flash_set('error', 'Bitte einen gültigen Namen und eine gültige E-Mail-Adresse eingeben.', 'register');
|
||||||
|
header('Location: /login/?lang=' . urlencode($lang) . '&view=register#auth');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strlen($password) < 8) {
|
||||||
|
flash_set('error', 'Das Passwort muss mindestens 8 Zeichen lang sein.', 'register');
|
||||||
|
header('Location: /login/?lang=' . urlencode($lang) . '&view=register#auth');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prüfen, ob E-Mail bereits existiert
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare('SELECT id FROM users WHERE email = :email LIMIT 1');
|
||||||
|
$stmt->execute([':email' => $email]);
|
||||||
|
$existing = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
flash_set('error', 'Es ist ein Fehler bei der Registrierung aufgetreten. Bitte versuche es später erneut.', 'register');
|
||||||
|
header('Location: /login/?lang=' . urlencode($lang) . '&view=register#auth');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($existing) {
|
||||||
|
flash_set('error', 'Diese E-Mail-Adresse ist bereits registriert.', 'register');
|
||||||
|
header('Location: /login/?lang=' . urlencode($lang) . '&view=register#auth');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Username aus E-Mail ableiten (oder einfach die komplette E-Mail nutzen)
|
||||||
|
$username = $email;
|
||||||
|
|
||||||
|
// Vor- und Nachname grob aus dem „Name“-Feld splitten
|
||||||
|
$firstName = $name;
|
||||||
|
$lastName = null;
|
||||||
|
|
||||||
|
$parts = preg_split('/\s+/', $name);
|
||||||
|
if (count($parts) >= 2) {
|
||||||
|
$firstName = array_shift($parts);
|
||||||
|
$lastName = implode(' ', $parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$stmt = $pdo->prepare('
|
||||||
|
INSERT INTO users
|
||||||
|
(username, email, password_hash, first_name, last_name, plan)
|
||||||
|
VALUES
|
||||||
|
(:username, :email, :password_hash, :first_name, :last_name, :plan)
|
||||||
|
');
|
||||||
|
$stmt->execute([
|
||||||
|
':username' => $username,
|
||||||
|
':email' => $email,
|
||||||
|
':password_hash' => $passwordHash,
|
||||||
|
':first_name' => $firstName,
|
||||||
|
':last_name' => $lastName,
|
||||||
|
':plan' => 'free',
|
||||||
|
]);
|
||||||
|
|
||||||
|
$userId = (int)$pdo->lastInsertId();
|
||||||
|
} catch (Throwable $e) {
|
||||||
|
flash_set('error', 'Die Registrierung ist fehlgeschlagen. Bitte versuche es später erneut.', 'register');
|
||||||
|
header('Location: /login/?lang=' . urlencode($lang) . '&view=register#auth');
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Direkt einloggen
|
||||||
|
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||||
|
@session_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
$initials = '';
|
||||||
|
if ($firstName !== '') {
|
||||||
|
$initials .= mb_substr($firstName, 0, 1);
|
||||||
|
}
|
||||||
|
if ($lastName !== null && $lastName !== '') {
|
||||||
|
$initials .= mb_substr($lastName, 0, 1);
|
||||||
|
}
|
||||||
|
if ($initials === '') {
|
||||||
|
$initials = mb_substr($username, 0, 2);
|
||||||
|
}
|
||||||
|
$initials = mb_strtoupper($initials);
|
||||||
|
|
||||||
|
$_SESSION['user'] = [
|
||||||
|
'id' => $userId,
|
||||||
|
'email' => $email,
|
||||||
|
'username' => $username,
|
||||||
|
'first_name' => $firstName,
|
||||||
|
'last_name' => $lastName,
|
||||||
|
'plan' => 'free',
|
||||||
|
'initials' => $initials,
|
||||||
|
];
|
||||||
|
|
||||||
|
flash_set('success', 'Konto erfolgreich erstellt. Willkommen bei USBCheck!', 'login');
|
||||||
|
|
||||||
|
// Redirect-Ziel prüfen (nur interne Pfade)
|
||||||
|
$target = is_string($redirect) ? trim($redirect) : '/';
|
||||||
|
if ($target === '' || $target[0] !== '/') {
|
||||||
|
$target = '/';
|
||||||
|
}
|
||||||
|
|
||||||
|
$sep = (strpos($target, '?') === false) ? '?' : '&';
|
||||||
|
$target = $target . $sep . 'lang=' . urlencode($lang);
|
||||||
|
|
||||||
|
header('Location: ' . $target);
|
||||||
|
exit;
|
||||||
@@ -76,39 +76,78 @@ function tpl_add_style(string $href, string $pos = 'header', ?string $version =
|
|||||||
|
|
||||||
function tpl(string $file, string $type = 'structure', string $site = 'main'): void
|
function tpl(string $file, string $type = 'structure', string $site = 'main'): void
|
||||||
{
|
{
|
||||||
|
|
||||||
// Basisordner
|
|
||||||
$base = __DIR__ . '/../partials/';
|
$base = __DIR__ . '/../partials/';
|
||||||
|
|
||||||
// Erlaubte Typen & Sites
|
// VALIDIERUNG: Nur einfache Check, kein Path-Traversal
|
||||||
$allowedTypes = ['structure', 'landing'];
|
if (preg_match('/[^a-zA-Z0-9_\-]/', $file)) {
|
||||||
$allowedSites = ['main', 'fakecheck','login'];
|
echo "<!-- tpl(): Ungültiger Template-Name -->";
|
||||||
|
return;
|
||||||
// Validierung
|
}
|
||||||
if (!in_array($type, $allowedTypes)) {
|
if (preg_match('/[^a-zA-Z0-9_\-]/', $type)) {
|
||||||
$type = 'structure';
|
echo "<!-- tpl(): Ungültiger Type -->";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (preg_match('/[^a-zA-Z0-9_\-]/', $site)) {
|
||||||
|
echo "<!-- tpl(): Ungültiger Site -->";
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!in_array($site, $allowedSites)) {
|
|
||||||
$site = 'main';
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zielpfad konstruieren
|
|
||||||
if ($type === 'landing') {
|
if ($type === 'landing') {
|
||||||
// landing -> landing/{site}/{file}.php
|
|
||||||
$path = $base . "landing/$site/$file.php";
|
$path = $base . "landing/$site/$file.php";
|
||||||
} else {
|
} else {
|
||||||
// structure -> structure/{file}.php
|
|
||||||
$path = $base . "structure/$file.php";
|
$path = $base . "structure/$file.php";
|
||||||
}
|
}
|
||||||
// 🔹 alle globalen Variablen (aus index.php) in den lokalen Scope holen
|
|
||||||
extract($GLOBALS, EXTR_SKIP);
|
extract($GLOBALS, EXTR_SKIP);
|
||||||
|
|
||||||
// Datei laden
|
|
||||||
if (file_exists($path)) {
|
if (file_exists($path)) {
|
||||||
include $path;
|
include $path;
|
||||||
} else {
|
} else {
|
||||||
echo "<!-- tpl(): Datei nicht gefunden: $path -->";
|
echo "<!-- tpl(): Datei nicht gefunden: $path -->";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flash-Meldung setzen (wird genau einmal nach Redirect angezeigt).
|
||||||
|
*
|
||||||
|
* @param string $type z.B. 'success', 'error', 'info', 'warning'
|
||||||
|
* @param string $message Die Meldung für den Nutzer
|
||||||
|
*/
|
||||||
|
function flash_set(string $type, string $message, string $context = null): void
|
||||||
|
{
|
||||||
|
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||||
|
@session_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
$_SESSION['flash'] = [
|
||||||
|
'type' => $type,
|
||||||
|
'message' => $message,
|
||||||
|
'context' => $context,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flash-Meldung holen und direkt löschen (Einmal-Anzeige).
|
||||||
|
*
|
||||||
|
* @return array|null ['type' => 'success|error|info|warning', 'message' => '...']
|
||||||
|
*/
|
||||||
|
function flash_get(): ?array
|
||||||
|
{
|
||||||
|
if (session_status() !== PHP_SESSION_ACTIVE) {
|
||||||
|
@session_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($_SESSION['flash']) || !is_array($_SESSION['flash'])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
$flash = $_SESSION['flash'];
|
||||||
|
unset($_SESSION['flash']);
|
||||||
|
|
||||||
|
$flash['type'] = $flash['type'] ?? 'info';
|
||||||
|
$flash['message'] = $flash['message'] ?? '';
|
||||||
|
$flash['context'] = $flash['context'] ?? null;
|
||||||
|
|
||||||
|
return $flash;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user