38751-vm/app/Controllers/AuthController.php
2026-02-25 22:26:07 +00:00

260 lines
9.6 KiB
PHP

<?php
namespace App\Controllers;
use App\Core\Controller;
class AuthController extends Controller {
public function loginForm() {
if (isset($_SESSION['user_id'])) {
$this->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');
}
}