From 9f6da1062505c36f692c229ed2e79506b6c4fa7e Mon Sep 17 00:00:00 2001 From: cschantz Date: Wed, 19 Nov 2025 18:12:20 -0500 Subject: [PATCH] Implement InterWorx support: user/domain/database management MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PHASE 1: Critical Bug Fixes 1. Fix list_interworx_users() fallback - Old: Broken find for *.conf directories - New: Parse vhost configs for SuexecUserGroup directives - Fallback: List /home directories 2. Enhance get_interworx_user_info() - Now returns: PRIMARY_DOMAIN, ALL_DOMAINS, EMAIL - Uses listaccounts.pex + vhost config parsing - Optional NodeWorx API for email 3. Enhance get_interworx_user_domains() - Returns primary domain from listaccounts.pex - Parses ALL vhost configs for secondary/addon domains - Filters out subdomains 4. Implement get_interworx_user_databases() - CRITICAL: Uses first 8 chars of PRIMARY DOMAIN as prefix - NOT username-based like cPanel! - Example: example.com → prefix examplec_ TESTING: - All functions syntax validated with bash -n - Ready for testing on actual InterWorx server RESEARCH: - Created /root/INTERWORX_RESEARCH.md (500+ line guide) - Documents all InterWorx vs cPanel differences - Includes implementation roadmap (Phases 1-5) --- lib/user-manager.sh | 83 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 5 deletions(-) diff --git a/lib/user-manager.sh b/lib/user-manager.sh index 909c566..5647fd4 100755 --- a/lib/user-manager.sh +++ b/lib/user-manager.sh @@ -64,8 +64,15 @@ list_interworx_users() { if [ -x "/usr/local/interworx/bin/listaccounts.pex" ]; then /usr/local/interworx/bin/listaccounts.pex --output user 2>/dev/null else - # Fallback: parse InterWorx config - find /home -maxdepth 1 -type d -name "*.conf" 2>/dev/null | xargs -I {} basename {} .conf + # Fallback: Parse Apache vhost configs for SuexecUserGroup directives + # Each InterWorx account has vhost files in /etc/httpd/conf.d/ + if [ -d "/etc/httpd/conf.d" ]; then + grep -h "^[[:space:]]*SuexecUserGroup" /etc/httpd/conf.d/vhost_*.conf 2>/dev/null | \ + awk '{print $2}' | sort -u + else + # Last resort: list /home directories (may include non-InterWorx users) + find /home -maxdepth 1 -type d ! -name "home" ! -name "interworx" -printf "%f\n" 2>/dev/null | sort + fi fi } @@ -160,10 +167,40 @@ get_interworx_user_info() { return 1 fi + # Try to get primary domain from listaccounts.pex first + local primary_domain="" + if [ -x "/usr/local/interworx/bin/listaccounts.pex" ]; then + primary_domain=$(/usr/local/interworx/bin/listaccounts.pex 2>/dev/null | \ + awk -v user="$username" '$1 == user {print $2; exit}') + fi + + # Fallback: Parse vhost configs to find primary domain + if [ -z "$primary_domain" ]; then + primary_domain=$(grep -l "SuexecUserGroup ${username}" /etc/httpd/conf.d/vhost_*.conf 2>/dev/null | \ + head -1 | sed 's|.*/vhost_||; s|\.conf$||') + fi + + # Get all domains for this user from vhost configs + local all_domains=$(grep -l "SuexecUserGroup ${username}" /etc/httpd/conf.d/vhost_*.conf 2>/dev/null | \ + sed 's|.*/vhost_||; s|\.conf$||' | tr '\n' ' ' | sed 's/[[:space:]]*$//') + + # Get disk usage local disk_used=$(du -sh "$home_dir" 2>/dev/null | awk '{print $1}') + # Try to get email from NodeWorx API (if available) + # Note: This requires nodeworx CLI which may need authentication + local email="" + if [ -x "/usr/local/interworx/bin/nodeworx.pex" ] && [ -n "$primary_domain" ]; then + email=$(nodeworx -u -n -c Siteworx -a listAccounts 2>/dev/null | \ + grep -A20 "\"domain\" => \"$primary_domain\"" | \ + grep "\"email\"" | head -1 | sed 's/.*=> "\(.*\)".*/\1/') + fi + echo "USER_EXISTS=yes" echo "USERNAME=$username" + echo "PRIMARY_DOMAIN=$primary_domain" + echo "ALL_DOMAINS=$all_domains" + echo "EMAIL=${email:-unknown}" echo "HOME_DIR=$home_dir" echo "DISK_USED=$disk_used" } @@ -233,8 +270,19 @@ get_plesk_user_domains() { get_interworx_user_domains() { local username="$1" + # Method 1: Use listaccounts.pex to get primary domain if [ -x "/usr/local/interworx/bin/listaccounts.pex" ]; then - /usr/local/interworx/bin/listaccounts.pex --user "$username" --output domain 2>/dev/null + /usr/local/interworx/bin/listaccounts.pex 2>/dev/null | \ + awk -v user="$username" '$1 == user {print $2}' + fi + + # Method 2: Parse vhost configs to get ALL domains (primary + secondary/addon) + # InterWorx creates vhost_domain.conf for each domain, with SuexecUserGroup directive + if [ -d "/etc/httpd/conf.d" ]; then + grep -l "SuexecUserGroup ${username}" /etc/httpd/conf.d/vhost_*.conf 2>/dev/null | \ + sed 's|.*/vhost_||; s|\.conf$||' | \ + grep -v "^${username}\." | \ + sort -u fi } @@ -280,8 +328,33 @@ get_plesk_user_databases() { get_interworx_user_databases() { local username="$1" - # InterWorx databases typically follow pattern: username_dbname - mysql -e "SHOW DATABASES" 2>/dev/null | grep "^${username}_" || true + # InterWorx uses the first 8 characters of the PRIMARY DOMAIN as database prefix + # NOT the username! (e.g., domain example.com → prefix: examplec_) + + # Get primary domain for this user + local primary_domain="" + if [ -x "/usr/local/interworx/bin/listaccounts.pex" ]; then + primary_domain=$(/usr/local/interworx/bin/listaccounts.pex 2>/dev/null | \ + awk -v user="$username" '$1 == user {print $2; exit}') + fi + + # Fallback: try to find from vhost configs + if [ -z "$primary_domain" ]; then + primary_domain=$(grep -l "SuexecUserGroup ${username}" /etc/httpd/conf.d/vhost_*.conf 2>/dev/null | \ + head -1 | sed 's|.*/vhost_||; s|\.conf$||') + fi + + if [ -z "$primary_domain" ]; then + # No domain found, try username pattern as last resort + mysql -e "SHOW DATABASES" 2>/dev/null | grep "^${username}_" || true + return + fi + + # Get first 8 characters of domain (removing dots) as database prefix + local db_prefix=$(echo "$primary_domain" | sed 's/\.//g' | cut -c1-8) + + # Query MySQL for databases with this prefix + mysql -e "SHOW DATABASES" 2>/dev/null | grep "^${db_prefix}_" || true } #############################################################################