From 6620244d03dc9a4c774117a8aec225941b05bfe1 Mon Sep 17 00:00:00 2001 From: Mikunj Date: Wed, 5 Dec 2018 16:35:28 +1100 Subject: [PATCH] Show main window on correct password; --- _locales/en/messages.json | 8 +++++ app/password_util.js | 9 +++++ background.html | 2 +- js/views/launcher_view.js | 22 +++++++++--- launcher.html | 13 +++++--- launcher_preload.js | 13 +++++++- main.js | 68 ++++++++++++++++++++++++++------------ stylesheets/_global.scss | 2 +- stylesheets/_launcher.scss | 24 ++++++++++---- 9 files changed, 122 insertions(+), 39 deletions(-) create mode 100644 app/password_util.js diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 17e41fc90..39ac0e218 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1684,5 +1684,13 @@ "copiedMnemonic": { "message": "Copied mnemonic to clipboard", "description": "A toast message telling the user that the mnemonic was copied" + }, + + "launcherViewTitle": { + "message": "Type in your password", + "description": "The title shown when user needs to type in a password to unlock the messenger" + }, + "unlock": { + "message": "Unlock" } } diff --git a/app/password_util.js b/app/password_util.js new file mode 100644 index 000000000..e2fef063a --- /dev/null +++ b/app/password_util.js @@ -0,0 +1,9 @@ +const { sha512 } = require('js-sha512'); + +const generateHash = (phrase) => sha512(phrase); +const matchesHash = (phrase, hash) => sha512(phrase) === hash; + +module.exports = { + generateHash, + matchesHash, +}; \ No newline at end of file diff --git a/background.html b/background.html index 84f605bda..482796562 100644 --- a/background.html +++ b/background.html @@ -598,7 +598,7 @@ diff --git a/launcher_preload.js b/launcher_preload.js index fdd5041da..3c50a6796 100644 --- a/launcher_preload.js +++ b/launcher_preload.js @@ -4,6 +4,7 @@ const { ipcRenderer } = require('electron'); const url = require('url'); const i18n = require('./js/modules/i18n'); +const passwordUtil = require('./app/password_util'); const userConfig = require('./app/user_config'); const config = url.parse(window.location.toString(), true).query; @@ -22,10 +23,20 @@ window.Signal = Signal.setup({ getRegionCode: () => null, }); +window.passwordUtil = passwordUtil; window.userConfig = userConfig; window.getEnvironment = () => config.environment; window.getVersion = () => config.version; window.getAppInstance = () => config.appInstance; -window.onLogin = (passPhrase) => ipcRenderer.send('launcher_login', passPhrase); +window.onLogin = (passPhrase) => new Promise((resolve, reject) => { + ipcRenderer.once('launcher-login-response', (event, error) => { + if (error) { + return reject(error); + } + return resolve(); + }); + ipcRenderer.send('launcher-login', passPhrase); +}); + require('./js/logging'); diff --git a/main.js b/main.js index 94a02b58f..c921d916c 100644 --- a/main.js +++ b/main.js @@ -51,6 +51,7 @@ const config = require('./app/config'); // Very important to put before the single instance check, since it is based on the // userData directory. const userConfig = require('./app/user_config'); +const passwordUtil = require('./app/password_util'); const importMode = process.argv.some(arg => arg === '--import') || config.get('import'); @@ -306,12 +307,6 @@ function createWindow() { mainWindow.flashFrame(false); }); - // Ingested in preload.js via a sendSync call - ipc.on('locale-data', event => { - // eslint-disable-next-line no-param-reassign - event.returnValue = locale.messages; - }); - if (config.environment === 'test') { mainWindow.loadURL(prepareURL([__dirname, 'test', 'index.html'])); } else if (config.environment === 'test-lib') { @@ -460,12 +455,6 @@ function showLauncher() { captureClicks(launcherWindow); - // Ingested in preload.js via a sendSync call - ipc.on('locale-data', event => { - // eslint-disable-next-line no-param-reassign - event.returnValue = locale.messages; - }); - launcherWindow.on('close', e => { // If the application is terminating, just do the default if ( @@ -732,6 +721,19 @@ app.on('ready', async () => { locale = loadLocale({ appLocale, logger }); } + const key = getDefaultSQLKey(); + + // If we have a password set then show the launcher + // Otherwise show the main window + const passHash = userConfig.get('passHash'); + if (passHash) { + showLauncher(); + } else { + await showMainWindow(key); + } +}); + +function getDefaultSQLKey() { let key = userConfig.get('key'); if (!key) { console.log( @@ -742,15 +744,8 @@ app.on('ready', async () => { userConfig.set('key', key); } - // If we have a password set then show the launcher - // Otherwise show the main window - const passHash = userConfig.get('passHash'); - if (!passHash) { - showLauncher(); - } else { - await showMainWindow(key); - } -}); + return key; +} async function showMainWindow(sqlKey) { const userDataPath = await getRealPath(app.getPath('userData')); @@ -908,6 +903,12 @@ app.on('web-contents-created', (createEvent, contents) => { }); }); +// Ingested in preload.js via a sendSync call +ipc.on('locale-data', event => { + // eslint-disable-next-line no-param-reassign + event.returnValue = locale.messages; +}); + ipc.on('set-badge-count', (event, count) => { app.setBadgeCount(count); }); @@ -961,6 +962,31 @@ ipc.on('update-tray-icon', (event, unreadCount) => { } }); +// Launch screen related IPC calls +ipc.on('launcher-login', async (event, passPhrase) => { + const sendError = (e) => event.sender.send('launcher-login-response', e); + + // Check if the phrase matches with the hash we have stored + const hash = userConfig.get('passHash'); + const hashMatches = passPhrase && passwordUtil.matchesHash(passPhrase, hash); + if (hash && !hashMatches) { + sendError('Invalid password'); + return; + } + + // If we don't have a hash then use the default sql key to unlock the db + const key = hash ? passPhrase : getDefaultSQLKey(); + try { + await showMainWindow(key); + if (launcherWindow) { + launcherWindow.close(); + launcherWindow = null; + } + } catch (e) { + sendError('Failed to decrypt SQL database'); + } +}); + // Debug Log-related IPC calls ipc.on('show-debug-log', showDebugLogWindow); diff --git a/stylesheets/_global.scss b/stylesheets/_global.scss index 12152f21c..972f78f41 100644 --- a/stylesheets/_global.scss +++ b/stylesheets/_global.scss @@ -805,7 +805,7 @@ textarea { overflow-y: auto; } -#standalone { +.standalone { color: $color-dark-05; height: auto; padding: 0; diff --git a/stylesheets/_launcher.scss b/stylesheets/_launcher.scss index 2e59ed30f..7dac09b02 100644 --- a/stylesheets/_launcher.scss +++ b/stylesheets/_launcher.scss @@ -1,10 +1,16 @@ .launcher { - display: flex; - align-items: center; - justify-content: center; - height: 100%; - background: $color-dark-85; - color: $color-dark-05; + .content-wrapper { + display: flex; + align-items: center; + justify-content: center; + color: $color-dark-05; + width: 100%; + height: 100%; + } + + .content { + margin: 3em; + } .inputs { display: flex; @@ -14,4 +20,10 @@ input { width: 30em; } + + .error { + font-weight: bold; + font-size: 16px; + margin-top: 1em; + } }