bad5955d41
Converted unsafe 'for var in $list' loops to 'while read' loops to properly handle items with spaces in names. reference-db.sh (4 fixes): - Line 172: Database iteration (SHOW DATABASES) - Line 330: Server alias iteration (space-separated aliases) - Line 345: Domain iteration (get_user_domains) - Line 414: WordPress config file paths (find results) user-manager.sh (4 fixes): - Line 396: Domain iteration in cPanel log paths - Line 404: Domain iteration in Plesk log paths - Line 410: Domain iteration in InterWorx log paths - Line 632: User iteration (list_all_users) Pattern changes: - for item in $list → while IFS= read -r item - Added [ -z "$item" ] && continue for safety - Used echo "$list" | while or piped commands directly This prevents word splitting on spaces in database names, domain names, file paths, and usernames.
771 lines
26 KiB
Bash
Executable File
771 lines
26 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
#############################################################################
|
|
# User Manager Library
|
|
# Dynamic user listing and management for cPanel/Plesk/InterWorx
|
|
#############################################################################
|
|
|
|
# Source dependencies
|
|
if [ -z "$TOOLKIT_BASE_DIR" ]; then
|
|
_LIB_SRCDIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
[ -f "$_LIB_SRCDIR/common-functions.sh" ] && source "$_LIB_SRCDIR/common-functions.sh" || { echo "ERROR: common-functions.sh not found" >&2; return 1; }
|
|
[ -f "$_LIB_SRCDIR/system-detect.sh" ] && source "$_LIB_SRCDIR/system-detect.sh" || { echo "ERROR: system-detect.sh not found" >&2; return 1; }
|
|
fi
|
|
|
|
# Initialize temp session directory if not set
|
|
if [ -z "$TEMP_SESSION_DIR" ]; then
|
|
TEMP_SESSION_DIR="/tmp/server-toolkit-$$"
|
|
mkdir -p "$TEMP_SESSION_DIR" 2>/dev/null
|
|
fi
|
|
|
|
#############################################################################
|
|
# USER LISTING (Control Panel Specific)
|
|
#############################################################################
|
|
|
|
list_all_users() {
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
list_cpanel_users
|
|
;;
|
|
plesk)
|
|
list_plesk_users
|
|
;;
|
|
interworx)
|
|
list_interworx_users
|
|
;;
|
|
*)
|
|
list_system_users
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# cPanel user listing
|
|
list_cpanel_users() {
|
|
local cpanel_users_dir="${SYS_CPANEL_USERS_DIR:-/var/cpanel/users}"
|
|
if [ -d "$cpanel_users_dir" ]; then
|
|
ls "$cpanel_users_dir" 2>/dev/null || true
|
|
else
|
|
# Fallback: parse /etc/trueuserdomains
|
|
awk -F: '{print $2}' /etc/trueuserdomains 2>/dev/null | sort -u || true
|
|
fi
|
|
}
|
|
|
|
# Plesk user listing
|
|
list_plesk_users() {
|
|
# Use plesk_list_users() if available (from plesk-helpers.sh)
|
|
if type plesk_list_users >/dev/null 2>&1; then
|
|
plesk_list_users
|
|
elif command_exists mysql && [ -f /etc/psa/.psa.shadow ]; then
|
|
# Fallback: Try MySQL query
|
|
mysql -Ns psa -e "SELECT login FROM sys_users WHERE type='user'" 2>/dev/null
|
|
else
|
|
# Last resort: list directories
|
|
find /var/www/vhosts -maxdepth 1 -type d -printf "%f\n" 2>/dev/null | \
|
|
grep -v "^system$\|^default$\|^chroot$\|^\.skel$\|^fs$\|^fs-passwd$" | \
|
|
grep -v "^\."
|
|
fi
|
|
}
|
|
|
|
# InterWorx user listing
|
|
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 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
|
|
}
|
|
|
|
# System users (no control panel)
|
|
list_system_users() {
|
|
# List users with home directories in /home and valid shells
|
|
awk -F: '$6 ~ /^\/home\// && $7 !~ /nologin|false/ {print $1}' /etc/passwd
|
|
}
|
|
|
|
#############################################################################
|
|
# USER INFORMATION
|
|
#############################################################################
|
|
|
|
get_user_info() {
|
|
local username="$1"
|
|
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
get_cpanel_user_info "$username"
|
|
;;
|
|
plesk)
|
|
get_plesk_user_info "$username"
|
|
;;
|
|
interworx)
|
|
get_interworx_user_info "$username"
|
|
;;
|
|
*)
|
|
get_system_user_info "$username"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# cPanel user info
|
|
get_cpanel_user_info() {
|
|
local username="$1"
|
|
local user_file="${SYS_CPANEL_USERS_DIR:-/var/cpanel/users}/${username}"
|
|
|
|
if [ ! -f "$user_file" ]; then
|
|
echo "USER_EXISTS=no"
|
|
return 1
|
|
fi
|
|
|
|
# Parse cPanel user file
|
|
local primary_domain=$(grep "^DNS=" "$user_file" | cut -d= -f2)
|
|
local email=$(grep "^CONTACTEMAIL=" "$user_file" | cut -d= -f2)
|
|
|
|
# cPanel doesn't store HOMEDIR in user file - it's always /home/username
|
|
local home_dir="/home/${username}"
|
|
|
|
# Get addon/parked domains
|
|
local all_domains=$(grep "^DNS" "$user_file" | cut -d= -f2 | tr '\n' ' ')
|
|
|
|
# Get disk usage
|
|
local disk_used=$(du -sh "$home_dir" 2>/dev/null | awk '{print $1}')
|
|
|
|
echo "USER_EXISTS=yes"
|
|
echo "USERNAME=$username"
|
|
echo "PRIMARY_DOMAIN=$primary_domain"
|
|
echo "ALL_DOMAINS=$all_domains"
|
|
echo "EMAIL=$email"
|
|
echo "HOME_DIR=$home_dir"
|
|
echo "DISK_USED=$disk_used"
|
|
}
|
|
|
|
# Plesk user info
|
|
get_plesk_user_info() {
|
|
local username="$1"
|
|
|
|
if ! command_exists mysql || [ ! -f /etc/psa/.psa.shadow ]; then
|
|
echo "USER_EXISTS=no"
|
|
return 1
|
|
fi
|
|
|
|
local home_dir="/var/www/vhosts/${username}"
|
|
local primary_domain=$(mysql -Ns psa -e "SELECT name FROM domains WHERE id IN (SELECT domain_id FROM sys_users WHERE login='$username')" 2>/dev/null | head -1)
|
|
local disk_used=$(du -sh "$home_dir" 2>/dev/null | awk '{print $1}')
|
|
|
|
echo "USER_EXISTS=yes"
|
|
echo "USERNAME=$username"
|
|
echo "PRIMARY_DOMAIN=$primary_domain"
|
|
echo "HOME_DIR=$home_dir"
|
|
echo "DISK_USED=$disk_used"
|
|
}
|
|
|
|
# InterWorx user info
|
|
get_interworx_user_info() {
|
|
local username="$1"
|
|
local home_dir="/home/${username}"
|
|
|
|
if [ ! -d "$home_dir" ]; then
|
|
echo "USER_EXISTS=no"
|
|
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 "\"domain\" => \"$primary_domain\"" 2>/dev/null | head -1 | \
|
|
grep "\"email\"" 2>/dev/null | 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"
|
|
}
|
|
|
|
# System user info (no control panel)
|
|
get_system_user_info() {
|
|
local username="$1"
|
|
local user_entry=$(getent passwd "$username")
|
|
|
|
if [ -z "$user_entry" ]; then
|
|
echo "USER_EXISTS=no"
|
|
return 1
|
|
fi
|
|
|
|
local home_dir=$(echo "$user_entry" | cut -d: -f6)
|
|
local disk_used=$(du -sh "$home_dir" 2>/dev/null | awk '{print $1}')
|
|
|
|
echo "USER_EXISTS=yes"
|
|
echo "USERNAME=$username"
|
|
echo "HOME_DIR=$home_dir"
|
|
echo "DISK_USED=$disk_used"
|
|
}
|
|
|
|
#############################################################################
|
|
# USER DOMAINS
|
|
#############################################################################
|
|
|
|
get_user_domains() {
|
|
[ -z "$1" ] && return 1
|
|
local username="$1"
|
|
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
get_cpanel_user_domains "$username"
|
|
;;
|
|
plesk)
|
|
get_plesk_user_domains "$username"
|
|
;;
|
|
interworx)
|
|
get_interworx_user_domains "$username"
|
|
;;
|
|
*)
|
|
echo ""
|
|
;;
|
|
esac
|
|
}
|
|
|
|
get_cpanel_user_domains() {
|
|
[ -z "$1" ] && return 1
|
|
local username="$1"
|
|
|
|
# Primary domain (format: domain: user)
|
|
grep ": ${username}$" /etc/trueuserdomains 2>/dev/null | cut -d: -f1 || true
|
|
|
|
# Addon domains
|
|
if [ -f "/etc/userdatadomains" ]; then
|
|
grep "==${username}$" /etc/userdatadomains 2>/dev/null | cut -d: -f1 || true
|
|
fi
|
|
}
|
|
|
|
get_plesk_user_domains() {
|
|
[ -z "$1" ] && return 1
|
|
local username="$1"
|
|
|
|
# Try MySQL query first
|
|
if command_exists mysql && [ -f /etc/psa/.psa.shadow ]; then
|
|
local domains=$(mysql -Ns psa -e "SELECT d.name FROM domains d JOIN sys_users u ON d.id=u.domain_id WHERE u.login='$username'" 2>/dev/null)
|
|
if [ -n "$domains" ]; then
|
|
echo "$domains"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
# Fallback: Use Plesk CLI if available
|
|
if [ -x "/usr/local/psa/bin/plesk" ]; then
|
|
/usr/local/psa/bin/plesk bin site --list 2>/dev/null | grep -i "$username" || true
|
|
fi
|
|
|
|
# Last resort: Check if vhosts directory exists for this user
|
|
if [ -d "/var/www/vhosts/$username" ]; then
|
|
echo "$username"
|
|
fi
|
|
}
|
|
|
|
get_interworx_user_domains() {
|
|
[ -z "$1" ] && return 1
|
|
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 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 -vF "${username}." 2>/dev/null | \
|
|
sort -u
|
|
fi
|
|
}
|
|
|
|
#############################################################################
|
|
# USER DATABASES
|
|
#############################################################################
|
|
|
|
get_user_databases() {
|
|
local username="$1"
|
|
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
get_cpanel_user_databases "$username"
|
|
;;
|
|
plesk)
|
|
get_plesk_user_databases "$username"
|
|
;;
|
|
interworx)
|
|
get_interworx_user_databases "$username"
|
|
;;
|
|
*)
|
|
# Try to find databases matching username pattern
|
|
mysql -e "SHOW DATABASES" 2>/dev/null | grep "^${username}_"
|
|
;;
|
|
esac
|
|
}
|
|
|
|
get_cpanel_user_databases() {
|
|
local username="$1"
|
|
|
|
# cPanel databases typically follow pattern: username_dbname
|
|
mysql -e "SHOW DATABASES" 2>/dev/null | grep "^${username}_" 2>/dev/null || true
|
|
}
|
|
|
|
get_plesk_user_databases() {
|
|
local username="$1"
|
|
|
|
if command_exists mysql && [ -f /etc/psa/.psa.shadow ]; then
|
|
mysql -Ns psa -e "SELECT db.name FROM data_bases db JOIN domains d ON db.dom_id=d.id JOIN sys_users u ON d.id=u.domain_id WHERE u.login='$username'" 2>/dev/null
|
|
fi
|
|
}
|
|
|
|
get_interworx_user_databases() {
|
|
local username="$1"
|
|
|
|
# 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
|
|
}
|
|
|
|
#############################################################################
|
|
# USER LOG FILES
|
|
#############################################################################
|
|
|
|
get_user_log_files() {
|
|
local username="$1"
|
|
local domains=$(get_user_domains "$username")
|
|
|
|
case "$SYS_CONTROL_PANEL" in
|
|
cpanel)
|
|
# Iterate safely over domains (handles spaces in domain names)
|
|
echo "$domains" | while IFS= read -r domain; do
|
|
[ -z "$domain" ] && continue
|
|
echo "${SYS_LOG_DIR}/${domain}"
|
|
echo "${SYS_LOG_DIR}/${domain}-ssl_log"
|
|
done
|
|
;;
|
|
plesk)
|
|
echo "/var/www/vhosts/${username}/statistics/logs/access_log"
|
|
echo "/var/www/vhosts/${username}/statistics/logs/error_log"
|
|
# Iterate safely over domains (handles spaces in domain names)
|
|
echo "$domains" | while IFS= read -r domain; do
|
|
[ -z "$domain" ] && continue
|
|
echo "/var/www/vhosts/${domain}/statistics/logs/access_log"
|
|
echo "/var/www/vhosts/${domain}/statistics/logs/error_log"
|
|
done
|
|
;;
|
|
interworx)
|
|
# Iterate safely over domains (handles spaces in domain names)
|
|
echo "$domains" | while IFS= read -r domain; do
|
|
[ -z "$domain" ] && continue
|
|
echo "/home/${username}/var/${domain}/logs/access_log"
|
|
echo "/home/${username}/var/${domain}/logs/error_log"
|
|
done
|
|
;;
|
|
esac | grep -v "^$" | sort -u
|
|
}
|
|
|
|
#############################################################################
|
|
# USER SELECTION MENU
|
|
#############################################################################
|
|
|
|
select_user_interactive() {
|
|
local prompt="${1:-Select a user}"
|
|
local users=($(list_all_users))
|
|
local total_users=${#users[@]}
|
|
|
|
if [ "${total_users:-0}" -eq 0 ]; then
|
|
print_error "No users found" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Build user info cache to avoid repeated get_user_domains calls
|
|
declare -A user_primary_domain
|
|
declare -A user_domain_count
|
|
|
|
for user in "${users[@]}"; do
|
|
local domains=$(get_user_domains "$user" 2>/dev/null | grep -v "^$")
|
|
if [ -n "$domains" ]; then
|
|
user_domain_count["$user"]=$(echo "$domains" | wc -l)
|
|
user_primary_domain["$user"]=$(echo "$domains" | head -1)
|
|
else
|
|
user_domain_count["$user"]=0
|
|
user_primary_domain["$user"]="(no domains)"
|
|
fi
|
|
done
|
|
|
|
# Send all display output to stderr so it shows on screen (not captured by $(...))
|
|
{
|
|
echo ""
|
|
print_section "$prompt"
|
|
echo ""
|
|
echo "Found $total_users user(s) on this server"
|
|
echo "───────────────────────────────────────────────────────────────────────────────"
|
|
|
|
# Auto-show list if 10 or fewer users
|
|
if [ "${total_users:-0}" -le 10 ]; then
|
|
echo ""
|
|
for user in "${users[@]}"; do
|
|
echo -e " ${GREEN}$user${NC} - ${user_primary_domain[$user]} (${user_domain_count[$user]} domains)"
|
|
done
|
|
fi
|
|
|
|
echo ""
|
|
echo "───────────────────────────────────────────────────────────────────────────────"
|
|
echo ""
|
|
echo "Options:"
|
|
if [ "${total_users:-0}" -gt 10 ]; then
|
|
echo " L - List all $total_users users"
|
|
fi
|
|
echo " S [text] - Search/filter users (e.g., 's pick' or 's example.com')"
|
|
echo " [username] - Enter exact username"
|
|
echo " A - All users (system-wide scan)"
|
|
echo " 0 - Cancel/Go back"
|
|
echo ""
|
|
} >&2
|
|
|
|
read -p "Enter choice> " choice
|
|
|
|
case "$choice" in
|
|
[Aa]|ALL|all)
|
|
echo "ALL"
|
|
return 0
|
|
;;
|
|
[Ss]\ *|[Ss])
|
|
# Search mode
|
|
local search_term="${choice#[Ss] }" # Remove 'S ' prefix
|
|
search_term="${search_term#[Ss]}" # Remove 'S' if no space
|
|
|
|
if [ -z "$search_term" ]; then
|
|
# No search term provided, ask for it
|
|
read -p "Enter search term (username or domain)> " search_term >&2
|
|
fi
|
|
|
|
if [ -z "$search_term" ]; then
|
|
print_error "No search term provided" >&2
|
|
return 1
|
|
fi
|
|
|
|
# Search and build match array
|
|
local -a matched_users
|
|
local -a menu_items
|
|
|
|
for user in "${users[@]}"; do
|
|
# Case-insensitive partial match in username or domain
|
|
if [[ "${user,,}" == *"${search_term,,}"* ]] || [[ "${user_primary_domain[$user],,}" == *"${search_term,,}"* ]]; then
|
|
matched_users+=("$user")
|
|
menu_items+=("$user - ${user_primary_domain[$user]} (${user_domain_count[$user]} domains)")
|
|
fi
|
|
done
|
|
|
|
if [ ${#matched_users[@]} -eq 0 ]; then
|
|
print_error "No users found matching '$search_term'" >&2
|
|
return 1
|
|
elif [ ${#matched_users[@]} -eq 1 ]; then
|
|
# Single match - ask for confirmation
|
|
{
|
|
echo ""
|
|
echo "Found 1 match: ${matched_users[0]} - ${user_primary_domain[${matched_users[0]}]} (${user_domain_count[${matched_users[0]}]} domains)"
|
|
echo ""
|
|
} >&2
|
|
read -p "Use this user? (Y/n)> " confirm >&2
|
|
if [[ ! $confirm =~ ^[Nn]$ ]]; then
|
|
echo "${matched_users[0]}"
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
else
|
|
# Multiple matches - show interactive arrow-key menu
|
|
{
|
|
echo ""
|
|
echo "Found ${#matched_users[@]} matches for '$search_term'"
|
|
echo "Use arrow keys (↑/↓) to navigate, Enter to select:"
|
|
echo ""
|
|
} >&2
|
|
|
|
PS3="Select user> "
|
|
select option in "${menu_items[@]}" "Cancel"; do
|
|
if [ "$option" = "Cancel" ]; then
|
|
return 1
|
|
elif [ -n "$option" ]; then
|
|
# Extract username from selected menu item (before the ' - ')
|
|
local selected_user="${matched_users[$((REPLY-1))]}"
|
|
echo "$selected_user"
|
|
return 0
|
|
fi
|
|
done >&2
|
|
fi
|
|
;;
|
|
[Ll]|LIST|list)
|
|
# Show full list
|
|
{
|
|
echo ""
|
|
echo "Complete user list ($total_users users):"
|
|
echo "───────────────────────────────────────────────────────────────────────────────"
|
|
for user in "${users[@]}"; do
|
|
echo -e " ${GREEN}$user${NC} - ${user_primary_domain[$user]} (${user_domain_count[$user]} domains)"
|
|
done
|
|
echo "───────────────────────────────────────────────────────────────────────────────"
|
|
echo ""
|
|
} >&2
|
|
# Ask again after showing list
|
|
read -p "Enter username (or A for all, 0 to cancel)> " choice
|
|
# Re-evaluate choice
|
|
if [[ " ${users[@]} " =~ " ${choice} " ]]; then
|
|
echo "$choice"
|
|
return 0
|
|
elif [ "$choice" = "A" ] || [ "$choice" = "a" ]; then
|
|
echo "ALL"
|
|
return 0
|
|
elif [ "$choice" = "0" ]; then
|
|
return 1
|
|
else
|
|
print_error "User '$choice' not found" >&2
|
|
return 1
|
|
fi
|
|
;;
|
|
0|cancel|back)
|
|
return 1
|
|
;;
|
|
"")
|
|
print_error "No input provided" >&2
|
|
return 1
|
|
;;
|
|
*)
|
|
# Check if it's an exact username match
|
|
if [[ " ${users[@]} " =~ " ${choice} " ]]; then
|
|
echo "$choice"
|
|
return 0
|
|
fi
|
|
|
|
# Not exact match
|
|
print_error "User '$choice' not found" >&2
|
|
if [ "${total_users:-0}" -gt 10 ]; then
|
|
echo " Tip: Type 'L' to list all users" >&2
|
|
fi
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
#############################################################################
|
|
# USER PROCESSES
|
|
#############################################################################
|
|
|
|
get_user_processes() {
|
|
local username="$1"
|
|
|
|
ps aux | grep "$username" 2>/dev/null | grep -v grep
|
|
}
|
|
|
|
get_user_top_processes() {
|
|
local username="$1"
|
|
local limit="${2:-10}"
|
|
|
|
ps aux | grep "$username" 2>/dev/null | grep -v grep | sort -k3 -rn | head -n "$limit"
|
|
}
|
|
|
|
#############################################################################
|
|
# DATABASE HELPER FUNCTIONS
|
|
#############################################################################
|
|
|
|
get_database_owner() {
|
|
local db_name="$1"
|
|
|
|
# Try to determine owner from database name prefix (common cPanel convention)
|
|
# Database names are typically: username_dbname
|
|
local prefix=$(echo "$db_name" | cut -d_ -f1)
|
|
|
|
# Check if this prefix matches a user (iterate safely over usernames)
|
|
list_all_users | while IFS= read -r user; do
|
|
[ -z "$user" ] && continue
|
|
if [ "$user" = "$prefix" ]; then
|
|
echo "$user"
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
# If no match, return unknown
|
|
echo "unknown"
|
|
}
|
|
|
|
get_database_domain() {
|
|
local db_name="$1"
|
|
local owner=$(get_database_owner "$db_name")
|
|
|
|
# Try to get primary domain for the owner
|
|
if [ "$owner" != "unknown" ]; then
|
|
get_user_domains "$owner" 2>/dev/null | head -1
|
|
else
|
|
echo ""
|
|
fi
|
|
}
|
|
|
|
#############################################################################
|
|
# WORDPRESS DETECTION
|
|
#############################################################################
|
|
|
|
find_user_wordpress_sites() {
|
|
local username="$1"
|
|
local home_dir=$(get_user_info "$username" | grep "^HOME_DIR=" | cut -d= -f2)
|
|
|
|
if [ -z "$home_dir" ] || [ ! -d "$home_dir" ]; then
|
|
return 1
|
|
fi
|
|
|
|
# Find wp-config.php files
|
|
find "$home_dir" -name "wp-config.php" -type f 2>/dev/null | while read wp_config; do
|
|
local wp_dir=$(dirname "$wp_config")
|
|
local domain=$(basename "$(dirname "$wp_dir")" 2>/dev/null)
|
|
|
|
# Try to get actual domain from wp-config
|
|
local site_url=$(grep "WP_SITEURL\|WP_HOME" "$wp_config" | head -1 | grep -oP "https?://\K[^/'\"]+" 2>/dev/null || true)
|
|
|
|
if [ -n "$site_url" ]; then
|
|
echo "${site_url}|${wp_dir}"
|
|
else
|
|
echo "${domain}|${wp_dir}"
|
|
fi
|
|
done
|
|
}
|
|
|
|
#############################################################################
|
|
# DISPLAY FUNCTIONS
|
|
#############################################################################
|
|
|
|
show_user_summary() {
|
|
local username="$1"
|
|
|
|
print_section "User Summary: $username"
|
|
|
|
# Get user info
|
|
local user_info=$(get_user_info "$username")
|
|
|
|
if echo "$user_info" | grep -q "USER_EXISTS=no"; then
|
|
print_error "User does not exist"
|
|
return 1
|
|
fi
|
|
|
|
# Parse info
|
|
local primary_domain=$(echo "$user_info" | grep "^PRIMARY_DOMAIN=" | cut -d= -f2)
|
|
local home_dir=$(echo "$user_info" | grep "^HOME_DIR=" | cut -d= -f2)
|
|
local disk_used=$(echo "$user_info" | grep "^DISK_USED=" | cut -d= -f2)
|
|
|
|
# Display
|
|
echo " Username: $username"
|
|
[ -n "$primary_domain" ] && echo " Primary Domain: $primary_domain"
|
|
echo " Home Directory: $home_dir"
|
|
echo " Disk Usage: $disk_used"
|
|
echo ""
|
|
|
|
# Domains
|
|
local domains=$(get_user_domains "$username")
|
|
local domain_count=$(echo "$domains" | grep -v "^$" | wc -l)
|
|
echo " Domains ($domain_count):"
|
|
echo "$domains" | sed 's/^/ - /'
|
|
echo ""
|
|
|
|
# Databases
|
|
local databases=$(get_user_databases "$username")
|
|
local db_count=$(echo "$databases" | grep -v "^$" | wc -l)
|
|
echo " Databases ($db_count):"
|
|
echo "$databases" | sed 's/^/ - /'
|
|
echo ""
|
|
}
|
|
|
|
show_all_users_summary() {
|
|
print_section "All Users Summary"
|
|
|
|
local users=($(list_all_users))
|
|
local total_users=${#users[@]}
|
|
|
|
echo " Total Users: $total_users"
|
|
echo ""
|
|
|
|
printf " ${BOLD}%-20s %-30s %10s %10s${NC}\n" "Username" "Primary Domain" "Domains" "Databases"
|
|
echo " ────────────────────────────────────────────────────────────────────"
|
|
|
|
for user in "${users[@]}"; do
|
|
local primary=$(get_user_domains "$user" | head -1)
|
|
local domain_count=$(get_user_domains "$user" | grep -v "^$" | wc -l)
|
|
local db_count=$(get_user_databases "$user" | grep -v "^$" | wc -l)
|
|
|
|
printf " %-20s %-30s %10s %10s\n" "$user" "$primary" "$domain_count" "$db_count"
|
|
done
|
|
|
|
echo ""
|
|
}
|
|
|
|
# Export all functions for use in other scripts
|
|
export -f list_all_users
|
|
export -f list_cpanel_users
|
|
export -f list_plesk_users
|
|
export -f list_interworx_users
|
|
export -f list_system_users
|
|
export -f get_user_info
|
|
export -f get_user_domains
|
|
export -f get_cpanel_user_domains
|
|
export -f get_plesk_user_domains
|
|
export -f get_interworx_user_domains
|
|
export -f get_user_databases
|
|
export -f get_user_log_files
|
|
export -f select_user_interactive
|