From b727c237d48e2eea70be8e4ac5a299e38c5f8c31 Mon Sep 17 00:00:00 2001 From: Master3395 Date: Fri, 19 Sep 2025 01:09:48 +0200 Subject: [PATCH] Implement disk usage refresh feature for email accounts. Add a new endpoint and corresponding view to refresh disk usage, ensuring accurate display in the UI. Update JavaScript and HTML templates to support the new functionality, enhancing user experience with real-time updates. Refactor disk usage calculation for improved accuracy and error handling. --- faq.sh | 115 ------------------ mailServer/mailserverManager.py | 94 +++++++++++++- mailServer/static/mailServer/mailServer.js | 57 +++++++++ .../templates/mailServer/listEmails.html | 4 + mailServer/urls.py | 3 + mailServer/views.py | 9 ++ plogical/virtualHostUtilities.py | 28 ++++- 7 files changed, 190 insertions(+), 120 deletions(-) delete mode 100644 faq.sh diff --git a/faq.sh b/faq.sh deleted file mode 100644 index 40f5dd8ec..000000000 --- a/faq.sh +++ /dev/null @@ -1,115 +0,0 @@ -#!/bin/bash - - -RED='\033[0;31m' -GREEN='\033[0;32m' -BLUE='\033[0;34m' -PURPLE='\033[0;35m' -NC='\033[0m' # No Color - -#${RED}text${NC} -#${GREEN} ${BLUE} - -echo -e "Use Up/Down Arrow key to navigate\n" -echo -e "press ${RED}q${NC} to exit\n" -echo -e "Frequently Asked Question - -${PURPLE}1.${NC} How to reset CyberPanel admin password? - -execute command ${RED}adminPass YOUR_NEW_PASSWORD${NC} - -${BLUE}------------------------------------------------------------${NC} - -${PURPLE}2.${NC} How to reset LiteSpeed WebAdmin Console user/password ? - -execute command ${RED}/usr/local/lsws/admin/misc/admpass.sh${NC} - -${BLUE}------------------------------------------------------------${NC} - -${PURPLE}3.${NC} How to access LiteSpeed webadmin console ? - -Please check this post: ${GREEN}https://community.cyberpanel.net/c/support/55${NC} - -${BLUE}------------------------------------------------------------${NC} - -${PURPLE}4.${NC} What is MariaDB root password ? - -execute command ${RED}cat /etc/cyberpanel/mysqlPassword${NC} will show you the root password - -${BLUE}------------------------------------------------------------${NC} - -${PURPLE}5.${NC} Can I change MariaDB root passwod ? - -Yes , but after you changed , please make sure you have updated the password in following 2 files as well - -${RED}/etc/cyberpanel/mysqlPassword${NC} - -${RED}/usr/local/CyberCP/CyberCP/settings.py${NC} - -otherwise CyberPanel will not have access to database. - -${BLUE}------------------------------------------------------------${NC} - -${PURPLE}6.${NC} How to raise upload limit for cyberpanel's phpMyAdmin and File Manager? - -edit file ${RED}/usr/local/lsws/lsphp83/etc/php.ini${NC} for CentOS or openEuler - -${RED}/usr/local/lsws/lsphp83/etc/php/8.3/litespeed/php.ini${NC} for Ubuntu - -find 2 configurations: - -${RED}post_max_size${NC} and ${RED}upload_max_filesize${NC} , change from to higher number, e.g. ${RED}100M${NC} (don't miss the M) - -and then run ${RED}pkill lsphp${NC} to kill all current php process for new configuration to take effect. - -${BLUE}------------------------------------------------------------${NC} - -${PURPLE}7.${NC} How to add more IPs to my website(s) ? - -For OpenLiteSpeed, please check this post: ${GREEN}https://community.cyberpanel.net/c/support/55${NC} - -For LiteSpeed Enterprise, please check this post: ${GREEN}https://community.cyberpanel.net/c/support/55${NC} - -${BLUE}------------------------------------------------------------${NC} - -${PURPLE}8.${NC} How to remove 8090 port in CyberPanel URL ? - -Please check this post ${GREEN}https://blog.cyberpanel.net/2018/12/25/how-to-remove-port-8090-from-cyberpanel/${NC} - -${BLUE}------------------------------------------------------------${NC} - -${PURPLE}9.${NC} How to enable Auto-Index for my site ? - -Please check this post ${GREEN}https://community.cyberpanel.net/c/support/55${NC} - -${BLUE}------------------------------------------------------------${NC} - -${PURPLE}10.${NC} How to add additional headers for my website ? - -Please check this post ${GREEN}https://openlitespeed.org/kb/how-to-set-up-custom-headers/${NC} - -${BLUE}------------------------------------------------------------${NC} - -${PURPLE}11.${NC} How to mimic Apache deny/allow directive ? - -Please check this post ${GREEN}https://openlitespeed.org/kb/access-control/${NC} - -${BLUE}------------------------------------------------------------${NC} - -${PURPLE}12.${NC} How to fix max_allowed_packet error ? - -You may see this error when your PHP script requires a larger packet size - -add following code into ${RED}/etc/my.cnf${NC} - -${GREEN}[mysqld] -max_allowed_packet=500M${NC} - -and then restart MariaDB by command ${RED}systemctl restart mariadb${NC} - -${BLUE}------------------------------------------------------------${NC} - -${PURPLE}13.${NC} How to enable PHP error log ? - -Please check this post ${GREEN}https://community.cyberpanel.net/c/support/55${NC} -" \ No newline at end of file diff --git a/mailServer/mailserverManager.py b/mailServer/mailserverManager.py index f65f2c452..4a48ae1d5 100644 --- a/mailServer/mailserverManager.py +++ b/mailServer/mailserverManager.py @@ -216,7 +216,20 @@ class MailServerManager(multi.Thread): numberofEmails = 0 duration = '0m' - dic = {'id': count, 'email': items.email, 'DiskUsage': '%sMB' % items.DiskUsage, 'numberofEmails': numberofEmails, 'duration': duration} + # Fix disk usage display - ensure it shows proper format + disk_usage = items.DiskUsage + if not disk_usage or disk_usage == '0' or disk_usage == '0MB': + disk_usage = '0 MB' + elif not disk_usage.endswith('MB') and not disk_usage.endswith('GB') and not disk_usage.endswith('KB'): + # If it's just a number, assume it's in MB + try: + # Try to convert to number and add MB suffix + num_value = float(disk_usage) + disk_usage = f"{num_value:.1f} MB" + except: + disk_usage = '0 MB' + + dic = {'id': count, 'email': items.email, 'DiskUsage': disk_usage, 'numberofEmails': numberofEmails, 'duration': duration} count = count + 1 if checker == 0: @@ -576,8 +589,24 @@ class MailServerManager(multi.Thread): checker = 0 for items in records: + # Fix disk usage display - ensure it shows proper format + disk_usage = items.DiskUsage + if not disk_usage or disk_usage == '0' or disk_usage == '0MB': + disk_usage = '0 MB' + elif not disk_usage.endswith('MB') and not disk_usage.endswith('GB') and not disk_usage.endswith('KB'): + # If it's just a number, assume it's in MB + try: + # Try to convert to number and add MB suffix + num_value = float(disk_usage) + disk_usage = f"{num_value:.1f} MB" + except: + disk_usage = '0 MB' + elif disk_usage.endswith('MB'): + # Ensure proper formatting with space + disk_usage = disk_usage.replace('MB', ' MB') + dic = {'email': items.email, - 'DiskUsage': '%sMB' % items.DiskUsage.rstrip('MB') + 'DiskUsage': disk_usage } if checker == 0: @@ -2001,6 +2030,67 @@ protocol sieve { json_data = json.dumps(data_ret) return HttpResponse(json_data) + def refreshEmailDiskUsage(self): + """Refresh disk usage for all email accounts in a domain""" + try: + userID = self.request.session['userID'] + currentACL = ACLManager.loadedACL(userID) + + if ACLManager.currentContextPermission(currentACL, 'listEmails') == 0: + return ACLManager.loadErrorJson('refreshStatus', 0) + + data = json.loads(self.request.body) + domain = data['domain'] + + admin = Administrator.objects.get(pk=userID) + if ACLManager.checkOwnership(domain, admin, currentACL) == 1: + pass + else: + return ACLManager.loadErrorJson() + + try: + emailDomain = Domains.objects.get(domain=domain) + except: + final_dic = {'status': 0, 'refreshStatus': 0, 'error_message': "No email accounts exist for this domain!"} + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + # Refresh disk usage for all emails in this domain + emails = emailDomain.eusers_set.all() + updated_count = 0 + + for email in emails: + try: + # Calculate the email path + emailPath = '/home/vmail/%s/%s' % (domain, email.email.split('@')[0]) + + # Get updated disk usage + new_disk_usage = virtualHostUtilities.getDiskUsageofPath(emailPath) + + # Update the database + email.DiskUsage = new_disk_usage + email.save() + updated_count += 1 + + except Exception as e: + logging.CyberCPLogFileWriter.writeToFile(f"Error updating disk usage for {email.email}: {str(e)}") + continue + + final_dic = { + 'status': 1, + 'refreshStatus': 1, + 'error_message': "None", + 'updated_count': updated_count, + 'message': f"Successfully updated disk usage for {updated_count} email accounts" + } + final_json = json.dumps(final_dic) + return HttpResponse(final_json) + + except BaseException as msg: + data_ret = {'status': 0, 'refreshStatus': 0, 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + def main(): parser = argparse.ArgumentParser(description='CyberPanel') diff --git a/mailServer/static/mailServer/mailServer.js b/mailServer/static/mailServer/mailServer.js index cc9b2b939..6b6695052 100644 --- a/mailServer/static/mailServer/mailServer.js +++ b/mailServer/static/mailServer/mailServer.js @@ -1345,6 +1345,63 @@ app.controller('listEmails', function ($scope, $http) { }; + + $scope.refreshDiskUsage = function () { + if (!$scope.selectedDomain) { + new PNotify({ + title: 'Warning!', + text: 'Please select a domain first.', + type: 'warning' + }); + return; + } + + $scope.cyberpanelLoading = true; + + var url = "/email/refreshEmailDiskUsage"; + + var data = { + domain: $scope.selectedDomain, + }; + + var config = { + headers: { + 'X-CSRFToken': getCookie('csrftoken') + } + }; + + $http.post(url, data, config).then(refreshSuccess, refreshError); + + function refreshSuccess(response) { + $scope.cyberpanelLoading = false; + + if (response.data.refreshStatus === 1) { + // Refresh the email list to show updated disk usage + $scope.populateCurrentRecords(); + + new PNotify({ + title: 'Success!', + text: response.data.message || 'Disk usage refreshed successfully.', + type: 'success' + }); + } else { + new PNotify({ + title: 'Error!', + text: response.data.error_message || 'Failed to refresh disk usage.', + type: 'error' + }); + } + } + + function refreshError(response) { + $scope.cyberpanelLoading = false; + new PNotify({ + title: 'Error!', + text: 'Could not connect to server, please refresh this page.', + type: 'error' + }); + } + }; }); diff --git a/mailServer/templates/mailServer/listEmails.html b/mailServer/templates/mailServer/listEmails.html index 34743b5f0..a24efa73c 100644 --- a/mailServer/templates/mailServer/listEmails.html +++ b/mailServer/templates/mailServer/listEmails.html @@ -582,6 +582,10 @@ {% trans "Create Email" %} + {% trans "Debug Email Issues" %} diff --git a/mailServer/urls.py b/mailServer/urls.py index 91cd9aeeb..29d31a7d0 100644 --- a/mailServer/urls.py +++ b/mailServer/urls.py @@ -35,4 +35,7 @@ urlpatterns = [ ### email limits re_path(r'^EmailLimits$', views.EmailLimits, name='EmailLimits'), re_path(r'^SaveEmailLimitsNew$', views.SaveEmailLimitsNew, name='SaveEmailLimitsNew'), + + ### disk usage refresh + re_path(r'^refreshEmailDiskUsage$', views.refreshEmailDiskUsage, name='refreshEmailDiskUsage'), ] diff --git a/mailServer/views.py b/mailServer/views.py index 62f6ca9b8..579ed9076 100644 --- a/mailServer/views.py +++ b/mailServer/views.py @@ -262,5 +262,14 @@ def SaveEmailLimitsNew(request): json_data = json.dumps(data_ret) return HttpResponse(json_data) +def refreshEmailDiskUsage(request): + try: + msM = MailServerManager(request) + return msM.refreshEmailDiskUsage() + except KeyError as msg: + data_ret = {'refreshStatus': 0, 'error_message': str(msg)} + json_data = json.dumps(data_ret) + return HttpResponse(json_data) + diff --git a/plogical/virtualHostUtilities.py b/plogical/virtualHostUtilities.py index 59ba0bad1..d912a471b 100644 --- a/plogical/virtualHostUtilities.py +++ b/plogical/virtualHostUtilities.py @@ -1769,9 +1769,31 @@ local_name %s { @staticmethod def getDiskUsageofPath(path): try: - return subprocess.check_output('du -hs %s --block-size=1M' % (path), shell=True).decode("utf-8").split()[0] - except BaseException: - return '0MB' + # Check if path exists first + if not os.path.exists(path): + return '0 MB' + + # Use du command to get disk usage in MB + result = subprocess.check_output('du -sm %s' % (path), shell=True).decode("utf-8").strip() + + if result: + # Extract the number from the result (format: "123\t/path") + usage_mb = result.split('\t')[0] + try: + # Convert to float and format properly + usage_value = float(usage_mb) + if usage_value < 1: + return '0.1 MB' + else: + return f"{usage_value:.1f} MB" + except ValueError: + return '0 MB' + else: + return '0 MB' + except BaseException as e: + # Log the error for debugging + logging.CyberCPLogFileWriter.writeToFile(f"Error calculating disk usage for {path}: {str(e)}") + return '0 MB' @staticmethod def permissionControl(path):