Merge pull request #1697 from master3395/v2.5.5-dev

V2.5.5 dev
This commit is contained in:
Master3395
2026-02-15 03:05:02 +01:00
committed by GitHub
9 changed files with 193 additions and 67 deletions

View File

@@ -24,6 +24,13 @@ from firewall import views as firewall_views
# includes each installed plugin (under /plugins/<name>/) so settings and
# other plugin pages work for any installed plugin.
# Optional app: may be missing after clean clone or git clean -fd (not in all repo trees)
_optional_email_marketing = []
try:
_optional_email_marketing.append(path('emailMarketing/', include('emailMarketing.urls')))
except ModuleNotFoundError:
pass
urlpatterns = [
# Serve static files first (before catch-all routes)
re_path(r'^static/(?P<path>.*)$', serve, {'document_root': settings.STATIC_ROOT}),
@@ -47,7 +54,7 @@ urlpatterns = [
path('api/', include('api.urls')),
path('filemanager/', include('filemanager.urls')),
path('emailPremium/', include('emailPremium.urls')),
path('emailMarketing/', include('emailMarketing.urls')), # Default-installed (sidebar links to it)
*_optional_email_marketing,
path('manageservices/', include('manageServices.urls')),
path('plugins/', include('pluginHolder.urls')),
path('cloudAPI/', include('cloudAPI.urls')),

View File

@@ -122,9 +122,17 @@ app.controller('systemStatusInfo', function ($scope, $http, $timeout) {
$scope.uptimeLoaded = false;
$scope.uptime = 'Loading...';
// Defaults so template never shows undefined (avoids raw {$ cpuUsage $} when API is slow or fails)
$scope.cpuUsage = 0;
$scope.ramUsage = 0;
$scope.diskUsage = 0;
$scope.cpuCores = 0;
$scope.ramTotalMB = 0;
$scope.diskTotalGB = 0;
$scope.diskFreeGB = 0;
getStuff();
$scope.getSystemStatus = function() {
getStuff();
};
@@ -138,17 +146,15 @@ app.controller('systemStatusInfo', function ($scope, $http, $timeout) {
function ListInitialData(response) {
$scope.cpuUsage = response.data.cpuUsage;
$scope.ramUsage = response.data.ramUsage;
$scope.diskUsage = response.data.diskUsage;
// Total system information
$scope.cpuCores = response.data.cpuCores;
$scope.ramTotalMB = response.data.ramTotalMB;
$scope.diskTotalGB = response.data.diskTotalGB;
$scope.diskFreeGB = response.data.diskFreeGB;
// Get uptime if available
$scope.cpuUsage = response.data.cpuUsage != null ? response.data.cpuUsage : 0;
$scope.ramUsage = response.data.ramUsage != null ? response.data.ramUsage : 0;
$scope.diskUsage = response.data.diskUsage != null ? response.data.diskUsage : 0;
$scope.cpuCores = response.data.cpuCores != null ? response.data.cpuCores : 0;
$scope.ramTotalMB = response.data.ramTotalMB != null ? response.data.ramTotalMB : 0;
$scope.diskTotalGB = response.data.diskTotalGB != null ? response.data.diskTotalGB : 0;
$scope.diskFreeGB = response.data.diskFreeGB != null ? response.data.diskFreeGB : 0;
if (response.data.uptime) {
$scope.uptime = response.data.uptime;
$scope.uptimeLoaded = true;
@@ -162,6 +168,9 @@ app.controller('systemStatusInfo', function ($scope, $http, $timeout) {
function cantLoadInitialData(response) {
$scope.uptime = 'Unavailable';
$scope.uptimeLoaded = true;
$scope.cpuUsage = 0;
$scope.ramUsage = 0;
$scope.diskUsage = 0;
}
$timeout(getStuff, 60000); // Update every minute
@@ -902,7 +911,8 @@ app.controller('OnboardingCP', function ($scope, $http, $timeout, $window) {
});
app.controller('dashboardStatsController', function ($scope, $http, $timeout) {
// Single implementation registered under both names for compatibility (some templates/caches use newDashboardStat)
var dashboardStatsControllerFn = function ($scope, $http, $timeout) {
console.log('dashboardStatsController initialized');
// Card values
@@ -2455,4 +2465,6 @@ app.controller('dashboardStatsController', function ($scope, $http, $timeout) {
$scope.closeSSHActivityModal();
}
};
});
};
app.controller('dashboardStatsController', dashboardStatsControllerFn);
app.controller('newDashboardStat', dashboardStatsControllerFn);

View File

@@ -296,38 +296,51 @@
align-items: center;
justify-content: center;
}
/* Notification dropdown: always light panel with dark text so readable in both light and dark mode */
.notification-center-dropdown {
position: absolute;
top: calc(100% + 10px);
right: 0;
background: white;
border: 1px solid var(--border-color);
background: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 16px;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
width: 520px;
max-width: calc(100vw - 40px);
max-height: 600px;
overflow-y: auto;
z-index: 10000;
display: none;
flex-direction: column;
z-index: 10000;
overflow: hidden;
min-height: 0;
}
.notification-center-dropdown.show { display: block; }
.notification-center-header {
.notification-center-dropdown.show { display: flex; }
.notification-center-dropdown .notification-center-header {
padding: 1.25rem 1.5rem;
border-bottom: 1px solid var(--border-color);
border-bottom: 1px solid #e5e7eb;
display: flex;
justify-content: space-between;
align-items: center;
flex-shrink: 0;
}
.notification-center-header h3 { margin: 0; font-size: 1.25rem; font-weight: 700; }
.notification-center-list { padding: 1rem; }
.notification-center-empty { color: var(--text-secondary); padding: 1rem; }
.notification-center-dropdown .notification-center-header h3 { margin: 0; font-size: 1.25rem; font-weight: 700; color: #111827; }
.notification-center-list {
padding: 1rem;
flex: 1 1 0;
min-height: 0;
max-height: 480px;
overflow-y: auto;
overflow-x: hidden;
-webkit-overflow-scrolling: touch;
}
#notification-center-dropdown .notification-center-empty { color: #4b5563; padding: 1rem; }
.notification-center-item {
padding: 1.5rem;
border: 1px solid var(--border-color);
border: 1px solid #e5e7eb;
border-radius: 12px;
margin-bottom: 1rem;
background: white;
background: #ffffff;
overflow: visible;
}
.notification-center-item.dismissed { opacity: 0.7; background: #f9fafb; }
.notification-center-item-title {
@@ -336,36 +349,69 @@
display: flex;
align-items: center;
gap: 0.75rem;
color: #111827;
}
.notification-center-item-title .dismissed-badge {
font-size: 0.75rem;
color: #6b7280;
color: #374151;
margin-left: auto;
padding: 0.25rem 0.5rem;
background: #f3f4f6;
background: #e5e7eb;
border-radius: 6px;
}
.notification-center-item-text { color: var(--text-secondary); font-size: 0.95rem; margin-bottom: 1rem; line-height: 1.6; }
.notification-center-item-actions { display: flex; gap: 0.75rem; flex-wrap: wrap; }
.notification-center-item-link {
display: inline-flex;
align-items: center;
gap: 0.5rem;
color: white;
background: linear-gradient(135deg, var(--accent-color) 0%, #6d6bd4 100%);
text-decoration: none;
font-size: 0.9rem;
font-weight: 600;
padding: 0.75rem 1.5rem;
border-radius: 10px;
#notification-center-dropdown .notification-center-item-text { color: #4b5563; font-size: 0.95rem; margin-bottom: 1rem; line-height: 1.6; }
#notification-center-dropdown .notification-center-item-actions {
display: flex;
flex-direction: column;
gap: 1.25rem;
align-items: flex-start;
margin-top: 0.75rem;
width: 100%;
}
.notification-center-item-link-secondary {
#notification-center-dropdown .notification-center-item-actions .notification-center-item-link {
display: inline-flex;
align-items: center;
gap: 0.5rem;
color: var(--accent-color);
justify-content: center;
gap: 0.4rem;
color: #ffffff !important;
background: linear-gradient(135deg, #4f46e5 0%, #4338ca 100%) !important;
text-decoration: none;
font-size: 0.9rem;
font-size: 0.875rem;
font-weight: 600;
padding: 0.5rem 1.25rem;
border-radius: 8px;
white-space: nowrap;
flex-shrink: 0;
min-width: 160px;
width: auto;
min-height: 2.25rem;
line-height: 1.3;
box-sizing: border-box;
}
#notification-center-dropdown .notification-center-item-actions .notification-center-item-link:hover {
filter: brightness(1.1);
color: #ffffff !important;
}
#notification-center-dropdown .notification-center-item-actions .notification-center-item-link-secondary {
display: inline-flex;
align-items: center;
gap: 0.4rem;
color: #4338ca !important;
text-decoration: none;
font-size: 0.875rem;
font-weight: 500;
padding: 0.4rem 0.75rem;
white-space: nowrap;
flex-shrink: 0;
min-width: 120px;
width: auto;
min-height: 1.75rem;
line-height: 1.3;
box-sizing: border-box;
}
#notification-center-dropdown .notification-center-item-actions .notification-center-item-link-secondary:hover {
text-decoration: underline;
color: #3730a3 !important;
}
/* Sidebar */
@@ -2510,6 +2556,10 @@
document.addEventListener('DOMContentLoaded', function() {
loadNotificationCenter();
checkBackupStatus();
// Optional: open notification dropdown for testing (e.g. ?showNotifications=1)
if (window.location.search.indexOf('showNotifications=1') !== -1) {
setTimeout(function() { document.getElementById('notification-center-dropdown').classList.add('show'); }, 400);
}
// Show AI Scanner notification with a slight delay for better UX
setTimeout(checkAIScannerStatus, 1000);
// Show .htaccess notification with additional delay for staggered effect

View File

@@ -841,29 +841,27 @@ except:
fi
fi
# Download the working CyberPanel installation files
# Use master3395 fork which has our fixes
# Try to download the actual installer script (install/install.py) from the repository
echo "Downloading from: https://raw.githubusercontent.com/master3395/cyberpanel/v2.5.5-dev/cyberpanel.sh"
# Download the working CyberPanel installation files from upstream (usmannasir/cyberpanel)
echo "Downloading from: https://raw.githubusercontent.com/usmannasir/cyberpanel/v2.5.5-dev/cyberpanel.sh"
# First, try to download the repository archive to get the correct installer
# GitHub: branch archives use refs/heads/BRANCH; GitHub returns 302 redirect to codeload, so we must use -L
local archive_url=""
local installer_url="https://raw.githubusercontent.com/master3395/cyberpanel/v2.5.5-dev/cyberpanel.sh"
if curl -s -L --head "https://github.com/master3395/cyberpanel/archive/refs/heads/v2.5.5-dev.tar.gz" | grep -q "200 OK"; then
archive_url="https://github.com/master3395/cyberpanel/archive/refs/heads/v2.5.5-dev.tar.gz"
echo " Using development branch (v2.5.5-dev) from master3395/cyberpanel"
elif curl -s -L --head "https://github.com/master3395/cyberpanel/archive/v2.5.5-dev.tar.gz" | grep -q "200 OK"; then
archive_url="https://github.com/master3395/cyberpanel/archive/v2.5.5-dev.tar.gz"
echo " Using development branch (v2.5.5-dev) from master3395/cyberpanel"
local installer_url="https://raw.githubusercontent.com/usmannasir/cyberpanel/v2.5.5-dev/cyberpanel.sh"
if curl -s -L --head "https://github.com/usmannasir/cyberpanel/archive/refs/heads/v2.5.5-dev.tar.gz" | grep -q "200 OK"; then
archive_url="https://github.com/usmannasir/cyberpanel/archive/refs/heads/v2.5.5-dev.tar.gz"
echo " Using development branch (v2.5.5-dev) from usmannasir/cyberpanel"
elif curl -s -L --head "https://github.com/usmannasir/cyberpanel/archive/v2.5.5-dev.tar.gz" | grep -q "200 OK"; then
archive_url="https://github.com/usmannasir/cyberpanel/archive/v2.5.5-dev.tar.gz"
echo " Using development branch (v2.5.5-dev) from usmannasir/cyberpanel"
else
echo " Development branch archive not available, trying installer script directly..."
if ! curl -s -L --head "$installer_url" | grep -q "200 OK"; then
echo " Development branch not available, falling back to stable"
installer_url="https://raw.githubusercontent.com/master3395/cyberpanel/stable/cyberpanel.sh"
archive_url="https://github.com/master3395/cyberpanel/archive/stable.tar.gz"
installer_url="https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/cyberpanel.sh"
archive_url="https://github.com/usmannasir/cyberpanel/archive/stable.tar.gz"
else
archive_url="https://github.com/master3395/cyberpanel/archive/refs/heads/v2.5.5-dev.tar.gz"
archive_url="https://github.com/usmannasir/cyberpanel/archive/refs/heads/v2.5.5-dev.tar.gz"
fi
fi
@@ -884,8 +882,8 @@ except:
# Download the install directory (use archive_url set above; may be branch or stable)
echo "Downloading installation files..."
if [ -z "$archive_url" ] || [ "$installer_url" = "https://raw.githubusercontent.com/master3395/cyberpanel/stable/cyberpanel.sh" ]; then
archive_url="https://github.com/master3395/cyberpanel/archive/stable.tar.gz"
if [ -z "$archive_url" ] || [ "$installer_url" = "https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/cyberpanel.sh" ]; then
archive_url="https://github.com/usmannasir/cyberpanel/archive/stable.tar.gz"
fi
# Append cache-bust so CDNs/proxies don't serve old installer (GitHub ignores query params)
archive_url="${archive_url}?nocache=$(date +%s 2>/dev/null || echo 0)"
@@ -904,7 +902,7 @@ except:
fi
# Copy install directory to current location
if [ "$installer_url" = "https://raw.githubusercontent.com/master3395/cyberpanel/stable/cyberpanel.sh" ]; then
if [ "$installer_url" = "https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/cyberpanel.sh" ]; then
if [ -d "cyberpanel-stable" ]; then
cp -r cyberpanel-stable/install . 2>/dev/null || true
cp -r cyberpanel-stable/install.sh . 2>/dev/null || true

View File

@@ -15,7 +15,7 @@
if [[ $(id -u) -ne 0 ]] 2>/dev/null; then
echo ""
echo "This script must be run as root."
echo "Run: sudo bash <(curl -sL https://raw.githubusercontent.com/master3395/cyberpanel/stable/cyberpanel_upgrade.sh) -b v2.5.5-dev"
echo "Run: sudo bash <(curl -sL https://raw.githubusercontent.com/usmannasir/cyberpanel/stable/cyberpanel_upgrade.sh) -b v2.5.5-dev"
echo "Or: sudo su - then run the same command without sudo"
echo ""
exit 1
@@ -1395,6 +1395,50 @@ fi
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Main_Upgrade function completed" | tee -a /var/log/cyberpanel_upgrade_debug.log
}
# Sync /usr/local/CyberCP to the latest commit of the upgrade branch so Version Management
# page shows Current commit matching Latest (avoids "please upgrade" when upgrade already ran).
# Backs up and restores CyberCP/settings.py so production DB/config are not overwritten by the repo.
Sync_CyberCP_To_Latest() {
if [[ ! -d /usr/local/CyberCP/.git ]]; then
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] No .git in /usr/local/CyberCP, skipping sync" | tee -a /var/log/cyberpanel_upgrade_debug.log
return 0
fi
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Syncing /usr/local/CyberCP to latest commit for branch: $Branch_Name" | tee -a /var/log/cyberpanel_upgrade_debug.log
# Backup production settings so sync does not overwrite DB credentials / local config
if [[ -f /usr/local/CyberCP/CyberCP/settings.py ]]; then
cp /usr/local/CyberCP/CyberCP/settings.py /tmp/cyberpanel_settings_backup.py
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Backed up settings.py for restore after sync" | tee -a /var/log/cyberpanel_upgrade_debug.log
fi
(
cd /usr/local/CyberCP
git fetch origin 2>&1 | tee -a /var/log/cyberpanel_upgrade_debug.log
if git show-ref -q "refs/remotes/origin/$Branch_Name"; then
git checkout -B "$Branch_Name" "origin/$Branch_Name" 2>&1 | tee -a /var/log/cyberpanel_upgrade_debug.log
else
git checkout "$Branch_Name" 2>/dev/null || true
git pull --ff-only origin "$Branch_Name" 2>&1 | tee -a /var/log/cyberpanel_upgrade_debug.log || true
fi
)
local sync_code=$?
# Restore production settings so panel keeps working (DB, secrets, etc.)
if [[ -f /tmp/cyberpanel_settings_backup.py ]]; then
cp /tmp/cyberpanel_settings_backup.py /usr/local/CyberCP/CyberCP/settings.py
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Restored settings.py after sync" | tee -a /var/log/cyberpanel_upgrade_debug.log
fi
# LiteSpeed serves /static/ from public/static/; ensure it has latest baseTemplate static files (e.g. dashboard JS)
if [[ -d /usr/local/CyberCP/public/static ]] && [[ -d /usr/local/CyberCP/baseTemplate/static/baseTemplate ]]; then
rsync -a /usr/local/CyberCP/baseTemplate/static/baseTemplate/ /usr/local/CyberCP/public/static/baseTemplate/ 2>/dev/null || \
cp -r /usr/local/CyberCP/baseTemplate/static/baseTemplate/* /usr/local/CyberCP/public/static/baseTemplate/ 2>/dev/null || true
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Synced baseTemplate static to public/static" | tee -a /var/log/cyberpanel_upgrade_debug.log
fi
if [[ $sync_code -eq 0 ]]; then
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Sync completed. Current HEAD: $(git -C /usr/local/CyberCP rev-parse HEAD 2>/dev/null || echo 'unknown')" | tee -a /var/log/cyberpanel_upgrade_debug.log
else
echo -e "[$(date +"%Y-%m-%d %H:%M:%S")] Sync returned code $sync_code (non-fatal)" | tee -a /var/log/cyberpanel_upgrade_debug.log
fi
return 0
}
Post_Upgrade_System_Tweak() {
if [[ "$Server_OS" = "CentOS" ]] ; then
@@ -1816,6 +1860,7 @@ echo -e " 1. Access your CyberPanel at the URL above"
echo -e " 2. Change the default admin password"
echo -e " 3. Configure your domains and websites"
echo -e " 4. Check system status in the dashboard"
echo -e " 5. Check DB version with: mariadb -V (use mariadb, not mysql, to avoid deprecation warning)"
echo -e "\n🧹 Cleaning up temporary files..."
rm -rf /root/cyberpanel_upgrade_tmp
@@ -1883,6 +1928,8 @@ Pre_Upgrade_Required_Components
Main_Upgrade
Sync_CyberCP_To_Latest
Post_Upgrade_System_Tweak
Post_Install_Display_Final_Info

View File

@@ -10,6 +10,8 @@
<span style="display: none" id="password">{{ password }}</span>
<form style="display: none" name="loginform" id="loginform" action="/phpmyadmin/phpmyadminsignin.php" method="post">
{% csrf_token %}
<input type="hidden" name="host" value="{{ host|default:'127.0.0.1' }}"/>
<input type="hidden" name="port" value="{{ port|default:'3306' }}"/>
<p>
<label for="user_login">Username or Email Address</label>
<input type="text" name="username" id="user_login" class="input" value="" size="20" autocapitalize="off"/>

View File

@@ -294,6 +294,11 @@ def fetchDetailsPHPMYAdmin(request):
data = {}
data['userName'] = mysqluser
data['password'] = password
# Use 127.0.0.1 so phpMyAdmin connects via TCP (port 3306), same as main MariaDB
data['host'] = jsonData.get('mysqlhost', '127.0.0.1') or '127.0.0.1'
if data['host'] == 'localhost':
data['host'] = '127.0.0.1'
data['port'] = str(jsonData.get('mysqlport', 3306))
proc = httpProc(request, 'databases/AutoLogin.html',
data, 'admin')
@@ -309,6 +314,8 @@ def fetchDetailsPHPMYAdmin(request):
data = {}
data['userName'] = 'root'
data['password'] = password
data['host'] = '127.0.0.1'
data['port'] = '3306'
# return redirect(returnURL)
proc = httpProc(request, 'databases/AutoLogin.html',
@@ -333,6 +340,8 @@ def fetchDetailsPHPMYAdmin(request):
data = {}
data['userName'] = admin.userName
data['password'] = password.decode()
data['host'] = '127.0.0.1'
data['port'] = '3306'
# return redirect(returnURL)
proc = httpProc(request, 'databases/AutoLogin.html',

View File

@@ -47,10 +47,11 @@ try {
$username = htmlspecialchars($_POST['username'], ENT_QUOTES, 'UTF-8');
$password = $_POST['password'];
$host = isset($_POST['host']) ? trim($_POST['host']) : 'localhost';
$_SESSION['PMA_single_signon_user'] = $username;
$_SESSION['PMA_single_signon_password'] = $password;
$_SESSION['PMA_single_signon_host'] = 'localhost';
$_SESSION['PMA_single_signon_host'] = $host;
@session_write_close();

View File

@@ -24,7 +24,7 @@ fi
echo "Upgrading CyberPanel from branch: $BRANCH_NAME"
rm -f /usr/local/cyberpanel_upgrade.sh
wget -O /usr/local/cyberpanel_upgrade.sh https://raw.githubusercontent.com/master3395/cyberpanel/$BRANCH_NAME/cyberpanel_upgrade.sh 2>/dev/null
wget -O /usr/local/cyberpanel_upgrade.sh https://raw.githubusercontent.com/usmannasir/cyberpanel/$BRANCH_NAME/cyberpanel_upgrade.sh 2>/dev/null
chmod 700 /usr/local/cyberpanel_upgrade.sh
# Pass -b so upgrade script skips branch prompt and uses our branch
/usr/local/cyberpanel_upgrade.sh -b "$BRANCH_NAME" $EXTRA_ARGS