diff --git a/databases/static/databases/databases.js b/databases/static/databases/databases.js
index 0eb8469fb..8dd93d53c 100644
--- a/databases/static/databases/databases.js
+++ b/databases/static/databases/databases.js
@@ -2,6 +2,8 @@
* Created by usman on 8/6/17.
*/
+/* Ensure we register controllers on the CyberCP app (avoids ctrlreg if load order differs) */
+var app = (typeof window.app !== 'undefined' && window.app) ? window.app : angular.module('CyberCP');
/* Java script code to create database */
app.controller('createDatabase', function ($scope, $http) {
@@ -694,7 +696,7 @@ app.controller('Mysqlmanager', function ($scope, $http, $compile, $window, $time
$scope.cyberPanelLoading = true;
- url = "/dataBases/getMysqlstatus";
+ url = "/dataBases/getMysqlstatus?t=" + (Date.now ? Date.now() : new Date().getTime());
var data = {};
@@ -715,6 +717,8 @@ app.controller('Mysqlmanager', function ($scope, $http, $compile, $window, $time
try {
data = JSON.parse(data);
} catch (e) {
+ $scope.uptime = $scope.connections = $scope.Slow_queries = '—';
+ $scope.processes = [];
new PNotify({ title: 'Error!', text: 'Invalid response from server.', type: 'error' });
return;
}
@@ -749,7 +753,21 @@ app.controller('Mysqlmanager', function ($scope, $http, $compile, $window, $time
function cantLoadInitialDatas(response) {
$scope.cyberPanelLoading = false;
- var msg = (response.data && response.data.error_message) || (response.statusText || 'Cannot load MySQL status.');
+ $scope.uptime = '—';
+ $scope.connections = '—';
+ $scope.Slow_queries = '—';
+ $scope.processes = [];
+ var msg = 'Cannot load MySQL status.';
+ if (response && response.status) {
+ msg = 'Request failed: ' + response.status + (response.statusText ? ' ' + response.statusText : '');
+ }
+ if (response && response.data) {
+ if (typeof response.data === 'string' && response.data.length < 200) {
+ msg = response.data;
+ } else if (response.data.error_message) {
+ msg = response.data.error_message;
+ }
+ }
new PNotify({
title: 'Error!',
text: msg,
diff --git a/databases/templates/databases/mysqlmanager.html b/databases/templates/databases/mysqlmanager.html
index 9ebac5523..16b495e76 100644
--- a/databases/templates/databases/mysqlmanager.html
+++ b/databases/templates/databases/mysqlmanager.html
@@ -644,8 +644,8 @@
+ ng-bind="(process.info && process.info !== 'NULL') ? process.info : 'No query'"
+ ng-attr-title="{$ (process.info && process.info !== 'NULL') ? process.info : 'No query' $}">
|
diff --git a/plogical/CyberPanelUpgrade.py b/plogical/CyberPanelUpgrade.py
index a9179374b..df6abdac6 100644
--- a/plogical/CyberPanelUpgrade.py
+++ b/plogical/CyberPanelUpgrade.py
@@ -79,6 +79,7 @@ class UpgradeCyberPanel:
Upgrade.CLMigrations()
Upgrade.IncBackupMigrations()
Upgrade.applyLoginSystemMigrations()
+ Upgrade.homeDirectoryMigrations()
Upgrade.s3BackupMigrations()
Upgrade.containerMigrations()
Upgrade.manageServiceMigrations()
diff --git a/plogical/mysqlUtilities.py b/plogical/mysqlUtilities.py
index 28756e8d1..92eef09f8 100644
--- a/plogical/mysqlUtilities.py
+++ b/plogical/mysqlUtilities.py
@@ -531,47 +531,63 @@ password=%s
data['status'] = 1
for items in result:
- if items[0] == 'Uptime':
- data['uptime'] = mysqlUtilities.GetTime(items[1])
- elif items[0] == 'Connections':
- data['connections'] = items[1]
- elif items[0] == 'Slow_queries':
- data['Slow_queries'] = items[1]
+ if not items or len(items) < 2:
+ continue
+ key = (items[0] or '').strip()
+ val = items[1]
+ if key == 'Uptime':
+ try:
+ data['uptime'] = mysqlUtilities.GetTime(val)
+ except (TypeError, ValueError):
+ data['uptime'] = str(val) if val is not None else '0'
+ elif key == 'Connections':
+ data['connections'] = val
+ elif key == 'Slow_queries':
+ data['Slow_queries'] = val
- ## Process List
-
- cursor.execute("show processlist")
+ ## Process List (column-name based so it works with any MySQL/MariaDB version)
+ cursor.execute("SHOW FULL PROCESSLIST")
+ if cursor.description:
+ col_names = [col[0].lower() if col[0] else '' for col in cursor.description]
+ else:
+ col_names = []
result = cursor.fetchall()
json_data = "["
checker = 0
- for items in result:
- # SHOW PROCESSLIST: Id, User, Host, db, Command, Time, State, Info [, Progress]
- if items[3] is None or len(str(items[3])) == 0:
+ for row in result:
+ if col_names:
+ row_dict = dict(zip(col_names, row)) if len(col_names) == len(row) else {}
+ else:
+ row_dict = {}
+ # Support both MySQL and MariaDB column names (Id/id, User/user, db/DB, etc.)
+ def get_col(*keys, default=None):
+ for k in keys:
+ v = row_dict.get(k) if row_dict else None
+ if v is not None and (not isinstance(v, str) or len(str(v).strip()) > 0):
+ return v
+ return default
+
+ database = get_col('db', 'database', default='NULL')
+ if database is None or (isinstance(database, str) and len(database.strip()) == 0):
database = 'NULL'
- else:
- database = items[3]
-
- if len(items) > 6 and items[6] is not None and len(str(items[6])) > 0:
- state = items[6]
- else:
+ state = get_col('state', default='NULL')
+ if state is None or (isinstance(state, str) and len(str(state).strip()) == 0):
state = 'NULL'
-
- if len(items) > 7 and items[7] is not None and len(str(items[7])) > 0:
- info = items[7]
- else:
- info = 'NULL'
+ info = get_col('info', default=None)
+ if info is None or (isinstance(info, str) and len(str(info).strip()) == 0):
+ info = 'No query'
dic = {
- 'id': items[0],
- 'user': items[1],
+ 'id': get_col('id', default=0),
+ 'user': get_col('user', default=''),
'database': database,
- 'command': items[4] if len(items) > 4 else '',
- 'time': items[5] if len(items) > 5 else 0,
+ 'command': get_col('command', default=''),
+ 'time': get_col('time', 'time_ms', default=0),
'state': state,
'info': info,
- 'progress': items[8] if len(items) > 8 else 0,
+ 'progress': get_col('progress', default=0),
}
if checker == 0:
diff --git a/plogical/upgrade.py b/plogical/upgrade.py
index 6f534aba0..b10ffb670 100644
--- a/plogical/upgrade.py
+++ b/plogical/upgrade.py
@@ -2382,6 +2382,50 @@ CREATE TABLE `websiteFunctions_backupsv2` (`id` integer AUTO_INCREMENT NOT NULL
except OSError as msg:
Upgrade.stdOut(str(msg) + " [applyLoginSystemMigrations]")
+ @staticmethod
+ def homeDirectoryMigrations():
+ """Create home_directories and user_home_mappings tables if missing (Modify Website home directory feature)."""
+ try:
+ connection, cursor = Upgrade.setupConnection('cyberpanel')
+ try:
+ cursor.execute("""
+ CREATE TABLE IF NOT EXISTS `home_directories` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `name` varchar(50) NOT NULL UNIQUE,
+ `path` varchar(255) NOT NULL UNIQUE,
+ `is_active` tinyint(1) NOT NULL DEFAULT 1,
+ `is_default` tinyint(1) NOT NULL DEFAULT 0,
+ `max_users` integer NOT NULL DEFAULT 0,
+ `description` longtext,
+ `created_at` datetime(6) NOT NULL,
+ `updated_at` datetime(6) NOT NULL
+ )
+ """)
+ except Exception:
+ pass
+ try:
+ cursor.execute("""
+ CREATE TABLE IF NOT EXISTS `user_home_mappings` (
+ `id` integer AUTO_INCREMENT NOT NULL PRIMARY KEY,
+ `user_id` integer NOT NULL UNIQUE,
+ `home_directory_id` integer NOT NULL,
+ `created_at` datetime(6) NOT NULL,
+ `updated_at` datetime(6) NOT NULL,
+ CONSTRAINT `user_home_mappings_user_id_fk` FOREIGN KEY (`user_id`)
+ REFERENCES `loginSystem_administrator` (`id`) ON DELETE CASCADE,
+ CONSTRAINT `user_home_mappings_home_directory_id_fk` FOREIGN KEY (`home_directory_id`)
+ REFERENCES `home_directories` (`id`) ON DELETE CASCADE
+ )
+ """)
+ except Exception:
+ pass
+ try:
+ connection.close()
+ except Exception:
+ pass
+ except Exception:
+ pass
+
@staticmethod
def s3BackupMigrations():
try:
@@ -5851,6 +5895,7 @@ slowlog = /var/log/php{version}-fpm-slow.log
##
Upgrade.applyLoginSystemMigrations()
+ Upgrade.homeDirectoryMigrations()
## Put function here to update custom ACLs
diff --git a/public/static/databases/databases.js b/public/static/databases/databases.js
index 7b10cf48a..8dd93d53c 100644
--- a/public/static/databases/databases.js
+++ b/public/static/databases/databases.js
@@ -2,6 +2,8 @@
* Created by usman on 8/6/17.
*/
+/* Ensure we register controllers on the CyberCP app (avoids ctrlreg if load order differs) */
+var app = (typeof window.app !== 'undefined' && window.app) ? window.app : angular.module('CyberCP');
/* Java script code to create database */
app.controller('createDatabase', function ($scope, $http) {
@@ -10,22 +12,72 @@ app.controller('createDatabase', function ($scope, $http) {
$(".dbDetails").hide();
$(".generatedPasswordDetails").hide();
$('#create-database-select').select2();
+
+ // Initialize preview if website is already selected
+ setTimeout(function() {
+ if ($scope.databaseWebsite) {
+ var truncatedName = $scope.getTruncatedWebName($scope.databaseWebsite);
+ $("#domainDatabase").text(truncatedName);
+ $("#domainUsername").text(truncatedName);
+ $(".dbDetails").show();
+ }
+ }, 100);
});
+ // Helper function to get truncated website name
+ $scope.getTruncatedWebName = function(domain) {
+ if (!domain) return '';
+
+ // Remove hyphens and get first part before dot
+ var webName = domain.replace(/-/g, '').split('.')[0];
+
+ // Truncate to 4 characters if longer than 5
+ if (webName.length > 5) {
+ webName = webName.substring(0, 4);
+ }
+
+ return webName;
+ };
+
$('#create-database-select').on('select2:select', function (e) {
var data = e.params.data;
$scope.databaseWebsite = data.text;
$(".dbDetails").show();
- $("#domainDatabase").text(getWebsiteName(data.text));
- $("#domainUsername").text(getWebsiteName(data.text));
+
+ // Use local truncation function to ensure consistency
+ var truncatedName = $scope.getTruncatedWebName(data.text);
+ $("#domainDatabase").text(truncatedName);
+ $("#domainUsername").text(truncatedName);
+
+ // Apply scope to update Angular bindings
+ $scope.$apply();
});
$scope.showDetailsBoxes = function () {
$scope.dbDetails = false;
}
+
+ // Function called when website selection changes
+ $scope.websiteChanged = function() {
+ if ($scope.databaseWebsite) {
+ $(".dbDetails").show();
+ var truncatedName = $scope.getTruncatedWebName($scope.databaseWebsite);
+ $("#domainDatabase").text(truncatedName);
+ $("#domainUsername").text(truncatedName);
+ }
+ }
$scope.createDatabaseLoading = true;
+
+ // Watch for changes to databaseWebsite to update preview
+ $scope.$watch('databaseWebsite', function(newValue, oldValue) {
+ if (newValue && newValue !== oldValue) {
+ var truncatedName = $scope.getTruncatedWebName(newValue);
+ $("#domainDatabase").text(truncatedName);
+ $("#domainUsername").text(truncatedName);
+ }
+ });
$scope.createDatabase = function () {
@@ -39,14 +91,8 @@ app.controller('createDatabase', function ($scope, $http) {
var dbPassword = $scope.dbPassword;
var webUserName = "";
- // getting website username
-
- webUserName = databaseWebsite.replace(/-/g, '');
- webUserName = webUserName.split(".")[0];
-
- if (webUserName.length > 5) {
- webUserName = webUserName.substring(0, 4);
- }
+ // getting website username - use the same truncation function for consistency
+ webUserName = $scope.getTruncatedWebName(databaseWebsite);
var url = "/dataBases/submitDBCreation";
@@ -75,9 +121,15 @@ app.controller('createDatabase', function ($scope, $http) {
$scope.createDatabaseLoading = true;
$scope.dbDetails = false;
+ var successMessage = 'Database successfully created.';
+ if (response.data.dbName && response.data.dbUsername) {
+ successMessage = 'Database successfully created.\n' +
+ 'Database Name: ' + response.data.dbName + '\n' +
+ 'Database User: ' + response.data.dbUsername;
+ }
new PNotify({
title: 'Success!',
- text: 'Database successfully created.',
+ text: successMessage,
type: 'success'
});
} else {
@@ -589,8 +641,34 @@ app.controller('phpMyAdmin', function ($scope, $http, $window) {
function ListInitialDatas(response) {
$scope.cyberPanelLoading = true;
if (response.data.status === 1) {
- var rUrl = '/phpmyadmin/phpmyadminsignin.php?username=' + response.data.username + '&token=' + response.data.token;
- $window.location.href = rUrl;
+ //var rUrl = '/phpmyadmin/phpmyadminsignin.php?username=' + response.data.username + '&token=' + response.data.token;
+ //$window.location.href = rUrl;
+
+ var form = document.createElement('form');
+ form.method = 'post';
+ form.action = '/phpmyadmin/phpmyadminsignin.php';
+
+// Create input elements for username and token
+ var usernameInput = document.createElement('input');
+ usernameInput.type = 'hidden';
+ usernameInput.name = 'username';
+ usernameInput.value = response.data.username;
+
+ var tokenInput = document.createElement('input');
+ tokenInput.type = 'hidden';
+ tokenInput.name = 'token';
+ tokenInput.value = response.data.token;
+
+// Append input elements to the form
+ form.appendChild(usernameInput);
+ form.appendChild(tokenInput);
+
+// Append the form to the body
+ document.body.appendChild(form);
+
+// Submit the form
+ form.submit();
+
} else {
}
@@ -603,3 +681,415 @@ app.controller('phpMyAdmin', function ($scope, $http, $window) {
}
});
+
+
+app.controller('Mysqlmanager', function ($scope, $http, $compile, $window, $timeout) {
+ $scope.cyberPanelLoading = false;
+ $scope.mysql_status = 'test';
+ $scope.uptime = '—';
+ $scope.connections = '—';
+ $scope.Slow_queries = '—';
+ $scope.processes = [];
+
+
+ $scope.getstatus = function () {
+
+ $scope.cyberPanelLoading = true;
+
+ url = "/dataBases/getMysqlstatus?t=" + (Date.now ? Date.now() : new Date().getTime());
+
+ var data = {};
+
+ var config = {
+ headers: {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+
+ $http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
+
+
+ function ListInitialDatas(response) {
+ $scope.cyberPanelLoading = false;
+ var data = response.data;
+ if (typeof data === 'string') {
+ try {
+ data = JSON.parse(data);
+ } catch (e) {
+ $scope.uptime = $scope.connections = $scope.Slow_queries = '—';
+ $scope.processes = [];
+ new PNotify({ title: 'Error!', text: 'Invalid response from server.', type: 'error' });
+ return;
+ }
+ }
+ if (data && data.status === 1) {
+ $scope.uptime = data.uptime || '—';
+ $scope.connections = data.connections != null ? data.connections : '—';
+ $scope.Slow_queries = data.Slow_queries != null ? data.Slow_queries : '—';
+ try {
+ $scope.processes = typeof data.processes === 'string' ? JSON.parse(data.processes || '[]') : (data.processes || []);
+ } catch (e) {
+ $scope.processes = [];
+ }
+ if (typeof $scope.showStatus === 'function') {
+ $timeout($scope.showStatus, 3000);
+ }
+
+ new PNotify({
+ title: 'Success',
+ text: 'Successfully Fetched',
+ type: 'success'
+ });
+ } else {
+ new PNotify({
+ title: 'Error!',
+ text: (data && data.error_message) || 'Could not load MySQL status.',
+ type: 'error'
+ });
+ }
+
+ }
+
+ function cantLoadInitialDatas(response) {
+ $scope.cyberPanelLoading = false;
+ $scope.uptime = '—';
+ $scope.connections = '—';
+ $scope.Slow_queries = '—';
+ $scope.processes = [];
+ var msg = 'Cannot load MySQL status.';
+ if (response && response.status) {
+ msg = 'Request failed: ' + response.status + (response.statusText ? ' ' + response.statusText : '');
+ }
+ if (response && response.data) {
+ if (typeof response.data === 'string' && response.data.length < 200) {
+ msg = response.data;
+ } else if (response.data.error_message) {
+ msg = response.data.error_message;
+ }
+ }
+ new PNotify({
+ title: 'Error!',
+ text: msg,
+ type: 'error'
+ });
+ }
+
+ }
+
+ $scope.refreshProcesses = function () {
+ var icon = document.querySelector('.refresh-btn i');
+ if (icon) {
+ icon.style.animation = 'spin 1s linear';
+ setTimeout(function () { icon.style.animation = ''; }, 1000);
+ }
+ $scope.getstatus();
+ };
+
+ $scope.getstatus();
+});
+
+
+app.controller('OptimizeMysql', function ($scope, $http) {
+ $scope.cyberPanelLoading = true;
+
+ $scope.generateRecommendations = function () {
+ $scope.cyberhosting = false;
+ url = "/dataBases/generateRecommendations";
+
+ var data = {
+ detectedRam: $("#detectedRam").text()
+ };
+
+ var config = {
+ headers: {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data, config).then(ListInitialData, cantLoadInitialData);
+
+
+ function ListInitialData(response) {
+ $scope.cyberhosting = true;
+ if (response.data.status === 1) {
+ $scope.suggestedContent = response.data.generatedConf;
+
+ } else {
+ new PNotify({
+ title: 'Error!',
+ text: response.data.error_message,
+ type: 'error'
+ });
+ }
+
+ }
+
+ function cantLoadInitialData(response) {
+ $scope.cyberhosting = true;
+ new PNotify({
+ title: 'Error!',
+ text: 'Could not connect to server, please refresh this page.',
+ type: 'error'
+ });
+ }
+
+ };
+
+
+ $scope.applyMySQLChanges = function () {
+ $scope.cyberhosting = false;
+ url = "/dataBases/applyMySQLChanges";
+
+ var encodedContent = encodeURIComponent($scope.suggestedContent);
+
+ var data = {
+ suggestedContent: encodedContent
+ };
+
+ var config = {
+ headers: {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data, config).then(ListInitialData, cantLoadInitialData);
+
+
+ function ListInitialData(response) {
+ $scope.cyberhosting = true;
+ if (response.data.status === 1) {
+
+ new PNotify({
+ title: 'Success',
+ text: 'Changes successfully applied.',
+ type: 'success'
+ });
+
+
+ } else {
+ new PNotify({
+ title: 'Error!',
+ text: response.data.error_message,
+ type: 'error'
+ });
+ }
+
+ }
+
+ function cantLoadInitialData(response) {
+ $scope.cyberhosting = true;
+ new PNotify({
+ title: 'Error!',
+ text: 'Could not connect to server, please refresh this page.',
+ type: 'error'
+ });
+ }
+
+ };
+
+
+ $scope.restartMySQL = function () {
+ $scope.cyberPanelLoading = false;
+
+ url = "/dataBases/restartMySQL";
+
+ var data = {};
+
+ var config = {
+ headers: {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+
+ $http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
+
+
+ function ListInitialDatas(response) {
+ $scope.cyberPanelLoading = true;
+ if (response.data.status === 1) {
+ new PNotify({
+ title: 'Success',
+ text: 'Successfully Done',
+ type: 'success'
+ });
+ } else {
+ new PNotify({
+ title: 'Error!',
+ text: response.data.error_message,
+ type: 'error'
+ });
+ }
+
+ }
+
+ function cantLoadInitialData(response) {
+ $scope.cyberhosting = true;
+ new PNotify({
+ title: 'Error!',
+ text: 'Could not connect to server, please refresh this page.',
+ type: 'error'
+ });
+ }
+ }
+})
+
+
+app.controller('mysqlupdate', function ($scope, $http, $timeout) {
+ $scope.cyberPanelLoading = true;
+ $scope.dbLoading = true;
+ $scope.modeSecInstallBox = true;
+ $scope.modsecLoading = true;
+ $scope.failedToStartInallation = true;
+ $scope.couldNotConnect = true;
+ $scope.modSecSuccessfullyInstalled = true;
+ $scope.installationFailed = true;
+
+ $scope.Upgardemysql = function () {
+ $scope.dbLoading = false;
+ $scope.installform = true;
+ $scope.modSecNotifyBox = true;
+ $scope.modeSecInstallBox = false;
+ $scope.modsecLoading = false;
+ $scope.failedToStartInallation = true;
+ $scope.couldNotConnect = true;
+ $scope.modSecSuccessfullyInstalled = true;
+ $scope.installationFailed = true;
+
+
+ url = "/dataBases/upgrademysqlnow";
+
+ var data = {
+ mysqlversion: $scope.version
+ };
+
+ var config = {
+ headers: {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+ $http.post(url, data, config).then(ListInitialData, cantLoadInitialData);
+
+
+ function ListInitialData(response) {
+ $scope.cyberhosting = true;
+ if (response.data.status === 1) {
+ $scope.modSecNotifyBox = true;
+ $scope.modeSecInstallBox = false;
+ $scope.modsecLoading = false;
+ $scope.failedToStartInallation = true;
+ $scope.couldNotConnect = true;
+ $scope.modSecSuccessfullyInstalled = true;
+ $scope.installationFailed = true;
+
+ $scope.statusfile = response.data.tempStatusPath
+
+ $timeout(getRequestStatus, 1000);
+
+ } else {
+ $scope.errorMessage = response.data.error_message;
+
+ $scope.modSecNotifyBox = false;
+ $scope.modeSecInstallBox = true;
+ $scope.modsecLoading = true;
+ $scope.failedToStartInallation = false;
+ $scope.couldNotConnect = true;
+ $scope.modSecSuccessfullyInstalled = true;
+ }
+
+ }
+
+ function cantLoadInitialData(response) {
+ $scope.cyberhosting = true;
+ new PNotify({
+ title: 'Error!',
+ text: 'Could not connect to server, please refresh this page.',
+ type: 'error'
+ });
+ }
+ }
+
+
+ function getRequestStatus() {
+
+ $scope.modSecNotifyBox = true;
+ $scope.modeSecInstallBox = false;
+ $scope.modsecLoading = false;
+ $scope.failedToStartInallation = true;
+ $scope.couldNotConnect = true;
+ $scope.modSecSuccessfullyInstalled = true;
+ $scope.installationFailed = true;
+
+ url = "/dataBases/upgrademysqlstatus";
+
+ var data = {
+ statusfile: $scope.statusfile
+ };
+
+ var config = {
+ headers: {
+ 'X-CSRFToken': getCookie('csrftoken')
+ }
+ };
+
+
+ $http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
+
+
+ function ListInitialDatas(response) {
+
+
+ if (response.data.abort === 0) {
+
+ $scope.modSecNotifyBox = true;
+ $scope.modeSecInstallBox = false;
+ $scope.modsecLoading = false;
+ $scope.failedToStartInallation = true;
+ $scope.couldNotConnect = true;
+ $scope.modSecSuccessfullyInstalled = true;
+ $scope.installationFailed = true;
+
+ $scope.requestData = response.data.requestStatus;
+ $timeout(getRequestStatus, 1000);
+ } else {
+ // Notifications
+ $timeout.cancel();
+ $scope.modSecNotifyBox = false;
+ $scope.modeSecInstallBox = false;
+ $scope.modsecLoading = true;
+ $scope.failedToStartInallation = true;
+ $scope.couldNotConnect = true;
+
+ $scope.requestData = response.data.requestStatus;
+
+ if (response.data.installed === 0) {
+ $scope.installationFailed = false;
+ $scope.errorMessage = response.data.error_message;
+ } else {
+ $scope.modSecSuccessfullyInstalled = false;
+ $timeout(function () {
+ $window.location.reload();
+ }, 3000);
+ }
+
+ }
+
+ }
+
+ function cantLoadInitialDatas(response) {
+
+ $scope.modSecNotifyBox = false;
+ $scope.modeSecInstallBox = false;
+ $scope.modsecLoading = true;
+ $scope.failedToStartInallation = true;
+ $scope.couldNotConnect = false;
+ $scope.modSecSuccessfullyInstalled = true;
+ $scope.installationFailed = true;
+
+
+ }
+
+ }
+});
\ No newline at end of file
diff --git a/public/static/websiteFunctions/websiteFunctions.js b/public/static/websiteFunctions/websiteFunctions.js
index 060b8a7e1..ab881df98 100644
--- a/public/static/websiteFunctions/websiteFunctions.js
+++ b/public/static/websiteFunctions/websiteFunctions.js
@@ -10765,7 +10765,7 @@ app.controller('modifyWebsitesController', ['$scope', '$http', function ($scope,
// Load home directories on page load
$scope.loadHomeDirectories = function() {
- $http.post('/userManagement/getUserHomeDirectories/', {})
+ $http.post('/users/getUserHomeDirectories', {})
.then(function(response) {
if (response.data.status === 1) {
$scope.homeDirectories = response.data.directories;
diff --git a/static/databases/databases.js b/static/databases/databases.js
index 0c5bbb12e..8dd93d53c 100644
--- a/static/databases/databases.js
+++ b/static/databases/databases.js
@@ -2,6 +2,8 @@
* Created by usman on 8/6/17.
*/
+/* Ensure we register controllers on the CyberCP app (avoids ctrlreg if load order differs) */
+var app = (typeof window.app !== 'undefined' && window.app) ? window.app : angular.module('CyberCP');
/* Java script code to create database */
app.controller('createDatabase', function ($scope, $http) {
@@ -683,14 +685,18 @@ app.controller('phpMyAdmin', function ($scope, $http, $window) {
app.controller('Mysqlmanager', function ($scope, $http, $compile, $window, $timeout) {
$scope.cyberPanelLoading = false;
- $scope.mysql_status = 'test'
+ $scope.mysql_status = 'test';
+ $scope.uptime = '—';
+ $scope.connections = '—';
+ $scope.Slow_queries = '—';
+ $scope.processes = [];
$scope.getstatus = function () {
$scope.cyberPanelLoading = true;
- url = "/dataBases/getMysqlstatus";
+ url = "/dataBases/getMysqlstatus?t=" + (Date.now ? Date.now() : new Date().getTime());
var data = {};
@@ -706,12 +712,29 @@ app.controller('Mysqlmanager', function ($scope, $http, $compile, $window, $time
function ListInitialDatas(response) {
$scope.cyberPanelLoading = false;
- if (response.data.status === 1) {
- $scope.uptime = response.data.uptime;
- $scope.connections = response.data.connections;
- $scope.Slow_queries = response.data.Slow_queries;
- $scope.processes = JSON.parse(response.data.processes);
- $timeout($scope.showStatus, 3000);
+ var data = response.data;
+ if (typeof data === 'string') {
+ try {
+ data = JSON.parse(data);
+ } catch (e) {
+ $scope.uptime = $scope.connections = $scope.Slow_queries = '—';
+ $scope.processes = [];
+ new PNotify({ title: 'Error!', text: 'Invalid response from server.', type: 'error' });
+ return;
+ }
+ }
+ if (data && data.status === 1) {
+ $scope.uptime = data.uptime || '—';
+ $scope.connections = data.connections != null ? data.connections : '—';
+ $scope.Slow_queries = data.Slow_queries != null ? data.Slow_queries : '—';
+ try {
+ $scope.processes = typeof data.processes === 'string' ? JSON.parse(data.processes || '[]') : (data.processes || []);
+ } catch (e) {
+ $scope.processes = [];
+ }
+ if (typeof $scope.showStatus === 'function') {
+ $timeout($scope.showStatus, 3000);
+ }
new PNotify({
title: 'Success',
@@ -721,7 +744,7 @@ app.controller('Mysqlmanager', function ($scope, $http, $compile, $window, $time
} else {
new PNotify({
title: 'Error!',
- text: response.data.error_message,
+ text: (data && data.error_message) || 'Could not load MySQL status.',
type: 'error'
});
}
@@ -730,15 +753,39 @@ app.controller('Mysqlmanager', function ($scope, $http, $compile, $window, $time
function cantLoadInitialDatas(response) {
$scope.cyberPanelLoading = false;
+ $scope.uptime = '—';
+ $scope.connections = '—';
+ $scope.Slow_queries = '—';
+ $scope.processes = [];
+ var msg = 'Cannot load MySQL status.';
+ if (response && response.status) {
+ msg = 'Request failed: ' + response.status + (response.statusText ? ' ' + response.statusText : '');
+ }
+ if (response && response.data) {
+ if (typeof response.data === 'string' && response.data.length < 200) {
+ msg = response.data;
+ } else if (response.data.error_message) {
+ msg = response.data.error_message;
+ }
+ }
new PNotify({
title: 'Error!',
- text: "cannot load",
+ text: msg,
type: 'error'
});
}
}
+ $scope.refreshProcesses = function () {
+ var icon = document.querySelector('.refresh-btn i');
+ if (icon) {
+ icon.style.animation = 'spin 1s linear';
+ setTimeout(function () { icon.style.animation = ''; }, 1000);
+ }
+ $scope.getstatus();
+ };
+
$scope.getstatus();
});
diff --git a/to-do/DEPLOY-BEFORE-PUSH-V2.5.5-DEV.md b/to-do/DEPLOY-BEFORE-PUSH-V2.5.5-DEV.md
new file mode 100644
index 000000000..60ebf62c2
--- /dev/null
+++ b/to-do/DEPLOY-BEFORE-PUSH-V2.5.5-DEV.md
@@ -0,0 +1,26 @@
+# Deploy Locally Before Push (v2.5.5-dev)
+
+## Rule
+**Always deploy to the local CyberPanel installation before pushing to v2.5.5-dev.**
+
+When deploying and pushing changes:
+
+1. **First: Deploy locally**
+ Copy all modified/relevant files from the repo to `/usr/local/CyberCP`, preserving directory structure.
+
+2. **Then: Commit and push**
+ Stage the same files, commit (author: `master3395`), and push to `origin v2.5.5-dev`.
+
+## Order
+1. Deploy → 2. Commit → 3. Push
+
+Never push to v2.5.5-dev without deploying to `/usr/local/CyberCP` first.
+
+## Example
+```bash
+# 1. Deploy
+cp /home/cyberpanel-repo/path/to/file /usr/local/CyberCP/path/to/
+
+# 2. Commit and push
+cd /home/cyberpanel-repo && git add ... && git commit -m "..." --author="master3395 " && git push origin v2.5.5-dev
+```
diff --git a/to-do/DEPLOY-MYSQL-MANAGER-TO-SERVER.md b/to-do/DEPLOY-MYSQL-MANAGER-TO-SERVER.md
new file mode 100644
index 000000000..beca2ceca
--- /dev/null
+++ b/to-do/DEPLOY-MYSQL-MANAGER-TO-SERVER.md
@@ -0,0 +1,53 @@
+# Deploy MySQL Manager fixes to the server (e.g. 207.180.193.210)
+
+## Why you still see no data
+
+- The URL **https://207.180.193.210:2087** is the **remote server** (or your server’s public IP). It is **not** “localhost.”
+- Our earlier deploy commands ran on the machine where the repo lives. If that machine is **not** the one serving 207.180.193.210, then the panel you open in the browser is still running the **old** code and old `databases.js`.
+- Seeing **`{$ Slow_queries $}`** (literal text) and empty processes means the **Mysqlmanager** controller or the updated JS is not running on the server that serves that URL.
+
+## Fix: run the deploy on the server that serves 207.180.193.210
+
+You must copy the updated files into CyberPanel **on the same machine** that serves https://207.180.193.210:2087 (i.e. where `/usr/local/CyberCP` is used by the panel).
+
+### Option A – You have the repo on that server (e.g. at `/home/cyberpanel-repo`)
+
+SSH to **207.180.193.210** (or the host that serves that IP) and run:
+
+```bash
+# Path to repo on THAT server (change if different)
+REPO=/home/cyberpanel-repo
+
+cp "$REPO/plogical/mysqlUtilities.py" /usr/local/CyberCP/plogical/
+cp "$REPO/databases/views.py" /usr/local/CyberCP/databases/
+cp "$REPO/databases/static/databases/databases.js" /usr/local/CyberCP/databases/static/databases/
+cp "$REPO/static/databases/databases.js" /usr/local/CyberCP/static/databases/
+# LiteSpeed serves /static/ from public/static/ – must deploy here or the browser gets the old file
+mkdir -p /usr/local/CyberCP/public/static/databases
+cp "$REPO/static/databases/databases.js" /usr/local/CyberCP/public/static/databases/
+
+# Restart panel so changes are used
+systemctl restart lscpd
+
+echo "MySQL Manager deploy done. Hard-refresh the MySQL Manager page (Ctrl+Shift+R)."
+```
+
+### Option B – Repo is only on another machine (e.g. your dev box)
+
+1. Copy the **four files** from the machine that has the repo to **207.180.193.210** (e.g. with `scp` or `rsync`):
+ - `plogical/mysqlUtilities.py`
+ - `databases/views.py`
+ - `databases/static/databases/databases.js`
+ - `static/databases/databases.js`
+
+2. On **207.180.193.210**, run the same `cp` commands as in Option A, using the paths where you put those files instead of `$REPO`.
+
+3. Restart the panel:
+ `systemctl restart lscpd`
+
+### After deploy
+
+- Open **https://207.180.193.210:2087/dataBases/MysqlManager**
+- Do a **hard refresh**: **Ctrl+Shift+R** (or Cmd+Shift+R on Mac) so the browser doesn’t use cached `databases.js`.
+
+If you still see no data, open the browser **Developer Tools (F12) → Console** and note any red errors (e.g. `ctrlreg` or 404 for `databases.js`), then share that message.
diff --git a/userManagment/homeDirectoryViews.py b/userManagment/homeDirectoryViews.py
index af0f71070..96f1403d4 100644
--- a/userManagment/homeDirectoryViews.py
+++ b/userManagment/homeDirectoryViews.py
@@ -169,7 +169,7 @@ def getHomeDirectoryStats(request):
return JsonResponse({'status': 0, 'error_message': str(e)})
def getUserHomeDirectories(request):
- """Get available home directories for user creation"""
+ """Get available home directories for user creation. Returns empty list if tables do not exist."""
try:
userID = request.session['userID']
currentACL = ACLManager.loadedACL(userID)
@@ -177,7 +177,7 @@ def getUserHomeDirectories(request):
if currentACL['admin'] != 1 and currentACL['createNewUser'] != 1:
return JsonResponse({'status': 0, 'error_message': 'Unauthorized access'})
- # Get active home directories
+ # Get active home directories (tables home_directories / user_home_mappings may not exist yet)
home_dirs = HomeDirectory.objects.filter(is_active=True).order_by('name')
directories = []
@@ -196,7 +196,8 @@ def getUserHomeDirectories(request):
except Exception as e:
logging.CyberCPLogFileWriter.writeToFile(f"Error getting user home directories: {str(e)}")
- return JsonResponse({'status': 0, 'error_message': str(e)})
+ # If tables don't exist (e.g. user_home_mappings), return empty list so Modify Website still works
+ return JsonResponse({'status': 1, 'directories': []})
def migrateUser(request):
"""Migrate user to different home directory"""
diff --git a/userManagment/templates/userManagment/userMigration.html b/userManagment/templates/userManagment/userMigration.html
index a2ac444ca..2b924f2d0 100644
--- a/userManagment/templates/userManagment/userMigration.html
+++ b/userManagment/templates/userManagment/userMigration.html
@@ -95,7 +95,7 @@ function loadUsers() {
function loadHomeDirectories() {
$.ajax({
- url: '/userManagement/getUserHomeDirectories/',
+ url: '/users/getUserHomeDirectories',
type: 'POST',
data: JSON.stringify({}),
contentType: 'application/json',
diff --git a/websiteFunctions/website.py b/websiteFunctions/website.py
index 0f004f2f3..b2e0d2e0e 100644
--- a/websiteFunctions/website.py
+++ b/websiteFunctions/website.py
@@ -3592,10 +3592,14 @@ context /cyberpanel_suspension_page.html {
currentPack = modifyWeb.package.packageName
owner = modifyWeb.admin.userName
- # Get current home directory information
- from userManagment.homeDirectoryUtils import HomeDirectoryUtils
- current_home = HomeDirectoryUtils.getUserHomeDirectoryObject(owner)
- currentHomeDirectory = current_home.name if current_home else 'Default'
+ # Get current home directory information (optional: tables may not exist yet)
+ currentHomeDirectory = 'Default'
+ try:
+ from userManagment.homeDirectoryUtils import HomeDirectoryUtils
+ current_home = HomeDirectoryUtils.getUserHomeDirectoryObject(owner)
+ currentHomeDirectory = current_home.name if current_home else 'Default'
+ except Exception:
+ pass
data_ret = {'status': 1, 'modifyStatus': 1, 'error_message': "None", "adminEmail": email,
"packages": json_data, "current_pack": currentPack, "adminNames": admin_data,
|