Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/duplicati/duplicati.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'Duplicati/Server/webroot/ngax/scripts/controllers/EditBackupController.js')
-rw-r--r--Duplicati/Server/webroot/ngax/scripts/controllers/EditBackupController.js264
1 files changed, 231 insertions, 33 deletions
diff --git a/Duplicati/Server/webroot/ngax/scripts/controllers/EditBackupController.js b/Duplicati/Server/webroot/ngax/scripts/controllers/EditBackupController.js
index 8e9f31e25..5ee523386 100644
--- a/Duplicati/Server/webroot/ngax/scripts/controllers/EditBackupController.js
+++ b/Duplicati/Server/webroot/ngax/scripts/controllers/EditBackupController.js
@@ -1,4 +1,4 @@
-backupApp.controller('EditBackupController', function ($scope, $routeParams, $location, $timeout, AppService, AppUtils, SystemInfo, DialogService, EditBackupService, gettext, gettextCatalog) {
+backupApp.controller('EditBackupController', function ($rootScope, $scope, $routeParams, $location, $timeout, AppService, AppUtils, SystemInfo, DialogService, EditBackupService, gettext, gettextCatalog) {
$scope.SystemInfo = SystemInfo.watch($scope);
$scope.AppUtils = AppUtils;
@@ -6,14 +6,22 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
$scope.RepeatPasshrase = null;
$scope.PasswordStrength = 'unknown';
$scope.CurrentStep = 0;
- $scope.EditUriState = false;
$scope.showhiddenfolders = false;
$scope.EditSourceAdvanced = false;
$scope.EditFilterAdvanced = false;
+ $scope.DefaultFilters = [];
$scope.ExcludeAttributes = [];
$scope.ExcludeLargeFiles = false;
+ $scope.defaultFilterSetAll = 'All';
+ $scope.defaultFilterSets = [
+ { 'name': gettextCatalog.getString('Windows'), 'value': 'Windows' },
+ { 'name': gettextCatalog.getString('OSX'), 'value': 'OSX' },
+ { 'name': gettextCatalog.getString('Linux'), 'value': 'Linux' },
+ { 'name': gettextCatalog.getString('All'), 'value': $scope.defaultFilterSetAll },
+ ];
+
$scope.fileAttributes = [
{'name': gettextCatalog.getString('Hidden files'), 'value': 'hidden'},
{'name': gettextCatalog.getString('System files'), 'value': 'system'},
@@ -25,7 +33,6 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
function computePassPhraseStrength() {
var strengthMap = {
- '': gettextCatalog.getString("Empty"),
'x': gettextCatalog.getString("Passwords do not match"),
0: gettextCatalog.getString("Useless"),
1: gettextCatalog.getString("Very weak"),
@@ -43,7 +50,7 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
else
scope.PassphraseScore = (zxcvbn(passphrase) || {'score': -1}).score;
- scope.PassphraseScoreString = strengthMap[scope.PassphraseScore] || gettextCatalog.getString('Unknown');
+ scope.PassphraseScoreString = strengthMap[scope.PassphraseScore];
}
$scope.$watch('Options["passphrase"]', computePassPhraseStrength);
@@ -56,20 +63,32 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
};
$scope.togglePassphraseVisibility = function() {
- this.ShowPassphrase = !this.ShowPassphrase;;
+ this.ShowPassphrase = !this.ShowPassphrase;
};
$scope.nextPage = function() {
- $scope.CurrentStep = Math.min(3, $scope.CurrentStep + 1);
+ $scope.CurrentStep = Math.min(4, $scope.CurrentStep + 1);
};
$scope.prevPage = function() {
$scope.CurrentStep = Math.max(0, $scope.CurrentStep - 1);
+ };
+ $scope.setBuilduriFn = function(builduriFn) {
+ $scope.builduri = builduriFn;
};
- $scope.HideEditUri = function() {
- scope.EditUriState = false;
+ $scope.importUrl = function () {
+ DialogService.textareaDialog('Import URL', 'Enter a Backup destination URL:', null, gettextCatalog.getString('Enter URL'), [gettextCatalog.getString('Cancel'), gettextCatalog.getString('OK')], null, function(btn, input) {
+ if (btn == 1)
+ scope.Backup.TargetURL = input;
+ });
+ };
+
+ $scope.copyUrlToClipboard = function () {
+ $scope.builduri(function(res) {
+ DialogService.textareaDialog('Copy URL', null, null, res, [gettextCatalog.getString('OK')], 'templates/copy_clipboard_buttons.html');
+ });
};
var oldSchedule = null;
@@ -125,23 +144,19 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
}
});
});
- };
+ }
if (scope.manualSourcePath.substr(scope.manualSourcePath.length - 1, 1) != dirsep) {
- DialogService.dialog(gettextCatalog.getString('Include a file?'), gettextCatalog.getString("The path does not end with a '{0}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?", dirsep), [gettextCatalog.getString('No'), gettextCatalog.getString('Yes')], function(ix) {
+ DialogService.dialog(gettextCatalog.getString('Include a file?'), gettextCatalog.getString("The path does not end with a '{{dirsep}}' character, which means that you include a file, not a folder.\n\nDo you want to include the specified file?", {dirsep: dirsep}), [gettextCatalog.getString('No'), gettextCatalog.getString('Yes')], function(ix) {
if (ix == 1)
continuation();
});
} else {
continuation();
}
-
-
-
-
};
- $scope.toggleArraySelection = function (lst, value) {
+ function toggleArraySelection(lst, value) {
var ix = lst.indexOf(value);
if (ix > -1)
@@ -150,6 +165,61 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
lst.push(value);
};
+ $scope.toggleAllowedDays = function(value) {
+ if ($scope.Schedule.AllowedDays == null)
+ $scope.Schedule.AllowedDays = [];
+ toggleArraySelection($scope.Schedule.AllowedDays, value);
+ };
+
+ $scope.isDefaultFilterSetEnabled = function (value) {
+ if ($scope.DefaultFilters == null)
+ $scope.DefaultFilters = [];
+ if (value != $scope.defaultFilterSetAll && $scope.isDefaultFilterSetEnabled($scope.defaultFilterSetAll))
+ {
+ return true;
+ }
+
+ return $scope.DefaultFilters.indexOf(value) > -1;
+ };
+
+ $scope.toggleDefaultFilters = function (value) {
+ if ($scope.DefaultFilters == null)
+ $scope.DefaultFilters = [];
+ if (value == $scope.defaultFilterSetAll)
+ {
+ var wasAllEnabled = $scope.isDefaultFilterSetEnabled($scope.defaultFilterSetAll);
+ $scope.DefaultFilters = [];
+ if (!wasAllEnabled)
+ {
+ for (var index = 0; index < $scope.defaultFilterSets.length; index++)
+ {
+ $scope.DefaultFilters.push($scope.defaultFilterSets[index].value);
+ }
+ }
+ }
+ else
+ {
+ if ($scope.isDefaultFilterSetEnabled($scope.defaultFilterSetAll))
+ {
+ toggleArraySelection($scope.DefaultFilters, $scope.defaultFilterSetAll);
+ }
+
+ toggleArraySelection($scope.DefaultFilters, value);
+
+ // If everything but the 'all' group is enabled, enable it
+ if ($scope.DefaultFilters.length >= $scope.defaultFilterSets.length - 1)
+ {
+ toggleArraySelection($scope.DefaultFilters, $scope.defaultFilterSetAll);
+ }
+ }
+ };
+
+ $scope.toggleExcludeAttributes = function(value) {
+ if ($scope.ExcludeAttributes == null)
+ $scope.ExcludeAttributes = [];
+ toggleArraySelection($scope.ExcludeAttributes, value);
+ };
+
$scope.save = function() {
if (!EditBackupService.preValidate($scope))
@@ -160,7 +230,7 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
Schedule: angular.copy($scope.Schedule)
};
- var opts = angular.copy($scope.Options);
+ var opts = angular.copy($scope.Options, opts);
if (!$scope.ExcludeLargeFiles)
delete opts['--skip-files-larger-than'];
@@ -174,6 +244,30 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
if (!AppUtils.parse_extra_options(scope.ExtendedOptions, opts))
return false;
+ for (var n in $scope.servermodulesettings)
+ opts['--' + n] = $scope.servermodulesettings[n];
+
+ var defaultFilters = ($scope.DefaultFilters || []).concat((opts['--default-filters'] || '').split(/[,;\|]+/));
+ var filterMap = { '': true };
+
+ // Remove duplicates
+ for (var i = defaultFilters.length - 1; i >= 0; i--) {
+ defaultFilters[i] = (defaultFilters[i] || '').trim();
+ var cmp = defaultFilters[i].toLowerCase();
+ if (filterMap[cmp])
+ defaultFilters.splice(i, 1);
+ else
+ filterMap[cmp] = true;
+ }
+
+ if (defaultFilters.length == 0)
+ delete opts['--default-filters'];
+ else
+ if (filterMap[$scope.defaultFilterSetAll.toLowerCase()])
+ opts['--default-filters'] = $scope.defaultFilterSetAll;
+ else
+ opts['--default-filters'] = defaultFilters.join(',');
+
var exclattr = ($scope.ExcludeAttributes || []).concat((opts['--exclude-files-attributes'] || '').split(','));
var exclmap = { '': true };
@@ -190,7 +284,7 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
if (exclattr.length == 0)
delete opts['--exclude-files-attributes'];
else
- opts['--exclude-files-attributes'] = exclattr.join(',')
+ opts['--exclude-files-attributes'] = exclattr.join(',');
if (($scope.Backup.Name || '').trim().length == 0) {
DialogService.dialog(gettextCatalog.getString('Missing name'), gettextCatalog.getString('You must enter a name for the backup'));
@@ -213,15 +307,9 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
}
}
- if (($scope.Backup.TargetURL || '').trim().length == 0) {
- DialogService.dialog(gettextCatalog.getString('Missing destination'), gettextCatalog.getString('You must enter a destination where the backups are stored'));
- $scope.CurrentStep = 0;
- return;
- }
-
if ($scope.Backup.Sources == null || $scope.Backup.Sources.length == 0) {
DialogService.dialog(gettextCatalog.getString('Missing sources'), gettextCatalog.getString('You must choose at least one source folder'));
- $scope.CurrentStep = 1;
+ $scope.CurrentStep = 2;
return;
}
@@ -230,6 +318,21 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
if ($scope.KeepType == 'versions' || $scope.KeepType == '')
delete opts['keep-time'];
+ if ($scope.KeepType == 'time' && (opts['keep-time'] || '').trim().length == 0)
+ {
+ DialogService.dialog(gettextCatalog.getString('Invalid retention time'), gettextCatalog.getString('You must enter a valid duration for the time to keep backups'));
+ $scope.CurrentStep = 4;
+ return;
+ }
+
+ if ($scope.KeepType == 'versions' && (parseInt(opts['keep-versions']) <= 0 || isNaN(parseInt(opts['keep-versions']))))
+ {
+ DialogService.dialog(gettextCatalog.getString('Invalid retention time'), gettextCatalog.getString('You must enter a positive number of backups to keep'));
+ $scope.CurrentStep = 4;
+ return;
+ }
+
+
result.Backup.Settings = [];
for(var k in opts) {
var origfilter = "";
@@ -328,6 +431,19 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
};
+ function checkForValidBackupDestination(continuation) {
+ var success = false;
+ $scope.builduri(function(res) {
+ result.Backup.TargetURL = res;
+ $scope.Backup.TargetURL = res;
+ success = true;
+ continuation();
+ });
+
+ if (!success)
+ $scope.CurrentStep = 1;
+ }
+
function checkForDisabledEncryption(continuation) {
if (encryptionEnabled || $scope.Backup.TargetURL.indexOf('file://') == 0 || $scope.SystemInfo.EncryptionModules.length == 0)
continuation();
@@ -370,10 +486,12 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
// Chain calls
checkForGeneratedPassphrase(function() {
- checkForDisabledEncryption(function() {
- warnWeakPassphrase(function() {
- checkForExistingDb(function() {
- EditBackupService.postValidate($scope, postDb);
+ checkForValidBackupDestination(function() {
+ checkForDisabledEncryption(function() {
+ warnWeakPassphrase(function() {
+ checkForExistingDb(function () {
+ EditBackupService.postValidate($scope, postDb);
+ });
});
});
});
@@ -386,9 +504,11 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
AppService.put('/backup/' + $routeParams.backupid, result, {'headers': {'Content-Type': 'application/json'}}).then(function() {
$location.path('/');
}, AppUtils.connectionError);
- };
+ }
- checkForChangedPassphrase(putDb);
+ checkForChangedPassphrase(function() {
+ checkForValidBackupDestination(putDb);
+ });
}
};
@@ -420,6 +540,38 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
if ($scope.ExcludeLargeFiles)
$scope.Options['--skip-files-larger-than'] = extopts['--skip-files-larger-than'];
+ var defaultFilters = (extopts['--default-filters'] || '').split(/[,;\|]+/);
+ var defaultFiltersActive = [];
+ var filterMap = {};
+
+ for (var i = defaultFilters.length - 1; i >= 0; i--) {
+ var cmp = (defaultFilters[i] || '').trim().toLowerCase();
+
+ // Remove empty entries
+ if (cmp.length == 0) {
+ defaultFilters.splice(i, 1);
+ continue;
+ }
+
+ for (var j = scope.defaultFilterSets.length - 1; j >= 0; j--) {
+ if (scope.defaultFilterSets[j].value.toLowerCase() == cmp) {
+ // Remote duplicates
+ if (filterMap[cmp] == null) {
+ defaultFiltersActive.push(scope.defaultFilterSets[j].value);
+ filterMap[cmp] = true;
+ }
+ defaultFilters.splice(i, 1);
+ break;
+ }
+ }
+ }
+
+ $scope.DefaultFilters = defaultFiltersActive;
+ if (defaultFilters.length == 0)
+ delete extopts['--default-filters'];
+ else
+ extopts['--default-filters'] = defaultFilters.join(',');
+
var exclattr = (extopts['--exclude-files-attributes'] || '').split(',');
var dispattr = [];
var dispmap = {};
@@ -465,11 +617,16 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
$scope.KeepType = 'versions';
}
- var delopts = ['--skip-files-larger-than', '--no-encryption']
+ var delopts = ['--skip-files-larger-than', '--no-encryption'];
for(var n in delopts)
delete extopts[delopts[n]];
$scope.ExtendedOptions = AppUtils.serializeAdvancedOptionsToArray(extopts);
+
+ $scope.servermodulesettings = {};
+ AppUtils.extractServerModuleOptions($scope.ExtendedOptions, $scope.ServerModules, $scope.servermodulesettings, 'SupportedLocalCommands');
+
+ $scope.showAdvanced = $scope.ExtendedOptions.length > 0;
var now = new Date();
if ($scope.Schedule != null) {
@@ -502,6 +659,20 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
}
}
+ function setupServerModules()
+ {
+ var mods = [];
+ if ($scope.SystemInfo.ServerModules != null)
+ for(var ix in $scope.SystemInfo.ServerModules)
+ {
+ var m = $scope.SystemInfo.ServerModules[ix];
+ if (m.SupportedLocalCommands != null && m.SupportedLocalCommands.length > 0)
+ mods.push(m);
+ }
+
+ $scope.ServerModules = mods;
+ };
+
function reloadOptionsList()
{
if ($scope.Options == null)
@@ -514,9 +685,32 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
if (ix > 0)
backmodule = backmodule.substr(0, ix);
- $scope.ExtendedOptionList = AppUtils.buildOptionList($scope.SystemInfo, encmodule, compmodule, backmodule);
+ $scope.ExtendedOptionList = AppUtils.buildOptionList($scope.SystemInfo, encmodule, compmodule, backmodule);
+ setupServerModules();
+
+ AppUtils.extractServerModuleOptions($scope.ExtendedOptions, $scope.ServerModules, $scope.servermodulesettings, 'SupportedLocalCommands');
+ };
+
+ function checkAllowedDaysConfig()
+ {
+ if ($scope.Schedule == null || $scope.Schedule.AllowedDays == null)
+ return;
+
+ // Remove invalid values
+ var alldays = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'];
+ for (var i = $scope.Schedule.AllowedDays.length - 1; i >= 0; i--)
+ if (alldays.indexOf($scope.Schedule.AllowedDays[i]) < 0)
+ $scope.Schedule.AllowedDays.splice(i, 1);
+
+ // Empty and all are the same, but the UI confuses if no days are selected
+ if ($scope.Schedule.AllowedDays.length == 0)
+ $timeout(function() {
+ $scope.Schedule.AllowedDays = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'];
+ });
};
+ setupServerModules();
+
$scope.$watch("Options['encryption-module']", reloadOptionsList);
$scope.$watch("Options['compression-module']", reloadOptionsList);
$scope.$watch("Options['--compression-module']", reloadOptionsList);
@@ -526,19 +720,23 @@ backupApp.controller('EditBackupController', function ($scope, $routeParams, $lo
if ($scope.Options != null && $scope.Options['--skip-files-larger-than'] == null)
$scope.Options['--skip-files-larger-than'] = '100MB';
});
+ $scope.$watch("Schedule.AllowedDays", checkAllowedDaysConfig, true);
if ($routeParams.backupid == null) {
AppService.get('/backupdefaults').then(function(data) {
$scope.rawddata = data.data.data;
+
+ if ($location.$$path.indexOf('/add-import') == 0 && $rootScope.importConfig != null)
+ angular.merge($scope.rawddata, $rootScope.importConfig);
+
setupScope($scope.rawddata);
}, function(data) {
AppUtils.connectionError(gettextCatalog.getString('Failed to read backup defaults:') + ' ', data);
$location.path('/');
});
-
} else {
AppService.get('/backup/' + $routeParams.backupid).then(function(data) {