redirect('/profile'); } $this->view('auth/login'); } public function registerForm() { if (isset($_SESSION['user_id'])) { $this->redirect('/profile'); } // Check GET first, then Session $ref = $_GET['ref'] ?? ($_SESSION['global_ref'] ?? ''); $this->view('auth/register', ['ref' => $ref]); } public function login() { $username = $_POST['username'] ?? ''; $password = $_POST['password'] ?? ''; $ip = get_client_ip(); $db = db_pdo(); // Anti-Brute Force check by IP (for non-existent users) $stmt = $db->prepare("SELECT attempts, last_attempt FROM login_logs WHERE ip_address = ?"); $stmt->execute([$ip]); $ip_log = $stmt->fetch(); if ($ip_log && $ip_log['attempts'] >= 10 && (time() - strtotime($ip_log['last_attempt'])) < 900) { $this->view('auth/login', ['error' => 'Too many failed attempts from this IP. Please try again in 15 minutes.']); return; } $stmt = $db->prepare("SELECT * FROM users WHERE username = ?"); $stmt->execute([$username]); $user = $stmt->fetch(); if ($user) { // Check if account is banned if ($user['is_banned']) { $this->view('auth/login', ['error' => 'Your account has been banned. Please contact support.']); return; } // Check brute force for specific user if ($user['login_attempts'] >= 5 && (time() - strtotime($user['last_attempt_time'])) < 900) { $this->view('auth/login', ['error' => 'Too many failed attempts. Please try again in 15 minutes.']); return; } if (password_verify($password, $user['password'])) { // Reset attempts $stmt = $db->prepare("UPDATE users SET login_attempts = 0, last_ip = ? WHERE id = ?"); $stmt->execute([$ip, $user['id']]); $_SESSION['user_id'] = $user['id']; $_SESSION['username'] = $user['username']; $_SESSION['role'] = $user['role']; if ($user['role'] === 'admin') { $this->redirect('/admin'); } else { $this->redirect('/profile'); } } else { // Increment attempts $stmt = $db->prepare("UPDATE users SET login_attempts = login_attempts + 1, last_attempt_time = NOW() WHERE id = ?"); $stmt->execute([$user['id']]); $this->view('auth/login', ['error' => __('error_invalid_login')]); } } else { // Log failed attempt by IP if ($ip_log) { $stmt = $db->prepare("UPDATE login_logs SET attempts = attempts + 1, last_attempt = NOW() WHERE ip_address = ?"); $stmt->execute([$ip]); } else { $stmt = $db->prepare("INSERT INTO login_logs (ip_address, attempts) VALUES (?, 1)"); $stmt->execute([$ip]); } $this->view('auth/login', ['error' => __('error_invalid_login')]); } } public function register() { $username = $_POST['username'] ?? ''; $password = $_POST['password'] ?? ''; $confirm_password = $_POST['confirm_password'] ?? ''; $ref_code = $_POST['ref_code'] ?? ''; $honeypot = $_POST['full_name'] ?? ''; // Hidden field $ip = get_client_ip(); // Bot protection (Honeypot) if (!empty($honeypot)) { // Silent fail or show error $this->view('auth/register', ['error' => 'Bot detected.', 'ref' => $ref_code]); return; } if ($password !== $confirm_password) { $this->view('auth/register', ['error' => __('error_password_mismatch'), 'ref' => $ref_code]); return; } $db = db_pdo(); // Multi-account check (Anti-bot/Anti-cheat) $stmt = $db->prepare("SELECT COUNT(*) FROM users WHERE registration_ip = ? AND created_at > DATE_SUB(NOW(), INTERVAL 1 HOUR)"); $stmt->execute([$ip]); if ($stmt->fetchColumn() >= 3) { $this->view('auth/register', ['error' => 'Too many registrations from this IP. Please try again later.', 'ref' => $ref_code]); return; } // Check if username exists $stmt = $db->prepare("SELECT id FROM users WHERE username = ?"); $stmt->execute([$username]); if ($stmt->fetch()) { $this->view('auth/register', ['error' => __('error_username_exists'), 'ref' => $ref_code]); return; } $hashed_password = password_hash($password, PASSWORD_DEFAULT); $referral_code = substr(md5(uniqid($username, true)), 0, 8); $referred_by = null; if (!empty($ref_code)) { $stmt = $db->prepare("SELECT id FROM users WHERE referral_code = ?"); $stmt->execute([$ref_code]); $referrer = $stmt->fetch(); if ($referrer) { $referred_by = $referrer['id']; // Anti-self referral check $stmt_ip = $db->prepare("SELECT registration_ip FROM users WHERE id = ?"); $stmt_ip->execute([$referred_by]); $referrer_ip = $stmt_ip->fetchColumn(); if ($referrer_ip === $ip) { // Possible self-referral, mark but allow or block? // Let's block if IP matches exactly $this->view('auth/register', ['error' => 'Self-referral is not allowed.', 'ref' => $ref_code]); return; } } } $stmt = $db->prepare("INSERT INTO users (username, password, referral_code, referred_by, role, balance, registration_ip, last_ip) VALUES (?, ?, ?, ?, 'user', 0, ?, ?)"); $stmt->execute([$username, $hashed_password, $referral_code, $referred_by, $ip, $ip]); $userId = $db->lastInsertId(); if ($referred_by) { // Reward referrer $stmt = $db->prepare("UPDATE users SET points = points + 10, total_referrals = total_referrals + 1 WHERE id = ?"); $stmt->execute([$referred_by]); } $_SESSION['user_id'] = $userId; $_SESSION['username'] = $username; $_SESSION['role'] = 'user'; $this->redirect('/profile'); } public function logout() { session_destroy(); $this->redirect('/'); } public function profile() { if (!isset($_SESSION['user_id'])) { $this->redirect('/login'); } $db = db_pdo(); $stmt = $db->prepare("SELECT * FROM users WHERE id = ?"); $stmt->execute([$_SESSION['user_id']]); $user = $stmt->fetch(); $stmt = $db->prepare("SELECT * FROM withdrawals WHERE user_id = ? ORDER BY created_at DESC"); $stmt->execute([$user['id']]); $withdrawals = $stmt->fetchAll(); $this->view('auth/profile', [ 'user' => $user, 'withdrawals' => $withdrawals, 'success' => $_SESSION['success'] ?? null, 'error' => $_SESSION['error'] ?? null ]); unset($_SESSION['success'], $_SESSION['error']); } public function requestWithdrawal() { if (!isset($_SESSION['user_id'])) { if (is_ajax()) { header('Content-Type: application/json'); echo json_encode(['error' => 'Unauthorized']); exit; } $this->redirect('/login'); } $amount = (float)($_POST['amount'] ?? 0); $method = $_POST['method'] ?? ''; $details = $_POST['details'] ?? ''; if ($amount < 10000) { // Minimum WD $error = __('error_min_withdraw'); if (is_ajax()) { header('Content-Type: application/json'); echo json_encode(['error' => $error]); exit; } $_SESSION['error'] = $error; $this->redirect('/profile'); } $db = db_pdo(); $stmt = $db->prepare("SELECT balance FROM users WHERE id = ?"); $stmt->execute([$_SESSION['user_id']]); $balance = $stmt->fetchColumn(); if ($balance < $amount) { $error = __('error_insufficient_balance'); if (is_ajax()) { header('Content-Type: application/json'); echo json_encode(['error' => $error]); exit; } $_SESSION['error'] = $error; $this->redirect('/profile'); } // Deduct balance $stmt = $db->prepare("UPDATE users SET balance = balance - ? WHERE id = ?"); $stmt->execute([$amount, $_SESSION['user_id']]); // Create WD request $stmt = $db->prepare("INSERT INTO withdrawals (user_id, amount, method, account_details, status) VALUES (?, ?, ?, ?, 'pending')"); $stmt->execute([$_SESSION['user_id'], $amount, $method, $details]); $success = __('success_withdraw_submitted'); if (is_ajax()) { header('Content-Type: application/json'); echo json_encode(['success' => $success, 'new_balance' => $balance - $amount]); exit; } $_SESSION['success'] = $success; $this->redirect('/profile'); } }