From d58273bb383da33377cdfdc190dbb4fd233fe855 Mon Sep 17 00:00:00 2001 From: meriadec Date: Mon, 16 Apr 2018 18:08:08 +0200 Subject: [PATCH] Work on set password --- src/components/IsUnlocked.js | 2 +- src/components/SettingsPage/PasswordModal.js | 156 ++++++++++++------ src/components/SettingsPage/index.js | 2 +- .../SettingsPage/sections/Profile.js | 24 ++- src/reducers/settings.js | 5 +- 5 files changed, 136 insertions(+), 53 deletions(-) diff --git a/src/components/IsUnlocked.js b/src/components/IsUnlocked.js index e184aaea..c70b5cea 100644 --- a/src/components/IsUnlocked.js +++ b/src/components/IsUnlocked.js @@ -1,10 +1,10 @@ // @flow +import bcrypt from 'bcryptjs' import React, { Component } from 'react' import { connect } from 'react-redux' import { compose } from 'redux' import { translate } from 'react-i18next' -import bcrypt from 'bcryptjs' import type { Account } from '@ledgerhq/wallet-common/lib/types' import type { Settings, T } from 'types/common' diff --git a/src/components/SettingsPage/PasswordModal.js b/src/components/SettingsPage/PasswordModal.js index f21394b8..1e653e81 100644 --- a/src/components/SettingsPage/PasswordModal.js +++ b/src/components/SettingsPage/PasswordModal.js @@ -1,6 +1,10 @@ // @flow import React, { PureComponent } from 'react' +import { connect } from 'react-redux' +import bcrypt from 'bcryptjs' + +import { unlock } from 'reducers/application' import Box from 'components/base/Box' import Button from 'components/base/Button' @@ -10,68 +14,128 @@ import { Modal, ModalContent, ModalBody, ModalTitle, ModalFooter } from 'compone import type { T } from 'types/common' +const mapDispatchToProps = { + unlock, +} + type Props = { t: T, onClose: Function, + unlock: Function, + isPasswordEnabled: boolean, + currentPasswordHash: string, + onChangePassword: Function, +} + +type State = { + currentPassword: string, + newPassword: string, + repeatPassword: string, } -class PasswordModal extends PureComponent { +class PasswordModal extends PureComponent { + state = { + currentPassword: '', + newPassword: '', + repeatPassword: '', + } + + handleSave = (e: SyntheticEvent) => { + if (e) { + e.preventDefault() + } + if (!this.isValid()) { + return + } + const { currentPassword, newPassword, repeatPassword } = this.state + const { isPasswordEnabled, currentPasswordHash, onChangePassword } = this.props + if (isPasswordEnabled) { + const calculatedPasswordHash = bcrypt.hashSync(currentPassword, 8) + if (calculatedPasswordHash !== currentPasswordHash) { + return + } + onChangePassword(newPassword) + } else if (newPassword === repeatPassword) { + onChangePassword(newPassword) + } + } + + handleInputChange = key => value => this.setState({ [key]: value }) + + isValid = () => { + const { newPassword, repeatPassword } = this.state + return newPassword && newPassword === repeatPassword + } + render() { - const { t, onClose, ...props } = this.props + const { t, isPasswordEnabled, onClose, ...props } = this.props + const isValid = this.isValid() return ( ( - - {t('settings:profile.passwordModalTitle')} - - - {t('settings:profile.passwordModalSubtitle')} - - - {t('settings:profile.passwordModalDesc')} - - - - - - - - - - - - +
+ + {t('settings:profile.passwordModalTitle')} + + + {t('settings:profile.passwordModalSubtitle')} + + + {t('settings:profile.passwordModalDesc')} + + {isPasswordEnabled && ( + + + + + )} + + + + + + + + - - - - - - - + + + + + + +
)} /> ) } } -export default PasswordModal +export default connect(null, mapDispatchToProps)(PasswordModal) diff --git a/src/components/SettingsPage/index.js b/src/components/SettingsPage/index.js index 3c8bd4b6..a4f45b67 100644 --- a/src/components/SettingsPage/index.js +++ b/src/components/SettingsPage/index.js @@ -43,7 +43,7 @@ type State = { class SettingsPage extends PureComponent { state = { - tab: 0, + tab: 2, } _items = [] diff --git a/src/components/SettingsPage/sections/Profile.js b/src/components/SettingsPage/sections/Profile.js index d3580600..c636cbbe 100644 --- a/src/components/SettingsPage/sections/Profile.js +++ b/src/components/SettingsPage/sections/Profile.js @@ -3,11 +3,12 @@ import React, { PureComponent } from 'react' import { connect } from 'react-redux' import { remote } from 'electron' +import bcrypt from 'bcryptjs' import type { Settings, T } from 'types/common' import { unlock } from 'reducers/application' -import db from 'helpers/db' +import db, { setEncryptionKey } from 'helpers/db' import Input from 'components/base/Input' import CheckBox from 'components/base/CheckBox' @@ -32,7 +33,6 @@ type Props = { t: T, settings: Settings, saveSettings: Function, - // unlock: Function, } type State = { @@ -73,6 +73,21 @@ class TabProfile extends PureComponent { } } + handleChangePassword = (password: ?string) => { + const { saveSettings, unlock } = this.props + const hash = bcrypt.hashSync(password, 8) + setEncryptionKey('accounts', password) + window.requestIdleCallback(() => { + saveSettings({ + password: { + isEnabled: hash !== undefined, + value: hash, + }, + }) + unlock() + }) + } + render() { const { t, settings } = this.props const { username, isHardResetModalOpened, isPasswordModalOpened } = this.state @@ -125,8 +140,11 @@ class TabProfile extends PureComponent { ) diff --git a/src/reducers/settings.js b/src/reducers/settings.js index 9775eb56..67c90041 100644 --- a/src/reducers/settings.js +++ b/src/reducers/settings.js @@ -15,7 +15,8 @@ const defaultState: SettingsState = { language: 'en', orderAccounts: 'balance|asc', password: { - state: false, + isEnabled: false, + value: '', }, } @@ -35,7 +36,7 @@ const handlers: Object = { } export const hasPassword = (state: Object) => - get(state.settings, 'password.state', defaultState.password.state) + get(state.settings, 'password.isEnabled', defaultState.password.isEnabled) export const getCounterValueCode = (state: Object) => get(state.settings, 'counterValue', defaultState.counterValue)