Browse Source

password related changes

master
Anastasia Poupeney 7 years ago
parent
commit
07ba5f0677
  1. 19
      src/components/IsUnlocked.js
  2. 34
      src/components/Onboarding/steps/Analytics.js
  3. 45
      src/components/Onboarding/steps/SetPassword.js
  4. 21
      src/components/SettingsPage/DisablePasswordModal.js
  5. 47
      src/components/SettingsPage/PasswordForm.js
  6. 56
      src/components/SettingsPage/PasswordModal.js
  7. 7
      src/components/base/Input/index.js
  8. 6
      src/components/modals/AccountSettingRenderBody.js
  9. 1
      static/i18n/en/common.yml
  10. 30
      static/i18n/en/password.yml
  11. 13
      static/i18n/en/settings.yml

19
src/components/IsUnlocked.js

@ -11,8 +11,6 @@ import type { SettingsState as Settings } from 'reducers/settings'
import type { T } from 'types/common'
import IconLockScreen from 'icons/LockScreen'
import { ErrorMessageInput } from 'components/base/Input'
import get from 'lodash/get'
import { setEncryptionKey } from 'helpers/db'
@ -119,21 +117,13 @@ class IsUnlocked extends Component<Props, State> {
}
}
handleFocusInput = () => {
if (this._input && this._input !== null) {
this._input.focus()
}
}
_input: ?HTMLInputElement
render() {
const { inputValue, incorrectPassword } = this.state
const { isLocked, t } = this.props
if (isLocked) {
return (
<Box sticky alignItems="center" justifyContent="center" onClick={this.handleFocusInput}>
<Box sticky alignItems="center" justifyContent="center">
<form onSubmit={this.handleSubmit}>
<Box align="center">
<IconLockScreen size={136} />
@ -146,17 +136,12 @@ class IsUnlocked extends Component<Props, State> {
<Box style={{ minWidth: 230 }}>
<InputPassword
autoFocus
innerRef={(n: any) => (this._input = n)}
placeholder={t('common:lockScreen.inputPlaceholder')}
type="password"
onChange={this.handleChangeInput('password')}
value={inputValue.password}
error={incorrectPassword && t('password:errorMessageIncorrectPassword')}
/>
{incorrectPassword && (
<ErrorMessageInput>
{t('password:errorMessageIncorrectPassword')}
</ErrorMessageInput>
)}
</Box>
</Box>
</form>

34
src/components/Onboarding/steps/Analytics.js

@ -2,8 +2,6 @@
import React, { PureComponent } from 'react'
import styled from 'styled-components'
import { connect } from 'react-redux'
import { saveSettings } from 'actions/settings'
import Box from 'components/base/Box'
import CheckBox from 'components/base/CheckBox'
@ -12,19 +10,21 @@ import OnboardingFooter from '../OnboardingFooter'
import type { StepProps } from '..'
const mapDispatchToProps = { saveSettings }
type State = {
analyticsToggle: boolean,
termsConditionsToggle: boolean,
sentryLogsToggle: boolean,
}
const INITIAL_STATE = {
analyticsToggle: false,
termsConditionsToggle: false,
sentryLogsToggle: false,
}
class Analytics extends PureComponent<StepProps, State> {
state = {
analyticsToggle: false,
termsConditionsToggle: false,
sentryLogsToggle: false,
}
state = INITIAL_STATE
handleSentryLogsToggle = (isChecked: boolean) => {
this.setState({ sentryLogsToggle: !this.state.sentryLogsToggle })
this.props.saveSettings({
@ -40,8 +40,15 @@ class Analytics extends PureComponent<StepProps, State> {
handleTermsToggle = () => {
this.setState({ termsConditionsToggle: !this.state.termsConditionsToggle })
}
handleNavBack = () => {
const { savePassword, prevStep } = this.props
savePassword(undefined)
prevStep()
}
render() {
const { nextStep, prevStep, t } = this.props
const { nextStep, t } = this.props
const { analyticsToggle, termsConditionsToggle, sentryLogsToggle } = this.state
return (
@ -85,7 +92,7 @@ class Analytics extends PureComponent<StepProps, State> {
flow={2}
t={t}
nextStep={nextStep}
prevStep={prevStep}
prevStep={this.handleNavBack}
isContinueDisabled={!termsConditionsToggle}
/>
</Box>
@ -93,10 +100,7 @@ class Analytics extends PureComponent<StepProps, State> {
}
}
export default connect(
null,
mapDispatchToProps,
)(Analytics)
export default Analytics
export const AnalyticsText = styled(Box).attrs({
ff: 'Open Sans|Regular',

45
src/components/Onboarding/steps/SetPassword.js

@ -2,31 +2,26 @@
import React, { PureComponent, Fragment } from 'react'
import bcrypt from 'bcryptjs'
import { colors } from 'styles/theme'
import { colors, radii } from 'styles/theme'
import styled from 'styled-components'
import { radii } from 'styles/theme'
import { setEncryptionKey } from 'helpers/db'
import Box from 'components/base/Box'
import Button from 'components/base/Button'
import PasswordModal from 'components/SettingsPage/PasswordModal'
import OnboardingFooter from '../OnboardingFooter'
import IconChevronRight from 'icons/ChevronRight'
import { ErrorMessageInput } from 'components/base/Input'
import PasswordForm from '../../SettingsPage/PasswordForm'
import type { StepProps } from '..'
import { Title, Description, DisclaimerBox, Inner } from '../helperComponents'
import { Title, Description, DisclaimerBox } from '../helperComponents'
type State = {
currentPassword: string,
newPassword: string,
confirmPassword: string,
incorrectPassword: boolean,
submitError: boolean,
}
const INITIAL_STATE = {
@ -34,7 +29,6 @@ const INITIAL_STATE = {
newPassword: '',
confirmPassword: '',
incorrectPassword: false,
submitError: false,
}
class SetPassword extends PureComponent<StepProps, State> {
@ -45,15 +39,15 @@ class SetPassword extends PureComponent<StepProps, State> {
e.preventDefault()
}
if (!this.isValid()) {
this.setState({ submitError: true })
return
}
const { newPassword } = this.state
const { nextStep } = this.props
const { nextStep, savePassword } = this.props
setEncryptionKey('accounts', newPassword)
const hash = newPassword ? bcrypt.hashSync(newPassword, 8) : undefined
this.props.savePassword(hash)
savePassword(hash)
this.handleReset()
nextStep()
}
@ -68,18 +62,12 @@ class SetPassword extends PureComponent<StepProps, State> {
isValid = () => {
const { newPassword, confirmPassword } = this.state
return newPassword === confirmPassword ? true : false
return newPassword === confirmPassword
}
render() {
const { nextStep, prevStep, t, savePassword, settings } = this.props
const {
newPassword,
currentPassword,
incorrectPassword,
confirmPassword,
submitError,
} = this.state
const { nextStep, prevStep, t, settings } = this.props
const { newPassword, currentPassword, incorrectPassword, confirmPassword } = this.state
const isPasswordEnabled = settings.password.isEnabled === true
@ -87,17 +75,17 @@ class SetPassword extends PureComponent<StepProps, State> {
{
key: 'note1',
icon: <IconChevronRight size={12} style={{ color: colors.smoke }} />,
desc: t('onboarding:writeSeed.disclaimer.note1'),
desc: t('onboarding:setPassword.disclaimer.note1'),
},
{
key: 'note2',
icon: <IconChevronRight size={12} style={{ color: colors.smoke }} />,
desc: t('onboarding:writeSeed.disclaimer.note2'),
desc: t('onboarding:setPassword.disclaimer.note2'),
},
{
key: 'note3',
icon: <IconChevronRight size={12} style={{ color: colors.smoke }} />,
desc: t('onboarding:writeSeed.disclaimer.note3'),
desc: t('onboarding:setPassword.disclaimer.note3'),
},
]
@ -119,15 +107,12 @@ class SetPassword extends PureComponent<StepProps, State> {
currentPassword={currentPassword}
confirmPassword={confirmPassword}
incorrectPassword={incorrectPassword}
isValid={this.isValid}
onChange={this.handleInputChange}
t={t}
/>
{!this.isValid() && (
<ErrorMessageInput style={{ width: 300 }}>
{t('password:errorMessageNotMatchingPassword')}
</ErrorMessageInput>
)}
<DisclaimerBox mt={6} disclaimerNotes={disclaimerNotes} />
<DisclaimerBox mt={7} disclaimerNotes={disclaimerNotes} />
</Box>
</Fragment>
</Box>
@ -138,7 +123,7 @@ class SetPassword extends PureComponent<StepProps, State> {
</Button>
<Box horizontal ml="auto">
<Button padded disabled={false} onClick={() => nextStep()} mx={2}>
Skip This Step
{t('common:skipThisStep')}
</Button>
<Button
padded

21
src/components/SettingsPage/DisablePasswordModal.js

@ -7,7 +7,6 @@ import Box from 'components/base/Box'
import Button from 'components/base/Button'
import InputPassword from 'components/base/InputPassword'
import Label from 'components/base/Label'
import { ErrorMessageInput } from 'components/base/Input'
import { Modal, ModalContent, ModalBody, ModalTitle, ModalFooter } from 'components/base/Modal'
import type { T } from 'types/common'
@ -30,6 +29,7 @@ const INITIAL_STATE = {
incorrectPassword: false,
}
// TODO: combine with the refactored password form
class DisablePasswordModal extends PureComponent<Props, State> {
state = INITIAL_STATE
@ -71,44 +71,41 @@ class DisablePasswordModal extends PureComponent<Props, State> {
render={({ onClose }) => (
<form onSubmit={this.disablePassword}>
<ModalBody onClose={onClose}>
<ModalTitle>{t('settings:profile.disablePasswordModalTitle')}</ModalTitle>
<ModalTitle>{t('password:disablePassword.title')}</ModalTitle>
<ModalContent>
<Box ff="Open Sans" color="smoke" fontSize={4} textAlign="center" px={4}>
{t('settings:profile.disablePasswordModalDesc')}
{t('password:disablePassword.desc')}
<Box px={7} mt={4} flow={3}>
{isPasswordEnabled && (
<Box flow={1}>
<Label htmlFor="password">
{t('settings:profile.disablePasswordModalInput')}
{t('password:inputFields.currentPassword.label')}
</Label>
<InputPassword
autoFocus
type="password"
placeholder={t('settings:profile.disablePasswordModalInput')}
placeholder={t('password:inputFields.currentPassword.placeholder')}
id="password"
onChange={this.handleInputChange('currentPassword')}
value={currentPassword}
error={incorrectPassword && t('password:errorMessageIncorrectPassword')}
/>
{incorrectPassword && (
<ErrorMessageInput>
{t('password:errorMessageIncorrectPassword')}
</ErrorMessageInput>
)}
</Box>
)}
</Box>
</Box>
</ModalContent>
<ModalFooter horizontal align="center" justify="flex-end" flow={2}>
<Button type="button" onClick={onClose}>
<Button type="button" padded onClick={onClose}>
{t('common:cancel')}
</Button>
<Button
primary
padded
onClick={this.disablePassword}
disabled={!currentPassword && !incorrectPassword}
>
{t('settings:profile.disablePasswordModalSave')}
{t('common:save')}
</Button>
</ModalFooter>
</ModalBody>

47
src/components/SettingsPage/PasswordForm.js

@ -1,26 +1,22 @@
// @flow
import React, { PureComponent, Fragment } from 'react'
import { connect } from 'react-redux'
import bcrypt from 'bcryptjs'
import React, { PureComponent } from 'react'
import Box from 'components/base/Box'
import Button from 'components/base/Button'
import InputPassword from 'components/base/InputPassword'
import Label from 'components/base/Label'
import { ErrorMessageInput } from 'components/base/Input'
import type { T } from 'types/common'
type Props = {
t: T,
isPasswordEnabled: boolean,
currentPassword: string,
newPassword: string,
confirmPassword: string,
incorrectPassword: boolean,
onSubmit: Function,
isValid: () => boolean,
onChange: Function,
}
@ -33,54 +29,55 @@ class PasswordForm extends PureComponent<Props> {
newPassword,
incorrectPassword,
confirmPassword,
isValid,
onChange,
onSubmit,
} = this.props
// TODO: adjust design to separate 3 fields
return (
<form onSubmit={onSubmit}>
<Box px={7} mt={4} flow={3}>
{isPasswordEnabled && (
<Box flow={1}>
<Label htmlFor="currentPassword">{t('password:currentPassword.label')}</Label>
<Box flow={1} mb={5}>
<Label htmlFor="currentPassword">
{t('password:inputFields.currentPassword.label')}
</Label>
<InputPassword
autoFocus
type="password"
placeholder={t('password:currentPassword.placeholder')}
placeholder={t('password:inputFields.currentPassword.placeholder')}
id="currentPassword"
onChange={onChange('currentPassword')}
value={currentPassword}
error={incorrectPassword && t('password:errorMessageIncorrectPassword')}
/>
{incorrectPassword && (
<ErrorMessageInput>{t('password:errorMessageIncorrectPassword')}</ErrorMessageInput>
)}
</Box>
)}
<Box flow={1}>
{isPasswordEnabled && (
<Label htmlFor="newPassword">{t('password:newPassword.label')}</Label>
)}
<Label htmlFor="newPassword">{t('password:inputFields.newPassword.label')}</Label>
<InputPassword
style={{ mt: 4, width: 240 }}
autoFocus
placeholder={t('password:newPassword.placeholder')}
autoFocus={!isPasswordEnabled}
placeholder={t('password:inputFields.newPassword.placeholder')}
id="newPassword"
onChange={onChange('newPassword')}
value={newPassword}
// withStrength
/>
</Box>
<Box flow={1}>
{isPasswordEnabled && (
<Label htmlFor="confirmPassword">{t('password:confirmPassword.label')}</Label>
)}
<Label htmlFor="confirmPassword">
{t('password:inputFields.confirmPassword.label')}
</Label>
<InputPassword
style={{ width: 240 }}
placeholder={t('password:confirmPassword.placeholder')}
placeholder={t('password:inputFields.confirmPassword.placeholder')}
id="confirmPassword"
onChange={onChange('confirmPassword')}
value={confirmPassword}
// withStrength
error={
!isValid() &&
confirmPassword.length > 0 &&
t('password:errorMessageNotMatchingPassword')
}
/>
</Box>
</Box>

56
src/components/SettingsPage/PasswordModal.js

@ -1,32 +1,22 @@
// @flow
import React, { PureComponent } from 'react'
import { connect } from 'react-redux'
import bcrypt from 'bcryptjs'
import { unlock } from 'reducers/application'
import type { T } from 'types/common'
import Box from 'components/base/Box'
import Button from 'components/base/Button'
import InputPassword from 'components/base/InputPassword'
import Label from 'components/base/Label'
import { Modal, ModalContent, ModalBody, ModalTitle, ModalFooter } from 'components/base/Modal'
import { ErrorMessageInput } from 'components/base/Input'
import PasswordForm from './PasswordForm'
import type { T } from 'types/common'
const mapDispatchToProps = {
unlock,
}
type Props = {
t: T,
onClose: Function,
unlock: Function,
onClose: () => void,
onChangePassword: (?string) => void,
isPasswordEnabled: boolean,
currentPasswordHash: string,
onChangePassword: Function,
}
type State = {
@ -47,13 +37,15 @@ class PasswordModal extends PureComponent<Props, State> {
state = INITIAL_STATE
handleSave = (e: SyntheticEvent<HTMLFormElement>) => {
const { currentPassword, newPassword } = this.state
if (e) {
e.preventDefault()
}
if (!this.isValid()) {
return
}
const { currentPassword, newPassword, confirmPassword } = this.state
const { isPasswordEnabled, currentPasswordHash, onChangePassword } = this.props
if (isPasswordEnabled) {
if (!bcrypt.compareSync(currentPassword, currentPasswordHash)) {
@ -76,14 +68,13 @@ class PasswordModal extends PureComponent<Props, State> {
handleReset = () => this.setState(INITIAL_STATE)
isValid = () => {
const { newPassword } = this.state
return newPassword
const { newPassword, confirmPassword } = this.state
return newPassword === confirmPassword
}
render() {
const { t, isPasswordEnabled, onClose, ...props } = this.props
const { currentPassword, newPassword, incorrectPassword, confirmPassword } = this.state
const isValid = this.isValid()
return (
<Modal
{...props}
@ -91,13 +82,21 @@ class PasswordModal extends PureComponent<Props, State> {
onClose={onClose}
render={({ onClose }) => (
<ModalBody onClose={onClose}>
<ModalTitle>{t('settings:profile.passwordModalTitle')}</ModalTitle>
{isPasswordEnabled ? (
<ModalTitle>{t('password:changePassword.title')}</ModalTitle>
) : (
<ModalTitle>{t('password:setPassword.title')}</ModalTitle>
)}
<ModalContent>
<Box ff="Museo Sans|Regular" color="dark" textAlign="center" mb={2} mt={3}>
{t('settings:profile.passwordModalSubtitle')}
{isPasswordEnabled
? t('password:changePassword.subTitle')
: t('password:setPassword.subTitle')}
</Box>
<Box ff="Open Sans" color="smoke" fontSize={4} textAlign="center" px={4}>
{t('settings:profile.passwordModalDesc')}
{isPasswordEnabled
? t('password:changePassword.desc')
: t('password:setPassword.desc')}
</Box>
<PasswordForm
onSubmit={this.handleSave}
@ -106,16 +105,22 @@ class PasswordModal extends PureComponent<Props, State> {
currentPassword={currentPassword}
confirmPassword={confirmPassword}
incorrectPassword={incorrectPassword}
isValid={this.isValid}
onChange={this.handleInputChange}
t={t}
/>
</ModalContent>
<ModalFooter horizontal align="center" justify="flex-end" flow={2}>
<Button type="button" onClick={onClose}>
<Button type="button" padded onClick={onClose}>
{t('common:cancel')}
</Button>
<Button primary onClick={this.handleSave} disabled={!isValid}>
{t('settings:profile.passwordModalSave')}
<Button
padded
primary
onClick={this.handleSave}
disabled={!this.isValid() || !newPassword.length || !confirmPassword.length}
>
{t('common:save')}
</Button>
</ModalFooter>
</ModalBody>
@ -125,7 +130,4 @@ class PasswordModal extends PureComponent<Props, State> {
}
}
export default connect(
null,
mapDispatchToProps,
)(PasswordModal)
export default PasswordModal

7
src/components/base/Input/index.js

@ -48,13 +48,6 @@ const Base = styled.input.attrs({
}
`
export const ErrorMessageInput = styled(Box).attrs({
alignItems: 'flex-start',
color: 'alertRed',
ff: 'Open Sans|SemiBold',
fontSize: 3,
})``
export const Textarea = styled.textarea.attrs({
p: 2,
fontSize: 4,

6
src/components/modals/AccountSettingRenderBody.js

@ -18,7 +18,7 @@ import Spoiler from 'components/base/Spoiler'
import CryptoCurrencyIcon from 'components/CryptoCurrencyIcon'
import Box from 'components/base/Box'
import Button from 'components/base/Button'
import Input, { ErrorMessageInput } from 'components/base/Input'
import Input from 'components/base/Input'
import Select from 'components/base/LegacySelect'
import { ModalBody, ModalTitle, ModalFooter, ModalContent } from 'components/base/Modal'
@ -143,10 +143,8 @@ class HelperComp extends PureComponent<Props, State> {
onChange={this.handleChangeName}
renderLeft={<InputLeft currency={account.currency} />}
onFocus={e => this.handleFocus(e, 'accountName')}
error={accountNameError && t('account:settings.accountName.error')}
/>
{accountNameError && (
<ErrorMessageInput>{t('account:settings.accountName.error')}</ErrorMessageInput>
)}
</Box>
</Container>
<Container>

1
static/i18n/en/common.yml

@ -6,6 +6,7 @@ confirm: Confirm
cancel: Cancel
delete: Delete
continue: Continue
skipThisStep: Skip This Step
chooseWalletPlaceholder: Choose a wallet...
currency: Currency
selectAccount: Select an account

30
static/i18n/en/password.yml

@ -5,12 +5,24 @@ warning_3: Warning 3
warning_4: Warning 4
errorMessageIncorrectPassword: The password you entered is incorrect.
errorMessageNotMatchingPassword: Passwords don't match.
newPassword:
label: New Password
placeholder: New Password
confirmPassword:
label: Confirm Password
placeholder: Confirm Password
currentPassword:
label: Current Password
placeholder: Current Password
inputFields:
newPassword:
label: Password
placeholder: Password
confirmPassword:
label: Confirm Password
placeholder: Confirm Password
currentPassword:
label: Current Password
placeholder: Current Password
changePassword:
title: Edit Password
subTitle: Change your password
desc: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh diam. In eget ipsum arcu donec finibus
setPassword:
title: Set Password
subTitle: Set a password to lock your application
desc: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh diam. In eget ipsum arcu donec finibus
disablePassword:
title: Disable Password
desc: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh diam.

13
static/i18n/en/settings.yml

@ -23,22 +23,9 @@ currencies:
explorer: Blockchain explorer
explorerDesc: Lorem ipsum dolor sit amet
profile:
username: Username
usernameDesc: Lorem ipsum dolor sit amet
password: Password
passwordDesc: Lorem ipsum dolor sit amet
changePassword: Change password
passwordModalTitle: Password
passwordModalSubtitle: Set a password to lock your application
passwordModalDesc: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh diam.
passwordModalPasswordInput: Current password
passwordModalNewPasswordInput: New password
passwordModalRepeatPasswordInput: Repeat password
passwordModalSave: Save
disablePasswordModalTitle: Disable Password
disablePasswordModalDesc: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer non nibh diam.
disablePasswordModalInput: Current password
disablePasswordModalSave: Save
sync: Sync accounts
syncDesc: Lorem ipsum dolor sit amet
export: Export logs

Loading…
Cancel
Save