iptv-stream-web/setup.php
Vincent 41cd7a4fd8 Add comprehensive unit tests for Security, UserModel, and Validation utilities
- Implemented SecurityTest to validate token generation, CSRF protection, input sanitization, and rate limiting.
- Created UserModelTest to ensure correct database operations for user management, including creation, updating, banning, and fetching active users.
- Developed ValidationTest to verify input validation and sanitization for user IDs, nicknames, messages, and API requests.
- Introduced Security and Validation utility classes with methods for secure token generation, input sanitization, and comprehensive validation rules.
2025-09-30 21:22:28 -04:00

377 lines
12 KiB
PHP

<?php
/**
* Interactive Setup Script for Dodgers IPTV
* Automates the installation and configuration process
*/
// Enable all error reporting for setup
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
echo "\n🎯 DODGERS IPTV - AUTOMATED SETUP SCRIPT\n";
echo str_repeat("=", 50) . "\n\n";
// Configuration
$setup = [
'checks' => [],
'warnings' => [],
'errors' => [],
'steps' => 0
];
function logStep($message) {
global $setup;
$setup['steps']++;
echo "[$setup[steps]] $message\n";
}
function logSuccess($message) {
echo "$message\n";
}
function logWarning($message) {
global $setup;
$setup['warnings'][] = $message;
echo " ⚠️ $message\n";
}
function logError($message) {
global $setup;
$setup['errors'][] = $message;
echo "$message\n";
}
function checkRequirement($name, $check, $required = true) {
logStep("Checking $name...");
try {
$result = $check();
if ($result['status']) {
logSuccess($result['message']);
return true;
} else {
if ($required) {
logError($result['message']);
return false;
} else {
logWarning($result['message']);
return true;
}
}
} catch (Exception $e) {
logError("Exception: " . $e->getMessage());
return false;
}
}
// System Requirements Check
echo "🔧 SYSTEM REQUIREMENTS CHECK\n";
echo str_repeat("-", 30) . "\n";
checkRequirement("PHP Version", function() {
$version = PHP_VERSION;
if (version_compare($version, '8.1.0', '>=')) {
return ['status' => true, 'message' => "PHP $version - Excellent!"];
} elseif (version_compare($version, '7.4.0', '>=')) {
return ['status' => true, 'message' => "PHP $version - Compatible but consider upgrading"];
} else {
return ['status' => false, 'message' => "PHP $version - Must be 8.1+ for optimal security"];
}
});
checkRequirement("PDO Extension", function() {
if (extension_loaded('pdo')) {
return ['status' => true, 'message' => "PDO extension loaded"];
}
return ['status' => false, 'message' => "PDO extension required for database operations"];
});
checkRequirement("SQLite PDO Driver", function() {
if (extension_loaded('pdo_sqlite')) {
return ['status' => true, 'message' => "SQLite PDO driver loaded"];
}
return ['status' => false, 'message' => "SQLite PDO driver required for database"];
});
checkRequirement("MBString Extension", function() {
if (extension_loaded('mbstring')) {
return ['status' => true, 'message' => "MBString extension loaded"];
}
return ['status' => false, 'message' => "MBString extension recommended for UTF-8 support"];
});
checkRequirement("JSON Extension", function() {
if (extension_loaded('json')) {
return ['status' => true, 'message' => "JSON extension loaded"];
}
return ['status' => false, 'message' => "JSON extension required"];
});
checkRequirement("File Permissions", function() {
$tests = [
'.' => 'read',
'logs/' => 'write',
'data/' => 'write',
'migrations/' => 'read'
];
foreach ($tests as $path => $permission) {
if ($permission === 'read' && !is_readable($path)) {
return ['status' => false, 'message' => "$path is not readable"];
}
if ($permission === 'write' && !is_writable($path)) {
if (!is_dir($path)) {
mkdir($path, 0755, true);
if (!is_writable($path)) {
return ['status' => false, 'message' => "$path is not writable (could not create)"];
}
} else {
return ['status' => false, 'message' => "$path is not writable"];
}
}
}
return ['status' => true, 'message' => "All required files/directories have proper permissions"];
});
checkRequirement("Composer Dependencies", function() {
if (file_exists('vendor/autoload.php')) {
return ['status' => true, 'message' => "Composer dependencies installed"];
}
return ['status' => false, 'message' => "Run 'composer install' to install dependencies"];
}, false);
// Configuration File Check
echo "\n📝 CONFIGURATION CHECK\n";
echo str_repeat("-", 30) . "\n";
checkRequirement("Environment Configuration", function() {
if (file_exists('.env')) {
return ['status' => true, 'message' => ".env file exists"];
}
return ['status' => false, 'message' => ".env file missing - copy .env.example"];
}, false);
// Database Setup
echo "\n🗄️ DATABASE SETUP\n";
echo str_repeat("-", 30) . "\n";
// Include autoloader to load all classes
if (file_exists('includes/autoloader.php')) {
require_once 'includes/autoloader.php';
}
checkRequirement(" Database Initialization", function() {
try {
// Test database connection - Database class should now be auto-loaded
$db = Database::getInstance();
// Check if tables exist
$tables = ['users', 'chat_messages', 'active_viewers'];
$stmt = $db->query("SELECT name FROM sqlite_master WHERE type='table'");
$existingTables = $stmt->fetchAll(PDO::FETCH_COLUMN);
$missingTables = array_diff($tables, $existingTables);
if (empty($missingTables)) {
return ['status' => true, 'message' => "All database tables exist"];
} else {
return ['status' => false, 'message' => "Missing tables: " . implode(', ', $missingTables) . " - run database migrations"];
}
} catch (Exception $e) {
return ['status' => false, 'message' => "Database connection failed: " . $e->getMessage() . " - check Database.php configuration"];
}
}, false);
// Test Core Classes
echo "\n🧪 CORE CLASSES TEST\n";
echo str_repeat("-", 30) . "\n";
$classes = [
'Config' => 'includes/Config.php',
'Security' => 'utils/Security.php',
'Validation' => 'utils/Validation.php',
'Database' => 'includes/Database.php',
'UserModel' => 'models/UserModel.php',
'ChatMessageModel' => 'models/ChatMessageModel.php',
'ActiveViewerModel' => 'models/ActiveViewerModel.php',
'ErrorHandler' => 'includes/ErrorHandler.php',
'ChatServer' => 'services/ChatServer.php'
];
foreach ($classes as $className => $file) {
checkRequirement("$className Class", function() use ($className, $file) {
if (!file_exists($file)) {
return ['status' => false, 'message' => "$file not found"];
}
try {
require_once $file;
if (class_exists($className)) {
return ['status' => true, 'message' => "Class loaded successfully"];
} else {
return ['status' => false, 'message' => "Class $className not found in $file"];
}
} catch (Exception $e) {
return ['status' => false, 'message' => "Failed to load class: " . $e->getMessage()];
}
});
}
// Functional Tests
echo "\n⚙️ FUNCTIONAL TESTS\n";
echo str_repeat("-", 30) . "\n";
checkRequirement("Security Functions", function() {
if (!class_exists('Security')) return ['status' => false, 'message' => "Security class not loaded"];
try {
// Test token generation
$token = Security::generateSecureToken(16);
if (strlen($token) !== 32) {
return ['status' => false, 'message' => "Token generation failed (wrong length)"];
}
// Test user ID generation
$userId = Security::generateSecureUserId();
if (strlen($userId) !== 32) {
return ['status' => false, 'message' => "User ID generation failed"];
}
// Test validation
$validation = Validation::validateUserId($userId);
if (!$validation['valid']) {
return ['status' => false, 'message' => "User ID validation failed"];
}
return ['status' => true, 'message' => "Security and validation functions working"];
} catch (Exception $e) {
return ['status' => false, 'message' => "Error testing functions: " . $e->getMessage()];
}
});
checkRequirement("Admin Password Generation", function() {
// Check if generate_hash.php exists and is executable
if (!file_exists('generate_hash.php')) {
return ['status' => false, 'message' => "generate_hash.php script missing"];
}
// Test basic admin functionality
if (!class_exists('Security')) return ['status' => false, 'message' => "Cannot test admin functions"];
try {
// Test admin authentication check (should fail without setup)
$auth = Security::isAdminAuthenticated();
// This might be false (expected for new setup)
return ['status' => true, 'message' => "Admin authentication system loaded (not yet configured)"];
} catch (Exception $e) {
return ['status' => false, 'message' => "Error testing admin functions: " . $e->getMessage()];
}
}, false);
// Configuration Generation
echo "\n🔧 CONFIGURATION ASSISTANT\n";
echo str_repeat("-", 30) . "\n";
if (!file_exists('.env')) {
echo "Creating .env configuration file...\n";
$envTemplate = <<<'EOT'
# Dodgers IPTV Environment Configuration
# Generated by setup.php
# Environment Settings
APP_ENV=development
SECRET_KEY=%SECRET_KEY%
# Database Configuration
DB_DATABASE=data/app.db
# Admin Credentials (configure these!)
ADMIN_USERNAME=admin
ADMIN_PASSWORD_HASH=%ADMIN_HASH%
# Stream Configuration
STREAM_BASE_URL=http://127.0.0.1:8080
STREAM_ALLOWED_IPS=127.0.0.1,localhost
# Security Settings
RATE_LIMIT_REQUESTS=100
RATE_LIMIT_WINDOW=60
SESSION_TIMEOUT=3600
# Logging
LOG_LEVEL=DEBUG
LOG_FILE=logs/app.log
# Cache Settings
CACHE_ENABLED=true
CACHE_TTL=3600
EOT;
// Generate secure defaults
$secretKey = bin2hex(random_bytes(32));
$adminHash = password_hash('changeme', PASSWORD_ARGON2I);
$envContent = str_replace(
['%SECRET_KEY%', '%ADMIN_HASH%'],
[$secretKey, $adminHash],
$envTemplate
);
$result = file_put_contents('.env', $envContent);
if ($result !== false) {
logSuccess("Created .env file with secure defaults");
logWarning("IMPORTANT: Change the default admin password!");
echo "\n Run: php generate_hash.php\n";
echo " Then copy the hash to ADMIN_PASSWORD_HASH in .env\n\n";
} else {
logError("Failed to create .env file");
}
} else {
logSuccess(".env file already exists");
}
// Final Summary
echo "\n🎯 SETUP SUMMARY\n";
echo str_repeat("=", 50) . "\n";
echo "\n✅ Completed Checks: " . count(array_filter($setup['checks'])) . "\n";
echo "⚠️ Warnings: " . count($setup['warnings']) . "\n";
echo "❌ Errors: " . count($setup['errors']) . "\n\n";
if (!empty($setup['warnings'])) {
echo "WARNINGS:\n";
foreach ($setup['warnings'] as $warning) {
echo "$warning\n";
}
echo "\n";
}
if (!empty($setup['errors'])) {
echo "CRITICAL ERRORS (must fix):\n";
foreach ($setup['errors'] as $error) {
echo "$error\n";
}
echo "\n";
echo "🚨 SETUP INCOMPLETE - Please resolve the errors above\n\n";
exit(1);
}
// Success Message
echo "🎉 SETUP COMPLETE! Your Dodgers IPTV system is ready!\n\n";
echo "Next Steps:\n";
echo " 1. Configure admin credentials: php generate_hash.php\n";
echo " 2. Set up your web server (see DEPLOYMENT.md)\n";
echo " 3. Access your application and test the features\n";
echo " 4. Run tests: make test\n";
echo " 5. Deploy to production (see DEPLOYMENT.md)\n\n";
echo "🚀 Happy Streaming!\n";
echo str_repeat("=", 50) . "\n\n";
?>