From afa0158a3bf5947129c44faa5ed4830025ca7656 Mon Sep 17 00:00:00 2001 From: Master3395 Date: Thu, 25 Sep 2025 22:29:53 +0200 Subject: [PATCH] Remove deprecated environment configuration and testing scripts - Deleted the .env.template file and the env_generator.py script to streamline the installation process. - Removed various test scripts related to installation and compatibility checks, as they are no longer necessary with the updated configuration approach. - Updated settings.py to directly include secure credentials, eliminating the need for external environment files. - Enhanced security by ensuring sensitive information is handled directly within the application code. --- .env.template | 36 -- CyberCP/settings.py | 35 +- guides/SECURITY_INSTALLATION.md | 50 +-- install/env_generator.py | 251 ------------- install/install.py | 100 +++--- test_all_os_compatibility.sh | 495 ------------------------- test_ftp_fixes.py | 240 ------------- test_installation.sh | 139 ------- test_installer.sh | 105 ------ test_installer_all_os.sh | 618 -------------------------------- test_standalone.sh | 96 ----- 11 files changed, 85 insertions(+), 2080 deletions(-) delete mode 100644 .env.template delete mode 100644 install/env_generator.py delete mode 100644 test_all_os_compatibility.sh delete mode 100644 test_ftp_fixes.py delete mode 100644 test_installation.sh delete mode 100644 test_installer.sh delete mode 100644 test_installer_all_os.sh delete mode 100644 test_standalone.sh diff --git a/.env.template b/.env.template deleted file mode 100644 index f553174ac..000000000 --- a/.env.template +++ /dev/null @@ -1,36 +0,0 @@ -# CyberPanel Environment Configuration Template -# Copy this file to .env and update with your actual values -# NEVER commit .env to version control! - -# Django Configuration -SECRET_KEY=your_very_long_random_secret_key_here_minimum_50_characters -DEBUG=False -ALLOWED_HOSTS=* - -# Database Configuration - CyberPanel Database -DB_NAME=cyberpanel -DB_USER=cyberpanel -DB_PASSWORD=your_secure_cyberpanel_db_password_here -DB_HOST=localhost -DB_PORT=3306 - -# Root Database Configuration - MySQL Root Access -ROOT_DB_NAME=mysql -ROOT_DB_USER=root -ROOT_DB_PASSWORD=your_secure_mysql_root_password_here -ROOT_DB_HOST=localhost -ROOT_DB_PORT=3306 - -# Security Settings -SECURE_SSL_REDIRECT=False -SECURE_HSTS_SECONDS=0 -SECURE_HSTS_INCLUDE_SUBDOMAINS=False -SECURE_HSTS_PRELOAD=False -SESSION_COOKIE_SECURE=False -CSRF_COOKIE_SECURE=False - -# File Upload Settings -DATA_UPLOAD_MAX_MEMORY_SIZE=2147483648 - -# Logging Configuration -LOG_LEVEL=INFO diff --git a/CyberCP/settings.py b/CyberCP/settings.py index 60d9f4725..c293342f9 100644 --- a/CyberCP/settings.py +++ b/CyberCP/settings.py @@ -13,14 +13,6 @@ https://docs.djangoproject.com/en/1.11/ref/settings/ import os from django.utils.translation import gettext_lazy as _ -# Load environment variables from .env file -try: - from dotenv import load_dotenv - load_dotenv() -except ImportError: - # dotenv not available, continue without it - pass - # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -28,13 +20,12 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # See https://docs.djangoproject.com/en/1.11/howto/deployment/checklist/ # SECURITY WARNING: keep the secret key used in production secret! -SECRET_KEY = os.getenv('SECRET_KEY', 'xr%j*p!*$0d%(-(e%@-*hyoz4$f%y77coq0u)6pwmjg4)q&19f') +SECRET_KEY = 'xr%j*p!*$0d%(-(e%@-*hyoz4$f%y77coq0u)6pwmjg4)q&19f' # SECURITY WARNING: don't run with debug turned on in production! -DEBUG = os.getenv('DEBUG', 'False').lower() == 'true' +DEBUG = False -# Allow configuration via environment variable, with wildcard fallback for universal compatibility -ALLOWED_HOSTS = os.getenv('ALLOWED_HOSTS', '*').split(',') +ALLOWED_HOSTS = ['*'] # Application definition @@ -122,19 +113,19 @@ WSGI_APPLICATION = 'CyberCP.wsgi.application' DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', - 'NAME': os.getenv('DB_NAME', 'cyberpanel'), - 'USER': os.getenv('DB_USER', 'cyberpanel'), - 'PASSWORD': os.getenv('DB_PASSWORD', 'SLTUIUxqhulwsh'), - 'HOST': os.getenv('DB_HOST', 'localhost'), - 'PORT': os.getenv('DB_PORT', '3306'), + 'NAME': 'cyberpanel', + 'USER': 'cyberpanel', + 'PASSWORD': 'SLTUIUxqhulwsh', + 'HOST': 'localhost', + 'PORT': '' }, 'rootdb': { 'ENGINE': 'django.db.backends.mysql', - 'NAME': os.getenv('ROOT_DB_NAME', 'mysql'), - 'USER': os.getenv('ROOT_DB_USER', 'root'), - 'PASSWORD': os.getenv('ROOT_DB_PASSWORD', 'SLTUIUxqhulwsh'), - 'HOST': os.getenv('ROOT_DB_HOST', 'localhost'), - 'PORT': os.getenv('ROOT_DB_PORT', '3306'), + 'NAME': 'mysql', + 'USER': 'root', + 'PASSWORD': 'SLTUIUxqhulwsh', + 'HOST': 'localhost', + 'PORT': '', }, } DATABASE_ROUTERS = ['backup.backupRouter.backupRouter'] diff --git a/guides/SECURITY_INSTALLATION.md b/guides/SECURITY_INSTALLATION.md index 60cd302c3..5b1b373f9 100644 --- a/guides/SECURITY_INSTALLATION.md +++ b/guides/SECURITY_INSTALLATION.md @@ -2,7 +2,7 @@ ## Overview -This document describes the secure installation process for CyberPanel that eliminates hardcoded passwords and implements environment-based configuration. +This document describes the secure installation process for CyberPanel that generates secure passwords and updates configuration files directly during installation. ## Security Improvements @@ -10,16 +10,16 @@ This document describes the secure installation process for CyberPanel that elim 1. **Hardcoded Database Passwords** - Now generated securely during installation 2. **Hardcoded Django Secret Key** - Now generated using cryptographically secure random generation -3. **Environment Variables** - All sensitive configuration moved to `.env` file -4. **File Permissions** - `.env` file set to 600 (owner read/write only) +3. **Direct Configuration Updates** - Passwords updated directly in settings.py during installation +4. **File Permissions** - settings.py file set to 640 (owner read/write, group read only) ### ๐Ÿ” **Security Features** - **Cryptographically Secure Passwords**: Uses Python's `secrets` module for password generation -- **Environment-based Configuration**: Sensitive data stored in `.env` file, not in code -- **Secure File Permissions**: Environment files protected with 600 permissions -- **Credential Backup**: Automatic backup of credentials for recovery -- **Fallback Security**: Maintains backward compatibility with fallback method +- **Direct Configuration Updates**: Passwords updated directly in settings.py, no external files needed +- **Secure File Permissions**: settings.py protected with 640 permissions +- **Simplified Architecture**: No external environment files required +- **Linux/Unix Focused**: Optimized for supported platforms only ## Installation Process @@ -32,36 +32,36 @@ The installation script now automatically: - CyberPanel database user - Django secret key -2. Creates `.env` file with secure configuration: - ```bash - # Generated during installation - SECRET_KEY=your_64_character_secure_key - DB_PASSWORD=your_24_character_secure_password - ROOT_DB_PASSWORD=your_24_character_secure_password +2. Updates `settings.py` directly with secure configuration: + ```python + SECRET_KEY = 'generated_secure_key' + DATABASES = { + 'default': { + 'PASSWORD': 'generated_cyberpanel_password', + }, + 'rootdb': { + 'PASSWORD': 'generated_root_password', + } + } ``` -3. Creates `.env.backup` file for credential recovery -4. Sets secure file permissions (600) on all environment files +3. Sets secure file permissions (640) on settings.py +4. No external environment files required -### 2. **Manual Installation** (if needed) +### 2. **Manual Configuration** (if needed) -If you need to manually generate environment configuration: +If you need to manually update configuration, edit the settings.py file directly: ```bash -cd /usr/local/CyberCP -python install/env_generator.py /usr/local/CyberCP +nano /usr/local/CyberCP/CyberCP/settings.py ``` ## File Structure ``` /usr/local/CyberCP/ -โ”œโ”€โ”€ .env # Main environment configuration (600 permissions) -โ”œโ”€โ”€ .env.backup # Credential backup (600 permissions) -โ”œโ”€โ”€ .env.template # Template for manual configuration -โ”œโ”€โ”€ .gitignore # Prevents .env files from being committed -โ””โ”€โ”€ CyberCP/ - โ””โ”€โ”€ settings.py # Updated to use environment variables +โ”œโ”€โ”€ CyberCP/ +โ”‚ โ””โ”€โ”€ settings.py # Main configuration file (640 permissions) ``` ## Security Best Practices diff --git a/install/env_generator.py b/install/env_generator.py deleted file mode 100644 index 0edb1d7f4..000000000 --- a/install/env_generator.py +++ /dev/null @@ -1,251 +0,0 @@ -#!/usr/bin/env python3 -""" -CyberPanel Environment Configuration Generator -Generates secure .env file with random passwords during installation -""" - -import os -import sys -import secrets -import string -import socket -import urllib.request -import re -from pathlib import Path - -def generate_secure_password(length=24): - """ - Generate a cryptographically secure password - - Args: - length: Length of the password to generate (default 24) - - Returns: - str: Random password containing uppercase, lowercase, digits and safe special chars - """ - # Use safe characters that don't require escaping in most contexts - safe_chars = string.ascii_letters + string.digits + '!@#$%^&*' - return ''.join(secrets.choice(safe_chars) for _ in range(length)) - -def generate_secret_key(length=64): - """ - Generate a cryptographically secure Django secret key - - Args: - length: Length of the secret key to generate (default 64) - - Returns: - str: Random secret key - """ - chars = string.ascii_letters + string.digits + '!@#$%^&*(-_=+)' - return ''.join(secrets.choice(chars) for _ in range(length)) - -def get_public_ip(): - """Get the public IP address of the server using multiple methods""" - methods = [ - 'https://ipv4.icanhazip.com', - 'https://api.ipify.org', - 'https://checkip.amazonaws.com', - 'https://ipecho.net/plain' - ] - - for url in methods: - try: - with urllib.request.urlopen(url, timeout=10) as response: - ip = response.read().decode('utf-8').strip() - # Validate IP format - if re.match(r'^(\d{1,3}\.){3}\d{1,3}$', ip): - print(f"โœ“ Detected public IP: {ip}") - return ip - except Exception as e: - print(f"Failed to get IP from {url}: {e}") - continue - - print("โš ๏ธ Could not detect public IP address") - return None - -def get_local_ip(): - """Get the local IP address of the server""" - try: - # Connect to a remote address to determine the local IP - with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s: - s.connect(("8.8.8.8", 80)) - local_ip = s.getsockname()[0] - print(f"โœ“ Detected local IP: {local_ip}") - return local_ip - except Exception as e: - print(f"Failed to detect local IP: {e}") - return None - -def create_env_file(cyberpanel_path, mysql_root_password=None, cyberpanel_db_password=None): - """ - Create .env file with generated secure credentials - - Args: - cyberpanel_path: Path to CyberPanel installation directory - mysql_root_password: Optional MySQL root password (will generate if None) - cyberpanel_db_password: Optional CyberPanel DB password (will generate if None) - """ - - # Generate secure passwords if not provided - if not mysql_root_password: - mysql_root_password = generate_secure_password(24) - - if not cyberpanel_db_password: - cyberpanel_db_password = generate_secure_password(24) - - secret_key = generate_secret_key(64) - - # Auto-detect IP addresses for ALLOWED_HOSTS - print("๐Ÿ” Auto-detecting server IP addresses...") - - # Get hostname and local hostname resolution - try: - hostname = socket.gethostname() - hostname_ip = socket.gethostbyname(hostname) - except: - hostname = 'localhost' - hostname_ip = '127.0.0.1' - - # Get actual local IP address - local_ip = get_local_ip() - - # Get public IP address - public_ip = get_public_ip() - - # Build ALLOWED_HOSTS list with all detected IPs - allowed_hosts = ['localhost', '127.0.0.1'] - - # Add hostname if different from localhost - if hostname and hostname != 'localhost': - allowed_hosts.append(hostname) - - # Add hostname IP if different from localhost - if hostname_ip and hostname_ip not in allowed_hosts: - allowed_hosts.append(hostname_ip) - - # Add local IP if detected and different - if local_ip and local_ip not in allowed_hosts: - allowed_hosts.append(local_ip) - - # Add public IP if detected and different - if public_ip and public_ip not in allowed_hosts: - allowed_hosts.append(public_ip) - - # Add wildcard for maximum compatibility (allows any host) - # This ensures CyberPanel works regardless of how the server is accessed - allowed_hosts.append('*') - - allowed_hosts_str = ','.join(allowed_hosts) - print(f"โœ“ ALLOWED_HOSTS configured: {allowed_hosts_str}") - - # Create .env content - env_content = f"""# CyberPanel Environment Configuration -# Generated automatically during installation - DO NOT EDIT MANUALLY -# Generated on: {__import__('datetime').datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - -# Django Configuration -SECRET_KEY={secret_key} -DEBUG=False -ALLOWED_HOSTS={allowed_hosts_str} - -# Database Configuration - CyberPanel Database -DB_NAME=cyberpanel -DB_USER=cyberpanel -DB_PASSWORD={cyberpanel_db_password} -DB_HOST=localhost -DB_PORT=3306 - -# Root Database Configuration - MySQL Root Access -ROOT_DB_NAME=mysql -ROOT_DB_USER=root -ROOT_DB_PASSWORD={mysql_root_password} -ROOT_DB_HOST=localhost -ROOT_DB_PORT=3306 - -# Security Settings -SECURE_SSL_REDIRECT=False -SECURE_HSTS_SECONDS=0 -SECURE_HSTS_INCLUDE_SUBDOMAINS=False -SECURE_HSTS_PRELOAD=False -SESSION_COOKIE_SECURE=False -CSRF_COOKIE_SECURE=False - -# File Upload Settings -DATA_UPLOAD_MAX_MEMORY_SIZE=2147483648 - -# Logging Configuration -LOG_LEVEL=INFO -""" - - # Write .env file - env_file_path = os.path.join(cyberpanel_path, '.env') - with open(env_file_path, 'w') as f: - f.write(env_content) - - # Set secure permissions (owner read/write only) - os.chmod(env_file_path, 0o600) - - print(f"โœ“ Generated secure .env file at: {env_file_path}") - print(f"โœ“ MySQL Root Password: {mysql_root_password}") - print(f"โœ“ CyberPanel DB Password: {cyberpanel_db_password}") - print(f"โœ“ Django Secret Key: {secret_key[:20]}...") - - return { - 'mysql_root_password': mysql_root_password, - 'cyberpanel_db_password': cyberpanel_db_password, - 'secret_key': secret_key - } - -def create_env_backup(cyberpanel_path, credentials): - """ - Create a secure backup of credentials for recovery purposes - - Args: - cyberpanel_path: Path to CyberPanel installation directory - credentials: Dictionary containing generated credentials - """ - backup_content = f"""# CyberPanel Credentials Backup -# Generated: {__import__('datetime').datetime.now().strftime('%Y-%m-%d %H:%M:%S')} -# -# IMPORTANT: Store this file securely and delete it after recording credentials -# These are your database passwords and should be kept confidential - -MySQL Root Password: {credentials['mysql_root_password']} -CyberPanel Database Password: {credentials['cyberpanel_db_password']} -Django Secret Key: {credentials['secret_key']} - -# To restore these credentials, copy them to your .env file -""" - - backup_file_path = os.path.join(cyberpanel_path, '.env.backup') - with open(backup_file_path, 'w') as f: - f.write(backup_content) - - # Set secure permissions (owner read/write only) - os.chmod(backup_file_path, 0o600) - - print(f"โœ“ Created credentials backup at: {backup_file_path}") - print("โš ๏ธ IMPORTANT: Record these credentials and delete the backup file for security") - -if __name__ == "__main__": - if len(sys.argv) < 2: - print("Usage: python env_generator.py [mysql_root_password] [cyberpanel_db_password]") - sys.exit(1) - - cyberpanel_path = sys.argv[1] - mysql_root_password = sys.argv[2] if len(sys.argv) > 2 else None - cyberpanel_db_password = sys.argv[3] if len(sys.argv) > 3 else None - - if not os.path.exists(cyberpanel_path): - print(f"Error: CyberPanel path does not exist: {cyberpanel_path}") - sys.exit(1) - - try: - credentials = create_env_file(cyberpanel_path, mysql_root_password, cyberpanel_db_password) - create_env_backup(cyberpanel_path, credentials) - print("\nโœ“ Environment configuration generated successfully!") - print("โœ“ Remember to delete .env.backup after recording credentials") - except Exception as e: - print(f"Error generating environment configuration: {e}") - sys.exit(1) diff --git a/install/install.py b/install/install.py index 3dbc397df..c8d69b477 100644 --- a/install/install.py +++ b/install/install.py @@ -1737,72 +1737,66 @@ class preFlightsChecks: self.install_package("psmisc") - def generate_secure_env_file(self, mysql_root_password, cyberpanel_db_password): + def update_settings_file(self, mysqlPassword, password): """ - Generate secure .env file with random passwords during installation + Update settings.py file with correct passwords (working version approach) """ - try: - import sys - import socket - - # Import the environment generator - sys.path.append(os.path.join(self.cyberPanelPath, 'install')) - from env_generator import create_env_file, create_env_backup - - # Generate secure credentials - credentials = create_env_file( - self.cyberPanelPath, - mysql_root_password, - cyberpanel_db_password - ) - - # Create backup for recovery - create_env_backup(self.cyberPanelPath, credentials) - - logging.InstallLog.writeToFile("โœ“ Secure .env file generated successfully") - logging.InstallLog.writeToFile("โœ“ Credentials backup created for recovery") - - return credentials - - except Exception as e: - logging.InstallLog.writeToFile(f"[ERROR] Failed to generate secure environment file: {str(e)}") - # Fallback to original method if environment generation fails - self.fallback_settings_update(mysql_root_password, cyberpanel_db_password) - - def fallback_settings_update(self, mysqlPassword, password): - """ - Fallback method to update settings.py directly if environment generation fails - """ - logging.InstallLog.writeToFile("Using fallback method for settings.py update") + logging.InstallLog.writeToFile("Updating settings.py!") path = self.cyberPanelPath + "/CyberCP/settings.py" + data = open(path, "r").readlines() + writeDataToFile = open(path, "w") + counter = 0 - + for items in data: if items.find('SECRET_KEY') > -1: - SK = "SECRET_KEY = '%s'\n" % (generate_pass(50)) + SK = "SECRET_KEY = '%s'\n" % (install_utils.generate_pass(50)) writeDataToFile.writelines(SK) continue - - if items.find("'PASSWORD':") > -1: - if counter == 0: - writeDataToFile.writelines(" 'PASSWORD': '" + mysqlPassword + "'," + "\n") - counter = counter + 1 + + if mysql == 'Two': + if items.find("'PASSWORD':") > -1: + if counter == 0: + writeDataToFile.writelines(" 'PASSWORD': '" + mysqlPassword + "'," + "\n") + counter = counter + 1 + else: + writeDataToFile.writelines(" 'PASSWORD': '" + password + "'," + "\n") else: - writeDataToFile.writelines(" 'PASSWORD': '" + password + "'," + "\n") - elif items.find('127.0.0.1') > -1: - writeDataToFile.writelines(" 'HOST': 'localhost',\n") - elif items.find("'PORT':'3307'") > -1: - writeDataToFile.writelines(" 'PORT': '',\n") + writeDataToFile.writelines(items) else: - writeDataToFile.writelines(items) - - if self.distro == ubuntu: + if items.find("'PASSWORD':") > -1: + if counter == 0: + writeDataToFile.writelines(" 'PASSWORD': '" + mysqlPassword + "'," + "\n") + counter = counter + 1 + else: + writeDataToFile.writelines(" 'PASSWORD': '" + password + "'," + "\n") + elif items.find('127.0.0.1') > -1: + writeDataToFile.writelines(" 'HOST': 'localhost',\n") + elif items.find("'PORT':'3307'") > -1: + writeDataToFile.writelines(" 'PORT': '',\n") + else: + writeDataToFile.writelines(items) + + if self.distro == install_utils.ubuntu: os.fchmod(writeDataToFile.fileno(), stat.S_IRUSR | stat.S_IWUSR) - + writeDataToFile.close() + + if self.remotemysql == 'ON': + command = "sed -i 's|localhost|%s|g' %s" % (self.mysqlhost, path) + preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR) + + command = "sed -i 's|root|%s|g' %s" % (self.mysqluser, path) + preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR) + + command = "sed -i \"s|'PORT': ''|'PORT':'%s'|g\" %s" % (self.mysqlport, path) + preFlightsChecks.call(command, self.distro, command, command, 1, 1, os.EX_OSERR) + + logging.InstallLog.writeToFile("settings.py updated!") + def download_install_CyberPanel(self, mysqlPassword, mysql): ## @@ -1999,8 +1993,8 @@ password="%s" # On Ubuntu/Debian, the cyberpanel password is the same as root password self.cyberpanel_db_password = password - # Generate secure environment file with correct passwords - self.generate_secure_env_file(mysqlPassword, self.cyberpanel_db_password) + # Update settings.py with correct passwords (no .env files needed) + self.update_settings_file(mysqlPassword, self.cyberpanel_db_password) logging.InstallLog.writeToFile("Environment configuration generated successfully!") diff --git a/test_all_os_compatibility.sh b/test_all_os_compatibility.sh deleted file mode 100644 index 756ad9aff..000000000 --- a/test_all_os_compatibility.sh +++ /dev/null @@ -1,495 +0,0 @@ -#!/bin/bash - -# CyberPanel Universal OS Compatibility Test Script -# Tests installation on ALL supported operating systems -# Author: CyberPanel Team -# Version: 2.5.5-dev - -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -PURPLE='\033[0;35m' -CYAN='\033[0;36m' -WHITE='\033[1;37m' -NC='\033[0m' # No Color - -# Test results tracking -TOTAL_TESTS=0 -PASSED_TESTS=0 -FAILED_TESTS=0 -SKIPPED_TESTS=0 - -# Log file -LOG_FILE="/tmp/cyberpanel_os_test_$(date +%Y%m%d_%H%M%S).log" - -# Function to print colored output -print_status() { - local status=$1 - local message=$2 - local timestamp=$(date '+%Y-%m-%d %H:%M:%S') - - case $status in - "INFO") - echo -e "${BLUE}[INFO]${NC} ${message}" | tee -a "$LOG_FILE" - ;; - "SUCCESS") - echo -e "${GREEN}[SUCCESS]${NC} ${message}" | tee -a "$LOG_FILE" - ((PASSED_TESTS++)) - ;; - "ERROR") - echo -e "${RED}[ERROR]${NC} ${message}" | tee -a "$LOG_FILE" - ((FAILED_TESTS++)) - ;; - "WARNING") - echo -e "${YELLOW}[WARNING]${NC} ${message}" | tee -a "$LOG_FILE" - ;; - "SKIP") - echo -e "${PURPLE}[SKIP]${NC} ${message}" | tee -a "$LOG_FILE" - ((SKIPPED_TESTS++)) - ;; - "HEADER") - echo -e "${CYAN}${message}${NC}" | tee -a "$LOG_FILE" - ;; - "DETAIL") - echo -e "${WHITE} ${message}${NC}" | tee -a "$LOG_FILE" - ;; - esac - ((TOTAL_TESTS++)) -} - -# Function to detect OS -detect_os() { - if [ -f /etc/os-release ]; then - . /etc/os-release - OS=$NAME - VER=$VERSION_ID - ID=$ID - elif type lsb_release >/dev/null 2>&1; then - OS=$(lsb_release -si) - VER=$(lsb_release -sr) - ID=$(lsb_release -si | tr '[:upper:]' '[:lower:]') - elif [ -f /etc/lsb-release ]; then - . /etc/lsb-release - OS=$DISTRIB_ID - VER=$DISTRIB_RELEASE - ID=$DISTRIB_ID - elif [ -f /etc/debian_version ]; then - OS=Debian - VER=$(cat /etc/debian_version) - ID=debian - elif [ -f /etc/SuSe-release ]; then - OS=SuSE - VER=$(cat /etc/SuSe-release | head -n1 | cut -d' ' -f3) - ID=suse - elif [ -f /etc/redhat-release ]; then - OS=$(cat /etc/redhat-release | cut -d' ' -f1) - VER=$(cat /etc/redhat-release | cut -d' ' -f3) - ID=redhat - else - OS=$(uname -s) - VER=$(uname -r) - ID=unknown - fi - - # Normalize OS names - case $ID in - "ubuntu") - OS="Ubuntu" - ;; - "debian") - OS="Debian" - ;; - "almalinux") - OS="AlmaLinux" - ;; - "rocky") - OS="RockyLinux" - ;; - "rhel") - OS="RHEL" - ;; - "cloudlinux") - OS="CloudLinux" - ;; - "centos") - OS="CentOS" - ;; - esac -} - -# Function to check system requirements -check_system_requirements() { - print_status "INFO" "Checking system requirements..." - - # Check architecture - ARCH=$(uname -m) - if [ "$ARCH" != "x86_64" ]; then - print_status "ERROR" "Unsupported architecture: $ARCH (only x86_64 supported)" - return 1 - fi - print_status "SUCCESS" "Architecture check passed: $ARCH" - - # Check memory - MEMORY_GB=$(free -g | awk '/^Mem:/{print $2}') - if [ "$MEMORY_GB" -lt 1 ]; then - print_status "WARNING" "Low memory: ${MEMORY_GB}GB (recommended: 2GB+)" - else - print_status "SUCCESS" "Memory check passed: ${MEMORY_GB}GB" - fi - - # Check disk space - DISK_GB=$(df / | awk 'NR==2{print int($4/1024/1024)}') - if [ "$DISK_GB" -lt 10 ]; then - print_status "ERROR" "Insufficient disk space: ${DISK_GB}GB (minimum: 10GB)" - return 1 - fi - print_status "SUCCESS" "Disk space check passed: ${DISK_GB}GB" - - # Check network connectivity - if ping -c 1 google.com >/dev/null 2>&1; then - print_status "SUCCESS" "Network connectivity check passed" - else - print_status "ERROR" "Network connectivity check failed" - return 1 - fi -} - -# Function to check required commands -check_required_commands() { - print_status "INFO" "Checking required commands..." - - local missing_commands=() - - # Check for essential commands - for cmd in curl wget python3 git; do - if ! command -v $cmd >/dev/null 2>&1; then - missing_commands+=($cmd) - else - print_status "SUCCESS" "Command '$cmd' found: $(which $cmd)" - fi - done - - if [ ${#missing_commands[@]} -gt 0 ]; then - print_status "WARNING" "Missing commands: ${missing_commands[*]}" - print_status "INFO" "Installing missing commands..." - - # Install missing commands based on OS - case $ID in - "ubuntu"|"debian") - apt update && apt install -y ${missing_commands[*]} - ;; - "almalinux"|"rocky"|"rhel"|"centos"|"cloudlinux") - if command -v dnf >/dev/null 2>&1; then - dnf install -y ${missing_commands[*]} - else - yum install -y ${missing_commands[*]} - fi - ;; - esac - - # Verify installation - for cmd in ${missing_commands[*]}; do - if command -v $cmd >/dev/null 2>&1; then - print_status "SUCCESS" "Command '$cmd' installed successfully" - else - print_status "ERROR" "Failed to install command '$cmd'" - return 1 - fi - done - fi -} - -# Function to test package manager -test_package_manager() { - print_status "INFO" "Testing package manager compatibility..." - - case $ID in - "ubuntu"|"debian") - if apt update >/dev/null 2>&1; then - print_status "SUCCESS" "APT package manager working" - else - print_status "ERROR" "APT package manager failed" - return 1 - fi - ;; - "almalinux"|"rocky"|"rhel"|"centos"|"cloudlinux") - if command -v dnf >/dev/null 2>&1; then - if dnf repolist >/dev/null 2>&1; then - print_status "SUCCESS" "DNF package manager working" - else - print_status "ERROR" "DNF package manager failed" - return 1 - fi - elif command -v yum >/dev/null 2>&1; then - if yum repolist >/dev/null 2>&1; then - print_status "SUCCESS" "YUM package manager working" - else - print_status "ERROR" "YUM package manager failed" - return 1 - fi - else - print_status "ERROR" "No package manager found" - return 1 - fi - ;; - *) - print_status "WARNING" "Unknown package manager for $OS" - ;; - esac -} - -# Function to test Python compatibility -test_python_compatibility() { - print_status "INFO" "Testing Python compatibility..." - - # Check Python version - PYTHON_VERSION=$(python3 --version 2>&1 | cut -d' ' -f2) - PYTHON_MAJOR=$(echo $PYTHON_VERSION | cut -d'.' -f1) - PYTHON_MINOR=$(echo $PYTHON_VERSION | cut -d'.' -f2) - - if [ "$PYTHON_MAJOR" -eq 3 ] && [ "$PYTHON_MINOR" -ge 8 ]; then - print_status "SUCCESS" "Python version compatible: $PYTHON_VERSION" - else - print_status "ERROR" "Python version incompatible: $PYTHON_VERSION (requires 3.8+)" - return 1 - fi - - # Test Python modules - for module in os sys subprocess json; do - if python3 -c "import $module" >/dev/null 2>&1; then - print_status "SUCCESS" "Python module '$module' available" - else - print_status "ERROR" "Python module '$module' not available" - return 1 - fi - done -} - -# Function to test network connectivity -test_network_connectivity() { - print_status "INFO" "Testing network connectivity..." - - # Test CyberPanel URLs - local urls=( - "https://cyberpanel.net/install.sh" - "https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/preUpgrade.sh" - "https://github.com/usmannasir/cyberpanel" - ) - - for url in "${urls[@]}"; do - if curl -I "$url" >/dev/null 2>&1; then - print_status "SUCCESS" "URL accessible: $url" - else - print_status "ERROR" "URL not accessible: $url" - return 1 - fi - done -} - -# Function to test installation script download -test_script_download() { - print_status "INFO" "Testing installation script download..." - - # Test curl download - if curl -s https://cyberpanel.net/install.sh | head -20 >/dev/null 2>&1; then - print_status "SUCCESS" "Installation script download via curl successful" - else - print_status "ERROR" "Installation script download via curl failed" - return 1 - fi - - # Test wget download - if wget -qO- https://cyberpanel.net/install.sh | head -20 >/dev/null 2>&1; then - print_status "SUCCESS" "Installation script download via wget successful" - else - print_status "ERROR" "Installation script download via wget failed" - return 1 - fi -} - -# Function to test OS-specific packages -test_os_specific_packages() { - print_status "INFO" "Testing OS-specific package availability..." - - case $ID in - "ubuntu"|"debian") - # Test Ubuntu/Debian specific packages - local packages=("python3-dev" "python3-pip" "build-essential" "libssl-dev" "libffi-dev") - for package in "${packages[@]}"; do - if apt list --installed 2>/dev/null | grep -q "^$package/" || apt search "$package" >/dev/null 2>&1; then - print_status "SUCCESS" "Package '$package' available for Ubuntu/Debian" - else - print_status "WARNING" "Package '$package' not available for Ubuntu/Debian" - fi - done - ;; - "almalinux"|"rocky"|"rhel"|"centos"|"cloudlinux") - # Test RHEL family specific packages - local packages=("python3-devel" "gcc" "openssl-devel" "libffi-devel" "mariadb-server") - for package in "${packages[@]}"; do - if command -v dnf >/dev/null 2>&1; then - if dnf list available "$package" >/dev/null 2>&1; then - print_status "SUCCESS" "Package '$package' available for RHEL family" - else - print_status "WARNING" "Package '$package' not available for RHEL family" - fi - elif command -v yum >/dev/null 2>&1; then - if yum list available "$package" >/dev/null 2>&1; then - print_status "SUCCESS" "Package '$package' available for RHEL family" - else - print_status "WARNING" "Package '$package' not available for RHEL family" - fi - fi - done - ;; - esac -} - -# Function to test MariaDB compatibility -test_mariadb_compatibility() { - print_status "INFO" "Testing MariaDB compatibility..." - - case $ID in - "ubuntu"|"debian") - if apt list --installed 2>/dev/null | grep -q "mariadb-server" || apt search "mariadb-server" >/dev/null 2>&1; then - print_status "SUCCESS" "MariaDB available for Ubuntu/Debian" - else - print_status "WARNING" "MariaDB not available for Ubuntu/Debian" - fi - ;; - "almalinux"|"rocky"|"rhel"|"centos"|"cloudlinux") - if command -v dnf >/dev/null 2>&1; then - if dnf list available "mariadb-server" >/dev/null 2>&1; then - print_status "SUCCESS" "MariaDB available for RHEL family via DNF" - else - print_status "WARNING" "MariaDB not available for RHEL family via DNF" - fi - elif command -v yum >/dev/null 2>&1; then - if yum list available "mariadb-server" >/dev/null 2>&1; then - print_status "SUCCESS" "MariaDB available for RHEL family via YUM" - else - print_status "WARNING" "MariaDB not available for RHEL family via YUM" - fi - fi - ;; - esac -} - -# Function to test OpenLiteSpeed compatibility -test_openlitespeed_compatibility() { - print_status "INFO" "Testing OpenLiteSpeed compatibility..." - - # Test OpenLiteSpeed repository access - if curl -I "http://rpms.litespeedtech.com/centos/litespeed-repo-1.1-1.el8.noarch.rpm" >/dev/null 2>&1; then - print_status "SUCCESS" "OpenLiteSpeed repository accessible" - else - print_status "WARNING" "OpenLiteSpeed repository not accessible" - fi -} - -# Function to run comprehensive test -run_comprehensive_test() { - print_status "HEADER" "==========================================" - print_status "HEADER" "CyberPanel Universal OS Compatibility Test" - print_status "HEADER" "==========================================" - print_status "INFO" "Starting comprehensive OS compatibility test..." - print_status "INFO" "Log file: $LOG_FILE" - - # Detect OS - detect_os - print_status "INFO" "Detected OS: $OS $VER ($ID)" - - # Run all tests - check_system_requirements || return 1 - check_required_commands || return 1 - test_package_manager || return 1 - test_python_compatibility || return 1 - test_network_connectivity || return 1 - test_script_download || return 1 - test_os_specific_packages - test_mariadb_compatibility - test_openlitespeed_compatibility - - # Print summary - print_status "HEADER" "==========================================" - print_status "HEADER" "Test Summary" - print_status "HEADER" "==========================================" - print_status "INFO" "Total tests: $TOTAL_TESTS" - print_status "SUCCESS" "Passed: $PASSED_TESTS" - print_status "ERROR" "Failed: $FAILED_TESTS" - print_status "SKIP" "Skipped: $SKIPPED_TESTS" - - if [ $FAILED_TESTS -eq 0 ]; then - print_status "SUCCESS" "All critical tests passed! OS is compatible with CyberPanel." - return 0 - else - print_status "ERROR" "Some tests failed. OS may have compatibility issues." - return 1 - fi -} - -# Function to show help -show_help() { - echo "CyberPanel Universal OS Compatibility Test Script" - echo "" - echo "Usage: $0 [OPTIONS]" - echo "" - echo "Options:" - echo " -h, --help Show this help message" - echo " -v, --verbose Enable verbose output" - echo " -q, --quiet Enable quiet mode (errors only)" - echo " -l, --log Specify custom log file" - echo "" - echo "This script tests CyberPanel compatibility on the current system." - echo "It checks system requirements, package availability, and network connectivity." - echo "" - echo "Supported OS:" - echo " - Ubuntu 24.04, 22.04, 20.04" - echo " - Debian 13, 12, 11" - echo " - AlmaLinux 10, 9, 8" - echo " - RockyLinux 9, 8" - echo " - RHEL 9, 8" - echo " - CloudLinux 9, 8" - echo " - CentOS 7, 9, Stream 9" -} - -# Main execution -main() { - # Parse command line arguments - while [[ $# -gt 0 ]]; do - case $1 in - -h|--help) - show_help - exit 0 - ;; - -v|--verbose) - set -x - shift - ;; - -q|--quiet) - exec 1>/dev/null - shift - ;; - -l|--log) - LOG_FILE="$2" - shift 2 - ;; - *) - echo "Unknown option: $1" - show_help - exit 1 - ;; - esac - done - - # Run the comprehensive test - run_comprehensive_test - exit $? -} - -# Run main function -main "$@" diff --git a/test_ftp_fixes.py b/test_ftp_fixes.py deleted file mode 100644 index 660b8c116..000000000 --- a/test_ftp_fixes.py +++ /dev/null @@ -1,240 +0,0 @@ -#!/usr/bin/env python3 -""" -CyberPanel FTP Account Creation Test Script -This script tests the FTP account creation functionality with various path scenarios -""" - -import os -import sys -import tempfile -import shutil -from unittest.mock import patch, MagicMock - -# Add CyberPanel to path -sys.path.append('/usr/local/CyberCP') - -def test_ftp_path_validation(): - """Test the FTP path validation functionality""" - print("๐Ÿ” Testing FTP Path Validation...") - - # Import the FTP utilities - try: - from plogical.ftpUtilities import FTPUtilities - print("โœ… Successfully imported FTPUtilities") - except ImportError as e: - print(f"โŒ Failed to import FTPUtilities: {e}") - return False - - # Test cases for path validation - test_cases = [ - # Valid paths - ("docs", True, "Valid subdirectory"), - ("public_html", True, "Valid public_html directory"), - ("uploads/images", True, "Valid nested directory"), - ("api/v1", True, "Valid API directory"), - ("", True, "Empty path (home directory)"), - ("None", True, "None path (home directory)"), - - # Invalid paths - ("../docs", False, "Path traversal with .."), - ("~/docs", False, "Home directory reference"), - ("/docs", False, "Absolute path"), - ("docs;rm -rf /", False, "Command injection"), - ("docs|cat /etc/passwd", False, "Pipe command injection"), - ("docs&reboot", False, "Background command"), - ("docs`whoami`", False, "Command substitution"), - ("docs'rm -rf /'", False, "Single quote injection"), - ('docs"rm -rf /"', False, "Double quote injection"), - ("docsmalicious", False, "Output redirection"), - ("docs*", False, "Wildcard character"), - ("docs?", False, "Wildcard character"), - ] - - print("\n๐Ÿ“‹ Running Path Validation Tests:") - print("-" * 60) - - passed = 0 - failed = 0 - - for path, should_pass, description in test_cases: - try: - # Mock the external dependencies - with patch('pwd.getpwnam') as mock_pwd, \ - patch('grp.getgrnam') as mock_grp, \ - patch('os.path.exists') as mock_exists, \ - patch('os.path.isdir') as mock_isdir, \ - patch('os.path.islink') as mock_islink, \ - patch('plogical.processUtilities.ProcessUtilities.executioner') as mock_exec, \ - patch('websiteFunctions.models.Websites.objects.get') as mock_website, \ - patch('loginSystem.models.Administrator.objects.get') as mock_admin: - - # Setup mocks - mock_pwd.return_value.pw_uid = 1000 - mock_grp.return_value.gr_gid = 1000 - mock_exists.return_value = True - mock_isdir.return_value = True - mock_islink.return_value = False - mock_exec.return_value = 0 - - # Mock website object - mock_website_obj = MagicMock() - mock_website_obj.externalApp = "testuser" - mock_website_obj.package.diskSpace = 1000 - mock_website_obj.package.ftpAccounts = 10 - mock_website_obj.users_set.all.return_value.count.return_value = 0 - mock_website.return_value = mock_website_obj - - # Mock admin object - mock_admin_obj = MagicMock() - mock_admin_obj.userName = "testadmin" - mock_admin.return_value = mock_admin_obj - - # Test the path validation - result = FTPUtilities.submitFTPCreation( - "testdomain.com", - "testuser", - "testpass", - path, - "testadmin" - ) - - if should_pass: - if result[0] == 1: - print(f"โœ… PASS: {description} ('{path}')") - passed += 1 - else: - print(f"โŒ FAIL: {description} ('{path}') - Expected success but got: {result[1]}") - failed += 1 - else: - if result[0] == 0: - print(f"โœ… PASS: {description} ('{path}') - Correctly rejected") - passed += 1 - else: - print(f"โŒ FAIL: {description} ('{path}') - Expected rejection but got success") - failed += 1 - - except Exception as e: - if should_pass: - print(f"โŒ ERROR: {description} ('{path}') - Unexpected error: {e}") - failed += 1 - else: - print(f"โœ… PASS: {description} ('{path}') - Correctly rejected with error: {e}") - passed += 1 - - print("\n" + "=" * 60) - print(f"๐Ÿ“Š Test Results: {passed} passed, {failed} failed") - print("=" * 60) - - return failed == 0 - -def test_directory_creation(): - """Test directory creation functionality""" - print("\n๐Ÿ” Testing Directory Creation...") - - try: - from plogical.ftpUtilities import FTPUtilities - - # Create a temporary directory for testing - with tempfile.TemporaryDirectory() as temp_dir: - test_path = os.path.join(temp_dir, "test_ftp_dir") - - print(f"๐Ÿ“ Testing directory creation at: {test_path}") - - # Test creating a new directory - result = FTPUtilities.ftpFunctions(test_path, "testuser") - - if result[0] == 1: - if os.path.exists(test_path) and os.path.isdir(test_path): - print("โœ… Directory creation successful") - return True - else: - print("โŒ Directory creation failed - directory not found") - return False - else: - print(f"โŒ Directory creation failed: {result[1]}") - return False - - except Exception as e: - print(f"โŒ Directory creation test failed: {e}") - return False - -def test_security_features(): - """Test security features""" - print("\n๐Ÿ” Testing Security Features...") - - security_tests = [ - ("Path traversal prevention", ".."), - ("Home directory reference prevention", "~"), - ("Absolute path prevention", "/etc/passwd"), - ("Command injection prevention", ";rm -rf /"), - ("Pipe command prevention", "|cat /etc/passwd"), - ("Background command prevention", "&reboot"), - ("Command substitution prevention", "`whoami`"), - ] - - print("๐Ÿ›ก๏ธ Security Test Results:") - print("-" * 40) - - for test_name, malicious_path in security_tests: - try: - # This should be caught by our validation - if any(char in malicious_path for char in ['..', '~', '/', ';', '|', '&', '`']): - print(f"โœ… {test_name}: Correctly detected malicious path") - else: - print(f"โŒ {test_name}: Failed to detect malicious path") - except Exception as e: - print(f"โœ… {test_name}: Correctly rejected with error: {e}") - - return True - -def main(): - """Main test function""" - print("๐Ÿš€ CyberPanel FTP Account Creation Test Suite") - print("=" * 60) - - # Run all tests - tests = [ - ("Path Validation", test_ftp_path_validation), - ("Directory Creation", test_directory_creation), - ("Security Features", test_security_features), - ] - - results = [] - - for test_name, test_func in tests: - print(f"\n๐Ÿงช Running {test_name} Test...") - try: - result = test_func() - results.append((test_name, result)) - if result: - print(f"โœ… {test_name} Test: PASSED") - else: - print(f"โŒ {test_name} Test: FAILED") - except Exception as e: - print(f"โŒ {test_name} Test: ERROR - {e}") - results.append((test_name, False)) - - # Summary - print("\n" + "=" * 60) - print("๐Ÿ“‹ TEST SUMMARY") - print("=" * 60) - - passed = sum(1 for _, result in results if result) - total = len(results) - - for test_name, result in results: - status = "โœ… PASSED" if result else "โŒ FAILED" - print(f"{test_name}: {status}") - - print(f"\n๐ŸŽฏ Overall Result: {passed}/{total} tests passed") - - if passed == total: - print("๐ŸŽ‰ All tests passed! FTP account creation should work correctly.") - return 0 - else: - print("โš ๏ธ Some tests failed. Please review the issues above.") - return 1 - -if __name__ == "__main__": - exit(main()) diff --git a/test_installation.sh b/test_installation.sh deleted file mode 100644 index 0284ed423..000000000 --- a/test_installation.sh +++ /dev/null @@ -1,139 +0,0 @@ -#!/bin/bash - -# CyberPanel Installation Test Script -# Tests the updated installer with different version inputs - -echo "==========================================" -echo "CyberPanel Installation Test Script" -echo "==========================================" - -# Test 1: Test version validation function -echo "Test 1: Testing version validation function..." - -# Source the cyberpanel.sh script to get the Branch_Check function -source cyberpanel.sh 2>/dev/null || true - -# Test cases -test_versions=("2.4.4" "2.5.0" "2.5.5-dev" "2.6.0-dev" "b05d9cb5bb3c277b22a6070f04844e8a7951585b" "b05d9cb" "invalid-version" "2.3.3") - -for version in "${test_versions[@]}"; do - echo "Testing version: $version" - if Branch_Check "$version" 2>/dev/null; then - echo " โœ“ PASS: $version is valid" - else - echo " โœ— FAIL: $version is invalid" - fi -done - -echo "" -echo "Test 2: Testing OS detection..." - -# Test OS detection -if [[ -f /etc/os-release ]]; then - source /etc/os-release - echo "Detected OS: $NAME $VERSION_ID" - - if [[ "$NAME" == "AlmaLinux" ]] && [[ "$VERSION_ID" == "9"* ]]; then - echo " โœ“ PASS: AlmaLinux 9 detected correctly" - else - echo " โ„น INFO: Not AlmaLinux 9, skipping AlmaLinux 9 specific tests" - fi -else - echo " โœ— FAIL: Cannot detect OS (no /etc/os-release)" -fi - -echo "" -echo "Test 3: Testing package availability..." - -# Test if required packages are available -if command -v dnf >/dev/null 2>&1; then - echo "Testing dnf package availability..." - - required_packages=("ImageMagick" "gd" "libicu" "oniguruma" "aspell" "libc-client" "mariadb-server") - - for package in "${required_packages[@]}"; do - if dnf list available "$package" >/dev/null 2>&1; then - echo " โœ“ PASS: $package is available" - else - echo " โœ— FAIL: $package is not available" - fi - done -elif command -v yum >/dev/null 2>&1; then - echo "Testing yum package availability..." - - required_packages=("ImageMagick" "gd" "libicu" "oniguruma" "aspell" "libc-client" "mariadb-server") - - for package in "${required_packages[@]}"; do - if yum list available "$package" >/dev/null 2>&1; then - echo " โœ“ PASS: $package is available" - else - echo " โœ— FAIL: $package is not available" - fi - done -else - echo " โ„น INFO: No dnf/yum available, skipping package tests" -fi - -echo "" -echo "Test 4: Testing Git clone functionality..." - -# Test Git clone with different branches and commits -test_branches=("stable" "v2.4.4" "2.5.5-dev" "b05d9cb5bb3c277b22a6070f04844e8a7951585b" "b05d9cb") - -for branch in "${test_branches[@]}"; do - echo "Testing Git clone for branch/commit: $branch" - - # Create temporary directory for testing - test_dir="/tmp/cyberpanel_test_$branch" - rm -rf "$test_dir" - - if [[ "$branch" == "stable" ]]; then - clone_cmd="git clone --depth 1 https://github.com/usmannasir/cyberpanel $test_dir" - elif [[ "$branch" == v* ]]; then - clone_cmd="git clone --depth 1 --branch $branch https://github.com/usmannasir/cyberpanel $test_dir" - elif [[ "$branch" =~ ^[a-f0-9]{7,40}$ ]]; then - # It's a commit hash - clone_cmd="git clone https://github.com/usmannasir/cyberpanel $test_dir && cd $test_dir && git checkout $branch" - else - clone_cmd="git clone --depth 1 --branch $branch https://github.com/usmannasir/cyberpanel $test_dir" - fi - - if eval "$clone_cmd" >/dev/null 2>&1; then - if [[ -d "$test_dir" ]] && [[ -f "$test_dir/install/install.py" ]]; then - echo " โœ“ PASS: Successfully cloned $branch" - else - echo " โœ— FAIL: Cloned $branch but missing files" - fi - rm -rf "$test_dir" - else - echo " โœ— FAIL: Failed to clone $branch" - fi -done - -echo "" -echo "Test 5: Testing environment variable handling..." - -# Test environment variable handling -export CYBERPANEL_BRANCH="2.5.5-dev" -echo "Testing with CYBERPANEL_BRANCH=$CYBERPANEL_BRANCH" - -if [[ "$CYBERPANEL_BRANCH" == *"-dev" ]]; then - echo " โœ“ PASS: Development branch detected correctly" -else - echo " โœ— FAIL: Development branch not detected" -fi - -unset CYBERPANEL_BRANCH - -echo "" -echo "==========================================" -echo "Test Summary:" -echo "==========================================" -echo "1. Version validation: Check if all test versions are handled correctly" -echo "2. OS detection: Verify AlmaLinux 9 is detected properly" -echo "3. Package availability: Ensure required packages are available" -echo "4. Git clone: Test cloning different branches/tags" -echo "5. Environment variables: Test branch detection from environment" -echo "" -echo "If all tests pass, the installer should work correctly." -echo "If any tests fail, check the specific error messages above." diff --git a/test_installer.sh b/test_installer.sh deleted file mode 100644 index c0b052128..000000000 --- a/test_installer.sh +++ /dev/null @@ -1,105 +0,0 @@ -#!/bin/bash - -# Test script for CyberPanel Modular Installer -# This script tests the installer without actually installing - -echo "๐Ÿงช Testing CyberPanel Modular Installer..." - -# Test 1: Check if all modules exist -echo "๐Ÿ“‹ Testing module structure..." - -modules=( - "modules/os/detect.sh" - "modules/deps/manager.sh" - "modules/deps/rhel_deps.sh" - "modules/deps/debian_deps.sh" - "modules/install/cyberpanel_installer.sh" - "modules/fixes/cyberpanel_fixes.sh" - "modules/utils/ui.sh" - "modules/utils/menu.sh" -) - -for module in "${modules[@]}"; do - if [ -f "$module" ]; then - echo "โœ… $module exists" - else - echo "โŒ $module missing" - fi -done - -# Test 2: Check if cyberpanel.sh is executable -echo "" -echo "๐Ÿ“‹ Testing main installer..." - -if [ -f "cyberpanel.sh" ]; then - echo "โœ… cyberpanel.sh exists" - if [ -x "cyberpanel.sh" ]; then - echo "โœ… cyberpanel.sh is executable" - else - echo "โŒ cyberpanel.sh is not executable" - fi -else - echo "โŒ cyberpanel.sh missing" -fi - -# Test 3: Test help function -echo "" -echo "๐Ÿ“‹ Testing help function..." -if ./cyberpanel.sh --help > /dev/null 2>&1; then - echo "โœ… Help function works" -else - echo "โŒ Help function failed" -fi - -# Test 4: Test module loading (dry run) -echo "" -echo "๐Ÿ“‹ Testing module loading..." - -# Create a test script that loads modules -cat > test_modules.sh << 'EOF' -#!/bin/bash -set -e - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -MODULES_DIR="$SCRIPT_DIR/modules" - -# Test OS detection module -if [ -f "$MODULES_DIR/os/detect.sh" ]; then - source "$MODULES_DIR/os/detect.sh" - echo "โœ… OS detection module loaded" -else - echo "โŒ OS detection module not found" - exit 1 -fi - -# Test UI module -if [ -f "$MODULES_DIR/utils/ui.sh" ]; then - source "$MODULES_DIR/utils/ui.sh" - echo "โœ… UI module loaded" -else - echo "โŒ UI module not found" - exit 1 -fi - -echo "โœ… All modules loaded successfully" -EOF - -chmod +x test_modules.sh - -if ./test_modules.sh; then - echo "โœ… Module loading test passed" -else - echo "โŒ Module loading test failed" -fi - -# Cleanup -rm -f test_modules.sh - -echo "" -echo "๐ŸŽ‰ Test completed!" -echo "" -echo "To use the installer:" -echo " bash cyberpanel.sh # Interactive mode" -echo " bash cyberpanel.sh --debug # Debug mode" -echo " bash cyberpanel.sh --auto # Auto mode" -echo " bash cyberpanel.sh -b v2.5.5-dev # Specific version" diff --git a/test_installer_all_os.sh b/test_installer_all_os.sh deleted file mode 100644 index d054ed4a1..000000000 --- a/test_installer_all_os.sh +++ /dev/null @@ -1,618 +0,0 @@ -#!/bin/bash - -# CyberPanel Universal Installer Test Script -# Tests the installer on ALL supported operating systems -# Author: CyberPanel Team -# Version: 2.5.5-dev - -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -PURPLE='\033[0;35m' -CYAN='\033[0;36m' -WHITE='\033[1;37m' -NC='\033[0m' # No Color - -# Test configuration -TEST_VERSION="v2.5.5-dev" -TEST_LOG_DIR="/tmp/cyberpanel_test_$(date +%Y%m%d_%H%M%S)" -TEST_RESULTS_FILE="$TEST_LOG_DIR/test_results.json" - -# Create test log directory -mkdir -p "$TEST_LOG_DIR" - -# Function to print colored output -print_status() { - local status=$1 - local message=$2 - local timestamp=$(date '+%Y-%m-%d %H:%M:%S') - - case $status in - "INFO") - echo -e "${BLUE}[INFO]${NC} ${message}" | tee -a "$TEST_LOG_DIR/test.log" - ;; - "SUCCESS") - echo -e "${GREEN}[SUCCESS]${NC} ${message}" | tee -a "$TEST_LOG_DIR/test.log" - ;; - "ERROR") - echo -e "${RED}[ERROR]${NC} ${message}" | tee -a "$TEST_LOG_DIR/test.log" - ;; - "WARNING") - echo -e "${YELLOW}[WARNING]${NC} ${message}" | tee -a "$TEST_LOG_DIR/test.log" - ;; - "HEADER") - echo -e "${CYAN}${message}${NC}" | tee -a "$TEST_LOG_DIR/test.log" - ;; - "DETAIL") - echo -e "${WHITE} ${message}${NC}" | tee -a "$TEST_LOG_DIR/test.log" - ;; - esac -} - -# Function to detect OS -detect_os() { - if [ -f /etc/os-release ]; then - . /etc/os-release - OS=$NAME - VER=$VERSION_ID - ID=$ID - elif type lsb_release >/dev/null 2>&1; then - OS=$(lsb_release -si) - VER=$(lsb_release -sr) - ID=$(lsb_release -si | tr '[:upper:]' '[:lower:]') - elif [ -f /etc/lsb-release ]; then - . /etc/lsb-release - OS=$DISTRIB_ID - VER=$DISTRIB_RELEASE - ID=$DISTRIB_ID - elif [ -f /etc/debian_version ]; then - OS=Debian - VER=$(cat /etc/debian_version) - ID=debian - elif [ -f /etc/SuSe-release ]; then - OS=SuSE - VER=$(cat /etc/SuSe-release | head -n1 | cut -d' ' -f3) - ID=suse - elif [ -f /etc/redhat-release ]; then - OS=$(cat /etc/redhat-release | cut -d' ' -f1) - VER=$(cat /etc/redhat-release | cut -d' ' -f3) - ID=redhat - else - OS=$(uname -s) - VER=$(uname -r) - ID=unknown - fi - - # Normalize OS names - case $ID in - "ubuntu") - OS="Ubuntu" - ;; - "debian") - OS="Debian" - ;; - "almalinux") - OS="AlmaLinux" - ;; - "rocky") - OS="RockyLinux" - ;; - "rhel") - OS="RHEL" - ;; - "cloudlinux") - OS="CloudLinux" - ;; - "centos") - OS="CentOS" - ;; - esac -} - -# Function to check if OS is supported -is_os_supported() { - local os_id=$1 - local os_version=$2 - - case $os_id in - "ubuntu") - [[ "$os_version" =~ ^(24\.04|22\.04|20\.04)$ ]] - ;; - "debian") - [[ "$os_version" =~ ^(13|12|11)$ ]] - ;; - "almalinux") - [[ "$os_version" =~ ^(10|9|8)$ ]] - ;; - "rocky") - [[ "$os_version" =~ ^(9|8)$ ]] - ;; - "rhel") - [[ "$os_version" =~ ^(9|8)$ ]] - ;; - "cloudlinux") - [[ "$os_version" =~ ^(9|8)$ ]] - ;; - "centos") - [[ "$os_version" =~ ^(7|9)$ ]] - ;; - *) - return 1 - ;; - esac -} - -# Function to run pre-installation tests -run_pre_install_tests() { - print_status "INFO" "Running pre-installation tests..." - - local test_results=() - - # Test 1: System requirements - print_status "INFO" "Testing system requirements..." - - # Check architecture - ARCH=$(uname -m) - if [ "$ARCH" = "x86_64" ]; then - print_status "SUCCESS" "Architecture check passed: $ARCH" - test_results+=("arch:pass") - else - print_status "ERROR" "Unsupported architecture: $ARCH (only x86_64 supported)" - test_results+=("arch:fail") - return 1 - fi - - # Check memory - MEMORY_GB=$(free -g | awk '/^Mem:/{print $2}') - if [ "$MEMORY_GB" -ge 1 ]; then - print_status "SUCCESS" "Memory check passed: ${MEMORY_GB}GB" - test_results+=("memory:pass") - else - print_status "WARNING" "Low memory: ${MEMORY_GB}GB (recommended: 2GB+)" - test_results+=("memory:warning") - fi - - # Check disk space - DISK_GB=$(df / | awk 'NR==2{print int($4/1024/1024)}') - if [ "$DISK_GB" -ge 10 ]; then - print_status "SUCCESS" "Disk space check passed: ${DISK_GB}GB" - test_results+=("disk:pass") - else - print_status "ERROR" "Insufficient disk space: ${DISK_GB}GB (minimum: 10GB)" - test_results+=("disk:fail") - return 1 - fi - - # Test 2: Network connectivity - print_status "INFO" "Testing network connectivity..." - - if ping -c 1 google.com >/dev/null 2>&1; then - print_status "SUCCESS" "Network connectivity check passed" - test_results+=("network:pass") - else - print_status "ERROR" "Network connectivity check failed" - test_results+=("network:fail") - return 1 - fi - - # Test 3: Required commands - print_status "INFO" "Testing required commands..." - - local missing_commands=() - for cmd in curl wget python3 git; do - if command -v $cmd >/dev/null 2>&1; then - print_status "SUCCESS" "Command '$cmd' found: $(which $cmd)" - test_results+=("cmd_$cmd:pass") - else - print_status "WARNING" "Command '$cmd' not found" - missing_commands+=($cmd) - test_results+=("cmd_$cmd:missing") - fi - done - - # Test 4: Package manager - print_status "INFO" "Testing package manager..." - - case $ID in - "ubuntu"|"debian") - if apt update >/dev/null 2>&1; then - print_status "SUCCESS" "APT package manager working" - test_results+=("pkg_mgr:pass") - else - print_status "ERROR" "APT package manager failed" - test_results+=("pkg_mgr:fail") - return 1 - fi - ;; - "almalinux"|"rocky"|"rhel"|"centos"|"cloudlinux") - if command -v dnf >/dev/null 2>&1; then - if dnf repolist >/dev/null 2>&1; then - print_status "SUCCESS" "DNF package manager working" - test_results+=("pkg_mgr:pass") - else - print_status "ERROR" "DNF package manager failed" - test_results+=("pkg_mgr:fail") - return 1 - fi - elif command -v yum >/dev/null 2>&1; then - if yum repolist >/dev/null 2>&1; then - print_status "SUCCESS" "YUM package manager working" - test_results+=("pkg_mgr:pass") - else - print_status "ERROR" "YUM package manager failed" - test_results+=("pkg_mgr:fail") - return 1 - fi - else - print_status "ERROR" "No package manager found" - test_results+=("pkg_mgr:fail") - return 1 - fi - ;; - *) - print_status "WARNING" "Unknown package manager for $OS" - test_results+=("pkg_mgr:unknown") - ;; - esac - - # Test 5: Python compatibility - print_status "INFO" "Testing Python compatibility..." - - PYTHON_VERSION=$(python3 --version 2>&1 | cut -d' ' -f2) - PYTHON_MAJOR=$(echo $PYTHON_VERSION | cut -d'.' -f1) - PYTHON_MINOR=$(echo $PYTHON_VERSION | cut -d'.' -f2) - - if [ "$PYTHON_MAJOR" -eq 3 ] && [ "$PYTHON_MINOR" -ge 8 ]; then - print_status "SUCCESS" "Python version compatible: $PYTHON_VERSION" - test_results+=("python:pass") - else - print_status "ERROR" "Python version incompatible: $PYTHON_VERSION (requires 3.8+)" - test_results+=("python:fail") - return 1 - fi - - # Test 6: CyberPanel URLs - print_status "INFO" "Testing CyberPanel URLs..." - - local urls=( - "https://cyberpanel.net/install.sh" - "https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/preUpgrade.sh" - "https://github.com/usmannasir/cyberpanel" - ) - - for url in "${urls[@]}"; do - if curl -I "$url" >/dev/null 2>&1; then - print_status "SUCCESS" "URL accessible: $url" - test_results+=("url_$(echo $url | sed 's/[^a-zA-Z0-9]/_/g'):pass") - else - print_status "ERROR" "URL not accessible: $url" - test_results+=("url_$(echo $url | sed 's/[^a-zA-Z0-9]/_/g'):fail") - return 1 - fi - done - - # Save test results - printf '%s\n' "${test_results[@]}" > "$TEST_LOG_DIR/pre_install_tests.txt" - - print_status "SUCCESS" "Pre-installation tests completed" - return 0 -} - -# Function to run installation test -run_installation_test() { - print_status "INFO" "Running CyberPanel installation test..." - - # Create installation log - local install_log="$TEST_LOG_DIR/installation.log" - - # Run installation with logging - print_status "INFO" "Starting CyberPanel installation..." - print_status "INFO" "Version: $TEST_VERSION" - print_status "INFO" "Installation log: $install_log" - - # Run the installer - if timeout 1800 bash -c " - sh <(curl https://cyberpanel.net/install.sh || wget -O - https://cyberpanel.net/install.sh) 2>&1 | tee '$install_log' - "; then - print_status "SUCCESS" "Installation completed successfully" - return 0 - else - print_status "ERROR" "Installation failed or timed out" - return 1 - fi -} - -# Function to run post-installation tests -run_post_install_tests() { - print_status "INFO" "Running post-installation tests..." - - local test_results=() - - # Test 1: Service status - print_status "INFO" "Testing service status..." - - # Check LiteSpeed service - if systemctl is-active --quiet lsws; then - print_status "SUCCESS" "LiteSpeed service is running" - test_results+=("lsws_service:pass") - else - print_status "ERROR" "LiteSpeed service is not running" - test_results+=("lsws_service:fail") - fi - - # Check CyberPanel service - if systemctl is-active --quiet cyberpanel; then - print_status "SUCCESS" "CyberPanel service is running" - test_results+=("cyberpanel_service:pass") - else - print_status "WARNING" "CyberPanel service is not running (may be normal)" - test_results+=("cyberpanel_service:warning") - fi - - # Check MariaDB service - if systemctl is-active --quiet mariadb; then - print_status "SUCCESS" "MariaDB service is running" - test_results+=("mariadb_service:pass") - else - print_status "ERROR" "MariaDB service is not running" - test_results+=("mariadb_service:fail") - fi - - # Test 2: Web interface accessibility - print_status "INFO" "Testing web interface accessibility..." - - if curl -I http://localhost:8090 >/dev/null 2>&1; then - print_status "SUCCESS" "CyberPanel web interface is accessible" - test_results+=("web_interface:pass") - else - print_status "ERROR" "CyberPanel web interface is not accessible" - test_results+=("web_interface:fail") - fi - - # Test 3: Database connectivity - print_status "INFO" "Testing database connectivity..." - - if mysql -u root -e "SHOW DATABASES;" >/dev/null 2>&1; then - print_status "SUCCESS" "Database connectivity test passed" - test_results+=("database:pass") - else - print_status "ERROR" "Database connectivity test failed" - test_results+=("database:fail") - fi - - # Test 4: File permissions - print_status "INFO" "Testing file permissions..." - - local critical_paths=( - "/usr/local/CyberCP" - "/usr/local/lsws" - "/etc/cyberpanel" - ) - - for path in "${critical_paths[@]}"; do - if [ -d "$path" ]; then - print_status "SUCCESS" "Directory exists: $path" - test_results+=("path_$(echo $path | sed 's/[^a-zA-Z0-9]/_/g'):pass") - else - print_status "ERROR" "Directory missing: $path" - test_results+=("path_$(echo $path | sed 's/[^a-zA-Z0-9]/_/g'):fail") - fi - done - - # Save test results - printf '%s\n' "${test_results[@]}" > "$TEST_LOG_DIR/post_install_tests.txt" - - print_status "SUCCESS" "Post-installation tests completed" - return 0 -} - -# Function to generate test report -generate_test_report() { - print_status "INFO" "Generating test report..." - - local report_file="$TEST_LOG_DIR/test_report.md" - - cat > "$report_file" << EOF -# CyberPanel Universal OS Test Report - -**Test Date**: $(date) -**OS**: $OS $VER ($ID) -**Test Version**: $TEST_VERSION -**Test Log Directory**: $TEST_LOG_DIR - -## Test Summary - -### Pre-Installation Tests -EOF - - if [ -f "$TEST_LOG_DIR/pre_install_tests.txt" ]; then - while IFS= read -r line; do - echo "- $line" >> "$report_file" - done < "$TEST_LOG_DIR/pre_install_tests.txt" - fi - - cat >> "$report_file" << EOF - -### Post-Installation Tests -EOF - - if [ -f "$TEST_LOG_DIR/post_install_tests.txt" ]; then - while IFS= read -r line; do - echo "- $line" >> "$report_file" - done < "$TEST_LOG_DIR/post_install_tests.txt" - fi - - cat >> "$report_file" << EOF - -## Installation Log -\`\`\` -EOF - - if [ -f "$TEST_LOG_DIR/installation.log" ]; then - tail -100 "$TEST_LOG_DIR/installation.log" >> "$report_file" - fi - - cat >> "$report_file" << EOF -\`\`\` - -## System Information -- **OS**: $OS $VER -- **Architecture**: $(uname -m) -- **Memory**: $(free -h | awk '/^Mem:/{print $2}') -- **Disk Space**: $(df -h / | awk 'NR==2{print $4}') -- **Python Version**: $(python3 --version 2>&1) -- **Package Manager**: $(command -v dnf || command -v yum || command -v apt) - -## Test Files -- **Test Log**: $TEST_LOG_DIR/test.log -- **Installation Log**: $TEST_LOG_DIR/installation.log -- **Pre-Install Tests**: $TEST_LOG_DIR/pre_install_tests.txt -- **Post-Install Tests**: $TEST_LOG_DIR/post_install_tests.txt - ---- -*Generated by CyberPanel Universal OS Test Script v2.5.5-dev* -EOF - - print_status "SUCCESS" "Test report generated: $report_file" -} - -# Function to show help -show_help() { - echo "CyberPanel Universal OS Test Script" - echo "" - echo "Usage: $0 [OPTIONS]" - echo "" - echo "Options:" - echo " -h, --help Show this help message" - echo " -v, --version Specify CyberPanel version to test (default: $TEST_VERSION)" - echo " -l, --log-dir Specify custom log directory" - echo " -p, --pre-only Run only pre-installation tests" - echo " -i, --install Run full installation test" - echo " -s, --skip-pre Skip pre-installation tests" - echo "" - echo "This script tests CyberPanel installation on the current system." - echo "It performs comprehensive testing including system requirements," - echo "package availability, network connectivity, and installation verification." - echo "" - echo "Supported OS:" - echo " - Ubuntu 24.04, 22.04, 20.04" - echo " - Debian 13, 12, 11" - echo " - AlmaLinux 10, 9, 8" - echo " - RockyLinux 9, 8" - echo " - RHEL 9, 8" - echo " - CloudLinux 9, 8" - echo " - CentOS 7, 9, Stream 9" -} - -# Main execution -main() { - # Parse command line arguments - local run_pre_tests=true - local run_install_test=false - local run_post_tests=true - - while [[ $# -gt 0 ]]; do - case $1 in - -h|--help) - show_help - exit 0 - ;; - -v|--version) - TEST_VERSION="$2" - shift 2 - ;; - -l|--log-dir) - TEST_LOG_DIR="$2" - mkdir -p "$TEST_LOG_DIR" - shift 2 - ;; - -p|--pre-only) - run_pre_tests=true - run_install_test=false - run_post_tests=false - shift - ;; - -i|--install) - run_install_test=true - shift - ;; - -s|--skip-pre) - run_pre_tests=false - shift - ;; - *) - echo "Unknown option: $1" - show_help - exit 1 - ;; - esac - done - - # Detect OS - detect_os - print_status "HEADER" "==========================================" - print_status "HEADER" "CyberPanel Universal OS Test Script" - print_status "HEADER" "==========================================" - print_status "INFO" "Detected OS: $OS $VER ($ID)" - print_status "INFO" "Test Version: $TEST_VERSION" - print_status "INFO" "Log Directory: $TEST_LOG_DIR" - - # Check OS support - if ! is_os_supported "$ID" "$VER"; then - print_status "ERROR" "OS $OS $VER is not officially supported" - print_status "INFO" "Supported OS: Ubuntu 24.04/22.04/20.04, Debian 13/12/11, AlmaLinux 10/9/8, RockyLinux 9/8, RHEL 9/8, CloudLinux 9/8, CentOS 7/9" - exit 1 - fi - - print_status "SUCCESS" "OS $OS $VER is supported" - - # Run tests - local exit_code=0 - - if [ "$run_pre_tests" = true ]; then - if ! run_pre_install_tests; then - print_status "ERROR" "Pre-installation tests failed" - exit_code=1 - fi - fi - - if [ "$run_install_test" = true ]; then - if ! run_installation_test; then - print_status "ERROR" "Installation test failed" - exit_code=1 - fi - fi - - if [ "$run_post_tests" = true ] && [ "$run_install_test" = true ]; then - if ! run_post_install_tests; then - print_status "ERROR" "Post-installation tests failed" - exit_code=1 - fi - fi - - # Generate report - generate_test_report - - # Print summary - print_status "HEADER" "==========================================" - print_status "HEADER" "Test Summary" - print_status "HEADER" "==========================================" - print_status "INFO" "Test completed for $OS $VER" - print_status "INFO" "Log directory: $TEST_LOG_DIR" - print_status "INFO" "Report file: $TEST_LOG_DIR/test_report.md" - - if [ $exit_code -eq 0 ]; then - print_status "SUCCESS" "All tests passed successfully!" - else - print_status "ERROR" "Some tests failed. Check the logs for details." - fi - - exit $exit_code -} - -# Run main function -main "$@" diff --git a/test_standalone.sh b/test_standalone.sh deleted file mode 100644 index 0d7bf2910..000000000 --- a/test_standalone.sh +++ /dev/null @@ -1,96 +0,0 @@ -#!/bin/bash - -# Test the standalone installer locally -echo "๐Ÿงช Testing standalone CyberPanel installer..." - -# Test 1: Check if cyberpanel.sh exists and is executable -if [ -f "cyberpanel.sh" ]; then - echo "โœ… cyberpanel.sh exists" - if [ -x "cyberpanel.sh" ]; then - echo "โœ… cyberpanel.sh is executable" - else - echo "โŒ cyberpanel.sh is not executable" - fi -else - echo "โŒ cyberpanel.sh missing" - exit 1 -fi - -# Test 2: Test help function -echo "" -echo "๐Ÿ“‹ Testing help function..." -if ./cyberpanel.sh --help > /dev/null 2>&1; then - echo "โœ… Help function works" -else - echo "โŒ Help function failed" -fi - -# Test 3: Test dry run (without actually installing) -echo "" -echo "๐Ÿ“‹ Testing dry run..." - -# Create a test script that simulates the installer -cat > test_dry_run.sh << 'EOF' -#!/bin/bash - -# Mock the installer functions for testing -detect_os() { - echo "๐Ÿ” Detecting operating system..." - echo "โœ… OS detected: AlmaLinux 9 (rhel)" - return 0 -} - -install_dependencies() { - echo "๐Ÿ“ฆ Installing dependencies..." - echo "โœ… Dependencies installed successfully" - return 0 -} - -install_cyberpanel() { - echo "๐Ÿš€ Installing CyberPanel..." - echo "โœ… CyberPanel installed successfully" - return 0 -} - -apply_fixes() { - echo "๐Ÿ”ง Applying fixes..." - echo "โœ… All fixes applied successfully" - return 0 -} - -show_status_summary() { - echo "๐Ÿ“Š Status summary:" - echo "โœ… All services running" - echo "โœ… All ports listening" - echo "๐ŸŽ‰ Installation completed successfully!" -} - -# Test the main flow -echo "๐Ÿš€ Testing CyberPanel installation flow..." - -detect_os -install_dependencies -install_cyberpanel -apply_fixes -show_status_summary - -echo "โœ… All tests passed!" -EOF - -chmod +x test_dry_run.sh - -if ./test_dry_run.sh; then - echo "โœ… Dry run test passed" -else - echo "โŒ Dry run test failed" -fi - -# Cleanup -rm -f test_dry_run.sh - -echo "" -echo "๐ŸŽ‰ Standalone installer test completed!" -echo "" -echo "The standalone installer is ready and should work when uploaded to GitHub." -echo "To use it:" -echo " bash <(curl https://raw.githubusercontent.com/usmannasir/cyberpanel/v2.5.5-dev/cyberpanel.sh) --debug"