2017-01-31 07:50:28 +01:00
|
|
|
const Backbone = require('backbone');
|
|
|
|
const FeatureDetector = require('../../util/feature-detector');
|
|
|
|
const PasswordGenerator = require('../../util/password-generator');
|
|
|
|
const Alerts = require('../../comp/alerts');
|
|
|
|
const Launcher = require('../../comp/launcher');
|
|
|
|
const Storage = require('../../storage');
|
|
|
|
const Links = require('../../const/links');
|
|
|
|
const Format = require('../../util/format');
|
|
|
|
const Locale = require('../../util/locale');
|
|
|
|
const UrlUtil = require('../../util/url-util');
|
|
|
|
const kdbxweb = require('kdbxweb');
|
|
|
|
const FileSaver = require('filesaver');
|
2015-10-17 23:49:24 +02:00
|
|
|
|
2016-08-16 22:11:54 +02:00
|
|
|
const DefaultBackupPath = 'Backups/{name}.{date}.bak';
|
2016-08-16 22:55:17 +02:00
|
|
|
const DefaultBackupSchedule = '1w';
|
2016-08-16 22:11:54 +02:00
|
|
|
|
2017-01-31 07:50:28 +01:00
|
|
|
const SettingsFileView = Backbone.View.extend({
|
2015-12-16 22:50:45 +01:00
|
|
|
template: require('templates/settings/settings-file.hbs'),
|
2015-10-17 23:49:24 +02:00
|
|
|
|
2015-10-18 16:02:00 +02:00
|
|
|
events: {
|
2015-12-08 20:18:35 +01:00
|
|
|
'click .settings__file-button-save-default': 'saveDefault',
|
2016-03-26 09:57:58 +01:00
|
|
|
'click .settings__file-button-save-choose': 'toggleChooser',
|
2015-11-07 21:37:54 +01:00
|
|
|
'click .settings__file-button-close': 'closeFile',
|
2016-03-26 09:57:58 +01:00
|
|
|
'click .settings__file-save-to-file': 'saveToFile',
|
|
|
|
'click .settings__file-save-to-xml': 'saveToXml',
|
|
|
|
'click .settings__file-save-to-storage': 'saveToStorage',
|
2015-10-24 18:43:30 +02:00
|
|
|
'change #settings__file-key-file': 'keyFileChange',
|
2015-12-15 18:42:44 +01:00
|
|
|
'click #settings__file-file-select-link': 'triggerSelectFile',
|
2015-10-24 18:43:30 +02:00
|
|
|
'change #settings__file-file-select': 'fileSelected',
|
2015-10-22 22:51:40 +02:00
|
|
|
'focus #settings__file-master-pass': 'focusMasterPass',
|
2016-03-04 17:39:29 +01:00
|
|
|
'input #settings__file-master-pass': 'changeMasterPass',
|
2015-10-24 18:43:30 +02:00
|
|
|
'blur #settings__file-master-pass': 'blurMasterPass',
|
2016-03-04 17:39:29 +01:00
|
|
|
'input #settings__file-name': 'changeName',
|
|
|
|
'input #settings__file-def-user': 'changeDefUser',
|
2016-08-16 22:55:17 +02:00
|
|
|
'change #settings__file-backup-enabled': 'changeBackupEnabled',
|
|
|
|
'input #settings__file-backup-path': 'changeBackupPath',
|
|
|
|
'change #settings__file-backup-storage': 'changeBackupStorage',
|
|
|
|
'change #settings__file-backup-schedule': 'changeBackupSchedule',
|
|
|
|
'click .settings__file-button-backup': 'backupFile',
|
2015-10-24 18:43:30 +02:00
|
|
|
'change #settings__file-trash': 'changeTrash',
|
2016-03-04 17:39:29 +01:00
|
|
|
'input #settings__file-hist-len': 'changeHistoryLength',
|
|
|
|
'input #settings__file-hist-size': 'changeHistorySize',
|
2016-07-03 18:46:43 +02:00
|
|
|
'input #settings__file-key-rounds': 'changeKeyRounds',
|
2017-01-31 23:18:58 +01:00
|
|
|
'input #settings__file-key-change-force': 'changeKeyChangeForce',
|
|
|
|
'input .settings__input-kdf': 'changeKdfParameter'
|
2015-10-18 16:02:00 +02:00
|
|
|
},
|
|
|
|
|
2015-12-08 20:18:35 +01:00
|
|
|
appModel: null,
|
|
|
|
|
2015-10-23 22:12:12 +02:00
|
|
|
initialize: function() {
|
2016-03-04 17:39:29 +01:00
|
|
|
this.listenTo(this.model, 'change:syncing change:syncError change:syncDate', this.deferRender);
|
2015-10-23 22:12:12 +02:00
|
|
|
},
|
|
|
|
|
2015-10-17 23:49:24 +02:00
|
|
|
render: function() {
|
2017-01-31 07:50:28 +01:00
|
|
|
const storageProviders = [];
|
|
|
|
const fileStorage = this.model.get('storage');
|
2017-05-15 22:27:01 +02:00
|
|
|
let canBackup = false;
|
2016-07-17 13:30:38 +02:00
|
|
|
Object.keys(Storage).forEach(name => {
|
2017-01-31 07:50:28 +01:00
|
|
|
const prv = Storage[name];
|
2016-08-20 10:58:03 +02:00
|
|
|
if (!prv.system && prv.enabled) {
|
2016-08-21 18:07:59 +02:00
|
|
|
storageProviders.push({
|
|
|
|
name: prv.name, icon: prv.icon, iconSvg: prv.iconSvg, own: name === fileStorage, backup: prv.backup
|
|
|
|
});
|
2017-05-15 22:27:01 +02:00
|
|
|
if (!canBackup && prv.backup) {
|
|
|
|
canBackup = true;
|
|
|
|
}
|
2016-03-26 09:57:58 +01:00
|
|
|
}
|
|
|
|
});
|
2016-07-17 13:30:38 +02:00
|
|
|
storageProviders.sort((x, y) => (x.uipos || Infinity) - (y.uipos || Infinity));
|
2017-01-31 07:50:28 +01:00
|
|
|
const backup = this.model.get('backup');
|
2015-10-18 16:02:00 +02:00
|
|
|
this.renderTemplate({
|
2015-10-22 22:39:30 +02:00
|
|
|
cmd: FeatureDetector.actionShortcutSymbol(true),
|
2015-10-25 17:27:34 +01:00
|
|
|
supportFiles: !!Launcher,
|
2015-10-23 23:21:21 +02:00
|
|
|
desktopLink: Links.Desktop,
|
2015-10-22 22:39:30 +02:00
|
|
|
name: this.model.get('name'),
|
2015-10-23 22:12:12 +02:00
|
|
|
path: this.model.get('path'),
|
2015-10-25 17:27:34 +01:00
|
|
|
storage: this.model.get('storage'),
|
2015-10-26 22:07:43 +01:00
|
|
|
syncing: this.model.get('syncing'),
|
2015-12-12 09:53:50 +01:00
|
|
|
syncError: this.model.get('syncError'),
|
|
|
|
syncDate: Format.dtStr(this.model.get('syncDate')),
|
2015-10-25 10:44:19 +01:00
|
|
|
password: PasswordGenerator.present(this.model.get('passwordLength')),
|
2015-10-22 22:39:30 +02:00
|
|
|
defaultUser: this.model.get('defaultUser'),
|
|
|
|
recycleBinEnabled: this.model.get('recycleBinEnabled'),
|
2016-08-21 18:46:44 +02:00
|
|
|
backupEnabled: backup && backup.enabled,
|
2016-08-16 22:11:54 +02:00
|
|
|
backupStorage: backup && backup.storage,
|
|
|
|
backupPath: backup && backup.path || DefaultBackupPath.replace('{name}', this.model.get('name')),
|
2016-08-16 22:55:17 +02:00
|
|
|
backupSchedule: backup ? backup.schedule : DefaultBackupSchedule,
|
2015-10-22 22:39:30 +02:00
|
|
|
historyMaxItems: this.model.get('historyMaxItems'),
|
|
|
|
historyMaxSize: Math.round(this.model.get('historyMaxSize') / 1024 / 1024),
|
2016-03-26 09:57:58 +01:00
|
|
|
keyEncryptionRounds: this.model.get('keyEncryptionRounds'),
|
2016-07-03 18:46:43 +02:00
|
|
|
keyChangeForce: this.model.get('keyChangeForce') > 0 ? this.model.get('keyChangeForce') : null,
|
2017-01-31 23:18:58 +01:00
|
|
|
kdfParameters: this.kdfParametersToUi(this.model.get('kdfParameters')),
|
2017-05-15 22:27:01 +02:00
|
|
|
storageProviders: storageProviders,
|
|
|
|
canBackup: canBackup
|
2015-10-18 16:02:00 +02:00
|
|
|
});
|
2015-10-24 18:43:30 +02:00
|
|
|
if (!this.model.get('created')) {
|
|
|
|
this.$el.find('.settings__file-master-pass-warning').toggle(this.model.get('passwordChanged'));
|
|
|
|
}
|
|
|
|
this.renderKeyFileSelect();
|
|
|
|
},
|
|
|
|
|
2017-01-31 23:18:58 +01:00
|
|
|
kdfParametersToUi: function(kdfParameters) {
|
|
|
|
return kdfParameters ? _.extend({}, kdfParameters, { memory: Math.round(kdfParameters.memory / 1024) }) : null;
|
|
|
|
},
|
|
|
|
|
2015-10-24 18:43:30 +02:00
|
|
|
renderKeyFileSelect: function() {
|
2017-01-31 07:50:28 +01:00
|
|
|
const keyFileName = this.model.get('keyFileName');
|
|
|
|
const oldKeyFileName = this.model.get('oldKeyFileName');
|
|
|
|
const keyFileChanged = this.model.get('keyFileChanged');
|
|
|
|
const sel = this.$el.find('#settings__file-key-file');
|
2015-10-24 18:43:30 +02:00
|
|
|
sel.html('');
|
|
|
|
if (keyFileName && keyFileChanged) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const text = keyFileName !== 'Generated' ? Locale.setFileUseKeyFile + ' ' + keyFileName : Locale.setFileUseGenKeyFile;
|
2015-10-24 18:43:30 +02:00
|
|
|
$('<option/>').val('ex').text(text).appendTo(sel);
|
|
|
|
}
|
|
|
|
if (oldKeyFileName) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const useText = keyFileChanged ? Locale.setFileUseOldKeyFile : Locale.setFileUseKeyFile + ' ' + oldKeyFileName;
|
2015-12-17 19:25:25 +01:00
|
|
|
$('<option/>').val('old').text(useText).appendTo(sel);
|
2015-10-24 18:43:30 +02:00
|
|
|
}
|
2015-12-17 19:25:25 +01:00
|
|
|
$('<option/>').val('gen').text(Locale.setFileGenKeyFile).appendTo(sel);
|
|
|
|
$('<option/>').val('none').text(Locale.setFileDontUseKeyFile).appendTo(sel);
|
2015-10-24 18:43:30 +02:00
|
|
|
if (keyFileName && keyFileChanged) {
|
|
|
|
sel.val('ex');
|
|
|
|
} else if (!keyFileName) {
|
|
|
|
sel.val('none');
|
|
|
|
} else if (oldKeyFileName && keyFileName === oldKeyFileName && !keyFileChanged) {
|
|
|
|
sel.val('old');
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2015-12-08 20:18:35 +01:00
|
|
|
validatePassword: function(continueCallback) {
|
2015-10-24 18:43:30 +02:00
|
|
|
if (!this.model.get('passwordLength')) {
|
2015-12-08 19:02:50 +01:00
|
|
|
Alerts.yesno({
|
2015-12-17 19:25:25 +01:00
|
|
|
header: Locale.setFileEmptyPass,
|
|
|
|
body: Locale.setFileEmptyPassBody,
|
2016-07-17 13:30:38 +02:00
|
|
|
success: () => {
|
2015-12-08 20:18:35 +01:00
|
|
|
continueCallback();
|
2015-12-08 19:02:50 +01:00
|
|
|
},
|
2016-07-17 13:30:38 +02:00
|
|
|
cancel: () => {
|
|
|
|
this.$el.find('#settings__file-master-pass').focus();
|
2015-12-08 19:02:50 +01:00
|
|
|
}
|
2015-10-24 18:43:30 +02:00
|
|
|
});
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
2015-10-18 16:02:00 +02:00
|
|
|
},
|
|
|
|
|
2015-12-08 22:00:31 +01:00
|
|
|
save: function(arg) {
|
|
|
|
if (!arg) {
|
|
|
|
arg = {};
|
|
|
|
}
|
|
|
|
arg.startedByUser = true;
|
|
|
|
if (!arg.skipValidation) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const isValid = this.validatePassword(() => {
|
2015-12-08 22:00:31 +01:00
|
|
|
arg.skipValidation = true;
|
2016-07-17 13:30:38 +02:00
|
|
|
this.save(arg);
|
2015-12-08 22:00:31 +01:00
|
|
|
});
|
|
|
|
if (!isValid) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2015-12-12 16:43:43 +01:00
|
|
|
this.appModel.syncFile(this.model, arg);
|
2015-12-08 22:00:31 +01:00
|
|
|
},
|
|
|
|
|
2015-12-08 20:18:35 +01:00
|
|
|
saveDefault: function() {
|
2015-12-08 22:00:31 +01:00
|
|
|
this.save();
|
2015-12-08 20:18:35 +01:00
|
|
|
},
|
|
|
|
|
2016-03-26 09:57:58 +01:00
|
|
|
toggleChooser: function() {
|
|
|
|
this.$el.find('.settings__file-save-choose').toggleClass('hide');
|
|
|
|
},
|
|
|
|
|
2015-12-08 19:02:50 +01:00
|
|
|
saveToFile: function(skipValidation) {
|
2015-12-08 20:18:35 +01:00
|
|
|
if (skipValidation !== true && !this.validatePassword(this.saveToFile.bind(this, true))) {
|
2015-10-24 18:43:30 +02:00
|
|
|
return;
|
|
|
|
}
|
2017-01-31 07:50:28 +01:00
|
|
|
const fileName = this.model.get('name') + '.kdbx';
|
2015-12-10 22:31:47 +01:00
|
|
|
if (Launcher && !this.model.get('storage')) {
|
2016-07-17 13:30:38 +02:00
|
|
|
Launcher.getSaveFileName(fileName, path => {
|
2015-12-10 22:31:47 +01:00
|
|
|
if (path) {
|
2016-07-17 13:30:38 +02:00
|
|
|
this.save({storage: 'file', path: path});
|
2015-12-10 22:31:47 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
2016-07-17 13:30:38 +02:00
|
|
|
this.model.getData(data => {
|
2016-08-20 10:01:33 +02:00
|
|
|
if (!data) {
|
|
|
|
return;
|
|
|
|
}
|
2015-12-10 22:31:47 +01:00
|
|
|
if (Launcher) {
|
2016-07-17 13:30:38 +02:00
|
|
|
Launcher.getSaveFileName(fileName, path => {
|
2015-12-10 22:31:47 +01:00
|
|
|
if (path) {
|
2016-09-16 18:27:58 +02:00
|
|
|
Storage.file.save(path, null, data, err => {
|
2015-12-10 22:31:47 +01:00
|
|
|
if (err) {
|
|
|
|
Alerts.error({
|
2015-12-17 19:25:25 +01:00
|
|
|
header: Locale.setFileSaveError,
|
|
|
|
body: Locale.setFileSaveErrorBody + ' ' + path + ': \n' + err
|
2015-12-10 22:31:47 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
2017-01-31 07:50:28 +01:00
|
|
|
const blob = new Blob([data], {type: 'application/octet-stream'});
|
2015-12-10 22:31:47 +01:00
|
|
|
FileSaver.saveAs(blob, fileName);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2015-10-18 16:02:00 +02:00
|
|
|
},
|
|
|
|
|
2016-03-26 09:57:58 +01:00
|
|
|
saveToXml: function() {
|
2016-07-17 13:30:38 +02:00
|
|
|
this.model.getXml(xml => {
|
2017-01-31 07:50:28 +01:00
|
|
|
const blob = new Blob([xml], {type: 'text/xml'});
|
2015-11-03 22:59:57 +01:00
|
|
|
FileSaver.saveAs(blob, this.model.get('name') + '.xml');
|
2016-07-17 13:30:38 +02:00
|
|
|
});
|
2015-10-18 16:02:00 +02:00
|
|
|
},
|
|
|
|
|
2016-03-26 09:57:58 +01:00
|
|
|
saveToStorage: function(e) {
|
2016-03-27 18:38:33 +02:00
|
|
|
if (this.model.get('syncing') || this.model.get('demo')) {
|
2016-03-26 09:57:58 +01:00
|
|
|
return;
|
|
|
|
}
|
2017-01-31 07:50:28 +01:00
|
|
|
const storageName = $(e.target).closest('.settings__file-save-to-storage').data('storage');
|
|
|
|
const storage = Storage[storageName];
|
2016-03-26 09:57:58 +01:00
|
|
|
if (!storage) {
|
|
|
|
return;
|
|
|
|
}
|
2016-07-17 13:30:38 +02:00
|
|
|
if (this.model.get('storage') === storageName) {
|
|
|
|
this.save();
|
2016-03-27 18:38:33 +02:00
|
|
|
} else {
|
|
|
|
if (!storage.list) {
|
2016-03-27 20:39:16 +02:00
|
|
|
if (storage.name === 'webdav') {
|
|
|
|
Alerts.info({
|
|
|
|
icon: storage.icon,
|
|
|
|
header: Locale.setFileNoWebDavUpload,
|
|
|
|
body: Locale.setFileNoWebDavUploadBody
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
Alerts.notImplemented();
|
|
|
|
}
|
|
|
|
return;
|
2016-03-27 18:38:33 +02:00
|
|
|
}
|
2016-07-17 13:30:38 +02:00
|
|
|
this.model.set('syncing', true);
|
|
|
|
storage.list((err, files) => {
|
|
|
|
this.model.set('syncing', false);
|
2016-03-27 18:38:33 +02:00
|
|
|
if (err) {
|
|
|
|
return;
|
|
|
|
}
|
2017-01-31 07:50:28 +01:00
|
|
|
const expName = this.model.get('name').toLowerCase();
|
|
|
|
const existingFile = _.find(files, file => {
|
2016-03-27 18:38:33 +02:00
|
|
|
return UrlUtil.getDataFileName(file.name).toLowerCase() === expName;
|
|
|
|
});
|
|
|
|
if (existingFile) {
|
|
|
|
Alerts.yesno({
|
|
|
|
header: Locale.setFileAlreadyExists,
|
2016-07-17 13:30:38 +02:00
|
|
|
body: Locale.setFileAlreadyExistsBody.replace('{}', this.model.escape('name')),
|
|
|
|
success: () => {
|
|
|
|
this.model.set('syncing', true);
|
|
|
|
storage.remove(existingFile.path, err => {
|
|
|
|
this.model.set('syncing', false);
|
2016-03-27 18:38:33 +02:00
|
|
|
if (!err) {
|
2016-07-17 13:30:38 +02:00
|
|
|
this.save({storage: storageName});
|
2016-03-27 18:38:33 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
2016-07-17 13:30:38 +02:00
|
|
|
this.save({storage: storageName});
|
2016-03-27 18:38:33 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2016-03-26 09:57:58 +01:00
|
|
|
},
|
|
|
|
|
2015-11-07 21:37:54 +01:00
|
|
|
closeFile: function() {
|
|
|
|
if (this.model.get('modified')) {
|
|
|
|
Alerts.yesno({
|
2015-12-17 19:25:25 +01:00
|
|
|
header: Locale.setFileUnsaved,
|
|
|
|
body: Locale.setFileUnsavedBody,
|
2015-11-07 21:37:54 +01:00
|
|
|
buttons: [
|
2015-12-17 19:25:25 +01:00
|
|
|
{result: 'close', title: Locale.setFileCloseNoSave, error: true},
|
|
|
|
{result: '', title: Locale.setFileDontClose}
|
2015-11-07 21:37:54 +01:00
|
|
|
],
|
2016-07-17 13:30:38 +02:00
|
|
|
success: result => {
|
2015-11-07 21:37:54 +01:00
|
|
|
if (result === 'close') {
|
2016-07-17 13:30:38 +02:00
|
|
|
this.closeFileNoCheck();
|
2015-11-07 21:37:54 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} else {
|
|
|
|
this.closeFileNoCheck();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
closeFileNoCheck: function() {
|
2015-12-08 20:18:35 +01:00
|
|
|
this.appModel.closeFile(this.model);
|
2015-11-07 21:37:54 +01:00
|
|
|
},
|
|
|
|
|
2015-10-24 18:43:30 +02:00
|
|
|
keyFileChange: function(e) {
|
2015-10-22 20:03:44 +02:00
|
|
|
switch (e.target.value) {
|
2015-10-24 18:43:30 +02:00
|
|
|
case 'old':
|
|
|
|
this.selectOldKeyFile();
|
2015-10-22 20:03:44 +02:00
|
|
|
break;
|
|
|
|
case 'gen':
|
|
|
|
this.generateKeyFile();
|
|
|
|
break;
|
2015-10-24 18:43:30 +02:00
|
|
|
case 'none':
|
2015-10-22 20:03:44 +02:00
|
|
|
this.clearKeyFile();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
2015-10-24 18:43:30 +02:00
|
|
|
selectOldKeyFile: function() {
|
|
|
|
this.model.resetKeyFile();
|
|
|
|
this.renderKeyFileSelect();
|
2015-10-22 20:03:44 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
generateKeyFile: function() {
|
2017-01-31 07:50:28 +01:00
|
|
|
const keyFile = this.model.generateAndSetKeyFile();
|
|
|
|
const blob = new Blob([keyFile], {type: 'application/octet-stream'});
|
2015-10-24 18:43:30 +02:00
|
|
|
FileSaver.saveAs(blob, this.model.get('name') + '.key');
|
|
|
|
this.renderKeyFileSelect();
|
2015-10-22 20:03:44 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
clearKeyFile: function() {
|
2015-10-24 18:43:30 +02:00
|
|
|
this.model.removeKeyFile();
|
|
|
|
this.renderKeyFileSelect();
|
|
|
|
},
|
|
|
|
|
|
|
|
triggerSelectFile: function() {
|
|
|
|
this.$el.find('#settings__file-file-select').click();
|
|
|
|
},
|
|
|
|
|
|
|
|
fileSelected: function(e) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const file = e.target.files[0];
|
|
|
|
const reader = new FileReader();
|
2016-07-17 13:30:38 +02:00
|
|
|
reader.onload = e => {
|
2017-01-31 07:50:28 +01:00
|
|
|
const res = e.target.result;
|
2015-10-24 18:43:30 +02:00
|
|
|
this.model.setKeyFile(res, file.name);
|
|
|
|
this.renderKeyFileSelect();
|
2016-07-17 13:30:38 +02:00
|
|
|
};
|
2015-10-24 18:43:30 +02:00
|
|
|
reader.readAsArrayBuffer(file);
|
2015-10-22 22:39:30 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
focusMasterPass: function(e) {
|
2015-12-12 16:43:43 +01:00
|
|
|
e.target.value = '';
|
2015-10-23 22:12:12 +02:00
|
|
|
e.target.setAttribute('type', 'text');
|
2015-10-22 22:51:40 +02:00
|
|
|
},
|
|
|
|
|
2016-03-04 17:39:29 +01:00
|
|
|
changeMasterPass: function(e) {
|
2015-10-22 22:51:40 +02:00
|
|
|
if (!e.target.value) {
|
2015-10-24 18:43:30 +02:00
|
|
|
this.model.resetPassword();
|
|
|
|
this.$el.find('.settings__file-master-pass-warning').hide();
|
2015-10-23 22:12:12 +02:00
|
|
|
} else {
|
2015-10-24 18:43:30 +02:00
|
|
|
this.model.setPassword(kdbxweb.ProtectedValue.fromString(e.target.value));
|
|
|
|
if (!this.model.get('created')) {
|
|
|
|
this.$el.find('.settings__file-master-pass-warning').show();
|
|
|
|
}
|
2015-10-22 22:51:40 +02:00
|
|
|
}
|
2016-03-04 17:39:29 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
blurMasterPass: function(e) {
|
|
|
|
if (!e.target.value) {
|
|
|
|
this.model.resetPassword();
|
|
|
|
e.target.value = PasswordGenerator.present(this.model.get('passwordLength'));
|
|
|
|
this.$el.find('.settings__file-master-pass-warning').hide();
|
|
|
|
}
|
2015-10-23 22:12:12 +02:00
|
|
|
e.target.setAttribute('type', 'password');
|
2015-10-24 18:43:30 +02:00
|
|
|
},
|
|
|
|
|
2016-03-04 17:39:29 +01:00
|
|
|
changeName: function(e) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const value = $.trim(e.target.value);
|
2015-10-24 18:43:30 +02:00
|
|
|
if (!value) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.model.setName(value);
|
|
|
|
},
|
|
|
|
|
2016-03-04 17:39:29 +01:00
|
|
|
changeDefUser: function(e) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const value = $.trim(e.target.value);
|
2015-10-24 18:43:30 +02:00
|
|
|
this.model.setDefaultUser(value);
|
|
|
|
},
|
|
|
|
|
2016-08-16 22:55:17 +02:00
|
|
|
changeBackupEnabled: function(e) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const enabled = e.target.checked;
|
2016-08-16 22:55:17 +02:00
|
|
|
let backup = this.model.get('backup');
|
|
|
|
if (!backup) {
|
|
|
|
backup = { enabled: enabled, schedule: DefaultBackupSchedule };
|
2017-01-31 07:50:28 +01:00
|
|
|
const defaultPath = DefaultBackupPath.replace('{name}', this.model.get('name'));
|
2016-08-16 22:55:17 +02:00
|
|
|
if (Launcher) {
|
|
|
|
backup.storage = 'file';
|
2016-08-21 18:07:59 +02:00
|
|
|
backup.path = Launcher.getDocumentsPath(defaultPath);
|
2016-08-16 22:55:17 +02:00
|
|
|
} else {
|
2016-08-21 18:07:59 +02:00
|
|
|
backup.storage = 'dropbox';
|
|
|
|
backup.path = defaultPath;
|
2016-08-16 22:55:17 +02:00
|
|
|
}
|
2016-08-21 18:07:59 +02:00
|
|
|
// } else if (this.model.get('storage') === 'webdav') {
|
|
|
|
// backup.storage = 'webdav';
|
|
|
|
// backup.path = this.model.get('path') + '.{date}.bak';
|
|
|
|
// } else if (this.model.get('storage')) {
|
|
|
|
// backup.storage = this.model.get('storage');
|
|
|
|
// backup.path = DefaultBackupPath.replace('{name}', this.model.get('name'));
|
|
|
|
// } else {
|
|
|
|
// Object.keys(Storage).forEach(name => {
|
|
|
|
// var prv = Storage[name];
|
|
|
|
// if (!backup.storage && !prv.system && prv.enabled) {
|
|
|
|
// backup.storage = name;
|
|
|
|
// }
|
|
|
|
// });
|
|
|
|
// if (!backup.storage) {
|
|
|
|
// e.target.checked = false;
|
|
|
|
// return;
|
|
|
|
// }
|
|
|
|
// backup.path = DefaultBackupPath.replace('{name}', this.model.get('name'));
|
|
|
|
// }
|
2016-08-16 22:55:17 +02:00
|
|
|
this.$el.find('#settings__file-backup-storage').val(backup.storage);
|
|
|
|
this.$el.find('#settings__file-backup-path').val(backup.path);
|
|
|
|
}
|
2016-08-16 22:11:54 +02:00
|
|
|
this.$el.find('.settings__file-backups').toggleClass('hide', !enabled);
|
2016-08-16 22:55:17 +02:00
|
|
|
backup.enabled = enabled;
|
2016-08-16 23:24:08 +02:00
|
|
|
this.setBackup(backup);
|
2016-08-16 22:55:17 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
changeBackupPath: function(e) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const backup = this.model.get('backup');
|
2016-08-16 22:55:17 +02:00
|
|
|
backup.path = e.target.value.trim();
|
2016-08-16 23:24:08 +02:00
|
|
|
this.setBackup(backup);
|
2016-08-16 22:55:17 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
changeBackupStorage: function(e) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const backup = this.model.get('backup');
|
2016-08-16 22:55:17 +02:00
|
|
|
backup.storage = e.target.value;
|
2016-08-16 23:24:08 +02:00
|
|
|
this.setBackup(backup);
|
2016-08-16 22:55:17 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
changeBackupSchedule: function(e) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const backup = this.model.get('backup');
|
2016-08-16 22:55:17 +02:00
|
|
|
backup.schedule = e.target.value;
|
2016-08-16 23:24:08 +02:00
|
|
|
this.setBackup(backup);
|
|
|
|
},
|
|
|
|
|
|
|
|
setBackup: function(backup) {
|
2016-08-16 22:55:17 +02:00
|
|
|
this.model.set('backup', backup);
|
2016-08-16 23:24:08 +02:00
|
|
|
this.appModel.setFileBackup(this.model.id, backup);
|
2016-08-16 22:55:17 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
backupFile: function() {
|
2016-08-20 10:01:33 +02:00
|
|
|
if (this.backupInProgress) {
|
|
|
|
return;
|
|
|
|
}
|
2017-01-31 07:50:28 +01:00
|
|
|
const backupButton = this.$el.find('.settings__file-button-backup');
|
2016-08-20 10:01:33 +02:00
|
|
|
backupButton.text(Locale.setFileBackupNowWorking);
|
|
|
|
this.model.getData(data => {
|
|
|
|
if (!data) {
|
|
|
|
this.backupInProgress = false;
|
|
|
|
backupButton.text(Locale.setFileBackupNow);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.appModel.backupFile(this.model, data, (err) => {
|
|
|
|
this.backupInProgress = false;
|
|
|
|
backupButton.text(Locale.setFileBackupNow);
|
|
|
|
if (err) {
|
|
|
|
Alerts.error({
|
|
|
|
title: Locale.setFileBackupError,
|
|
|
|
body: Locale.setFileBackupErrorDescription + '<pre class="modal__pre">' + _.escape(err.toString()) + '</pre>'
|
|
|
|
});
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
2016-08-16 22:11:54 +02:00
|
|
|
},
|
|
|
|
|
2015-10-24 18:43:30 +02:00
|
|
|
changeTrash: function(e) {
|
|
|
|
this.model.setRecycleBinEnabled(e.target.checked);
|
|
|
|
},
|
|
|
|
|
2016-03-04 17:39:29 +01:00
|
|
|
changeHistoryLength: function(e) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const value = +e.target.value;
|
2015-10-24 18:43:30 +02:00
|
|
|
if (isNaN(value)) {
|
|
|
|
e.target.value = this.model.get('historyMaxItems');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.model.setHistoryMaxItems(value);
|
|
|
|
},
|
|
|
|
|
2016-03-04 17:39:29 +01:00
|
|
|
changeHistorySize: function(e) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const value = +e.target.value;
|
2015-10-24 18:43:30 +02:00
|
|
|
if (isNaN(value)) {
|
|
|
|
e.target.value = this.model.get('historyMaxSize') / 1024 / 1024;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.model.setHistoryMaxSize(value * 1024 * 1024);
|
|
|
|
},
|
|
|
|
|
2016-03-04 17:39:29 +01:00
|
|
|
changeKeyRounds: function(e) {
|
2017-01-31 07:50:28 +01:00
|
|
|
const value = +e.target.value;
|
2015-10-24 18:43:30 +02:00
|
|
|
if (isNaN(value)) {
|
|
|
|
e.target.value = this.model.get('keyEncryptionRounds');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.model.setKeyEncryptionRounds(value);
|
2016-07-03 18:46:43 +02:00
|
|
|
},
|
|
|
|
|
|
|
|
changeKeyChangeForce: function(e) {
|
2017-01-31 07:50:28 +01:00
|
|
|
let value = Math.round(e.target.value);
|
2016-07-03 18:46:43 +02:00
|
|
|
if (isNaN(value) || value <= 0) {
|
|
|
|
value = -1;
|
|
|
|
}
|
|
|
|
this.model.setKeyChange(true, value);
|
2017-01-31 23:18:58 +01:00
|
|
|
},
|
|
|
|
|
|
|
|
changeKdfParameter: function(e) {
|
|
|
|
const field = $(e.target).data('field');
|
|
|
|
const mul = $(e.target).data('mul') || 1;
|
|
|
|
const value = e.target.value * mul;
|
|
|
|
if (isNaN(value)) {
|
|
|
|
e.target.value = Math.round(this.model.get('kdfParameters')[field] / mul);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (value > 0) {
|
|
|
|
this.model.setKdfParameter(field, value);
|
|
|
|
}
|
2015-10-17 23:49:24 +02:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2016-03-14 06:04:55 +01:00
|
|
|
module.exports = SettingsFileView;
|