mirror of
https://github.com/usmannasir/cyberpanel.git
synced 2026-03-25 21:40:07 +01:00
fix(ftp): add idempotent custom_quota columns on users table
- CPScripts/ensure_ftp_users_quota_columns.py checks information_schema and ALTER TABLE users ADD COLUMN for custom_quota_enabled and custom_quota_size when missing (fixes MySQL 1054 on FTP account creation). - deploy-ftp-users-custom-quota-columns.sh copies script to CyberCP and runs repair; restarts lscpd when active. - upgrade_modules/10_post_tweak.sh runs the repair after upgrade sync.
This commit is contained in:
82
CPScripts/ensure_ftp_users_quota_columns.py
Normal file
82
CPScripts/ensure_ftp_users_quota_columns.py
Normal file
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Idempotent schema repair: add custom_quota_enabled and custom_quota_size to the
|
||||
Django ftp.Users table (Meta.db_table = 'users') if missing.
|
||||
|
||||
Fixes MySQL 1054: Unknown column 'custom_quota_enabled' in 'INSERT INTO'
|
||||
when creating FTP accounts after upgrading CyberPanel without a matching migration.
|
||||
|
||||
Usage:
|
||||
CP_DIR=/usr/local/CyberCP python3 ensure_ftp_users_quota_columns.py
|
||||
python3 ensure_ftp_users_quota_columns.py /usr/local/CyberCP
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
def main() -> int:
|
||||
try:
|
||||
if len(sys.argv) > 1 and sys.argv[1].strip():
|
||||
cp_dir = os.path.abspath(sys.argv[1].strip())
|
||||
else:
|
||||
cp_dir = os.path.abspath(os.environ.get("CP_DIR", "/usr/local/CyberCP"))
|
||||
|
||||
if not os.path.isdir(cp_dir):
|
||||
sys.stderr.write("ensure_ftp_users_quota_columns: CP directory not found: %s\n" % cp_dir)
|
||||
return 1
|
||||
|
||||
sys.path.insert(0, cp_dir)
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "CyberCP.settings")
|
||||
|
||||
import django
|
||||
|
||||
django.setup()
|
||||
|
||||
from django.db import connection
|
||||
|
||||
table = "users"
|
||||
alters = (
|
||||
("custom_quota_enabled", "TINYINT(1) NOT NULL DEFAULT 0"),
|
||||
("custom_quota_size", "INT NOT NULL DEFAULT 0"),
|
||||
)
|
||||
|
||||
with connection.cursor() as cursor:
|
||||
cursor.execute("SELECT DATABASE()")
|
||||
row = cursor.fetchone()
|
||||
dbname = row[0] if row else None
|
||||
if not dbname:
|
||||
sys.stderr.write(
|
||||
"ensure_ftp_users_quota_columns: could not resolve current database name.\n"
|
||||
)
|
||||
return 1
|
||||
|
||||
for col, definition in alters:
|
||||
cursor.execute(
|
||||
"""
|
||||
SELECT COUNT(*) FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s
|
||||
""",
|
||||
[dbname, table, col],
|
||||
)
|
||||
exists = cursor.fetchone()[0] > 0
|
||||
if exists:
|
||||
print("ensure_ftp_users_quota_columns: column %s already on %s; skipped." % (col, table))
|
||||
continue
|
||||
# identifiers are fixed literals; definition is controlled (no user input)
|
||||
cursor.execute(
|
||||
"ALTER TABLE `%s` ADD COLUMN `%s` %s" % (table, col, definition)
|
||||
)
|
||||
print("ensure_ftp_users_quota_columns: added column %s to %s." % (col, table))
|
||||
|
||||
print("ensure_ftp_users_quota_columns: done.")
|
||||
return 0
|
||||
except Exception as exc:
|
||||
sys.stderr.write("ensure_ftp_users_quota_columns: error: %s\n" % (exc,))
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
66
deploy-ftp-users-custom-quota-columns.sh
Executable file
66
deploy-ftp-users-custom-quota-columns.sh
Executable file
@@ -0,0 +1,66 @@
|
||||
#!/bin/bash
|
||||
# Add missing custom_quota_enabled / custom_quota_size columns to ftp Users table (users).
|
||||
# Fixes: (1054, "Unknown column 'custom_quota_enabled' in 'INSERT INTO'") on FTP account creation.
|
||||
#
|
||||
# Usage:
|
||||
# sudo bash /home/cyberpanel-repo/deploy-ftp-users-custom-quota-columns.sh
|
||||
# sudo bash deploy-ftp-users-custom-quota-columns.sh [REPO_DIR] [CP_DIR]
|
||||
|
||||
set -e
|
||||
|
||||
log() { echo "[$(date +%Y-%m-%d\ %H:%M:%S)] $*"; }
|
||||
err() { log "ERROR: $*" >&2; }
|
||||
|
||||
# Resolve REPO_DIR
|
||||
if [[ -n "$1" && -f "$1/CPScripts/ensure_ftp_users_quota_columns.py" ]]; then
|
||||
REPO_DIR="$1"
|
||||
shift
|
||||
elif [[ -f "$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)/CPScripts/ensure_ftp_users_quota_columns.py" ]]; then
|
||||
REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
elif [[ -f "/home/cyberpanel-repo/CPScripts/ensure_ftp_users_quota_columns.py" ]]; then
|
||||
REPO_DIR="/home/cyberpanel-repo"
|
||||
elif [[ -f "./CPScripts/ensure_ftp_users_quota_columns.py" ]]; then
|
||||
REPO_DIR="$(pwd)"
|
||||
else
|
||||
err "CPScripts/ensure_ftp_users_quota_columns.py not found."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
CP_DIR="${1:-/usr/local/CyberCP}"
|
||||
RESTART_LSCPD="${RESTART_LSCPD:-1}"
|
||||
|
||||
if [[ ! -d "$CP_DIR" ]]; then
|
||||
err "CyberPanel directory not found: $CP_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "REPO_DIR=$REPO_DIR"
|
||||
log "CP_DIR=$CP_DIR"
|
||||
|
||||
mkdir -p "$CP_DIR/CPScripts"
|
||||
cp -f "$REPO_DIR/CPScripts/ensure_ftp_users_quota_columns.py" "$CP_DIR/CPScripts/ensure_ftp_users_quota_columns.py"
|
||||
chmod 644 "$CP_DIR/CPScripts/ensure_ftp_users_quota_columns.py"
|
||||
log "Copied ensure_ftp_users_quota_columns.py to $CP_DIR/CPScripts/"
|
||||
|
||||
log "Ensuring FTP users table has custom quota columns..."
|
||||
export CP_DIR
|
||||
PY="$CP_DIR/bin/python"
|
||||
if [[ -x "$PY" ]]; then
|
||||
"$PY" "$CP_DIR/CPScripts/ensure_ftp_users_quota_columns.py" "$CP_DIR" || { err "Python repair failed"; exit 1; }
|
||||
else
|
||||
python3 "$CP_DIR/CPScripts/ensure_ftp_users_quota_columns.py" "$CP_DIR" || { err "Python repair failed"; exit 1; }
|
||||
fi
|
||||
|
||||
if [[ "$RESTART_LSCPD" =~ ^(1|yes|true)$ ]]; then
|
||||
if systemctl is-active --quiet lscpd 2>/dev/null; then
|
||||
log "Restarting lscpd..."
|
||||
systemctl restart lscpd || { err "lscpd restart failed"; exit 1; }
|
||||
log "lscpd restarted."
|
||||
else
|
||||
log "lscpd not running or not a systemd service; skip restart."
|
||||
fi
|
||||
else
|
||||
log "Skipping restart (set RESTART_LSCPD=1 to restart lscpd)."
|
||||
fi
|
||||
|
||||
log "Deploy complete. Test: Websites → FTP → Create FTP Account."
|
||||
@@ -368,6 +368,18 @@ if [ -f /usr/local/CyberCP/public/phpmyadmin/phpmyadminsignin.php ]; then
|
||||
grep -q "127.0.0.1" /usr/local/CyberCP/public/phpmyadmin/phpmyadminsignin.php && echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] phpMyAdmin signon default host set to 127.0.0.1" | tee -a /var/log/cyberpanel_upgrade_debug.log
|
||||
fi
|
||||
|
||||
# FTP users table: custom quota columns (fixes 1054 on Create FTP Account if schema predates model fields)
|
||||
if [[ -f /usr/local/CyberCP/CPScripts/ensure_ftp_users_quota_columns.py ]]; then
|
||||
if [[ -x /usr/local/CyberCP/bin/python ]]; then
|
||||
CP_DIR=/usr/local/CyberCP /usr/local/CyberCP/bin/python /usr/local/CyberCP/CPScripts/ensure_ftp_users_quota_columns.py /usr/local/CyberCP 2>&1 | tee -a /var/log/cyberpanel_upgrade_debug.log || true
|
||||
else
|
||||
CP_DIR=/usr/local/CyberCP python3 /usr/local/CyberCP/CPScripts/ensure_ftp_users_quota_columns.py /usr/local/CyberCP 2>&1 | tee -a /var/log/cyberpanel_upgrade_debug.log || true
|
||||
fi
|
||||
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Ran ensure_ftp_users_quota_columns (FTP users table custom quota columns)" | tee -a /var/log/cyberpanel_upgrade_debug.log
|
||||
else
|
||||
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] INFO: ensure_ftp_users_quota_columns.py not in CyberCP yet; run deploy-ftp-users-custom-quota-columns.sh after sync" | tee -a /var/log/cyberpanel_upgrade_debug.log
|
||||
fi
|
||||
|
||||
systemctl restart lscpd
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user