Dashboard, user management, and FTP quota fixes for v2.5.5-dev

- base: Clickable insight cards (Users, Websites, WordPress, DBs, Emails, FTP)
- base: data-cfasync=false on scripts for Cloudflare Rocket Loader compatibility
- userManagment: createUser/modifyUser/createACL/apiAccess fixes, alert logic
- websiteFunctions: FTP quota management, createWebsite, ACLManager fix
This commit is contained in:
master3395
2026-01-30 20:34:29 +01:00
parent bbd2e1b89f
commit 63877fba66
11 changed files with 201 additions and 152 deletions

View File

@@ -132,6 +132,16 @@
cursor: pointer;
}
a.insight-link {
text-decoration: none;
color: inherit;
display: block;
}
a.insight-link:hover {
color: inherit;
}
.insight-card:hover {
transform: translateY(-5px);
box-shadow: 0 5px 20px rgba(91,95,207,0.1);
@@ -730,53 +740,53 @@
<div class="insights-section">
<h2 class="section-title">INSIGHTS</h2>
<div class="insights-grid">
<div class="insight-card">
<a href="{% url 'listUsers' %}" class="insight-card insight-link">
<div class="insight-icon">
<i class="fas fa-users"></i>
</div>
<div class="insight-value">{$ totalUsers || 0 $}</div>
<div class="insight-label">Users</div>
</div>
</a>
<div class="insight-card">
<a href="{% url 'listWebsites' %}" class="insight-card insight-link">
<div class="insight-icon">
<i class="fas fa-globe"></i>
</div>
<div class="insight-value">{$ totalSites || 0 $}</div>
<div class="insight-label">Websites</div>
</div>
</a>
<div class="insight-card">
<a href="{% url 'ListWPSites' %}" class="insight-card insight-link">
<div class="insight-icon" style="background: #5b87da;">
<i class="fab fa-wordpress"></i>
</div>
<div class="insight-value">{$ totalWPSites || 0 $}</div>
<div class="insight-label">WordPress</div>
</div>
</a>
<div class="insight-card">
<a href="{% url 'listDBs' %}" class="insight-card insight-link">
<div class="insight-icon">
<i class="fas fa-database"></i>
</div>
<div class="insight-value">{$ totalDBs || 0 $}</div>
<div class="insight-label">Databases</div>
</div>
</a>
<div class="insight-card">
<a href="{% url 'listEmails' %}" class="insight-card insight-link">
<div class="insight-icon">
<i class="fas fa-envelope"></i>
</div>
<div class="insight-value">{$ totalEmails || 0 $}</div>
<div class="insight-label">Emails</div>
</div>
</a>
<div class="insight-card">
<a href="{% url 'listFTPAccounts' %}" class="insight-card insight-link">
<div class="insight-icon">
<i class="fas fa-folder"></i>
</div>
<div class="insight-value">{$ totalFTPUsers || 0 $}</div>
<div class="insight-label">FTP Users</div>
</div>
</a>
</div>
</div>

View File

@@ -42,9 +42,9 @@
<!-- Chart.js -->
<script src="{% static 'baseTemplate/custom-js/chart.umd.min.js' %}?v={{ CP_VERSION }}"></script>
<!-- PNotify -->
<!-- PNotify (data-cfasync=false ensures it loads before controllers that use it) -->
<link rel="stylesheet" type="text/css" href="{% static 'baseTemplate/custom-js/pnotify.custom.min.css' %}?v={{ CP_VERSION }}">
<script src="{% static 'baseTemplate/custom-js/pnotify.custom.min.js' %}?v={{ CP_VERSION }}"></script>
<script src="{% static 'baseTemplate/custom-js/pnotify.custom.min.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
<!-- Select2 (required by FTP create account; load after jQuery; exclude from Rocket Loader to preserve order) -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/css/select2.min.css">
@@ -2178,22 +2178,22 @@
{% block content %}{% endblock %}
</div>
<!-- Additional Scripts -->
<script src="{% static 'packages/packages.js' %}?v={{ CP_VERSION }}"></script>
<script src="{% static 'websiteFunctions/websiteFunctions.js' %}?v={{ CP_VERSION }}"></script>
<script src="{% static 'userManagment/userManagment.js' %}?v={{ CP_VERSION }}"></script>
<script src="{% static 'databases/databases.js' %}?v={{ CP_VERSION }}"></script>
<script src="{% static 'dns/dns.js' %}?v={{ CP_VERSION }}"></script>
<script src="{% static 'mailServer/mailServer.js' %}?v={{ CP_VERSION }}"></script>
<!-- Additional Scripts (data-cfasync=false ensures controllers load before Angular compiles) -->
<script src="{% static 'packages/packages.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
<script src="{% static 'websiteFunctions/websiteFunctions.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
<script src="{% static 'userManagment/userManagment.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
<script src="{% static 'databases/databases.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
<script src="{% static 'dns/dns.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
<script src="{% static 'mailServer/mailServer.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
<script src="{% static 'ftp/ftp.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
<script src="{% static 'backup/backup.js' %}?v={{ CP_VERSION }}"></script>
<script src="{% static 'managePHP/managePHP.js' %}?v={{ CP_VERSION }}"></script>
<script src="{% static 'serverLogs/serverLogs.js' %}?v={{ CP_VERSION }}"></script>
<script src="{% static 'serverStatus/serverStatus.js' %}?v={{ CP_VERSION }}"></script>
<script src="{% static 'firewall/firewall.js' %}?v={{ CP_VERSION }}"></script>
<script src="{% static 'emailPremium/emailPremium.js' %}?v={{ CP_VERSION }}"></script>
<script src="{% static 'manageServices/manageServices.js' %}?v={{ CP_VERSION }}"></script>
<script src="{% static 'CLManager/CLManager.js' %}?v={{ CP_VERSION }}"></script>
<script src="{% static 'backup/backup.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
<script src="{% static 'managePHP/managePHP.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
<script src="{% static 'serverLogs/serverLogs.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
<script src="{% static 'serverStatus/serverStatus.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
<script src="{% static 'firewall/firewall.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
<script src="{% static 'emailPremium/emailPremium.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
<script src="{% static 'manageServices/manageServices.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
<script src="{% static 'CLManager/CLManager.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
<!-- Scripts -->
<script>

View File

@@ -2,6 +2,15 @@
* Created by usman on 8/5/17.
*/
/* Safe notification - use PNotify if available, else fallback to alert */
function safePNotify(opts) {
if (typeof PNotify !== 'undefined') {
new PNotify(opts);
} else {
var msg = (opts.title || '') + (opts.text ? ': ' + opts.text : '');
alert(msg || JSON.stringify(opts));
}
}
/* Java script code to create account */
app.controller('createUserCtr', function ($scope, $http) {
@@ -51,7 +60,7 @@ app.controller('createUserCtr', function ($scope, $http) {
$scope.acctsLimit = true;
$scope.webLimits = true;
$scope.userCreated = true;
$scope.userCreationFailed = true;
$scope.userCreationFailed = false; // false = don't show error alert on load
$scope.couldNotConnect = true;
$scope.userCreationLoading = true;
$scope.combinedLength = true;
@@ -60,20 +69,24 @@ app.controller('createUserCtr', function ($scope, $http) {
$scope.webLimits = false;
$scope.userCreated = true;
$scope.userCreationFailed = true;
$scope.userCreationFailed = false; // hide error until we know the result
$scope.couldNotConnect = true;
$scope.userCreationLoading = false;
$scope.combinedLength = true;
var firstName = $scope.firstName;
var lastName = $scope.lastName;
var firstName = $scope.firstName || '';
var lastName = $scope.lastName || '';
var email = $scope.email;
var selectedACL = $scope.selectedACL;
var websitesLimits = $scope.websitesLimits;
var userName = $scope.userName;
var password = $scope.password;
if (firstName.length + lastName.length > 20) {
$scope.combinedLength = false;
$scope.userCreationLoading = true;
return;
}
var url = "/users/submitUserCreation";
@@ -91,7 +104,8 @@ app.controller('createUserCtr', function ($scope, $http) {
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
'X-CSRFToken': getCookie('csrftoken'),
'Content-Type': 'application/json'
}
};
@@ -102,42 +116,31 @@ app.controller('createUserCtr', function ($scope, $http) {
if (response.data.createStatus == 1) {
$scope.userCreated = false;
$scope.userCreationFailed = true;
$scope.userCreated = false; // show success
$scope.userCreationFailed = false; // hide error
$scope.couldNotConnect = true;
$scope.userCreationLoading = true;
$scope.userName = userName;
} else {
$scope.acctsLimit = false;
$scope.webLimits = false;
$scope.userCreated = true;
$scope.userCreationFailed = false;
$scope.userCreationFailed = true; // true = show error alert
$scope.couldNotConnect = true;
$scope.userCreationLoading = true;
$scope.errorMessage = response.data.error_message;
$scope.errorMessage = (response.data && (response.data.error_message || response.data.message || response.data.errorMessage)) || 'Unknown error';
}
}
function cantLoadInitialDatas(response) {
$scope.acctsLimit = false;
$scope.webLimits = false;
$scope.userCreated = true;
$scope.userCreationFailed = true;
$scope.couldNotConnect = false;
$scope.userCreationFailed = false; // hide server error, show connection error instead
$scope.couldNotConnect = false; // show "Could not connect" message
$scope.userCreationLoading = true;
}
@@ -181,10 +184,10 @@ app.controller('modifyUser', function ($scope, $http) {
$scope.acctDetailsFetched = true;
$scope.userAccountsLimit = true;
$scope.userModified = true;
$scope.canotModifyUser = true;
$scope.canotModifyUser = false; // false = don't show error alert on load
$scope.couldNotConnect = true;
$scope.canotFetchDetails = true;
$scope.detailsFetched = true;
$scope.canotFetchDetails = false; // false = don't show fetch error on load
$scope.detailsFetched = false; // false = don't show "details loaded" on load
$scope.accountTypeView = true;
$scope.websitesLimit = true;
$scope.qrHidden = true;
@@ -716,7 +719,7 @@ app.controller('deleteUser', function ($scope, $http) {
app.controller('createACLCTRL', function ($scope, $http) {
$scope.aclCreated = true;
$scope.aclCreationFailed = true;
$scope.aclCreationFailed = false; // false = don't show error alert on load
$scope.couldNotConnect = true;
$scope.aclLoading = true;
@@ -887,14 +890,14 @@ app.controller('createACLCTRL', function ($scope, $http) {
$scope.aclLoading = true;
if (response.data.status === 1) {
new PNotify({
safePNotify({
title: 'Success!',
text: 'ACL Successfully created.',
type: 'success'
});
} else {
new PNotify({
safePNotify({
title: 'Error!',
text: response.data.errorMessage,
type: 'error'
@@ -909,7 +912,7 @@ app.controller('createACLCTRL', function ($scope, $http) {
$scope.aclLoading = false;
new PNotify({
safePNotify({
title: 'Error!',
text: 'Could not connect to server, please refresh this page.',
type: 'error'
@@ -1108,14 +1111,14 @@ app.controller('deleteACTCTRL', function ($scope, $http) {
$scope.aclLoading = true;
if (response.data.status === 1) {
new PNotify({
safePNotify({
title: 'Success!',
text: 'ACL Successfully deleted.',
type: 'success'
});
} else {
new PNotify({
safePNotify({
title: 'Error!',
text: response.data.errorMessage,
type: 'error'
@@ -1127,7 +1130,7 @@ app.controller('deleteACTCTRL', function ($scope, $http) {
function cantLoadInitialDatas(response) {
$scope.aclLoading = true;
new PNotify({
safePNotify({
title: 'Error!',
text: 'Could not connect to server, please refresh this page.',
type: 'error'
@@ -1171,7 +1174,7 @@ app.controller('modifyACLCtrl', function ($scope, $http) {
if (response.data.status === 1) {
new PNotify({
safePNotify({
title: 'Success!',
text: 'Current settings successfully fetched',
type: 'success'
@@ -1251,7 +1254,7 @@ app.controller('modifyACLCtrl', function ($scope, $http) {
$scope.mailServerSSL = Boolean(response.data.mailServerSSL);
} else {
new PNotify({
safePNotify({
title: 'Error!',
text: response.data.errorMessage,
type: 'error'
@@ -1264,7 +1267,7 @@ app.controller('modifyACLCtrl', function ($scope, $http) {
$scope.aclLoading = false;
new PNotify({
safePNotify({
title: 'Error!',
text: 'Could not connect to server, please refresh this page.',
type: 'error'
@@ -1366,14 +1369,14 @@ app.controller('modifyACLCtrl', function ($scope, $http) {
$scope.aclLoading = true;
if (response.data.status === 1) {
new PNotify({
safePNotify({
title: 'Success!',
text: 'ACL Successfully modified.',
type: 'success'
});
} else {
new PNotify({
safePNotify({
title: 'Error!',
text: response.data.errorMessage,
type: 'error'
@@ -1388,7 +1391,7 @@ app.controller('modifyACLCtrl', function ($scope, $http) {
$scope.aclLoading = false;
new PNotify({
safePNotify({
title: 'Error!',
text: 'Could not connect to server, please refresh this page.',
type: 'error'
@@ -1580,14 +1583,14 @@ app.controller('changeUserACLCTRL', function ($scope, $http) {
$scope.aclLoading = true;
if (response.data.status === 1) {
new PNotify({
safePNotify({
title: 'Success!',
text: 'ACL Successfully changed.',
type: 'success'
});
} else {
new PNotify({
safePNotify({
title: 'Error!',
text: response.data.errorMessage,
type: 'error'
@@ -1599,7 +1602,7 @@ app.controller('changeUserACLCTRL', function ($scope, $http) {
function cantLoadInitialDatas(response) {
$scope.aclLoading = true;
new PNotify({
safePNotify({
title: 'Error!',
text: 'Could not connect to server, please refresh this page.',
type: 'error'
@@ -1642,14 +1645,14 @@ app.controller('resellerCenterCTRL', function ($scope, $http) {
$scope.aclLoading = true;
if (response.data.status === 1) {
new PNotify({
safePNotify({
title: 'Success!',
text: 'Changes successfully applied!',
type: 'success'
});
} else {
new PNotify({
safePNotify({
title: 'Error!',
text: response.data.errorMessage,
type: 'error'
@@ -1661,7 +1664,7 @@ app.controller('resellerCenterCTRL', function ($scope, $http) {
function cantLoadInitialDatas(response) {
$scope.aclLoading = true;
new PNotify({
safePNotify({
title: 'Error!',
text: 'Could not connect to server, please refresh this page.',
type: 'error'
@@ -1711,14 +1714,14 @@ app.controller('apiAccessCTRL', function ($scope, $http) {
if (response.data.status === 1) {
$scope.apiAccessDropDown = true;
new PNotify({
safePNotify({
title: 'Success!',
text: 'Changes successfully applied!',
type: 'success'
});
} else {
new PNotify({
safePNotify({
title: 'Error!',
text: response.data.error_message,
type: 'error'
@@ -1730,7 +1733,7 @@ app.controller('apiAccessCTRL', function ($scope, $http) {
function cantLoadInitialDatas(response) {
$scope.cyberpanelLoading = true;
new PNotify({
safePNotify({
title: 'Error!',
text: 'Could not connect to server, please refresh this page.',
type: 'error'
@@ -1771,13 +1774,13 @@ app.controller('apiUsersCTRL', function ($scope, $http) {
$scope.apiUsers = response.data.users;
$scope.filteredUsers = response.data.users;
new PNotify({
safePNotify({
title: 'Success!',
text: 'API users loaded successfully',
type: 'success'
});
} else {
new PNotify({
safePNotify({
title: 'Error!',
text: response.data.error_message,
type: 'error'
@@ -1787,7 +1790,7 @@ app.controller('apiUsersCTRL', function ($scope, $http) {
function loadAPIUsersError(response) {
$scope.apiUsersLoading = true;
new PNotify({
safePNotify({
title: 'Error!',
text: 'Could not load API users. Please refresh the page.',
type: 'error'
@@ -1816,7 +1819,7 @@ app.controller('apiUsersCTRL', function ($scope, $http) {
};
$scope.viewUserDetails = function(user) {
new PNotify({
safePNotify({
title: 'User Details',
text: 'Username: ' + user.userName + '<br>' +
'Full Name: ' + user.firstName + ' ' + user.lastName + '<br>' +
@@ -1859,13 +1862,13 @@ app.controller('apiUsersCTRL', function ($scope, $http) {
});
$scope.filteredUsers = $scope.apiUsers;
new PNotify({
safePNotify({
title: 'Success!',
text: 'API access disabled for ' + response.data.accountUsername,
type: 'success'
});
} else {
new PNotify({
safePNotify({
title: 'Error!',
text: response.data.error_message,
type: 'error'
@@ -1875,7 +1878,7 @@ app.controller('apiUsersCTRL', function ($scope, $http) {
function disableAPIError(response) {
$scope.apiUsersLoading = true;
new PNotify({
safePNotify({
title: 'Error!',
text: 'Could not disable API access. Please try again.',
type: 'error'
@@ -1919,14 +1922,14 @@ app.controller('listTableUsers', function ($scope, $http) {
$scope.records = JSON.parse(response.data.data);
new PNotify({
safePNotify({
title: 'Success!',
text: 'Users successfully fetched!',
type: 'success'
});
} else {
new PNotify({
safePNotify({
title: 'Error!',
text: response.data.error_message,
type: 'error'
@@ -1937,7 +1940,7 @@ app.controller('listTableUsers', function ($scope, $http) {
function cantLoadInitialDatas(response) {
$scope.cyberpanelLoading = true;
new PNotify({
safePNotify({
title: 'Error!',
text: 'Could not connect to server, please refresh this page.',
type: 'error'
@@ -1977,7 +1980,7 @@ app.controller('listTableUsers', function ($scope, $http) {
if (response.data.deleteStatus === 1) {
$scope.populateCurrentRecords();
$('#deleteModal').modal('hide');
new PNotify({
safePNotify({
title: 'Success!',
text: 'Users successfully deleted!',
type: 'success'
@@ -1985,7 +1988,7 @@ app.controller('listTableUsers', function ($scope, $http) {
} else {
new PNotify({
safePNotify({
title: 'Error!',
text: response.data.error_message,
type: 'error'
@@ -1999,7 +2002,7 @@ app.controller('listTableUsers', function ($scope, $http) {
function cantLoadInitialDatas(response) {
$scope.cyberpanelLoading = false;
new PNotify({
safePNotify({
title: 'Error!',
text: 'Could not connect to server, please refresh this page.',
type: 'error'
@@ -2041,14 +2044,14 @@ app.controller('listTableUsers', function ($scope, $http) {
if (response.data.status === 1) {
$scope.populateCurrentRecords();
$('#editModal').modal('hide');
new PNotify({
safePNotify({
title: 'Success!',
text: 'Changes successfully applied!',
type: 'success'
});
} else {
new PNotify({
safePNotify({
title: 'Error!',
text: response.data.errorMessage,
type: 'error'
@@ -2059,7 +2062,7 @@ app.controller('listTableUsers', function ($scope, $http) {
}
function cantLoadInitialDatas(response) {
new PNotify({
safePNotify({
title: 'Error!',
text: 'Could not connect to server, please refresh this page.',
type: 'error'
@@ -2095,14 +2098,14 @@ app.controller('listTableUsers', function ($scope, $http) {
if (response.data.status === 1) {
$scope.populateCurrentRecords();
$('#editModal').modal('hide');
new PNotify({
safePNotify({
title: 'Success!',
text: 'ACL Successfully changed.',
type: 'success'
});
} else {
new PNotify({
safePNotify({
title: 'Error!',
text: response.data.errorMessage,
type: 'error'
@@ -2114,7 +2117,7 @@ app.controller('listTableUsers', function ($scope, $http) {
function cantLoadInitialDatas(response) {
$scope.aclLoading = true;
new PNotify({
safePNotify({
title: 'Error!',
text: 'Could not connect to server, please refresh this page.',
type: 'error'
@@ -2148,7 +2151,7 @@ app.controller('listTableUsers', function ($scope, $http) {
$scope.cyberpanelLoading = true;
if (response.data.status === 1) {
$scope.populateCurrentRecords();
new PNotify({
safePNotify({
title: 'Success!',
text: 'Action successfully started.',
type: 'success'
@@ -2156,7 +2159,7 @@ app.controller('listTableUsers', function ($scope, $http) {
} else {
new PNotify({
safePNotify({
title: 'Error!',
text: response.data.error_message,
type: 'error'
@@ -2170,7 +2173,7 @@ app.controller('listTableUsers', function ($scope, $http) {
function cantLoadInitialDatas(response) {
$scope.cyberpanelLoading = false;
new PNotify({
safePNotify({
title: 'Error!',
text: 'Could not connect to server, please refresh this page.',
type: 'error'

View File

@@ -4,6 +4,8 @@
{% block content %}
{% load static %}
{# Ensure userManagment controllers load before Angular compiles this page #}
<script src="{% static 'userManagment/userManagment.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
@@ -576,24 +578,36 @@
<script>
// Tab switching functionality
function switchTab(tabName) {
var configContent = document.getElementById('configure-content');
var usersContent = document.getElementById('users-content');
var configTab = document.getElementById('configure-tab');
var usersTab = document.getElementById('users-tab');
if (!configContent || !usersContent) return;
// Hide all tab contents
document.getElementById('configure-content').classList.remove('active');
document.getElementById('users-content').classList.remove('active');
// Remove active class from all tabs
document.getElementById('configure-tab').classList.remove('active');
document.getElementById('users-tab').classList.remove('active');
configContent.classList.remove('active');
usersContent.classList.remove('active');
if (configTab) configTab.classList.remove('active');
if (usersTab) usersTab.classList.remove('active');
// Show selected tab content and add active class
if (tabName === 'configure') {
document.getElementById('configure-content').classList.add('active');
document.getElementById('configure-tab').classList.add('active');
configContent.classList.add('active');
if (configTab) configTab.classList.add('active');
} else if (tabName === 'users') {
document.getElementById('users-content').classList.add('active');
document.getElementById('users-tab').classList.add('active');
// Load API users when switching to users tab
if (typeof angular !== 'undefined' && angular.element(document.getElementById('users-content')).scope()) {
angular.element(document.getElementById('users-content')).scope().loadAPIUsers();
usersContent.classList.add('active');
if (usersTab) usersTab.classList.add('active');
// Load API users when switching to users tab - safely get scope and call if available
if (typeof angular !== 'undefined') {
var elem = angular.element(usersContent);
var scope = elem.scope();
if (scope && typeof scope.loadAPIUsers === 'function') {
try {
scope.$apply(function() { scope.loadAPIUsers(); });
} catch (e) {
scope.loadAPIUsers();
}
}
}
}
}

View File

@@ -4,6 +4,7 @@
{% block content %}
{% load static %}
<script src="{% static 'userManagment/userManagment.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
@@ -216,13 +217,13 @@
<i class="fa fa-plus"></i> {% trans "Create ACL" %}
</button>
</div>
<div ng-hide="aclCreated" class="alert alert-success">
<i class="fa fa-check-circle"></i> {% trans "ACL with name:" %} <strong>{$ aclName $}</strong> {% trans "is successfully created." %}
<div ng-cloak ng-show="aclCreated === false" class="alert alert-success">
<i class="fa fa-check-circle"></i> {% trans "ACL with name:" %} <strong><span ng-bind="aclName"></span></strong> {% trans "is successfully created." %}
</div>
<div ng-hide="aclCreationFailed" class="alert alert-danger">
<i class="fa fa-exclamation-circle"></i> {% trans "Cannot create ACL. Error message:" %} {$ errorMessage $}
<div ng-cloak ng-show="aclCreationFailed === true" class="alert alert-danger">
<i class="fa fa-exclamation-circle"></i> {% trans "Cannot create ACL. Error message:" %} <span ng-bind="errorMessage || 'Unknown error'"></span>
</div>
<div ng-hide="couldNotConnect" class="alert alert-danger">
<div ng-cloak ng-show="couldNotConnect === false" class="alert alert-danger">
<i class="fa fa-times-circle"></i> {% trans "Could not connect to server. Please refresh this page." %}
</div>
</form>

View File

@@ -4,6 +4,8 @@
{% block content %}
{% load static %}
{# Ensure createUserCtr is registered before Angular compiles #}
<script src="{% static 'userManagment/userManagment.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
@@ -250,9 +252,9 @@
<div class="form-col-6">
<div class="form-group">
<label class="form-label">{% trans "First Name" %}</label>
<input name="firstName" ng-pattern="/^[a-zA-Z ]+$/" type="text" class="form-control"
<input name="firstName" ng-pattern="/^[a-zA-Z ]*$/" type="text" class="form-control"
ng-model="firstName" required>
<div ng-show="createUser.firstName.$error.pattern" class="error-text">
<div ng-show="createUser.firstName.$dirty && createUser.firstName.$error.pattern" class="error-text">
{% trans "First Name should contain only alphabetic characters." %}
</div>
</div>
@@ -260,9 +262,9 @@
<div class="form-col-6">
<div class="form-group">
<label class="form-label">{% trans "Last Name" %}</label>
<input name="lastName" ng-pattern="/^[a-zA-Z ]+$/" type="text" class="form-control"
<input name="lastName" ng-pattern="/^[a-zA-Z ]*$/" type="text" class="form-control"
ng-model="lastName" required>
<div ng-show="createUser.lastName.$error.pattern" class="error-text">
<div ng-show="createUser.lastName.$dirty && createUser.lastName.$error.pattern" class="error-text">
{% trans "Last Name should contain only alphabetic characters." %}
</div>
</div>
@@ -272,7 +274,7 @@
<div class="form-group">
<label class="form-label">{% trans "Email Address" %}</label>
<input name="email" type="email" class="form-control" ng-model="email" required>
<div ng-show="createUser.email.$error.email" class="error-text">
<div ng-show="createUser.email.$dirty && createUser.email.$error.email" class="error-text">
{% trans "Please enter a valid email address" %}
</div>
</div>
@@ -348,19 +350,19 @@
</button>
</div>
<div ng-hide="userCreated" class="alert alert-success">
<i class="fa fa-check-circle"></i> {% trans "Account with username:" %} <strong>{$ userName $}</strong> {% trans "is successfully created." %}
<div ng-cloak ng-show="userCreated === false" class="alert alert-success">
<i class="fa fa-check-circle"></i> {% trans "Account with username:" %} <strong><span ng-bind="userName"></span></strong> {% trans "is successfully created." %}
</div>
<div ng-hide="userCreationFailed" class="alert alert-danger">
<i class="fa fa-exclamation-circle"></i> {% trans "Cannot create user. Error message:" %} {$ errorMessage $}
<div ng-cloak ng-show="userCreationFailed === true" class="alert alert-danger">
<i class="fa fa-exclamation-circle"></i> {% trans "Cannot create user. Error message:" %} <span ng-bind="errorMessage || 'Unknown error'"></span>
</div>
<div ng-hide="couldNotConnect" class="alert alert-danger">
<div ng-cloak ng-show="couldNotConnect === false" class="alert alert-danger">
<i class="fa fa-times-circle"></i> {% trans "Could not connect to server. Please refresh this page." %}
</div>
<div ng-hide="combinedLength" class="alert alert-danger">
<div ng-cloak ng-show="combinedLength === false" class="alert alert-danger">
<i class="fa fa-exclamation-triangle"></i> {% trans "Length of first and last name combined should be less than or equal to 20 characters" %}
</div>
</form>

View File

@@ -5,6 +5,7 @@
{% block content %}
{% load static %}
<script src="{% static 'userManagment/userManagment.js' %}?v={{ CP_VERSION }}" data-cfasync="false"></script>
{% get_current_language as LANGUAGE_CODE %}
<!-- Current language: {{ LANGUAGE_CODE }} -->
@@ -427,19 +428,19 @@
</button>
</div>
</div>
<div ng-hide="userModified" class="alert alert-success">
<i class="fa fa-check-circle"></i> {% trans "Account with username:" %} <strong>{$ userName $}</strong> {% trans "is successfully modified." %}
<div ng-cloak ng-show="userModified === false" class="alert alert-success">
<i class="fa fa-check-circle"></i> {% trans "Account with username:" %} <strong><span ng-bind="userName"></span></strong> {% trans "is successfully modified." %}
</div>
<div ng-hide="canotModifyUser" class="alert alert-danger">
<i class="fa fa-exclamation-circle"></i> {% trans "Cannot modify user. Error message:" %} {$ errorMessage $}
<div ng-cloak ng-show="canotModifyUser === true" class="alert alert-danger">
<i class="fa fa-exclamation-circle"></i> {% trans "Cannot modify user. Error message:" %} <span ng-bind="errorMessage || 'Unknown error'"></span>
</div>
<div ng-hide="couldNotConnect" class="alert alert-danger">
<div ng-cloak ng-show="couldNotConnect === false" class="alert alert-danger">
<i class="fa fa-times-circle"></i> {% trans "Could not connect to server. Please refresh this page." %}
</div>
<div ng-hide="canotFetchDetails" class="alert alert-danger">
<i class="fa fa-exclamation-circle"></i> {% trans "Cannot fetch details. Error message:" %} {$ errorMessage $}
<div ng-cloak ng-show="canotFetchDetails === true" class="alert alert-danger">
<i class="fa fa-exclamation-circle"></i> {% trans "Cannot fetch details. Error message:" %} <span ng-bind="errorMessage || 'Unknown error'"></span>
</div>
<div ng-hide="detailsFetched" class="alert alert-success">
<div ng-cloak ng-show="detailsFetched === true" class="alert alert-success">
<i class="fa fa-info-circle"></i> {% trans "User details loaded successfully." %}
</div>
</form>

View File

@@ -220,7 +220,7 @@ def submitUserCreation(request):
if ACLManager.CheckRegEx("^[\w'\-,.][^0-9_!¡?÷?¿/\\+=@#$%ˆ&*(){}|~<>;:[\]]{2,}$", firstName) == 0:
data_ret = {'status': 0, 'createStatus': 0, 'error_message': 'First Name can only contain alphabetic characters, and should be more than 2 characters long...'}
json_data = json.dumps(data_ret)
return HttpResponse(json_data)
return HttpResponse(json_data, content_type='application/json')
if ACLManager.CheckRegEx("^[\w'\-,.][^0-9_!¡?÷?¿/\\+=@#$%ˆ&*(){}|~<>;:[\]]{2,}$", lastName) == 0:
data_ret = {'status': 0, 'createStatus': 0, 'error_message': 'Last Name can only contain alphabetic characters, and should be more than 2 characters long...'}
@@ -362,7 +362,7 @@ def submitUserCreation(request):
data_ret = {'status': 1, 'createStatus': 1,
'error_message': "None"}
final_json = json.dumps(data_ret)
return HttpResponse(final_json)
return HttpResponse(final_json, content_type='application/json')
except Exception as e:
secure_log_error(e, 'submitUserCreation', request.session.get('userID', 'Unknown'))

View File

@@ -391,7 +391,7 @@
<label class="form-label">{% trans "Domain Name" %}</label>
<input name="dom" type="text" class="form-control" ng-model="domainNameCreate"
placeholder="{% trans "example.com (Do not enter WWW, it will be auto created)" %}" required>
<div ng-show="websiteCreationForm.dom.$error.pattern" class="field-error">
<div ng-show="websiteCreationForm.dom.$dirty && websiteCreationForm.dom.$error.pattern" class="field-error">
{% trans "Invalid Domain (Note: You don't need to add 'http' or 'https')" %}
</div>
</div>
@@ -401,7 +401,7 @@
<label class="form-label">{% trans "Email" %}</label>
<input type="email" name="email" class="form-control" ng-model="adminEmail"
placeholder="{% trans "admin@example.com" %}" required>
<div ng-show="websiteCreationForm.email.$error.email" class="field-error">
<div ng-show="websiteCreationForm.email.$dirty && websiteCreationForm.email.$error.email" class="field-error">
{% trans "Invalid Email" %}
</div>
</div>

View File

@@ -6,6 +6,24 @@ FTP Quota Management - CyberPanel
{% endblock %}
{% block content %}
<style>
/* Ensure FTP Quota info section is readable - dark text on light background */
.ftp-quota-info .alert-info {
background: #e0f2fe !important;
color: #0c4a6e !important;
border: 1px solid #7dd3fc;
}
.ftp-quota-info .alert-info h5,
.ftp-quota-info .alert-info p,
.ftp-quota-info .alert-info .btn-primary {
color: inherit !important;
}
.ftp-quota-info .alert-info .btn-primary {
background: #0284c7 !important;
border-color: #0284c7 !important;
color: white !important;
}
</style>
<div class="container-fluid">
<div class="row">
<div class="col-12">
@@ -18,7 +36,7 @@ FTP Quota Management - CyberPanel
</div>
<div class="card-body">
<!-- Enable FTP Quota Section -->
<div class="row mb-4">
<div class="row mb-4 ftp-quota-info">
<div class="col-12">
<div class="alert alert-info">
<h5><i class="fas fa-info-circle"></i> FTP Quota System</h5>

View File

@@ -8744,7 +8744,7 @@ StrictHostKeyChecking no
admin = Administrator.objects.get(pk=userID)
# Check if user has permission
if not ACLManager.checkIfUserIsAdmin(currentACL):
if not (currentACL.get('admin', 0) == 1):
return ACLManager.loadErrorJson('status', 0)
# Backup existing configurations
@@ -8811,7 +8811,7 @@ StrictHostKeyChecking no
admin = Administrator.objects.get(pk=userID)
# Check if user has permission
if not ACLManager.checkIfUserIsAdmin(currentACL):
if not (currentACL.get('admin', 0) == 1):
return ACLManager.loadErrorJson('status', 0)
quotas = FTPQuota.objects.all().order_by('-created_at')
@@ -8856,7 +8856,7 @@ StrictHostKeyChecking no
admin = Administrator.objects.get(pk=userID)
# Check if user has permission
if not ACLManager.checkIfUserIsAdmin(currentACL):
if not (currentACL.get('admin', 0) == 1):
return ACLManager.loadErrorJson('status', 0)
quota_id = data.get('quota_id')
@@ -8899,7 +8899,7 @@ StrictHostKeyChecking no
admin = Administrator.objects.get(pk=userID)
# Check if user has permission
if not ACLManager.checkIfUserIsAdmin(currentACL):
if not (currentACL.get('admin', 0) == 1):
return ACLManager.loadErrorJson('status', 0)
reset_type = data.get('reset_type', 'manual')
@@ -8970,7 +8970,7 @@ StrictHostKeyChecking no
admin = Administrator.objects.get(pk=userID)
# Check if user has permission
if not ACLManager.checkIfUserIsAdmin(currentACL):
if not (currentACL.get('admin', 0) == 1):
return ACLManager.loadErrorJson('status', 0)
logs = BandwidthResetLog.objects.all().order_by('-reset_at')[:50] # Last 50 entries
@@ -9013,7 +9013,7 @@ StrictHostKeyChecking no
admin = Administrator.objects.get(pk=userID)
# Check if user has permission
if not ACLManager.checkIfUserIsAdmin(currentACL):
if not (currentACL.get('admin', 0) == 1):
return ACLManager.loadErrorJson('status', 0)
schedule_type = data.get('schedule_type', 'monthly') # monthly, weekly, daily
@@ -9068,7 +9068,7 @@ StrictHostKeyChecking no
admin = Administrator.objects.get(pk=userID)
# Check if user has permission
if not ACLManager.checkIfUserIsAdmin(currentACL):
if not (currentACL.get('admin', 0) == 1):
return ACLManager.loadErrorJson('status', 0)
ip_address = data.get('ip_address')
@@ -9119,7 +9119,7 @@ StrictHostKeyChecking no
admin = Administrator.objects.get(pk=userID)
# Check if user has permission
if not ACLManager.checkIfUserIsAdmin(currentACL):
if not (currentACL.get('admin', 0) == 1):
return ACLManager.loadErrorJson('status', 0)
ip_address = data.get('ip_address')
@@ -9169,7 +9169,7 @@ StrictHostKeyChecking no
admin = Administrator.objects.get(pk=userID)
# Check if user has permission
if not ACLManager.checkIfUserIsAdmin(currentACL):
if not (currentACL.get('admin', 0) == 1):
return ACLManager.loadErrorJson('status', 0)
# Import firewall utilities
@@ -9203,7 +9203,7 @@ StrictHostKeyChecking no
admin = Administrator.objects.get(pk=userID)
# Check if user has permission
if not ACLManager.checkIfUserIsAdmin(currentACL):
if not (currentACL.get('admin', 0) == 1):
return ACLManager.loadErrorJson('status', 0)
ip_address = data.get('ip_address')