pdo = $pdo; $this->checkSession(); } public function checkSession(): void { if (isset($_SESSION['user_id'])) { $user = User::findByUsername($this->pdo, $_SESSION['username']); if (!$user || !$user['is_active']) { $this->logout(); } else { $this->user = $user; } } } public function login(string $username, string $password, string $ip = null): bool { $user = User::findByUsername($this->pdo, $username); if (!$user || !$user['is_active']) { return false; } // Verify password directly using the hash from database if (!password_verify($password, $user['password'])) { return false; } // Set session $_SESSION['user_id'] = $user['id']; $_SESSION['username'] = $user['username']; $_SESSION['role'] = $user['role']; // Update last login $this->updateUserLastLogin($user['id'], $ip); $this->user = $user; return true; } public function logout(): void { unset($_SESSION['user_id']); unset($_SESSION['username']); unset($_SESSION['role']); $this->user = null; } public function getCurrentUser(): ?array { return $this->user; } public function isLoggedIn(): bool { return $this->user !== null; } public function isAdmin(): bool { return $this->isLoggedIn() && $this->user['role'] === 'admin'; } public function requireLogin(): void { if (!$this->isLoggedIn()) { header('Location: /login'); exit; } } public function requireAdmin(): void { $this->requireLogin(); if (!$this->isAdmin()) { http_response_code(403); echo 'Access denied. Admin privileges required.'; exit; } } public function generateCSRFToken(): string { if (!isset($_SESSION['csrf_token'])) { $_SESSION['csrf_token'] = bin2hex(random_bytes(32)); } return $_SESSION['csrf_token']; } public function verifyCSRFToken(string $token): bool { return isset($_SESSION['csrf_token']) && $_SESSION['csrf_token'] === $token; } private function updateUserLastLogin(int $userId, string $ip = null): void { $stmt = $this->pdo->prepare("UPDATE users SET last_login_at = :last_login_at, login_ip = :login_ip WHERE id = :id"); $stmt->execute([ 'id' => $userId, 'last_login_at' => date('Y-m-d H:i:s'), 'login_ip' => $ip ]); } }