mirror of
https://github.com/myronblair/tomtomgames
synced 2026-06-30 17:51:08 -05:00
Security: remove test/debug/install files from production
This commit is contained in:
-117
@@ -1,117 +0,0 @@
|
||||
# ══════════════════════════════════════════════════════════
|
||||
# TomTomGames Security Configuration
|
||||
# ══════════════════════════════════════════════════════════
|
||||
|
||||
Options -Indexes -Includes
|
||||
ServerSignature Off
|
||||
|
||||
# ── Block all sensitive file types ───────────────────────
|
||||
<FilesMatch "\.(sql|env|log|sh|md|git|bak|backup|old|orig|tmp|swp|cfg|ini|conf|yaml|yml|json.bak)$">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</FilesMatch>
|
||||
|
||||
# ── Block direct access to sensitive PHP files ───────────
|
||||
<FilesMatch "^(phpcheck|test|test_mail|test_login|sgtest|install|config|db|auth|mailer|square|smtp)\.php$">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</FilesMatch>
|
||||
|
||||
# ── Block access to includes and vendor folders ──────────
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteRule ^includes/ - [F,L]
|
||||
RewriteRule ^vendor/ - [F,L]
|
||||
RewriteRule ^mail_queue/ - [F,L]
|
||||
RewriteRule ^\.git/ - [F,L]
|
||||
</IfModule>
|
||||
|
||||
# ── Block common attack vectors ──────────────────────────
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
|
||||
# Block SQL injection attempts in query strings
|
||||
RewriteCond %{QUERY_STRING} (union|select|insert|drop|delete|update|cast|exec|declare|char|convert|truncate).*= [NC,OR]
|
||||
RewriteCond %{QUERY_STRING} (<|%3C).*script.*(>|%3E) [NC,OR]
|
||||
RewriteCond %{QUERY_STRING} \.\./\.\. [NC,OR]
|
||||
RewriteCond %{QUERY_STRING} (javascript|vbscript|expression|applet|meta|xml|blink|link|iframe|input|embed|script|object|marquee) [NC]
|
||||
RewriteRule .* - [F,L]
|
||||
|
||||
# Block base64 encoded attacks
|
||||
RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [NC,OR]
|
||||
RewriteCond %{QUERY_STRING} base64_(en|de)code[^(]*\([^)]*\) [NC]
|
||||
RewriteRule .* - [F,L]
|
||||
|
||||
# Block common exploit scanners and bad bots
|
||||
RewriteCond %{HTTP_USER_AGENT} (nikto|sqlmap|havij|nessus|masscan|zgrab|python-requests/2\.6|libwww-perl|wget|curl\/7\.[0-4]) [NC]
|
||||
RewriteRule .* - [F,L]
|
||||
</IfModule>
|
||||
|
||||
# ── Block access to WordPress paths (scanners look for these) ──
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteRule ^wp-admin - [F,L]
|
||||
RewriteRule ^wp-login - [F,L]
|
||||
RewriteRule ^xmlrpc - [F,L]
|
||||
RewriteRule ^\.env - [F,L]
|
||||
RewriteRule ^composer\. - [F,L]
|
||||
</IfModule>
|
||||
|
||||
# ── Security Headers ──────────────────────────────────────
|
||||
<IfModule mod_headers.c>
|
||||
# Prevent MIME type sniffing
|
||||
Header always set X-Content-Type-Options "nosniff"
|
||||
|
||||
# Prevent clickjacking
|
||||
Header always set X-Frame-Options "DENY"
|
||||
|
||||
# XSS protection
|
||||
Header always set X-XSS-Protection "1; mode=block"
|
||||
|
||||
# Referrer policy
|
||||
Header always set Referrer-Policy "strict-origin-when-cross-origin"
|
||||
|
||||
# Permissions policy — disable dangerous browser features
|
||||
Header always set Permissions-Policy "camera=(), microphone=(), geolocation=(), payment=(), usb=(), magnetometer=(), gyroscope=()"
|
||||
|
||||
# Content Security Policy — restrict where resources can load from
|
||||
Header always set Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://web.squarecdn.com https://sandbox.web.squarecdn.com https://js.squareup.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; font-src 'self' https://fonts.gstatic.com; img-src 'self' data: https:; connect-src 'self' https: wss:; frame-src 'none'"
|
||||
|
||||
# Strict Transport Security — force HTTPS for 1 year
|
||||
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
||||
|
||||
# Remove server info headers
|
||||
Header unset Server
|
||||
Header unset X-Powered-By
|
||||
</IfModule>
|
||||
|
||||
# ── Canonical HTTPS + non-www redirect ───────────────────
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteCond %{HTTPS} off
|
||||
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
|
||||
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
|
||||
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
|
||||
</IfModule>
|
||||
|
||||
# ── Block PHP execution in uploads folder (if it exists) ─
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteRule ^uploads/.*\.php$ - [F,L]
|
||||
</IfModule>
|
||||
|
||||
# ── Gzip compression ──────────────────────────────────────
|
||||
<IfModule mod_deflate.c>
|
||||
AddOutputFilterByType DEFLATE text/html text/css text/javascript application/javascript application/json image/svg+xml
|
||||
</IfModule>
|
||||
|
||||
# ── Browser caching ───────────────────────────────────────
|
||||
<IfModule mod_expires.c>
|
||||
ExpiresActive On
|
||||
ExpiresByType text/html "access plus 1 hour"
|
||||
ExpiresByType text/css "access plus 1 month"
|
||||
ExpiresByType application/javascript "access plus 1 month"
|
||||
ExpiresByType image/svg+xml "access plus 1 month"
|
||||
ExpiresByType image/png "access plus 1 month"
|
||||
ExpiresByType image/jpeg "access plus 1 month"
|
||||
ExpiresByType image/webp "access plus 1 month"
|
||||
ExpiresByType application/json "access plus 1 day"
|
||||
</IfModule>
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
// Fix broadcast_list in admin.php on server - delete after running
|
||||
$f = '/home/tomtomgames.com/public_html/api/admin.php';
|
||||
$c = file_get_contents($f);
|
||||
|
||||
$idx = strpos($c, "case 'broadcast_list':");
|
||||
$end = strpos($c, " break;", $idx) + 14;
|
||||
|
||||
$new = "case 'broadcast_list':\n try {\n \$sql = \"SELECT b.id, b.subject, b.message, b.target, b.sent_at, u.username AS sender_name, (SELECT COUNT(*) FROM broadcast_reads WHERE broadcast_id=b.id) AS read_count, (SELECT COUNT(*) FROM broadcast_replies WHERE broadcast_id=b.id) AS reply_count, (SELECT COUNT(*) FROM users WHERE status='active' AND is_admin=0) AS total_players FROM broadcasts b JOIN users u ON b.admin_id=u.id ORDER BY b.sent_at DESC LIMIT 100\";\n \$stmt = db()->query(\$sql);\n echo json_encode(['success'=>true,'broadcasts'=>\$stmt->fetchAll()]);\n } catch(Exception \$e) {\n echo json_encode(['success'=>false,'error'=>\$e->getMessage()]);\n }\n break;";
|
||||
|
||||
$c = substr($c, 0, $idx) . $new . substr($c, $end);
|
||||
file_put_contents($f, $c);
|
||||
|
||||
// Verify it works
|
||||
require_once '/home/tomtomgames.com/includes/config.php';
|
||||
require_once '/home/tomtomgames.com/includes/db.php';
|
||||
|
||||
try {
|
||||
$stmt = db()->query("SELECT COUNT(*) FROM broadcasts");
|
||||
echo "OK - broadcasts in DB: " . $stmt->fetchColumn() . "\n";
|
||||
$stmt2 = db()->query("SELECT b.id, b.subject, b.sent_at, u.username AS sender_name FROM broadcasts b JOIN users u ON b.admin_id=u.id ORDER BY b.sent_at DESC LIMIT 5");
|
||||
$rows = $stmt2->fetchAll();
|
||||
echo "Query works - rows: " . count($rows) . "\n";
|
||||
foreach($rows as $r) echo " #{$r['id']}: {$r['subject']} by {$r['sender_name']}\n";
|
||||
} catch(Exception $e) {
|
||||
echo "ERROR: " . $e->getMessage() . "\n";
|
||||
}
|
||||
echo "DONE - delete this file\n";
|
||||
-206
@@ -1,206 +0,0 @@
|
||||
<?php
|
||||
$key = $_GET['key'] ?? '';
|
||||
if ($key !== 'TomGames2024Admin') die('<h2 style="font-family:sans-serif;color:red">Access denied. Add ?key=TomGames2024Admin to URL.</h2>');
|
||||
|
||||
require_once __DIR__ . '/../includes/config.php';
|
||||
|
||||
$log = [];
|
||||
function ok($msg) { global $log; $log[] = ['t'=>'ok', 'm'=>$msg]; }
|
||||
function err($msg) { global $log; $log[] = ['t'=>'err', 'm'=>$msg]; }
|
||||
function warn($msg) { global $log; $log[] = ['t'=>'warn','m'=>$msg]; }
|
||||
function info($msg) { global $log; $log[] = ['t'=>'info','m'=>$msg]; }
|
||||
|
||||
try {
|
||||
$pdo = new PDO("mysql:host=".DB_HOST.";dbname=".DB_NAME.";charset=utf8mb4", DB_USER, DB_PASS,
|
||||
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]);
|
||||
ok('Connected to <strong>'.DB_NAME.'</strong> as <strong>'.DB_USER.'</strong>');
|
||||
} catch (Exception $e) {
|
||||
die('<pre style="color:red">CONNECTION FAILED: '.htmlspecialchars($e->getMessage()).'</pre>');
|
||||
}
|
||||
|
||||
// Helper: check if column exists
|
||||
function colExists(PDO $pdo, string $table, string $col): bool {
|
||||
$r = $pdo->query("SHOW COLUMNS FROM `$table` LIKE '$col'")->fetch();
|
||||
return (bool)$r;
|
||||
}
|
||||
|
||||
// ── CREATE TABLES ───────────────────────────────────────────
|
||||
$tables = [
|
||||
'users' => "CREATE TABLE IF NOT EXISTS users (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(50) UNIQUE NOT NULL,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
alias VARCHAR(100) NOT NULL,
|
||||
email VARCHAR(150) UNIQUE,
|
||||
email_verified TINYINT(1) DEFAULT 0,
|
||||
tokens DECIMAL(10,2) DEFAULT 0,
|
||||
is_admin TINYINT(1) DEFAULT 0,
|
||||
status ENUM('active','suspended') DEFAULT 'active',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
last_login DATETIME
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
|
||||
|
||||
'pending_registrations' => "CREATE TABLE IF NOT EXISTS pending_registrations (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
username VARCHAR(50) NOT NULL,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
alias VARCHAR(100) NOT NULL,
|
||||
email VARCHAR(150) NOT NULL,
|
||||
token VARCHAR(64) UNIQUE NOT NULL,
|
||||
expires_at DATETIME NOT NULL,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
|
||||
|
||||
'token_purchases' => "CREATE TABLE IF NOT EXISTS token_purchases (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
tokens INT NOT NULL,
|
||||
amount_cents INT NOT NULL,
|
||||
payment_method VARCHAR(20) DEFAULT 'card',
|
||||
square_payment_id VARCHAR(255),
|
||||
platform_id VARCHAR(50),
|
||||
game_alias VARCHAR(100),
|
||||
player_name VARCHAR(100),
|
||||
billing_name VARCHAR(160),
|
||||
billing_address VARCHAR(200),
|
||||
billing_city VARCHAR(80),
|
||||
billing_state VARCHAR(2),
|
||||
billing_zip VARCHAR(10),
|
||||
billing_email VARCHAR(150),
|
||||
is_custom TINYINT(1) DEFAULT 0,
|
||||
failure_reason TEXT,
|
||||
card_brand VARCHAR(30),
|
||||
card_last4 VARCHAR(4),
|
||||
receipt_url VARCHAR(512),
|
||||
status ENUM('pending','completed','failed') DEFAULT 'pending',
|
||||
admin_note TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
|
||||
|
||||
'cashout_requests' => "CREATE TABLE IF NOT EXISTS cashout_requests (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
platform_id VARCHAR(50) NOT NULL,
|
||||
alias VARCHAR(100) NOT NULL,
|
||||
tokens DECIMAL(10,2) NOT NULL,
|
||||
status ENUM('pending','approved','rejected') DEFAULT 'pending',
|
||||
admin_note TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
resolved_at DATETIME,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
|
||||
|
||||
'saved_billing' => "CREATE TABLE IF NOT EXISTS saved_billing (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT UNIQUE NOT NULL,
|
||||
first_name VARCHAR(80),
|
||||
last_name VARCHAR(80),
|
||||
email VARCHAR(150),
|
||||
address VARCHAR(200),
|
||||
city VARCHAR(80),
|
||||
state VARCHAR(2),
|
||||
zip VARCHAR(10),
|
||||
card_brand VARCHAR(30),
|
||||
card_last4 VARCHAR(4),
|
||||
card_exp_month VARCHAR(2),
|
||||
card_exp_year VARCHAR(4),
|
||||
sq_card_id VARCHAR(255),
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
|
||||
|
||||
'chat_messages' => "CREATE TABLE IF NOT EXISTS chat_messages (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
sender ENUM('user','admin') NOT NULL,
|
||||
message TEXT NOT NULL,
|
||||
is_read TINYINT(1) DEFAULT 0,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4",
|
||||
];
|
||||
|
||||
foreach ($tables as $name => $sql) {
|
||||
try { $pdo->exec($sql); ok("Table <strong>$name</strong> ✓"); }
|
||||
catch (Exception $e) { err("Table <strong>$name</strong>: ".htmlspecialchars($e->getMessage())); }
|
||||
}
|
||||
|
||||
// ── ADD MISSING COLUMNS (compatible with MySQL 5.6/5.7/8) ──
|
||||
// Check existence first, then ALTER — works on all MySQL versions
|
||||
$addCols = [
|
||||
// [table, column, definition, after]
|
||||
['token_purchases', 'billing_name', "VARCHAR(160)", 'player_name'],
|
||||
['token_purchases', 'billing_address', "VARCHAR(200)", 'billing_name'],
|
||||
['token_purchases', 'billing_city', "VARCHAR(80)", 'billing_address'],
|
||||
['token_purchases', 'billing_state', "VARCHAR(2)", 'billing_city'],
|
||||
['token_purchases', 'billing_zip', "VARCHAR(10)", 'billing_state'],
|
||||
['token_purchases', 'billing_email', "VARCHAR(150)", 'billing_zip'],
|
||||
['token_purchases', 'is_custom', "TINYINT(1) DEFAULT 0", 'billing_email'],
|
||||
['token_purchases', 'failure_reason', "TEXT", 'is_custom'],
|
||||
['token_purchases', 'card_brand', "VARCHAR(30)", 'failure_reason'],
|
||||
['token_purchases', 'card_last4', "VARCHAR(4)", 'card_brand'],
|
||||
['token_purchases', 'receipt_url', "VARCHAR(512)", 'card_last4'],
|
||||
['token_purchases', 'admin_note', "TEXT", 'status'],
|
||||
['users', 'email_verified', "TINYINT(1) DEFAULT 0", 'email'],
|
||||
];
|
||||
|
||||
foreach ($addCols as [$tbl, $col, $def, $after]) {
|
||||
if (colExists($pdo, $tbl, $col)) {
|
||||
ok("Column <strong>$tbl.$col</strong> already exists ✓");
|
||||
} else {
|
||||
try {
|
||||
$pdo->exec("ALTER TABLE `$tbl` ADD COLUMN `$col` $def AFTER `$after`");
|
||||
ok("Column <strong>$tbl.$col</strong> added ✓");
|
||||
} catch (Exception $e) {
|
||||
err("Column <strong>$tbl.$col</strong>: ".htmlspecialchars($e->getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ── FIX ADMIN email_verified ────────────────────────────────
|
||||
try {
|
||||
$n = $pdo->exec("UPDATE users SET email_verified=1 WHERE is_admin=1");
|
||||
ok("Admin accounts email_verified set to 1 ($n updated)");
|
||||
} catch (Exception $e) { warn("Admin fix: ".htmlspecialchars($e->getMessage())); }
|
||||
|
||||
// ── SUMMARY ─────────────────────────────────────────────────
|
||||
$tables_now = $pdo->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN);
|
||||
info("All tables: <strong>".implode(', ', $tables_now)."</strong>");
|
||||
|
||||
try {
|
||||
$total = $pdo->query("SELECT COUNT(*) FROM users")->fetchColumn();
|
||||
$admins = $pdo->query("SELECT COUNT(*) FROM users WHERE is_admin=1")->fetchColumn();
|
||||
info("Users: <strong>$total total</strong>, $admins admin(s)");
|
||||
} catch (Exception $e) {}
|
||||
?>
|
||||
<!DOCTYPE html><html><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<title>TomTomGames DB Install</title>
|
||||
<style>
|
||||
body{font-family:'Segoe UI',sans-serif;background:#0a0a12;color:#e8e8f0;max-width:680px;margin:40px auto;padding:20px}
|
||||
h1{font-size:20px;margin-bottom:4px;background:linear-gradient(135deg,#f0c040,#00e5ff);-webkit-background-clip:text;-webkit-text-fill-color:transparent}
|
||||
.sub{color:#8888aa;font-size:13px;margin-bottom:24px}
|
||||
.row{padding:9px 14px;border-radius:7px;margin-bottom:5px;font-size:13px;display:flex;align-items:flex-start;gap:10px}
|
||||
.ok {background:rgba(0,230,118,.08);border:1px solid rgba(0,230,118,.2)}
|
||||
.err {background:rgba(255,68,68,.1);border:1px solid rgba(255,68,68,.3);color:#ff9999}
|
||||
.warn{background:rgba(255,214,10,.07);border:1px solid rgba(255,214,10,.2);color:#ffd60a}
|
||||
.info{background:rgba(0,229,255,.06);border:1px solid rgba(0,229,255,.15);color:#aaddff}
|
||||
.ic{flex-shrink:0;font-weight:700}
|
||||
.next{background:rgba(240,192,64,.07);border:1px solid rgba(240,192,64,.2);border-radius:10px;padding:16px;margin-top:24px}
|
||||
.next h2{color:#f0c040;font-size:14px;margin-bottom:8px}
|
||||
.next ol{padding-left:16px;line-height:2;color:#ccccdd;font-size:13px}
|
||||
.del{background:rgba(255,68,68,.07);border:1px solid rgba(255,68,68,.2);border-radius:7px;padding:10px 14px;margin-top:14px;font-size:12px;color:#ff9999}
|
||||
</style></head><body>
|
||||
<h1>🎮 TomTomGames — DB Install / Repair</h1>
|
||||
<div class="sub">Database: <strong><?= DB_NAME ?></strong></div>
|
||||
<?php foreach ($log as $e): $ic = $e['t']==='ok'?'✓':($e['t']==='err'?'✗':($e['t']==='warn'?'⚠':'ℹ')); ?>
|
||||
<div class="row <?= $e['t'] ?>"><span class="ic"><?= $ic ?></span><span><?= $e['m'] ?></span></div>
|
||||
<?php endforeach; ?>
|
||||
<div class="next"><h2>Next Steps</h2><ol>
|
||||
<li>All green ✓? Your database is fully set up</li>
|
||||
<li>Visit <strong>/create_admin.php</strong> to create admin account (if needed)</li>
|
||||
<li>Visit <strong>https://tomtomgames.com</strong> — app should load normally</li>
|
||||
<li><strong>Delete install.php</strong> from your server now</li>
|
||||
</ol></div>
|
||||
<div class="del">⚠ Delete <code>install.php</code> after use — it exposes DB structure.</div>
|
||||
</body></html>
|
||||
@@ -1,25 +0,0 @@
|
||||
<?php
|
||||
// Admin only diagnostic - delete after use
|
||||
$files = [
|
||||
'../../includes/db.php',
|
||||
'../../includes/auth.php',
|
||||
'../api/admin.php',
|
||||
];
|
||||
foreach ($files as $f) {
|
||||
$full = __DIR__ . '/' . $f;
|
||||
$out = shell_exec("php -l " . escapeshellarg($full) . " 2>&1");
|
||||
echo $f . ": " . trim($out) . "\n";
|
||||
}
|
||||
|
||||
// Also test DB connection directly
|
||||
try {
|
||||
require_once __DIR__ . '/../../includes/config.php';
|
||||
require_once __DIR__ . '/../../includes/db.php';
|
||||
$v = db()->query("SELECT COUNT(*) FROM users")->fetchColumn();
|
||||
echo "\nDB OK — users: $v\n";
|
||||
$v2 = db()->query("SELECT version FROM app_version ORDER BY id DESC LIMIT 1")->fetchColumn();
|
||||
echo "App version: $v2\n";
|
||||
} catch (Throwable $e) {
|
||||
echo "\nDB ERROR: " . $e->getMessage() . "\n";
|
||||
echo "File: " . $e->getFile() . " line " . $e->getLine() . "\n";
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../includes/config.php';
|
||||
require_once __DIR__ . '/../includes/db.php';
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
// Test what the referrals API would return for each user
|
||||
$users = db()->query("SELECT id, username, referral_code FROM users")->fetchAll();
|
||||
$out = [];
|
||||
foreach ($users as $u) {
|
||||
$out[] = [
|
||||
'id' => $u['id'],
|
||||
'username' => $u['username'],
|
||||
'referral_code' => $u['referral_code'],
|
||||
'referral_url' => 'https://tomtomgames.com/?ref=' . $u['referral_code'],
|
||||
];
|
||||
}
|
||||
|
||||
// Also check tiers
|
||||
$tiers = db()->query("SELECT id, name, min_referrals, tokens_per_ref, bonus_tokens, is_active FROM referral_tiers ORDER BY sort_order")->fetchAll();
|
||||
|
||||
echo json_encode([
|
||||
'users' => $out,
|
||||
'tiers' => $tiers,
|
||||
'tier_count' => count($tiers),
|
||||
], JSON_PRETTY_PRINT);
|
||||
@@ -1,96 +0,0 @@
|
||||
<?php
|
||||
require_once '/home/tomtomgames.com/includes/config.php';
|
||||
require_once '/home/tomtomgames.com/includes/db.php';
|
||||
|
||||
// 1. referral_tiers
|
||||
db()->exec("CREATE TABLE IF NOT EXISTS referral_tiers (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(100) NOT NULL,
|
||||
min_referrals INT NOT NULL DEFAULT 1,
|
||||
tokens_per_ref DECIMAL(10,2) NOT NULL DEFAULT 10,
|
||||
bonus_tokens DECIMAL(10,2) NOT NULL DEFAULT 0,
|
||||
description VARCHAR(300),
|
||||
is_active TINYINT(1) DEFAULT 1,
|
||||
sort_order INT DEFAULT 0,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
|
||||
echo "referral_tiers table OK\n";
|
||||
|
||||
// 2. Seed tiers
|
||||
$count = (int)db()->query("SELECT COUNT(*) FROM referral_tiers")->fetchColumn();
|
||||
if ($count == 0) {
|
||||
$seeds = [
|
||||
['Bronze Referrer', 1, 5, 0, 'Earn 5 tokens for each verified referral', 1, 0],
|
||||
['Silver Referrer', 5, 8, 25, 'Earn 8 tokens per referral + 25 bonus at 5 referrals', 1, 1],
|
||||
['Gold Referrer', 10, 10, 100, 'Earn 10 tokens per referral + 100 bonus at 10 referrals', 1, 2],
|
||||
['Elite Referrer', 25, 15, 250, 'Earn 15 tokens per referral + 250 bonus at 25 referrals', 1, 3],
|
||||
];
|
||||
$st = db()->prepare("INSERT INTO referral_tiers (name,min_referrals,tokens_per_ref,bonus_tokens,description,is_active,sort_order) VALUES (?,?,?,?,?,?,?)");
|
||||
foreach ($seeds as $s) $st->execute($s);
|
||||
echo "4 tiers seeded\n";
|
||||
} else {
|
||||
echo "Tiers already exist: $count\n";
|
||||
}
|
||||
|
||||
// 3. referrals table
|
||||
db()->exec("CREATE TABLE IF NOT EXISTS referrals (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
referrer_id INT NOT NULL,
|
||||
referred_id INT NOT NULL UNIQUE,
|
||||
tier_id INT,
|
||||
status ENUM('pending','verified','denied','deleted') DEFAULT 'pending',
|
||||
tokens_awarded DECIMAL(10,2) DEFAULT 0,
|
||||
admin_id INT,
|
||||
admin_note VARCHAR(300),
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
resolved_at DATETIME
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
|
||||
echo "referrals table OK\n";
|
||||
|
||||
// 4. referral_social_shares
|
||||
db()->exec("CREATE TABLE IF NOT EXISTS referral_social_shares (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
platform VARCHAR(50) NOT NULL,
|
||||
bonus_tokens DECIMAL(10,2) DEFAULT 5,
|
||||
status ENUM('pending','approved','denied') DEFAULT 'pending',
|
||||
admin_id INT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
resolved_at DATETIME
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
|
||||
echo "referral_social_shares table OK\n";
|
||||
|
||||
// 5. Add referral_code to users
|
||||
$cols = array_column(db()->query("SHOW COLUMNS FROM users")->fetchAll(), 'Field');
|
||||
if (!in_array('referral_code', $cols)) {
|
||||
db()->exec("ALTER TABLE users ADD COLUMN referral_code VARCHAR(20) UNIQUE");
|
||||
echo "referral_code column added\n";
|
||||
}
|
||||
|
||||
// 6. Add referred_by to users
|
||||
if (!in_array('referred_by', $cols)) {
|
||||
db()->exec("ALTER TABLE users ADD COLUMN referred_by INT DEFAULT NULL");
|
||||
echo "referred_by column added\n";
|
||||
}
|
||||
|
||||
// 7. Add referred_by to pending_registrations
|
||||
$pcols = array_column(db()->query("SHOW COLUMNS FROM pending_registrations")->fetchAll(), 'Field');
|
||||
if (!in_array('referred_by', $pcols)) {
|
||||
db()->exec("ALTER TABLE pending_registrations ADD COLUMN referred_by INT DEFAULT NULL");
|
||||
echo "pending_registrations.referred_by added\n";
|
||||
}
|
||||
|
||||
// 8. Generate codes for users missing one
|
||||
$users = db()->query("SELECT id FROM users WHERE referral_code IS NULL OR referral_code = ''")->fetchAll();
|
||||
$upd = db()->prepare("UPDATE users SET referral_code=? WHERE id=?");
|
||||
foreach ($users as $u) {
|
||||
$code = strtoupper(substr(md5($u['id'].uniqid()), 0, 8));
|
||||
$upd->execute([$code, $u['id']]);
|
||||
}
|
||||
echo count($users) . " users given referral codes\n";
|
||||
|
||||
// 9. Show sample
|
||||
$sample = db()->query("SELECT username, referral_code FROM users LIMIT 5")->fetchAll();
|
||||
foreach ($sample as $r) echo " " . $r['username'] . ": " . $r['referral_code'] . "\n";
|
||||
|
||||
echo "\nDONE\n";
|
||||
@@ -1,6 +0,0 @@
|
||||
<?php
|
||||
echo json_encode([
|
||||
'php' => PHP_VERSION,
|
||||
'time' => date('Y-m-d H:i:s'),
|
||||
'status' => 'ok'
|
||||
]);
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
// POST test - simulates exactly what the app does
|
||||
ob_start();
|
||||
try { require_once __DIR__ . '/../includes/auth.php'; } catch(Throwable $e) { ob_end_clean(); die(json_encode(['boot_error'=>$e->getMessage()])); }
|
||||
ob_end_clean();
|
||||
header('Content-Type: application/json');
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
$data = json_decode(file_get_contents('php://input'), true);
|
||||
$result = loginUser($data['username'] ?? '', $data['password'] ?? '');
|
||||
if ($result['success']) unset($result['user']['password']);
|
||||
echo json_encode($result);
|
||||
exit;
|
||||
}
|
||||
|
||||
// GET - show users
|
||||
$users = db()->query("SELECT id,username,alias,is_admin,email_verified,status FROM users")->fetchAll();
|
||||
echo json_encode(['users'=>$users,'session_id'=>session_id()]);
|
||||
@@ -1,91 +0,0 @@
|
||||
<?php
|
||||
// Standalone email test - no auth required for diagnosis
|
||||
// DELETE THIS FILE after confirming email works
|
||||
|
||||
$result = [];
|
||||
$result['php_version'] = PHP_VERSION;
|
||||
$result['mail_function_exists'] = function_exists('mail');
|
||||
$result['server_software'] = $_SERVER['SERVER_SOFTWARE'] ?? 'unknown';
|
||||
$result['hostname'] = gethostname();
|
||||
|
||||
// Check sendmail path
|
||||
$sendmail = ini_get('sendmail_path');
|
||||
$result['sendmail_path'] = $sendmail ?: 'not set';
|
||||
|
||||
// Check if we can detect SMTP settings
|
||||
$result['smtp_host'] = ini_get('SMTP') ?: 'not set';
|
||||
$result['smtp_port'] = ini_get('smtp_port') ?: 'not set';
|
||||
|
||||
$to = $_POST['to'] ?? '';
|
||||
$sent = false;
|
||||
$sendError = '';
|
||||
|
||||
if ($to && filter_var($to, FILTER_VALIDATE_EMAIL) && isset($_POST['send'])) {
|
||||
$subject = 'TomTomGames Email Test';
|
||||
$message = "This is a test email from TomTomGames.\n\nIf you received this, PHP mail() is working correctly on this server.";
|
||||
$headers = "From: noreply@tomtomgames.com\r\n";
|
||||
$headers .= "Reply-To: support@tomtomgames.com\r\n";
|
||||
$headers .= "X-Mailer: PHP/" . PHP_VERSION;
|
||||
|
||||
// Capture any mail errors
|
||||
set_error_handler(function($errno, $errstr) use (&$sendError) {
|
||||
$sendError = $errstr;
|
||||
});
|
||||
$sent = mail($to, $subject, $message, $headers, '-fnoreply@tomtomgames.com');
|
||||
restore_error_handler();
|
||||
$result['mail_return'] = $sent;
|
||||
$result['mail_error'] = $sendError ?: 'none';
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Email Test</title>
|
||||
<style>
|
||||
body{font-family:monospace;background:#0a0a12;color:#e8e8f0;padding:24px;max-width:600px;margin:0 auto}
|
||||
h2{color:#f0c040}
|
||||
.box{background:#1a1a2e;border:1px solid #333;border-radius:8px;padding:16px;margin:12px 0}
|
||||
.ok{color:#00e676}.err{color:#ff4444}.warn{color:#f0c040}
|
||||
input{background:#111;border:1px solid #444;color:#fff;padding:8px 12px;width:280px;border-radius:6px;font-size:14px}
|
||||
button{background:#f0c040;color:#000;border:none;padding:10px 20px;border-radius:6px;font-weight:700;cursor:pointer;margin-left:8px}
|
||||
label{display:block;margin-bottom:6px;color:#aaa;font-size:13px}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h2>TomTomGames — Email Diagnostics</h2>
|
||||
|
||||
<div class="box">
|
||||
<b>Server Info:</b><br>
|
||||
PHP: <span class="ok"><?= $result['php_version'] ?></span><br>
|
||||
Server: <?= htmlspecialchars($result['server_software']) ?><br>
|
||||
Hostname: <?= htmlspecialchars($result['hostname']) ?><br>
|
||||
mail() function: <span class="<?= $result['mail_function_exists'] ? 'ok' : 'err' ?>"><?= $result['mail_function_exists'] ? 'EXISTS' : 'MISSING' ?></span><br>
|
||||
sendmail_path: <span class="warn"><?= htmlspecialchars($result['sendmail_path']) ?></span><br>
|
||||
SMTP: <span class="warn"><?= htmlspecialchars($result['smtp_host']) ?>:<?= htmlspecialchars($result['smtp_port']) ?></span>
|
||||
</div>
|
||||
|
||||
<?php if ($to): ?>
|
||||
<div class="box">
|
||||
<b>Send Result:</b><br>
|
||||
To: <?= htmlspecialchars($to) ?><br>
|
||||
mail() returned: <span class="<?= $sent ? 'ok' : 'err' ?>"><?= $sent ? 'TRUE (queued for delivery)' : 'FALSE (failed)' ?></span><br>
|
||||
Error: <span class="warn"><?= htmlspecialchars($result['mail_error']) ?></span><br>
|
||||
<?php if ($sent): ?>
|
||||
<br><span class="ok">Check your inbox (and spam folder). If nothing arrives in 5 minutes, the server is not sending outbound mail.</span>
|
||||
<?php else: ?>
|
||||
<br><span class="err">mail() returned false — server cannot send email. You need to configure SMTP (PHPMailer) or enable sendmail.</span>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="box">
|
||||
<form method="POST">
|
||||
<label>Send test email to:</label>
|
||||
<input type="email" name="to" value="<?= htmlspecialchars($to) ?>" placeholder="your@email.com" required>
|
||||
<button type="submit" name="send" value="1">Send Test</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<p style="color:#555;font-size:11px">Delete test_mail.php after diagnosis is complete.</p>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user