diff --git a/app/view/preferences/Preferences.js b/app/view/preferences/Preferences.js index da2cf920..bdb63b95 100644 --- a/app/view/preferences/Preferences.js +++ b/app/view/preferences/Preferences.js @@ -90,6 +90,45 @@ Ext.define('Rambox.view.preferences.Preferences',{ ,value: config.systemtray_indicator ,hidden: Ext.os.is.MacOS } + ,{ + xtype: 'fieldset' + ,title: 'Master Password - Ask for password on startup' + ,collapsed: !config.master_password + ,checkboxToggle: true + ,checkboxName: 'master_password' + ,margin: '10 0 0 0' + ,padding: 10 + ,layout: 'hbox' + ,defaults: { labelAlign: 'top' } + ,items: [ + { + xtype: 'textfield' + ,inputType: 'password' + ,fieldLabel: 'Password' + ,name: 'master_password1' + ,itemId: 'pass' + ,flex: 1 + ,listeners: { + validitychange: function(field) { + field.next().validate(); + }, + blur: function(field) { + field.next().validate(); + } + } + } + ,{ + xtype: 'textfield' + ,inputType: 'password' + ,fieldLabel: 'Repeat Password' + ,name: 'master_password2' + ,margin: '0 0 0 10' + ,vtype: 'password' + ,initialPassField: 'pass' + ,flex: 1 + } + ] + } ,{ xtype: 'fieldset' ,title: 'Proxy (needs to relaunch) - Free IP:PORT Proxy List' diff --git a/app/view/preferences/PreferencesController.js b/app/view/preferences/PreferencesController.js index a1f13295..b635e075 100644 --- a/app/view/preferences/PreferencesController.js +++ b/app/view/preferences/PreferencesController.js @@ -13,6 +13,13 @@ Ext.define('Rambox.view.preferences.PreferencesController', { var values = me.getView().down('form').getForm().getFieldValues(); + // Master Password + if ( values.master_password && (Ext.isEmpty(values.master_password1) || Ext.isEmpty(values.master_password2)) ) return; + if ( values.master_password && (values.master_password1 !== values.master_password2) ) return; + if ( values.master_password ) values.master_password = Rambox.util.MD5.encypt(values.master_password1); + delete values.master_password1; + delete values.master_password2; + // Proxy if ( values.proxy && (Ext.isEmpty(values.proxyHost) || Ext.isEmpty(values.proxyPort)) ) return; diff --git a/electron/main.js b/electron/main.js index 631a5073..f07ad6b4 100644 --- a/electron/main.js +++ b/electron/main.js @@ -27,6 +27,7 @@ const config = new Config({ ,keep_in_taskbar_on_close: true ,start_minimized: false ,systemtray_indicator: true + ,master_password: false ,proxy: false ,proxyHost: '' ,proxyPort: '' @@ -203,6 +204,16 @@ function createWindow () { }); } +let mainMasterPasswordWindow; +function createMasterPasswordWindow() { + mainMasterPasswordWindow = new BrowserWindow({ + backgroundColor: '#0675A0' + ,frame: false + }); + mainMasterPasswordWindow.loadURL('file://' + __dirname + '/../masterpassword.html'); + mainMasterPasswordWindow.on('close', function() { mainMasterPasswordWindow = null }); +} + function updateBadge(title) { var messageCount = title.match(/\d+/g) ? parseInt(title.match(/\d+/g).join("")) : 0; @@ -245,6 +256,15 @@ ipcMain.on('setConfig', function(event, values) { updateBadge(mainWindow.getTitle()); }); +ipcMain.on('validateMasterPassword', function(event, pass) { + if ( config.get('master_password') === require('crypto').createHash('md5').update(pass).digest('hex') ) { + createWindow(); + mainMasterPasswordWindow.close(); + event.returnValue = true; + } + event.returnValue = false; +}); + // Handle Service Notifications ipcMain.on('setServiceNotifications', function(event, partition, op) { session.fromPartition(partition).setPermissionRequestHandler(function(webContents, permission, callback) { @@ -354,7 +374,9 @@ if ( config.get('proxy') ) app.commandLine.appendSwitch('proxy-server', config.g // This method will be called when Electron has finished // initialization and is ready to create browser windows. -app.on('ready', createWindow); +app.on('ready', function() { + config.get('master_password') ? createMasterPasswordWindow() : createWindow(); +}); // Quit when all windows are closed. app.on('window-all-closed', function () { @@ -368,8 +390,8 @@ app.on('window-all-closed', function () { app.on('activate', function () { // On OS X it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. - if (mainWindow === null) { - createWindow(); + if (mainWindow === null && mainMasterPasswordWindow === null ) { + config.get('master_password') ? createMasterPasswordWindow() : createWindow(); } }); diff --git a/masterpassword.html b/masterpassword.html new file mode 100644 index 00000000..264f30ee --- /dev/null +++ b/masterpassword.html @@ -0,0 +1,28 @@ + + + + + + + Rambox + + +
+
Master Password
+
+ + + diff --git a/overrides/form/field/VTypes.js b/overrides/form/field/VTypes.js new file mode 100644 index 00000000..551c5787 --- /dev/null +++ b/overrides/form/field/VTypes.js @@ -0,0 +1,37 @@ +Ext.apply(Ext.form.field.VTypes, { + daterange: function(val, field) { + var date = field.parseDate(val); + + if (!date) { + return false; + } + if (field.startDateField && (!this.dateRangeMax || (date.getTime() != this.dateRangeMax.getTime()))) { + var start = field.up('form').down('#' + field.startDateField); + start.setMaxValue(date); + start.validate(); + this.dateRangeMax = date; + } else if (field.endDateField && (!this.dateRangeMin || (date.getTime() != this.dateRangeMin.getTime()))) { + var end = field.up('form').down('#' + field.endDateField); + end.setMinValue(date); + end.validate(); + this.dateRangeMin = date; + } + /* + * Always return true since we're only using this vtype to set the + * min/max allowed values (these are tested for after the vtype test) + */ + return true; + }, + + daterangeText: 'Start date must be less than end date', + + password: function(val, field) { + if (field.initialPassField) { + var pwd = field.up('form').down('#' + field.initialPassField); + return (val == pwd.getValue()); + } + return true; + }, + + passwordText: 'Passwords do not match' +});