load(); } $db = new PDO( "mysql:host={$_ENV['DB_HOST']};dbname={$_ENV['DB_NAME']};charset=utf8mb4", $_ENV['DB_USER'], $_ENV['DB_PASS'], [ PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, ] ); } return $db; } /** * Check if user is logged in */ function isLoggedIn(): bool { return isset($_SESSION['user_id']) && isset($_SESSION['user']) && !empty($_SESSION['user']); } /** * Get current logged in user */ function getCurrentUser(): ?array { return $_SESSION['user'] ?? null; } /** * Check if user has specific role */ function hasRole(string $role): bool { if (!isLoggedIn()) { return false; } return ($_SESSION['user']['role'] ?? '') === $role; } /** * Check if user is admin */ function isAdmin(): bool { return hasRole('admin'); } /** * Check if user is guest */ function isGuest(): bool { return hasRole('guest'); } /** * Check if user can perform write operations */ function canWrite(): bool { return isLoggedIn() && isAdmin(); } /** * Check if user can create */ function canCreate(): bool { return isAdmin(); } /** * Check if user can edit */ function canEdit(): bool { return isAdmin(); } /** * Check if user can delete */ function canDelete(): bool { return isAdmin(); } /** * Check if user can sync with Talpa */ function canSync(): bool { return isAdmin(); } /** * Require user to be logged in, redirect to login if not */ function requireLogin(): void { if (!isLoggedIn()) { $currentUrl = $_SERVER['REQUEST_URI'] ?? '/'; $redirect = urlencode(ltrim($currentUrl, '/')); header("Location: /auth/login.php?redirect=$redirect"); exit; } } /** * Require user to have specific role */ function requireRole(string $role): void { requireLogin(); if (!hasRole($role)) { http_response_code(403); include __DIR__ . '/403.php'; exit; } } /** * Require admin role */ function requireAdmin(): void { requireRole('admin'); } /** * Check brute force protection * Returns true if user is blocked */ function isBlockedByBruteForce(string $username, string $ip): bool { try { $db = getAuthDb(); // Check by username $stmt = $db->prepare(" SELECT COUNT(*) FROM login_attempts WHERE username = ? AND success = 0 AND attempted_at > DATE_SUB(NOW(), INTERVAL 15 MINUTE) "); $stmt->execute([$username]); if ($stmt->fetchColumn() >= 5) { return true; } // Check by IP $stmt = $db->prepare(" SELECT COUNT(*) FROM login_attempts WHERE ip_address = ? AND success = 0 AND attempted_at > DATE_SUB(NOW(), INTERVAL 15 MINUTE) "); $stmt->execute([$ip]); if ($stmt->fetchColumn() >= 10) { return true; } } catch (Exception $e) { // If we can't check, allow the attempt } return false; } /** * Log a login attempt */ function logLoginAttempt(string $username, string $ip, bool $success): void { try { $db = getAuthDb(); $stmt = $db->prepare(" INSERT INTO login_attempts (username, ip_address, success) VALUES (?, ?, ?) "); $stmt->execute([$username, $ip, $success ? 1 : 0]); } catch (Exception $e) { // Silently fail } } /** * Attempt to login a user * Returns array with 'success', 'user', 'error' keys */ function attemptLogin(string $usernameOrEmail, string $password): array { $ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0'; // Check brute force if (isBlockedByBruteForce($usernameOrEmail, $ip)) { return [ 'success' => false, 'error' => 'Te veel mislukte inlogpogingen. Probeer het over 15 minuten opnieuw.' ]; } try { $db = getAuthDb(); // Find user by username or email $stmt = $db->prepare(" SELECT id, username, email, password_hash, role, is_active FROM users WHERE (username = ? OR email = ?) LIMIT 1 "); $stmt->execute([$usernameOrEmail, $usernameOrEmail]); $user = $stmt->fetch(); if (!$user) { logLoginAttempt($usernameOrEmail, $ip, false); return ['success' => false, 'error' => 'Ongeldige gebruikersnaam of wachtwoord.']; } if (!$user['is_active']) { logLoginAttempt($usernameOrEmail, $ip, false); return ['success' => false, 'error' => 'Dit account is gedeactiveerd. Neem contact op met de beheerder.']; } if (!password_verify($password, $user['password_hash'])) { logLoginAttempt($usernameOrEmail, $ip, false); return ['success' => false, 'error' => 'Ongeldige gebruikersnaam of wachtwoord.']; } // Success - create session session_regenerate_id(true); $_SESSION['user_id'] = $user['id']; $_SESSION['user'] = [ 'id' => $user['id'], 'username' => $user['username'], 'email' => $user['email'], 'role' => $user['role'], ]; $_SESSION['login_time'] = time(); // Log success logLoginAttempt($usernameOrEmail, $ip, true); // Update last login $stmt = $db->prepare("UPDATE users SET last_login = NOW() WHERE id = ?"); $stmt->execute([$user['id']]); return ['success' => true, 'user' => $_SESSION['user']]; } catch (Exception $e) { return ['success' => false, 'error' => 'Er is een fout opgetreden. Probeer het opnieuw.']; } } /** * Logout the current user */ function logout(): void { $_SESSION = []; if (ini_get('session.use_cookies')) { $params = session_get_cookie_params(); setcookie( session_name(), '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly'] ); } session_destroy(); } /** * Check session timeout (2 hours of inactivity) */ function checkSessionTimeout(): void { $timeout = 7200; // 2 hours if (isLoggedIn()) { if (isset($_SESSION['login_time']) && (time() - $_SESSION['login_time']) > $timeout) { logout(); header("Location: /auth/login.php?reason=timeout"); exit; } // Update last activity $_SESSION['login_time'] = time(); } } // Check session timeout on every request checkSessionTimeout();