2017-02-27 00:03:46 +01:00
backupApp . controller ( 'EditBackupController' , function ( $rootScope , $scope , $routeParams , $location , $timeout , AppService , AppUtils , SystemInfo , DialogService , EditBackupService , gettext , gettextCatalog ) {
2015-08-21 22:04:39 +02:00
2018-01-22 23:42:31 +01:00
var SMART_RETENTION = '1W:1D,4W:1W,12M:1M' ;
2016-09-15 11:39:27 +02:00
$scope . SystemInfo = SystemInfo . watch ( $scope );
2015-08-21 22:04:39 +02:00
$scope . AppUtils = AppUtils ;
2016-09-15 11:39:27 +02:00
$scope . RepeatPasshrase = null ;
$scope . PasswordStrength = 'unknown' ;
$scope . CurrentStep = 0 ;
2015-08-21 22:04:39 +02:00
$scope . showhiddenfolders = false ;
$scope . EditSourceAdvanced = false ;
$scope . EditFilterAdvanced = false ;
$scope . ExcludeAttributes = [];
$scope . ExcludeLargeFiles = false ;
$scope . fileAttributes = [
2018-11-19 17:27:11 +01:00
{ 'name' : gettextCatalog . getString ( 'Hidden files' ), 'value' : 'hidden' },
{ 'name' : gettextCatalog . getString ( 'System files' ), 'value' : 'system' },
2016-10-02 15:18:34 +02:00
{ 'name' : gettextCatalog . getString ( 'Temporary files' ), 'value' : 'temporary' }
2016-09-15 11:39:27 +02:00
];
2015-08-21 22:04:39 +02:00
2016-09-15 11:39:27 +02:00
var scope = $scope ;
2015-08-21 22:04:39 +02:00
2016-09-15 11:39:27 +02:00
function computePassPhraseStrength () {
2015-08-21 22:04:39 +02:00
var strengthMap = {
2018-11-21 09:55:56 +01:00
'x' : gettextCatalog . getString ( "Passphrases do not match" ),
2016-10-02 15:18:34 +02:00
0 : gettextCatalog . getString ( "Useless" ),
1 : gettextCatalog . getString ( "Very weak" ),
2 : gettextCatalog . getString ( "Weak" ),
3 : gettextCatalog . getString ( "Strong" ),
4 : gettextCatalog . getString ( "Very strong" )
2015-08-21 22:04:39 +02:00
};
var passphrase = scope . Options == null ? '' : scope . Options [ 'passphrase' ];
2018-11-19 17:27:11 +01:00
if ( scope . RepeatPasshrase != passphrase )
2016-09-15 11:39:27 +02:00
scope . PassphraseScore = 'x' ;
else if (( passphrase || '' ) == '' )
scope . PassphraseScore = '' ;
else
2018-04-22 13:48:39 +02:00
scope . PassphraseScore = ( zxcvbn ( passphrase . substring ( 0 , 100 )) || { 'score' : - 1 }). score ;
2016-09-15 11:39:27 +02:00
2016-10-15 18:22:29 +02:00
scope . PassphraseScoreString = strengthMap [ scope . PassphraseScore ];
2016-09-15 11:39:27 +02:00
}
$scope . $watch ( 'Options["passphrase"]' , computePassPhraseStrength );
$scope . $watch ( 'RepeatPasshrase' , computePassPhraseStrength );
2018-11-19 20:26:16 +01:00
$scope . checkGpgAsymmetric = function () {
if ( ! this . Options ) {
return false ;
}
if ( ! ( 'encryption-module' in this . Options )) {
return false ;
}
if ( ! this . Options [ 'encryption-module' ]) {
return false ;
}
if ( this . Options [ 'encryption-module' ]. indexOf ( 'gpg' ) < 0 ) {
return false ;
}
return this . ExtendedOptions . includes ( '--gpg-encryption-command=--encrypt' );
}
2016-09-15 11:39:27 +02:00
$scope . generatePassphrase = function () {
this . Options [ "passphrase" ] = this . RepeatPasshrase = AppUtils . generatePassphrase ();
this . ShowPassphrase = true ;
this . HasGeneratedPassphrase = true ;
};
$scope . togglePassphraseVisibility = function () {
2016-10-21 15:32:33 +02:00
this . ShowPassphrase = ! this . ShowPassphrase ;
2016-09-15 11:39:27 +02:00
};
$scope . nextPage = function () {
2016-10-21 15:32:33 +02:00
$scope . CurrentStep = Math . min ( 4 , $scope . CurrentStep + 1 );
2016-09-15 11:39:27 +02:00
};
$scope . prevPage = function () {
$scope . CurrentStep = Math . max ( 0 , $scope . CurrentStep - 1 );
2016-10-21 15:32:33 +02:00
};
$scope . setBuilduriFn = function ( builduriFn ) {
$scope . builduri = builduriFn ;
};
2016-09-15 11:39:27 +02:00
2016-10-21 15:32:33 +02:00
$scope . importUrl = function () {
2016-10-29 14:34:07 +02:00
DialogService . textareaDialog ( 'Import URL' , 'Enter a Backup destination URL:' , null , gettextCatalog . getString ( 'Enter URL' ), [ gettextCatalog . getString ( 'Cancel' ), gettextCatalog . getString ( 'OK' )], null , function ( btn , input ) {
2016-10-21 15:32:33 +02:00
if ( btn == 1 )
scope . Backup . TargetURL = input ;
});
2016-09-15 11:39:27 +02:00
};
2016-10-21 15:32:33 +02:00
$scope . copyUrlToClipboard = function () {
$scope . builduri ( function ( res ) {
2016-10-29 14:34:07 +02:00
DialogService . textareaDialog ( 'Copy URL' , null , null , res , [ gettextCatalog . getString ( 'OK' )], 'templates/copy_clipboard_buttons.html' );
2016-10-21 15:32:33 +02:00
});
2016-09-15 11:39:27 +02:00
};
var oldSchedule = null ;
$scope . toggleSchedule = function () {
if ( scope . Schedule == null ) {
if ( oldSchedule == null ) {
oldSchedule = {
Tags : [],
Repeat : '1D' ,
AllowedDays : []
};
}
scope . Schedule = oldSchedule ;
oldSchedule = null ;
} else {
oldSchedule = scope . Schedule ;
scope . Schedule = null ;
}
};
2015-08-21 22:04:39 +02:00
$scope . addManualSourcePath = function () {
if ( scope . validatingSourcePath )
return ;
if ( scope . manualSourcePath == null || scope . manualSourcePath == '' )
2016-09-15 11:39:27 +02:00
return ;
2015-08-21 22:04:39 +02:00
var dirsep = scope . SystemInfo . DirectorySeparator || '/' ;
if ( dirsep == '/' ) {
2016-09-15 11:39:27 +02:00
if ( scope . manualSourcePath . substr ( 0 , 1 ) != '/' && scope . manualSourcePath . substr ( 0 , 1 ) != '%' ) {
2016-10-02 15:18:34 +02:00
DialogService . dialog ( gettextCatalog . getString ( 'Relative paths not allowed' ), gettextCatalog . getString ( "The path must be an absolute path, i.e. it must start with a forward slash '/' " ));
2016-09-15 11:39:27 +02:00
return ;
}
2015-08-21 22:04:39 +02:00
}
2015-12-08 20:38:16 +01:00
function continuation () {
2016-09-15 11:39:27 +02:00
scope . validatingSourcePath = true ;
AppService . post ( '/filesystem/validate' , { path : scope . manualSourcePath }). then ( function () {
scope . validatingSourcePath = false ;
scope . Backup . Sources . push ( scope . manualSourcePath );
scope . manualSourcePath = null ;
}, function () {
scope . validatingSourcePath = false ;
2016-10-02 15:18:34 +02:00
DialogService . dialog ( gettextCatalog . getString ( 'Path not found' ), gettextCatalog . getString ( 'The path does not appear to exist, do you want to add it anyway?' ), [ gettextCatalog . getString ( 'No' ), gettextCatalog . getString ( 'Yes' )], function ( ix ) {
2016-09-15 11:39:27 +02:00
if ( ix == 1 ) {
scope . Backup . Sources . push ( scope . manualSourcePath );
scope . manualSourcePath = null ;
}
});
});
2016-10-21 15:32:33 +02:00
}
2015-12-08 20:38:16 +01:00
2015-08-21 22:04:39 +02:00
if ( scope . manualSourcePath . substr ( scope . manualSourcePath . length - 1 , 1 ) != dirsep ) {
2016-10-14 19:55:53 +02:00
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 ) {
2016-09-15 11:39:27 +02:00
if ( ix == 1 )
continuation ();
});
2015-12-08 20:38:16 +01:00
} else {
2016-09-15 11:39:27 +02:00
continuation ();
}
2015-08-21 22:04:39 +02:00
};
2017-02-26 23:39:16 +01:00
function toggleArraySelection ( lst , value ) {
2016-09-15 11:39:27 +02:00
var ix = lst . indexOf ( value );
if ( ix > - 1 )
lst . splice ( ix , 1 );
else
lst . push ( value );
};
2017-02-26 23:39:16 +01:00
$scope . toggleAllowedDays = function ( value ) {
if ( $scope . Schedule . AllowedDays == null )
$scope . Schedule . AllowedDays = [];
toggleArraySelection ( $scope . Schedule . AllowedDays , value );
};
$scope . toggleExcludeAttributes = function ( value ) {
if ( $scope . ExcludeAttributes == null )
$scope . ExcludeAttributes = [];
toggleArraySelection ( $scope . ExcludeAttributes , value );
};
2016-09-15 11:39:27 +02:00
$scope . save = function () {
if ( ! EditBackupService . preValidate ( $scope ))
return false ;
var result = {
Backup : angular . copy ( $scope . Backup ),
Schedule : angular . copy ( $scope . Schedule )
};
2017-01-25 12:01:01 +01:00
var opts = angular . copy ( $scope . Options , opts );
2016-09-15 11:39:27 +02:00
if ( ! $scope . ExcludeLargeFiles )
delete opts [ '--skip-files-larger-than' ];
var encryptionEnabled = true ;
if (( opts [ 'encryption-module' ] || '' ). length == 0 ) {
opts [ '--no-encryption' ] = 'true' ;
encryptionEnabled = false ;
}
if ( ! AppUtils . parse_extra_options ( scope . ExtendedOptions , opts ))
return false ;
2017-01-25 12:01:01 +01:00
for ( var n in $scope . servermodulesettings )
opts [ '--' + n ] = $scope . servermodulesettings [ n ];
2016-09-15 11:39:27 +02:00
var exclattr = ( $scope . ExcludeAttributes || []). concat (( opts [ '--exclude-files-attributes' ] || '' ). split ( ',' ));
var exclmap = { '' : true };
// Remove duplicates
for ( var i = exclattr . length - 1 ; i >= 0 ; i -- ) {
exclattr [ i ] = ( exclattr [ i ] || '' ). trim ();
var cmp = exclattr [ i ]. toLowerCase ();
if ( exclmap [ cmp ])
exclattr . splice ( i , 1 );
else
exclmap [ cmp ] = true ;
}
if ( exclattr . length == 0 )
delete opts [ '--exclude-files-attributes' ];
else
2016-10-21 15:32:33 +02:00
opts [ '--exclude-files-attributes' ] = exclattr . join ( ',' );
2016-09-15 11:39:27 +02:00
if (( $scope . Backup . Name || '' ). trim (). length == 0 ) {
2016-10-02 15:18:34 +02:00
DialogService . dialog ( gettextCatalog . getString ( 'Missing name' ), gettextCatalog . getString ( 'You must enter a name for the backup' ));
2016-09-15 11:39:27 +02:00
$scope . CurrentStep = 0 ;
return ;
}
2018-11-19 20:26:16 +01:00
if ( encryptionEnabled && ! $scope . checkGpgAsymmetric ()) {
2016-09-15 11:39:27 +02:00
if ( $scope . PassphraseScore === '' ) {
2016-10-02 15:18:34 +02:00
DialogService . dialog ( gettextCatalog . getString ( 'Missing passphrase' ), gettextCatalog . getString ( 'You must enter a passphrase or disable encryption' ));
2016-09-15 11:39:27 +02:00
$scope . CurrentStep = 0 ;
return ;
}
if ( $scope . PassphraseScore == 'x' ) {
2016-10-02 15:18:34 +02:00
DialogService . dialog ( gettextCatalog . getString ( 'Non-matching passphrase' ), gettextCatalog . getString ( 'Passphrases are not matching' ));
2016-09-15 11:39:27 +02:00
$scope . CurrentStep = 0 ;
return ;
}
}
if ( $scope . Backup . Sources == null || $scope . Backup . Sources . length == 0 ) {
2016-10-02 15:18:34 +02:00
DialogService . dialog ( gettextCatalog . getString ( 'Missing sources' ), gettextCatalog . getString ( 'You must choose at least one source folder' ));
2016-10-21 15:32:33 +02:00
$scope . CurrentStep = 2 ;
2016-09-15 11:39:27 +02:00
return ;
}
2018-02-21 21:09:56 +01:00
// Retention options are mutual exclusive -> allow only one to be selected at a time
2018-03-04 15:14:38 +01:00
function resetAllRetentionOptionsExcept ( optionToKeep ) {
2018-02-21 21:09:56 +01:00
[ 'keep-versions' , 'keep-time' , 'retention-policy' ]. forEach ( function ( entry ) {
if ( entry != optionToKeep ) {
delete opts [ entry ];
}
});
2018-01-22 23:42:31 +01:00
}
2018-11-19 17:27:11 +01:00
2018-02-21 21:09:56 +01:00
if ( $scope . KeepType == 'time' ) {
resetAllRetentionOptionsExcept ( 'keep-time' );
2018-11-19 17:27:11 +01:00
2018-02-21 21:09:56 +01:00
} else if ( $scope . KeepType == 'versions' ) {
resetAllRetentionOptionsExcept ( 'keep-versions' );
2018-11-19 17:27:11 +01:00
2018-02-21 21:09:56 +01:00
} else if ( $scope . KeepType == 'smart' || $scope . KeepType == 'custom' ) {
resetAllRetentionOptionsExcept ( 'retention-policy' );
2018-11-19 17:27:11 +01:00
2018-02-21 21:09:56 +01:00
} else {
resetAllRetentionOptionsExcept (); // keep none
2018-01-22 23:42:31 +01:00
}
2016-09-15 11:39:27 +02:00
2016-10-14 00:16:47 +02:00
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' ));
2016-10-21 15:32:33 +02:00
$scope . CurrentStep = 4 ;
2016-10-14 00:16:47 +02:00
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' ));
2016-10-21 15:32:33 +02:00
$scope . CurrentStep = 4 ;
2016-10-14 00:16:47 +02:00
return ;
}
2019-05-23 19:13:08 +02:00
var retentionPolicy = ( opts [ 'retention-policy' ] || '' );
2020-02-12 00:58:05 +01:00
var valid_chars = /^((\d+[smhDWMY]|U):(\d+[smhDWMY]|U),?)+$/ ;
2019-05-23 19:13:08 +02:00
var valid_commas = /^(\d*\w:\d*\w,)*\d*\w:\d*\w$/ ;
2019-05-25 20:45:11 +02:00
if ( $scope . KeepType == 'custom' && ( retentionPolicy . indexOf ( ':' ) <= 0 || valid_chars . test ( retentionPolicy ) === false || valid_commas . test ( retentionPolicy ) === false ))
2018-01-22 23:42:31 +01:00
{
2020-02-12 00:58:05 +01:00
DialogService . dialog ( gettextCatalog . getString ( 'Invalid retention time' ), gettextCatalog . getString ( 'You must enter a valid retention policy string' ));
2018-01-22 23:42:31 +01:00
$scope . CurrentStep = 4 ;
return ;
}
if ( $scope . KeepType == 'smart' )
opts [ 'retention-policy' ] = SMART_RETENTION ;
2016-10-14 00:16:47 +02:00
2016-09-15 11:39:27 +02:00
result . Backup . Settings = [];
for ( var k in opts ) {
var origfilter = "" ;
var origarg = null ;
for ( var i in $scope . rawddata . Backup . Settings )
if ( $scope . rawddata . Backup . Settings [ i ]. Name == k ) {
origfilter = $scope . rawddata . Backup . Settings [ i ]. Filter ;
origarg = $scope . rawddata . Backup . Settings [ i ]. Argument ;
break ;
}
result . Backup . Settings . push ({
Name : k ,
Value : opts [ k ],
Filter : origfilter ,
Argument : origarg
});
}
var filterstrings = result . Backup . Filters || [];
result . Backup . Filters = [];
for ( var f in filterstrings )
result . Backup . Filters . push ({
Order : result . Backup . Filters . length ,
Include : filterstrings [ f ]. substr ( 0 , 1 ) == '+' ,
Expression : filterstrings [ f ]. substr ( 1 )
});
function warnWeakPassphrase ( continuation ) {
if ( encryptionEnabled && ( $scope . PassphraseScore == 0 || $scope . PassphraseScore == 1 || $scope . PassphraseScore == 2 )) {
2016-10-02 15:18:34 +02:00
DialogService . dialog ( gettextCatalog . getString ( 'Weak passphrase' ), gettextCatalog . getString ( 'Your passphrase is easy to guess. Consider changing passphrase.' ), [ gettextCatalog . getString ( 'Cancel' ), gettextCatalog . getString ( 'Use weak passphrase' )], function ( ix ) {
2016-09-15 11:39:27 +02:00
if ( ix == 0 )
$scope . CurrentStep = 0 ;
else
continuation ();
});
}
else
continuation ();
};
function checkForGeneratedPassphrase ( continuation ) {
if ( ! $scope . HasGeneratedPassphrase || ! encryptionEnabled )
continuation ();
else
2017-11-05 13:46:10 -05:00
DialogService . dialog ( gettextCatalog . getString ( 'Autogenerated passphrase' ), gettextCatalog . getString ( 'You have generated a strong passphrase. Make sure you have made a safe copy of the passphrase, as the data cannot be recovered if you lose the passphrase.' ), [ gettextCatalog . getString ( 'Cancel' ), gettextCatalog . getString ( 'Yes, I have stored the passphrase safely' )], function ( ix ) {
2016-09-15 11:39:27 +02:00
if ( ix == 0 )
$scope . CurrentStep = 0 ;
else
{
// Don't ask again
$scope . HasGeneratedPassphrase = false ;
continuation ();
}
});
};
function checkForChangedPassphrase ( continuation ) {
function findPrevOpt ( key ) {
var sets = $scope . rawddata . Backup . Settings ;
for ( var k in sets )
if ( sets [ k ]. Name == key )
return sets [ k ];
return null ;
};
var previousEncryptionOpt = findPrevOpt ( '--no-encryption' );
var prevPassphraseOpt = findPrevOpt ( 'passphrase' );
var previousEncryptionModuleOpt = findPrevOpt ( 'encryption-module' );
var prevPassphrase = prevPassphraseOpt == null ? null : prevPassphraseOpt . Value ;
var previousEncryptionEnabled = previousEncryptionOpt == null ? true : ! AppUtils . parseBoolString ( previousEncryptionOpt . Value , true );
var previousEncryptionModule = ( ! previousEncryptionEnabled || previousEncryptionModuleOpt == null ) ? '' : ( previousEncryptionModuleOpt . Value || '' );
var encryptionModule = opts [ 'encryption-module' ] || '' ;
if ( encryptionEnabled && previousEncryptionEnabled && prevPassphrase != opts [ 'passphrase' ])
{
2016-10-02 15:18:34 +02:00
DialogService . dialog ( gettextCatalog . getString ( 'Passphrase changed' ), gettextCatalog . getString ( 'You have changed the passphrase, which is not supported. You are encouraged to create a new backup instead.' ), [ gettextCatalog . getString ( 'Cancel' ), gettextCatalog . getString ( 'Yes, please break my backup!' )], function ( ix ) {
2016-09-15 11:39:27 +02:00
if ( ix == 0 )
$scope . CurrentStep = 0 ;
else
continuation ();
2018-11-19 17:27:11 +01:00
});
2016-09-15 11:39:27 +02:00
}
else if ( encryptionEnabled != previousEncryptionEnabled || encryptionModule != previousEncryptionModule )
{
2016-10-02 15:18:34 +02:00
DialogService . dialog ( gettextCatalog . getString ( 'Encryption changed' ), gettextCatalog . getString ( 'You have changed the encryption mode. This may break stuff. You are encouraged to create a new backup instead' ), [ gettextCatalog . getString ( 'Cancel' ), gettextCatalog . getString ( 'Yes, I\'m brave!' )], function ( ix ) {
2016-09-15 11:39:27 +02:00
if ( ix == 1 )
continuation ();
2018-11-19 17:27:11 +01:00
});
2016-09-15 11:39:27 +02:00
}
else
continuation ();
};
2016-10-21 15:32:33 +02:00
function checkForValidBackupDestination ( continuation ) {
2016-11-08 13:35:08 +01:00
var success = false ;
2016-10-21 15:32:33 +02:00
$scope . builduri ( function ( res ) {
result . Backup . TargetURL = res ;
$scope . Backup . TargetURL = res ;
2016-11-08 13:35:08 +01:00
success = true ;
2016-10-21 15:32:33 +02:00
continuation ();
});
2016-11-08 13:35:08 +01:00
if ( ! success )
$scope . CurrentStep = 1 ;
2016-10-21 15:32:33 +02:00
}
2016-09-15 11:39:27 +02:00
function checkForDisabledEncryption ( continuation ) {
if ( encryptionEnabled || $scope . Backup . TargetURL . indexOf ( 'file://' ) == 0 || $scope . SystemInfo . EncryptionModules . length == 0 )
continuation ();
else
2016-10-02 15:18:34 +02:00
DialogService . dialog ( gettextCatalog . getString ( 'No encryption' ), gettextCatalog . getString ( 'You have chosen not to encrypt the backup. Encryption is recommended for all data stored on a remote server.' ), [ gettextCatalog . getString ( 'Cancel' ), gettextCatalog . getString ( 'Continue without encryption' )], function ( ix ) {
2016-09-15 11:39:27 +02:00
if ( ix == 0 )
$scope . CurrentStep = 0 ;
else
continuation ();
});
};
if ( $routeParams . backupid == null ) {
function postDb () {
AppService . post ( '/backups' , result , { 'headers' : { 'Content-Type' : 'application/json' }}). then ( function () {
$location . path ( '/' );
2018-11-19 17:27:11 +01:00
}, AppUtils . connectionError );
2016-09-15 11:39:27 +02:00
};
function checkForExistingDb ( continuation ) {
AppService . post ( '/remoteoperation/dbpath' , $scope . Backup . TargetURL , { 'headers' : { 'Content-Type' : 'application/text' }}). then (
function ( resp ) {
if ( resp . data . Exists ) {
2016-10-02 15:18:34 +02:00
DialogService . dialog ( gettextCatalog . getString ( 'Use existing database?' ), gettextCatalog . getString ( 'An existing local database for the storage has been found.\nRe-using the database will allow the command-line and server instances to work on the same remote storage.\n\n Do you wish to use the existing database?' ), [ gettextCatalog . getString ( 'Cancel' ), gettextCatalog . getString ( 'Yes' ), gettextCatalog . getString ( 'No' )], function ( ix ) {
2016-09-15 11:39:27 +02:00
if ( ix == 2 )
result . Backup . DBPath = resp . data . Path ;
if ( ix == 1 || ix == 2 )
continuation ();
});
}
else
continuation ();
}, AppUtils . connectionError
);
};
// Chain calls
checkForGeneratedPassphrase ( function () {
2016-11-08 13:34:15 +01:00
checkForValidBackupDestination ( function () {
checkForDisabledEncryption ( function () {
warnWeakPassphrase ( function () {
2016-10-21 15:32:33 +02:00
checkForExistingDb ( function () {
EditBackupService . postValidate ( $scope , postDb );
});
2016-09-15 11:39:27 +02:00
});
});
});
});
} else {
function putDb () {
AppService . put ( '/backup/' + $routeParams . backupid , result , { 'headers' : { 'Content-Type' : 'application/json' }}). then ( function () {
$location . path ( '/' );
}, AppUtils . connectionError );
2016-10-21 15:32:33 +02:00
}
2016-09-15 11:39:27 +02:00
2016-10-21 15:32:33 +02:00
checkForChangedPassphrase ( function () {
checkForValidBackupDestination ( putDb );
});
2016-09-15 11:39:27 +02:00
}
};
function setupScope ( data ) {
$scope . Backup = angular . copy ( data . Backup );
$scope . Schedule = angular . copy ( data . Schedule );
$scope . Options = {};
var extopts = {};
for ( var n in $scope . Backup . Settings ) {
var e = $scope . Backup . Settings [ n ];
if ( e . Name . indexOf ( '--' ) == 0 )
extopts [ e . Name ] = e . Value ;
else
$scope . Options [ e . Name ] = e . Value ;
}
var filters = $scope . Backup . Filters ;
$scope . Backup . Filters = [];
2018-10-17 09:02:39 -03:00
// If Description is anything other than a string, we are either creating a new
// backup or something went wrong when retrieving an existing one
// Either way we should set it to an empty string
if ( typeof $scope . Backup . Description !== 'string' ) {
$scope . Backup . Description = '' ;
}
2016-09-15 11:39:27 +02:00
$scope . Backup . Sources = $scope . Backup . Sources || [];
for ( var ix in filters )
$scope . Backup . Filters . push (( filters [ ix ]. Include ? '+' : '-' ) + filters [ ix ]. Expression );
$scope . ExcludeLargeFiles = ( extopts [ '--skip-files-larger-than' ] || '' ). trim (). length > 0 ;
if ( $scope . ExcludeLargeFiles )
$scope . Options [ '--skip-files-larger-than' ] = extopts [ '--skip-files-larger-than' ];
var exclattr = ( extopts [ '--exclude-files-attributes' ] || '' ). split ( ',' );
var dispattr = [];
var dispmap = {};
2018-11-19 17:27:11 +01:00
for ( var i = exclattr . length - 1 ; i >= 0 ; i -- ) {
2016-09-15 11:39:27 +02:00
var cmp = ( exclattr [ i ] || '' ). trim (). toLowerCase ();
2018-11-19 17:27:11 +01:00
2016-09-15 11:39:27 +02:00
// Remove empty entries
if ( cmp . length == 0 ) {
exclattr . splice ( i , 1 );
continue ;
}
for ( var j = scope . fileAttributes . length - 1 ; j >= 0 ; j -- ) {
if ( scope . fileAttributes [ j ]. value == cmp ) {
// Remote duplicates
if ( dispmap [ cmp ] == null ) {
dispattr . push ( scope . fileAttributes [ j ]. value );
dispmap [ cmp ] = true ;
}
exclattr . splice ( i , 1 );
2018-11-19 17:27:11 +01:00
break ;
2016-09-15 11:39:27 +02:00
}
}
}
$scope . ExcludeAttributes = dispattr ;
if ( exclattr . length == 0 )
delete extopts [ '--exclude-files-attributes' ];
else
extopts [ '--exclude-files-attributes' ] = exclattr . join ( ',' );
$scope . RepeatPasshrase = $scope . Options [ 'passphrase' ];
$scope . KeepType = '' ;
if (( $scope . Options [ 'keep-time' ] || '' ). trim (). length != 0 )
{
$scope . KeepType = 'time' ;
}
else if (( $scope . Options [ 'keep-versions' ] || '' ). trim (). length != 0 )
{
$scope . Options [ 'keep-versions' ] = parseInt ( $scope . Options [ 'keep-versions' ]);
$scope . KeepType = 'versions' ;
2018-01-22 23:42:31 +01:00
}
else if (( $scope . Options [ 'retention-policy' ] || '' ). trim (). length != 0 )
{
if (( $scope . Options [ 'retention-policy' ] || '' ). trim () == SMART_RETENTION )
$scope . KeepType = 'smart' ;
else
$scope . KeepType = 'custom' ;
2016-09-15 11:39:27 +02:00
}
2016-10-21 15:32:33 +02:00
var delopts = [ '--skip-files-larger-than' , '--no-encryption' ];
2016-09-15 11:39:27 +02:00
for ( var n in delopts )
delete extopts [ delopts [ n ]];
$scope . ExtendedOptions = AppUtils . serializeAdvancedOptionsToArray ( extopts );
2018-11-19 17:27:11 +01:00
2017-01-25 12:01:01 +01:00
$scope . servermodulesettings = {};
AppUtils . extractServerModuleOptions ( $scope . ExtendedOptions , $scope . ServerModules , $scope . servermodulesettings , 'SupportedLocalCommands' );
2016-09-15 11:39:27 +02:00
2016-11-27 12:02:34 +01:00
$scope . showAdvanced = $scope . ExtendedOptions . length > 0 ;
2016-09-15 11:39:27 +02:00
var now = new Date ();
if ( $scope . Schedule != null ) {
var time = AppUtils . parseDate ( $scope . Schedule . Time );
2015-08-26 12:37:35 +01:00
if ( isNaN ( time )) {
time = AppUtils . parseDate ( "1970-01-01T" + $scope . Schedule . Time );
if ( ! isNaN ( time ))
2016-09-15 11:39:27 +02:00
time = new Date ( now . getFullYear (), now . getMonth (), now . getDate (), time . getHours (), time . getMinutes (), time . getSeconds ());
2015-08-26 12:37:35 +01:00
if ( time < now )
2016-09-15 11:39:27 +02:00
time = new Date ( time . setDate ( time . getDate () + 1 ));
2015-08-26 12:37:35 +01:00
}
if ( isNaN ( time )) {
time = new Date ( now . getFullYear (), now . getMonth (), now . getDate (), 13 , 0 , 0 );
if ( time < now )
2016-09-15 11:39:27 +02:00
time = new Date ( time . setDate ( time . getDate () + 1 ));
2015-08-26 12:37:35 +01:00
}
$scope . Schedule . Time = time ;
2016-09-15 11:39:27 +02:00
} else {
2015-08-26 12:37:35 +01:00
time = new Date ( now . getFullYear (), now . getMonth (), now . getDate (), 13 , 0 , 0 );
if ( time < now )
2016-09-15 11:39:27 +02:00
time = new Date ( time . setDate ( time . getDate () + 1 ));
2015-08-26 12:37:35 +01:00
2016-09-15 11:39:27 +02:00
oldSchedule = {
Repeat : '1D' ,
Time : time
};
}
}
2015-08-21 22:04:39 +02:00
2017-01-25 12:01:01 +01:00
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 ;
};
2016-09-15 11:39:27 +02:00
function reloadOptionsList ()
{
if ( $scope . Options == null )
return ;
2015-12-07 22:03:40 +01:00
2016-09-15 11:39:27 +02:00
var encmodule = $scope . Options [ 'encryption-module' ] || '' ;
var compmodule = $scope . Options [ 'compression-module' ] || $scope . Options [ '--compression-module' ] || 'zip' ;
var backmodule = $scope . Backup . TargetURL || '' ;
var ix = backmodule . indexOf ( ':' );
if ( ix > 0 )
backmodule = backmodule . substr ( 0 , ix );
2015-12-07 22:03:40 +01:00
2018-11-19 17:27:11 +01:00
$scope . ExtendedOptionList = AppUtils . buildOptionList ( $scope . SystemInfo , encmodule , compmodule , backmodule );
2017-01-25 12:01:01 +01:00
setupServerModules ();
2018-11-19 17:27:11 +01:00
AppUtils . extractServerModuleOptions ( $scope . ExtendedOptions , $scope . ServerModules , $scope . servermodulesettings , 'SupportedLocalCommands' );
2016-09-15 11:39:27 +02:00
};
2015-12-07 22:03:40 +01:00
2017-03-22 23:28:10 +01:00
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' ];
});
};
2017-01-25 12:01:01 +01:00
setupServerModules ();
2016-09-15 11:39:27 +02:00
$scope . $watch ( "Options['encryption-module']" , reloadOptionsList );
$scope . $watch ( "Options['compression-module']" , reloadOptionsList );
$scope . $watch ( "Options['--compression-module']" , reloadOptionsList );
$scope . $watch ( "Backup.TargetURL" , reloadOptionsList );
$scope . $on ( 'systeminfochanged' , reloadOptionsList );
2016-09-20 15:36:39 +02:00
$scope . $watch ( 'ExcludeLargeFiles' , function () {
if ( $scope . Options != null && $scope . Options [ '--skip-files-larger-than' ] == null )
$scope . Options [ '--skip-files-larger-than' ] = '100MB' ;
});
2017-03-22 23:28:10 +01:00
$scope . $watch ( "Schedule.AllowedDays" , checkAllowedDaysConfig , true );
2015-12-07 22:03:40 +01:00
2016-09-15 11:39:27 +02:00
if ( $routeParams . backupid == null ) {
2015-08-21 22:04:39 +02:00
2016-09-15 11:39:27 +02:00
AppService . get ( '/backupdefaults' ). then ( function ( data ) {
2015-08-21 22:04:39 +02:00
2016-09-15 11:39:27 +02:00
$scope . rawddata = data . data . data ;
2017-02-27 00:03:46 +01:00
if ( $location . $$path . indexOf ( '/add-import' ) == 0 && $rootScope . importConfig != null )
angular . merge ( $scope . rawddata , $rootScope . importConfig );
2016-09-15 11:39:27 +02:00
setupScope ( $scope . rawddata );
2015-08-21 22:04:39 +02:00
2016-09-15 11:39:27 +02:00
}, function ( data ) {
2016-10-02 15:18:34 +02:00
AppUtils . connectionError ( gettextCatalog . getString ( 'Failed to read backup defaults:' ) + ' ' , data );
2016-09-15 11:39:27 +02:00
$location . path ( '/' );
});
} else {
2015-08-21 22:04:39 +02:00
2016-09-15 11:39:27 +02:00
AppService . get ( '/backup/' + $routeParams . backupid ). then ( function ( data ) {
2015-08-21 22:04:39 +02:00
2016-09-15 11:39:27 +02:00
$scope . rawddata = data . data . data ;
setupScope ( $scope . rawddata );
2015-08-21 22:04:39 +02:00
2016-09-15 11:39:27 +02:00
}, function () {
AppUtils . connectionError . apply ( AppUtils , arguments );
$location . path ( '/' );
});
}
});