#!/bin/bash # ========================================================================= # fix-db-connection.sh # ========================================================================= # Description: This script checks and fixes database connection issues on the # staging server that are causing E2E test failures. It specifically addresses # the "Access denied for user 'root'@'localhost'" error by verifying and # correcting database configuration settings in local scripts and configurations. # # Usage: ./bin/fix-db-connection.sh [--verbose] [--dry-run] # # Options: # --verbose Show detailed output during execution # --dry-run Show what would be done without making changes # # Author: Roo Code # Date: April 24, 2025 # ========================================================================= # Get absolute path to this script's directory SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Load environment variables ENV_FILE="$SCRIPT_DIR/../.env" if [ ! -f "$ENV_FILE" ]; then echo "Error: .env file not found at: $ENV_FILE" exit 1 fi source "$ENV_FILE" # Colors for output GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # Default options VERBOSE=false DRY_RUN=false # Parse command line arguments for arg in "$@"; do case $arg in --verbose) VERBOSE=true shift ;; --dry-run) DRY_RUN=true shift ;; --help) echo "Usage: $0 [--verbose] [--dry-run]" echo "" echo "Options:" echo " --verbose Show detailed output during execution" echo " --dry-run Show what would be done without making changes" echo " --help Show this help message" exit 0 ;; esac done # Function to check if a command was successful check_status() { if [ $? -eq 0 ]; then echo -e "${GREEN}✓ $1${NC}" return 0 else echo -e "${RED}✗ $1${NC}" return 1 fi } # Function to log verbose output log_verbose() { if [ "$VERBOSE" = true ]; then echo -e "${BLUE}[INFO] $1${NC}" fi } # Function to log error messages log_error() { echo -e "${RED}[ERROR] $1${NC}" } # Function to log warning messages log_warning() { echo -e "${YELLOW}[WARNING] $1${NC}" } # Function to log success messages log_success() { echo -e "${GREEN}[SUCCESS] $1${NC}" } # Function to check SSH connection check_ssh_connection() { log_verbose "Testing SSH connection to staging server..." if ! sshpass -p "$UPSKILL_STAGING_PASS" ssh -o StrictHostKeyChecking=no -o ConnectTimeout=10 "$UPSKILL_STAGING_SSH_USER@$UPSKILL_STAGING_IP" "echo 'SSH connection successful'" > /dev/null 2>&1; then log_error "Cannot connect to staging server. Please check your SSH credentials and network connection." exit 1 fi log_verbose "SSH connection successful." } # Function to check database connection from staging server check_remote_db_connection() { log_verbose "Testing database connection from staging server..." # Construct the MySQL command to run on the staging server local mysql_cmd="mysql -h localhost -u $UPSKILL_STAGING_DB_USER -p'$UPSKILL_STAGING_DB_PASSWORD' $UPSKILL_STAGING_DB_NAME -e 'SELECT 1;' 2>&1" # Execute the command on the staging server local result result=$(sshpass -p "$UPSKILL_STAGING_PASS" ssh -o StrictHostKeyChecking=no "$UPSKILL_STAGING_SSH_USER@$UPSKILL_STAGING_IP" "$mysql_cmd") # Check if the command was successful if [[ $result == *"1"* ]]; then log_success "Database connection from staging server successful." return 0 else log_error "Database connection from staging server failed: $result" return 1 fi } # Function to check database connection from local machine check_local_db_connection() { log_verbose "Testing database connection from local machine..." # Construct the MySQL command to run locally local mysql_cmd="mysql -h $UPSKILL_STAGING_IP -u $UPSKILL_STAGING_DB_USER -p'$UPSKILL_STAGING_DB_PASSWORD' $UPSKILL_STAGING_DB_NAME -e 'SELECT 1;' 2>&1" # Execute the command locally local result result=$(eval "$mysql_cmd") # Check if the command was successful if [[ $result == *"1"* ]]; then log_success "Database connection from local machine successful." return 0 else log_warning "Database connection from local machine failed: $result" log_verbose "This is expected if the database is not accessible from outside the server." return 1 fi } # Function to check WordPress database configuration check_wp_config() { log_verbose "Checking WordPress database configuration on staging server..." # Get the database configuration from wp-config.php local wp_config_cmd="cd $UPSKILL_STAGING_PATH && grep -E \"^define\\('DB_[A-Z]+', '.*'\\);\" wp-config.php" local wp_config wp_config=$(sshpass -p "$UPSKILL_STAGING_PASS" ssh -o StrictHostKeyChecking=no "$UPSKILL_STAGING_SSH_USER@$UPSKILL_STAGING_IP" "$wp_config_cmd") # Extract database settings local db_name=$(echo "$wp_config" | grep "DB_NAME" | sed -E "s/define\('DB_NAME', '(.*)'\);/\1/") local db_user=$(echo "$wp_config" | grep "DB_USER" | sed -E "s/define\('DB_USER', '(.*)'\);/\1/") local db_password=$(echo "$wp_config" | grep "DB_PASSWORD" | sed -E "s/define\('DB_PASSWORD', '(.*)'\);/\1/") local db_host=$(echo "$wp_config" | grep "DB_HOST" | sed -E "s/define\('DB_HOST', '(.*)'\);/\1/") echo "Current WordPress database configuration on staging server:" echo " DB_NAME: $db_name" echo " DB_USER: $db_user" echo " DB_HOST: $db_host" echo " DB_PASSWORD: [HIDDEN]" # Check if the configuration matches the environment variables if [ "$db_name" != "$UPSKILL_STAGING_DB_NAME" ]; then log_warning "DB_NAME in wp-config.php ($db_name) does not match .env file ($UPSKILL_STAGING_DB_NAME)" fi if [ "$db_user" != "$UPSKILL_STAGING_DB_USER" ]; then log_warning "DB_USER in wp-config.php ($db_user) does not match .env file ($UPSKILL_STAGING_DB_USER)" fi if [ "$db_password" != "$UPSKILL_STAGING_DB_PASSWORD" ]; then log_warning "DB_PASSWORD in wp-config.php does not match .env file" fi # Return the extracted values echo "$db_name|$db_user|$db_password|$db_host" } # Function to check for hardcoded database credentials in test files check_test_files() { log_verbose "Checking for hardcoded database credentials in test files..." # Search for 'root' user in test files local search_cmd="find $SCRIPT_DIR/.. -type f -name \"*.php\" -o -name \"*.js\" -o -name \"*.ts\" | xargs grep -l \"'root'\\|\\\"root\\\"\" 2>/dev/null || true" local files files=$(eval "$search_cmd") if [ -n "$files" ]; then echo "Found files with potential hardcoded 'root' database user:" echo "$files" return 0 else log_verbose "No files with hardcoded 'root' database user found." return 1 fi } # Function to check Playwright configuration check_playwright_config() { log_verbose "Checking Playwright configuration..." local config_file="$SCRIPT_DIR/../playwright.config.ts" if [ ! -f "$config_file" ]; then log_warning "Playwright configuration file not found: $config_file" return 1 fi # Check for database configuration in Playwright config local db_config db_config=$(grep -A 10 "database\|DB_" "$config_file" 2>/dev/null || true) if [ -n "$db_config" ]; then echo "Found database configuration in Playwright config:" echo "$db_config" return 0 else log_verbose "No database configuration found in Playwright config." return 1 fi } # Function to check E2E test files for database connection issues check_e2e_tests() { log_verbose "Checking E2E test files for database connection issues..." local tests_dir="$SCRIPT_DIR/../tests" if [ ! -d "$tests_dir" ]; then log_warning "Tests directory not found: $tests_dir" return 1 fi # Search for database connection code in E2E test files local search_cmd="find $tests_dir -type f -name \"*.spec.ts\" -o -name \"*.spec.js\" | xargs grep -l \"mysql\\|database\\|connection\\|root\" 2>/dev/null || true" local files files=$(eval "$search_cmd") if [ -n "$files" ]; then echo "Found E2E test files with potential database connection code:" echo "$files" return 0 else log_verbose "No E2E test files with database connection code found." return 1 fi } # Function to fix database connection in a file fix_file() { local file="$1" local backup_file="${file}.bak.$(date +%Y%m%d%H%M%S)" log_verbose "Fixing database connection in file: $file" # Create a backup of the file if [ "$DRY_RUN" = true ]; then log_verbose "Would create backup of $file to $backup_file" else cp "$file" "$backup_file" check_status "Created backup of $file" fi # Replace 'root' with the correct database user if [ "$DRY_RUN" = true ]; then log_verbose "Would replace 'root' with '$UPSKILL_STAGING_DB_USER' in $file" else sed -i.tmp "s/'root'/'$UPSKILL_STAGING_DB_USER'/g" "$file" sed -i.tmp "s/\"root\"/\"$UPSKILL_STAGING_DB_USER\"/g" "$file" rm -f "${file}.tmp" check_status "Replaced 'root' with '$UPSKILL_STAGING_DB_USER' in $file" fi # Replace hardcoded password if found if [ "$DRY_RUN" = true ]; then log_verbose "Would replace hardcoded password with '$UPSKILL_STAGING_DB_PASSWORD' in $file" else # This is a simplified approach; in a real scenario, you'd need a more sophisticated pattern matching sed -i.tmp "s/'password'/'$UPSKILL_STAGING_DB_PASSWORD'/g" "$file" sed -i.tmp "s/\"password\"/\"$UPSKILL_STAGING_DB_PASSWORD\"/g" "$file" rm -f "${file}.tmp" check_status "Replaced hardcoded password in $file" fi } # Function to check and fix wp-tests-config.php check_wp_tests_config() { log_verbose "Checking wp-tests-config.php..." local config_file="$SCRIPT_DIR/../wp-tests-config.php" if [ ! -f "$config_file" ]; then log_warning "wp-tests-config.php not found: $config_file" return 1 fi # Check for 'root' user in wp-tests-config.php local root_user root_user=$(grep -E "define\\( *'DB_USER', *'root' *\\)" "$config_file" 2>/dev/null || true) if [ -n "$root_user" ]; then echo "Found 'root' user in wp-tests-config.php:" echo "$root_user" # Fix wp-tests-config.php if [ "$DRY_RUN" = true ]; then log_verbose "Would update wp-tests-config.php to use '$UPSKILL_STAGING_DB_USER' instead of 'root'" else local backup_file="${config_file}.bak.$(date +%Y%m%d%H%M%S)" cp "$config_file" "$backup_file" sed -i.tmp "s/define( *'DB_USER', *'root' *)/define( 'DB_USER', '$UPSKILL_STAGING_DB_USER' )/g" "$config_file" sed -i.tmp "s/define( *'DB_PASSWORD', *'[^']*' *)/define( 'DB_PASSWORD', '$UPSKILL_STAGING_DB_PASSWORD' )/g" "$config_file" rm -f "${config_file}.tmp" check_status "Updated wp-tests-config.php to use correct database credentials" fi return 0 else log_verbose "No 'root' user found in wp-tests-config.php." return 1 fi } # Function to check and fix wp-tests-config-staging.php check_wp_tests_config_staging() { log_verbose "Checking wp-tests-config-staging.php..." local config_file="$SCRIPT_DIR/wp-tests-config-staging.php" if [ ! -f "$config_file" ]; then log_warning "wp-tests-config-staging.php not found: $config_file" return 1 fi # Check for 'root' user in wp-tests-config-staging.php local root_user root_user=$(grep -E "define\\( *'DB_USER', *'root' *\\)" "$config_file" 2>/dev/null || true) if [ -n "$root_user" ]; then echo "Found 'root' user in wp-tests-config-staging.php:" echo "$root_user" # Fix wp-tests-config-staging.php if [ "$DRY_RUN" = true ]; then log_verbose "Would update wp-tests-config-staging.php to use '$UPSKILL_STAGING_DB_USER' instead of 'root'" else local backup_file="${config_file}.bak.$(date +%Y%m%d%H%M%S)" cp "$config_file" "$backup_file" sed -i.tmp "s/define( *'DB_USER', *'root' *)/define( 'DB_USER', '$UPSKILL_STAGING_DB_USER' )/g" "$config_file" sed -i.tmp "s/define( *'DB_PASSWORD', *'[^']*' *)/define( 'DB_PASSWORD', '$UPSKILL_STAGING_DB_PASSWORD' )/g" "$config_file" rm -f "${config_file}.tmp" check_status "Updated wp-tests-config-staging.php to use correct database credentials" fi return 0 else log_verbose "No 'root' user found in wp-tests-config-staging.php." return 1 fi } # Main function main() { echo "=== Database Connection Fix Script ===" echo "Staging Server: $UPSKILL_STAGING_IP" echo "Database: $UPSKILL_STAGING_DB_NAME" echo "User: $UPSKILL_STAGING_DB_USER" echo "===============================" if [ "$DRY_RUN" = true ]; then echo -e "${YELLOW}Running in dry-run mode. No changes will be made.${NC}" fi # Step 1: Check SSH connection echo -e "\n${YELLOW}Step 1: Checking SSH connection...${NC}" check_ssh_connection check_status "SSH connection check" # Step 2: Check remote database connection echo -e "\n${YELLOW}Step 2: Checking database connection from staging server...${NC}" check_remote_db_connection check_status "Remote database connection check" # Step 3: Check WordPress configuration echo -e "\n${YELLOW}Step 3: Checking WordPress configuration...${NC}" check_wp_config check_status "WordPress configuration check" # Step 4: Check test files for hardcoded credentials echo -e "\n${YELLOW}Step 4: Checking test files for hardcoded credentials...${NC}" if check_test_files; then echo "Found files with potential hardcoded credentials. Fixing..." # Fix each file for file in $(find $SCRIPT_DIR/.. -type f -name "*.php" -o -name "*.js" -o -name "*.ts" | xargs grep -l "'root'\\|\"root\"" 2>/dev/null || true); do fix_file "$file" done else echo "No files with hardcoded 'root' credentials found." fi # Step 5: Check and fix wp-tests-config.php echo -e "\n${YELLOW}Step 5: Checking and fixing wp-tests-config.php...${NC}" check_wp_tests_config # Step 6: Check and fix wp-tests-config-staging.php echo -e "\n${YELLOW}Step 6: Checking and fixing wp-tests-config-staging.php...${NC}" check_wp_tests_config_staging # Step 7: Check Playwright configuration echo -e "\n${YELLOW}Step 7: Checking Playwright configuration...${NC}" check_playwright_config # Step 8: Check E2E test files echo -e "\n${YELLOW}Step 8: Checking E2E test files...${NC}" check_e2e_tests # Step 9: Verify fixes echo -e "\n${YELLOW}Step 9: Verifying fixes...${NC}" if [ "$DRY_RUN" = false ]; then # Check remote database connection again check_remote_db_connection check_status "Remote database connection verification" # Run a simple E2E test if available if [ -f "$SCRIPT_DIR/../node_modules/.bin/playwright" ]; then echo "Running a simple Playwright test to verify database connection..." cd "$SCRIPT_DIR/.." && npx playwright test -g "database connection" --headed check_status "Playwright test" else log_warning "Playwright not found. Skipping E2E test verification." fi else echo -e "${YELLOW}Skipping verification in dry-run mode.${NC}" fi # Summary echo -e "\n${YELLOW}Summary:${NC}" if [ "$DRY_RUN" = true ]; then echo "Dry run completed. No changes were made." echo "Run the script without --dry-run to apply the fixes." else echo "Database connection fix script completed." echo "If you encounter any issues, you can restore the backup files created during the fix process." fi } # Run the main function main