FTP: path normalization, post-create directory edit, enable/disable

- Resolve FTP home paths without duplicating /home/domain; support absolute paths under site home
- Add changeFTPDirectory API and list UI; improve create form path help
- Add setFTPAccountStatus (Status 0/1) with Enable/Disable on list page
- Pure-FTPd MySQL: require Status='1' for authentication in install templates
- Plugin signals for change directory and account status
This commit is contained in:
master3395
2026-03-24 20:22:56 +01:00
parent 836db0f378
commit 90fcc7b621
13 changed files with 649 additions and 86 deletions

View File

@@ -109,15 +109,7 @@ app.controller('createFTPAccount', function ($scope, $http) {
$scope.errorMessage = "Invalid path: Path cannot contain '..' or '~'";
return;
}
// Check if path starts with slash (should be relative)
if (path.startsWith("/")) {
$scope.ftpLoading = false;
resetFtpCreateAlerts();
$scope.alertFtpCreateError = true;
$scope.errorMessage = "Invalid path: Path must be relative (not starting with '/')";
return;
}
// Absolute paths under /home/... are allowed; server validates they stay inside the site home
}
var url = "/ftp/submitFTPCreation";
@@ -375,6 +367,7 @@ app.controller('listFTPAccounts', function ($scope, $http) {
$scope.ftpAccounts = true;
$scope.changePasswordBox = true;
$scope.quotaManagementBox = true;
$scope.directoryManagementBox = true;
$scope.notificationsBox = true;
var globalFTPUsername = "";
@@ -390,6 +383,8 @@ app.controller('listFTPAccounts', function ($scope, $http) {
$scope.couldNotConnect = true;
$scope.ftpLoading = false; // Don't show loading when opening password dialog
$scope.changePasswordBox = false;
$scope.quotaManagementBox = true;
$scope.directoryManagementBox = true;
$scope.notificationsBox = true;
$scope.ftpUsername = ftpUsername;
globalFTPUsername = ftpUsername;
@@ -454,6 +449,8 @@ app.controller('listFTPAccounts', function ($scope, $http) {
$scope.ftpLoading = true; // Show loading while fetching
$scope.ftpAccounts = true;
$scope.changePasswordBox = true;
$scope.quotaManagementBox = true;
$scope.directoryManagementBox = true;
var selectedDomain = $scope.selectedDomain;
@@ -479,7 +476,11 @@ app.controller('listFTPAccounts', function ($scope, $http) {
if (response.data.fetchStatus == 1) {
$scope.records = JSON.parse(response.data.data);
angular.forEach($scope.records, function (r) {
if (typeof r.acct_enabled === 'undefined') {
r.acct_enabled = true;
}
});
$scope.notificationsBox = false;
$scope.recordsFetched = false;
@@ -489,6 +490,8 @@ app.controller('listFTPAccounts', function ($scope, $http) {
$scope.ftpLoading = false; // Hide loading when done
$scope.ftpAccounts = false;
$scope.changePasswordBox = true;
$scope.quotaManagementBox = true;
$scope.directoryManagementBox = true;
$scope.domainFeteched = $scope.selectedDomain;
@@ -501,6 +504,8 @@ app.controller('listFTPAccounts', function ($scope, $http) {
$scope.ftpLoading = false; // Hide loading on error
$scope.ftpAccounts = true;
$scope.changePasswordBox = true;
$scope.quotaManagementBox = true;
$scope.directoryManagementBox = true;
$scope.errorMessage = response.data.error_message;
}
@@ -516,6 +521,8 @@ app.controller('listFTPAccounts', function ($scope, $http) {
$scope.ftpLoading = false; // Hide loading on connection error
$scope.ftpAccounts = true;
$scope.changePasswordBox = true;
$scope.quotaManagementBox = true;
$scope.directoryManagementBox = true;
}
@@ -542,6 +549,8 @@ app.controller('listFTPAccounts', function ($scope, $http) {
$scope.canNotChangePassword = true;
$scope.couldNotConnect = true;
$scope.ftpLoading = false;
$scope.changePasswordBox = true;
$scope.directoryManagementBox = true;
$scope.quotaManagementBox = false;
$scope.notificationsBox = true;
$scope.ftpUsername = record.user;
@@ -630,6 +639,80 @@ app.controller('listFTPAccounts', function ($scope, $http) {
}
};
$scope.manageDirectory = function (record) {
$scope.recordsFetched = true;
$scope.passwordChanged = true;
$scope.canNotChangePassword = true;
$scope.couldNotConnect = true;
$scope.ftpLoading = false;
$scope.changePasswordBox = true;
$scope.quotaManagementBox = true;
$scope.directoryManagementBox = false;
$scope.notificationsBox = true;
$scope.ftpUsername = record.user;
globalFTPUsername = record.user;
$scope.ftpPathEdit = record.dir || '';
};
$scope.changeDirectoryBtn = function () {
$scope.ftpLoading = true;
var url = "/ftp/changeFTPDirectory";
var pathVal = $scope.ftpPathEdit;
if (typeof pathVal === 'undefined' || pathVal === null) {
pathVal = '';
} else {
pathVal = String(pathVal).trim();
}
var data = {
ftpUserName: globalFTPUsername,
selectedDomain: $scope.selectedDomain,
path: pathVal
};
var config = {
headers: {
'X-CSRFToken': getCookie('csrftoken')
}
};
$http.post(url, data, config).then(ListInitialDatas, cantLoadInitialDatas);
function ListInitialDatas(response) {
if (response.data.changeDirectoryStatus === 1) {
$scope.ftpLoading = false;
$scope.directoryManagementBox = true;
if (typeof PNotify !== 'undefined') {
new PNotify({
title: 'Success!',
text: 'FTP directory updated successfully.',
type: 'success'
});
}
populateCurrentRecords();
} else {
$scope.ftpLoading = false;
$scope.errorMessage = response.data.error_message;
if (typeof PNotify !== 'undefined') {
new PNotify({
title: 'Error!',
text: response.data.error_message,
type: 'error'
});
}
}
}
function cantLoadInitialDatas() {
$scope.ftpLoading = false;
$scope.couldNotConnect = false;
if (typeof PNotify !== 'undefined') {
new PNotify({
title: 'Error!',
text: 'Could not connect to server.',
type: 'error'
});
}
}
};
});