Files
easystream-main/setup_wizard.php
SamiAhmed7777 d22b3e1c0d feat: Add complete Docker deployment with web-based setup wizard
Major additions:
- Web-based setup wizard (setup.php, setup_wizard.php, setup-wizard.js)
- Production Docker configuration (docker-compose.prod.yml, .env.production)
- Database initialization SQL files (deploy/init_settings.sql)
- Template builder system with drag-and-drop UI
- Advanced features (OAuth, CDN, enhanced analytics, monetization)
- Comprehensive documentation (deployment guides, quick start, feature docs)
- Design system with accessibility and responsive layout
- Deployment automation scripts (deploy.ps1, generate-secrets.ps1)

Setup wizard allows customization of:
- Platform name and branding
- Domain configuration
- Membership tiers and pricing
- Admin credentials
- Feature toggles

Database includes 270+ tables for complete video streaming platform with
advanced features for analytics, moderation, template building, and monetization.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-26 01:42:31 -07:00

306 lines
12 KiB
PHP

<?php
/*******************************************************************************************************************
| Software Name : EasyStream - Setup Wizard Backend
| Software Description : Handles setup wizard logic and database configuration
| Software Author : (c) Sami Ahmed
|*******************************************************************************************************************/
class SetupWizard {
private $pdo;
private $config;
public function __construct() {
$this->loadDatabaseConnection();
$this->config = [];
}
private function loadDatabaseConnection() {
try {
$db_host = getenv('DB_HOST') ?: 'db';
$db_name = getenv('DB_NAME') ?: 'easystream';
$db_user = getenv('DB_USER') ?: 'easystream';
$db_pass = getenv('DB_PASS') ?: 'easystream';
$this->pdo = new PDO(
"mysql:host=$db_host;dbname=$db_name;charset=utf8mb4",
$db_user,
$db_pass,
[
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false
]
);
} catch (PDOException $e) {
error_log("Setup Wizard DB Connection Error: " . $e->getMessage());
throw new Exception("Database connection failed. Please check your configuration.");
}
}
public function testDatabaseConnection($data) {
try {
// Test if tables exist
$stmt = $this->pdo->query("SHOW TABLES");
$tables = $stmt->fetchAll(PDO::FETCH_COLUMN);
$tableCount = count($tables);
// Check if db_settings table exists
$hasSettings = in_array('db_settings', $tables);
return [
'success' => true,
'message' => "Database connected successfully",
'tableCount' => $tableCount,
'hasSettings' => $hasSettings
];
} catch (Exception $e) {
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
public function saveConfiguration($data) {
try {
// Validate required fields
$required = ['platformName', 'domainName', 'contactEmail'];
foreach ($required as $field) {
if (empty($data[$field])) {
throw new Exception("Missing required field: $field");
}
}
// Save configuration to database
$settings = [
'site_name' => $data['platformName'],
'site_tagline' => $data['platformTagline'] ?? '',
'site_url' => $data['domainName'],
'site_email' => $data['contactEmail'],
'site_timezone' => $data['timezone'] ?? 'UTC',
// Branding
'theme_primary_color' => $data['primaryColor'] ?? '#667eea',
'theme_secondary_color' => $data['secondaryColor'] ?? '#764ba2',
'theme_default' => $data['defaultTheme'] ?? 'light',
'theme_allow_switching' => !empty($data['enableTheming']) ? '1' : '0',
// Membership tiers
'tier_free_name' => $data['tier1Name'] ?? 'Free',
'tier_free_upload_limit' => $data['tier1Upload'] ?? 100,
'tier_free_storage_limit' => $data['tier1Storage'] ?? 5,
'tier_premium_name' => $data['tier2Name'] ?? 'Premium',
'tier_premium_upload_limit' => $data['tier2Upload'] ?? 500,
'tier_premium_storage_limit' => $data['tier2Storage'] ?? 50,
'tier_premium_price' => $data['tier2Price'] ?? 9.99,
'tier_enterprise_name' => $data['tier3Name'] ?? 'Enterprise',
'tier_enterprise_upload_limit' => $data['tier3Upload'] ?? 2048,
'tier_enterprise_storage_limit' => $data['tier3Storage'] ?? 500,
'tier_enterprise_price' => $data['tier3Price'] ?? 49.99,
// Features
'feature_registration' => !empty($data['enableRegistration']) ? '1' : '0',
'feature_email_verification' => !empty($data['enableEmailVerification']) ? '1' : '0',
'feature_live_streaming' => !empty($data['enableLiveStreaming']) ? '1' : '0',
'feature_comments' => !empty($data['enableComments']) ? '1' : '0',
'feature_downloads' => !empty($data['enableDownloads']) ? '1' : '0',
'feature_monetization' => !empty($data['enableMonetization']) ? '1' : '0',
'feature_template_builder' => !empty($data['enableTemplateBuilder']) ? '1' : '0',
'feature_analytics' => !empty($data['enableAnalytics']) ? '1' : '0',
// Meta
'setup_completed' => '1',
'setup_date' => date('Y-m-d H:i:s'),
'setup_version' => '2.0'
];
// Check if db_settings table exists
$stmt = $this->pdo->query("SHOW TABLES LIKE 'db_settings'");
if ($stmt->rowCount() === 0) {
// Table doesn't exist yet, create it
$this->createSettingsTable();
}
// Insert or update settings
foreach ($settings as $key => $value) {
$stmt = $this->pdo->prepare("
INSERT INTO db_settings (cfg_name, cfg_value)
VALUES (?, ?)
ON DUPLICATE KEY UPDATE cfg_value = VALUES(cfg_value)
");
$stmt->execute([$key, $value]);
}
// Also write to config file for quick access
$this->writeConfigFile($settings);
return [
'success' => true,
'message' => 'Configuration saved successfully'
];
} catch (Exception $e) {
error_log("Setup Wizard Save Config Error: " . $e->getMessage());
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
public function createAdminUser($data) {
try {
// Validate required fields
if (empty($data['adminUsername']) || empty($data['adminEmail']) || empty($data['adminPassword'])) {
throw new Exception("All admin fields are required");
}
// Validate password match
if ($data['adminPassword'] !== $data['adminPasswordConfirm']) {
throw new Exception("Passwords do not match");
}
// Validate password strength
if (strlen($data['adminPassword']) < 8) {
throw new Exception("Password must be at least 8 characters long");
}
// Hash password
$passwordHash = password_hash($data['adminPassword'], PASSWORD_BCRYPT);
// Check if db_accountuser table exists
$stmt = $this->pdo->query("SHOW TABLES LIKE 'db_accountuser'");
if ($stmt->rowCount() === 0) {
throw new Exception("User table not found. Database may not be properly initialized.");
}
// Check if admin already exists
$stmt = $this->pdo->prepare("SELECT usr_id FROM db_accountuser WHERE usr_user = :username OR usr_email = :email");
$stmt->execute([
'username' => $data['adminUsername'],
'email' => $data['adminEmail']
]);
if ($stmt->rowCount() > 0) {
// Update existing admin
$stmt = $this->pdo->prepare("
UPDATE db_accountuser
SET usr_password = :password,
usr_email = :email,
usr_dname = :displayname,
usr_role = 'admin',
usr_status = 1,
usr_verified = 1
WHERE usr_user = :username OR usr_email = :email
");
} else {
// Insert new admin - use SET sql_mode to allow more flexible inserts
$this->pdo->exec("SET sql_mode=''");
$stmt = $this->pdo->prepare("
INSERT INTO db_accountuser (
usr_key, usr_user, usr_password, usr_email, usr_dname, usr_role, usr_status, usr_verified,
usr_IP, usr_logins, usr_lastlogin, usr_joindate, live_key
) VALUES (
1, :username, :password, :email, :displayname, 'admin', 1, 1,
'127.0.0.1', 0, NOW(), NOW(), ''
)
");
}
$stmt->execute([
'username' => $data['adminUsername'],
'password' => $passwordHash,
'email' => $data['adminEmail'],
'displayname' => $data['adminDisplayName'] ?? 'Administrator'
]);
return [
'success' => true,
'message' => 'Admin user created successfully'
];
} catch (Exception $e) {
error_log("Setup Wizard Create Admin Error: " . $e->getMessage());
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
public function finalizeSetup($data) {
try {
// Create .setup_complete file to prevent re-running setup
file_put_contents('.setup_complete', json_encode([
'completed_at' => date('Y-m-d H:i:s'),
'platform_name' => $data['platformName'] ?? 'EasyStream',
'domain' => $data['domainName'] ?? 'localhost',
'version' => '2.0'
]));
// Update Caddyfile with domain
if (!empty($data['domainName']) && $data['domainName'] !== 'localhost') {
$this->updateCaddyfile($data['domainName']);
}
// Clear any cached config
if (function_exists('opcache_reset')) {
opcache_reset();
}
return [
'success' => true,
'message' => 'Setup completed successfully',
'redirect' => '/'
];
} catch (Exception $e) {
error_log("Setup Wizard Finalize Error: " . $e->getMessage());
return [
'success' => false,
'error' => $e->getMessage()
];
}
}
private function createSettingsTable() {
$sql = "CREATE TABLE IF NOT EXISTS `db_settings` (
`cfg_name` VARCHAR(100) NOT NULL PRIMARY KEY,
`cfg_value` TEXT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci";
$this->pdo->exec($sql);
}
private function writeConfigFile($settings) {
$configContent = "<?php\n";
$configContent .= "// Auto-generated setup configuration\n";
$configContent .= "// Generated on " . date('Y-m-d H:i:s') . "\n\n";
foreach ($settings as $key => $value) {
$safeValue = addslashes($value);
$constantName = 'SETUP_' . strtoupper($key);
$configContent .= "define('$constantName', '$safeValue');\n";
}
// Write to f_core/config.setup.php
$configFile = __DIR__ . '/f_core/config.setup.php';
@file_put_contents($configFile, $configContent);
}
private function updateCaddyfile($domain) {
$caddyfile = __DIR__ . '/Caddyfile';
if (file_exists($caddyfile)) {
$content = @file_get_contents($caddyfile);
// Replace localhost with actual domain
$content = preg_replace('/http:\/\/localhost:\d+/', "https://$domain", $content);
$content = preg_replace('/^:80\s*\{/', "$domain {\n encode gzip", $content);
@file_put_contents($caddyfile, $content);
}
}
}
?>