Skip to content

Commit

Permalink
feat(sso): exchange password reset part one
Browse files Browse the repository at this point in the history
  • Loading branch information
TheLeoB committed Nov 27, 2021
1 parent ae8e0dd commit 794b1fb
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default ({ api, coreSagas, networks }) => {
// @ts-ignore
yield takeLatest(actions.loginRoutine.type, authSagas.loginRoutineSaga)
yield takeLatest(actions.exchangeLogin.type, authSagas.exchangeLogin)
yield takeLatest(actions.exchangeResetPassword.type, authSagas.exchangeResetPassword)
yield takeLatest(actions.continueLoginProcess, authSagas.continueLoginProcess)
}
}
15 changes: 15 additions & 0 deletions packages/blockchain-wallet-v4-frontend/src/data/auth/sagas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,20 @@ export default ({ api, coreSagas, networks }) => {
yield put(actions.modules.profile.signIn())
}

const exchangeResetPassword = function* (action) {
const email = action.payload
yield put(actions.auth.exchangeResetPasswordLoading())
yield put(startSubmit('exchangePasswordReset'))
try {
const response = yield call(api.exchangeResetPassword(email))
yield put(stopSubmit('exchangePasswordReset'))
yield put(actions.auth.exchangeResetPasswordSuccess(response))
} catch (e) {
yield put(actions.auth.exchangeLoginFailure(e))
yield put(stopSubmit('exchangePasswordReset'))
}
}

const exchangeLogin = function* (action) {
const { code, password, username } = action.payload
const unificationFlowType = yield select(selectors.auth.getAccountUnificationFlowType)
Expand Down Expand Up @@ -774,6 +788,7 @@ export default ({ api, coreSagas, networks }) => {
authorizeVerifyDevice,
continueLoginProcess,
exchangeLogin,
exchangeResetPassword,
getUserGeoLocation,
initializeLogin,
login,
Expand Down
21 changes: 20 additions & 1 deletion packages/blockchain-wallet-v4-frontend/src/data/auth/slice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import {
ExchangeLoginFailureType,
ExchangeLoginSuccessType,
ExchangeLoginType,
ExchangeResetPasswordFailureType,
ExchangeResetPasswordSuccessType,
LoginFailureType,
LoginSuccessType,
MetadataRestoreType,
Expand All @@ -27,7 +29,8 @@ const initialState: AuthStateType = {
exchangeAuth: {
exchangeLogin: Remote.NotAsked,
exchangeLoginError: undefined,
jwtToken: undefined
jwtToken: undefined,
resetPassword: Remote.NotAsked
},
firstLogin: false,
isAuthenticated: false,
Expand Down Expand Up @@ -99,6 +102,22 @@ const authSlice = createSlice({
exchangeLoginSuccess: (state, action: PayloadAction<ExchangeLoginSuccessType>) => {
state.exchangeAuth.exchangeLogin = Remote.Success(action.payload)
},
exchangeResetPassword: (state, action: PayloadAction<string>) => {},
exchangeResetPasswordFailure: (
state,
action: PayloadAction<ExchangeResetPasswordFailureType>
) => {
state.exchangeAuth.resetPassword = Remote.Failure(action.payload)
},
exchangeResetPasswordLoading: (state) => {
state.exchangeAuth.resetPassword = Remote.Loading
},
exchangeResetPasswordSuccess: (
state,
action: PayloadAction<ExchangeResetPasswordSuccessType>
) => {
state.exchangeAuth.resetPassword = Remote.Success(action.payload)
},
getUserGeoLocation: () => {},
initializeLogin: () => {},
initializeLoginFailure: () => {},
Expand Down
5 changes: 5 additions & 0 deletions packages/blockchain-wallet-v4-frontend/src/data/auth/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,10 @@ export type ExchangeLoginSuccessType = {}

export type ExchangeLoginFailureType = any

export type ExchangeResetPasswordSuccessType = any

export type ExchangeResetPasswordFailureType = any

export type LoginSuccessType = {}

export type LoginFailureType = string | boolean | undefined
Expand Down Expand Up @@ -184,6 +188,7 @@ export type AuthStateType = {
exchangeLogin: RemoteDataType<ExchangeLoginFailureType, ExchangeLoginSuccessType>
exchangeLoginError?: ExchangeErrorCodes
jwtToken?: string
resetPassword?: RemoteDataType<string, string>
}
firstLogin: boolean
isAuthenticated: boolean
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import React from 'react'
import { FormattedMessage } from 'react-intl'
import { connect, ConnectedProps } from 'react-redux'
import { LinkContainer } from 'react-router-bootstrap'
import { bindActionCreators, compose } from 'redux'
import { Field, InjectedFormProps, reduxForm } from 'redux-form'
import styled from 'styled-components'

import { Button, HeartbeatLoader, Link, Text } from 'blockchain-info-components'
import { FormGroup, FormItem, FormLabel, TextBox } from 'components/Form'
import { Wrapper } from 'components/Public'
import { actions, selectors } from 'data'
import { required, validEmail } from 'services/forms'

const FormWrapper = styled(Wrapper)`
padding: 32px 0;
`

const WrapperWithPadding = styled.div`
padding: 0 32px;
`

const SubCard = styled.div`
display: flex;
justify-content: center;
margin-top: 24px;
border-top: 1px solid ${(props) => props.theme.grey000};
padding: 0;
`
const SignUpText = styled(Text)`
&:hover {
font-weight: 600;
}
`

const EnterEmail = (props: InjectedFormProps<{}, Props> & Props) => {
const removeWhitespace = (string) => string.replace(/\s/g, ``)
return (
<FormWrapper>
<WrapperWithPadding>
<FormGroup>
<FormItem style={{ marginTop: '40px' }}>
<FormLabel htmlFor='email'>
<FormattedMessage id='scenes.register.youremail' defaultMessage='Your Email' />
</FormLabel>
<Field
component={TextBox}
data-e2e='exchangeEmail'
disableSpellcheck
name='email'
normalize={removeWhitespace}
validate={[required, validEmail]}
placeholder='Enter your email'
autoFocus
/>
</FormItem>
</FormGroup>
<Button
type='submit'
nature='primary'
fullwidth
height='48px'
// disabled={submitting || invalid || busy || !formValues?.email}
data-e2e='loginButton'
style={{ marginBottom: '16px' }}
>
{/* {submitting ? (
<HeartbeatLoader height='20px' width='20px' color='white' />
) : ( */}
<Text color='whiteFade900' size='16px' weight={600}>
<FormattedMessage id='buttons.continue' defaultMessage='Continue' />
</Text>
{/* )} */}
</Button>
</WrapperWithPadding>
<LinkContainer data-e2e='signupLink' to='/signup'>
<Link>
<SubCard>
<Text size='16px' color='grey600' weight={500} style={{ marginTop: '16px' }}>
<FormattedMessage
id='scenes.login.account_signup'
defaultMessage="Don't have a Blockchain Account?"
/>
</Text>
&nbsp;
<SignUpText size='16px' color='blue600' weight={600} style={{ marginTop: '16px' }}>
<FormattedMessage id='buttons.signup_now' defaultMessage='Sign up Now ->' />
</SignUpText>
</SubCard>
</Link>
</LinkContainer>
</FormWrapper>
)
}

const mapDispatchToProps = (dispatch) => ({
authActions: bindActionCreators(actions.auth, dispatch)
})

const connector = connect(null, mapDispatchToProps)
type Props = {}
const enhance = compose(reduxForm({ form: 'exchangePasswordReset' }), connector)

export default enhance(EnterEmail)
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ import { LinkContainer } from 'react-router-bootstrap'
import styled from 'styled-components'

import { Button, Link, Text, TextGroup } from 'blockchain-info-components'
import { Props } from 'components/Display/FiatDisplay'
import { Wrapper } from 'components/Public'

import ResetPassword from './ResetPassword'

const Row = styled.div`
display: flex;
justify-content: space-between;
Expand Down Expand Up @@ -48,89 +51,103 @@ const Footer = styled.div`
}
`

const Help = () => {
return (
<Wrapper>
<Header>
<Text size='20px' color='blue900' weight={600} capitalize>
<FormattedMessage id='copy.need_some_help' defaultMessage='Need some help?' />
</Text>
</Header>
<Row>
<Left>
<Text size='14px' color='grey800' weight={600}>
<FormattedMessage
id='scenes.help.forgotpassword'
defaultMessage='Forgot your password?'
/>
</Text>
<Text size='12px' color='grey800' weight={400}>
<FormattedMessage
id='scenes.help.password.explain_phrase'
defaultMessage='Directs to reset password form'
/>
class Help extends React.PureComponent<Props, State> {
constructor(props) {
super(props)
this.state = {
showHelpOptions: true
}
}

showPasswordResetForm = () => {
this.setState({ showHelpOptions: false })
}

render() {
return this.state.showHelpOptions ? (
<Wrapper>
<Header>
<Text size='20px' color='blue900' weight={600} capitalize>
<FormattedMessage id='copy.need_some_help' defaultMessage='Need some help?' />
</Text>
</Left>
<Right>
<LinkContainer to='/recover'>
<Button data-e2e='linkToRecover' nature='light'>
<FormattedMessage id='scenes.help.recover' defaultMessage='Recover Funds' />
</Header>
<Row>
<Left>
<Text size='14px' color='grey800' weight={600}>
<FormattedMessage
id='scenes.help.forgotpassword'
defaultMessage='Forgot your password?'
/>
</Text>
<Text size='12px' color='grey800' weight={400}>
<FormattedMessage
id='scenes.help.password.explain_phrase'
defaultMessage='Directs to reset password form'
/>
</Text>
</Left>
<Right>
<Button data-e2e='linkToRecover' nature='light' onClick={this.showPasswordResetForm}>
<FormattedMessage id='scenes.help.recover' defaultMessage='Reset Password' />
</Button>
</LinkContainer>
</Right>
</Row>
<Row>
<Left>
<Text size='14px' color='grey800' weight={600}>
<FormattedMessage id='scenes.help.2falost' defaultMessage='Lost your 2FA device?' />
</Text>
<Text size='12px' color='grey800' weight={400}>
<FormattedMessage
id='scenes.help.2fa.lostexplain_exchange'
defaultMessage='Learn how to reset 2FA for your Exchange account.'
/>
</Text>
</Left>
<Right>
<Link
href='https://exchange-support.blockchain.com/hc/en-us/articles/360029748191-How-can-I-reset-my-2-Factor-Authentication-2FA-'
target='_blank'
size='13px'
weight={500}
>
<Button data-e2e='linkToReset2fa' nature='light'>
<FormattedMessage id='scenes.help.reset' defaultMessage='Reset 2FA' />
</Right>
</Row>
<Row>
<Left>
<Text size='14px' color='grey800' weight={600}>
<FormattedMessage id='scenes.help.2falost' defaultMessage='Lost your 2FA device?' />
</Text>
<Text size='12px' color='grey800' weight={400}>
<FormattedMessage
id='scenes.help.2fa.lostexplain_exchange'
defaultMessage='Learn how to reset 2FA for your Exchange account.'
/>
</Text>
</Left>
<Right>
<Link
href='https://exchange-support.blockchain.com/hc/en-us/articles/360029748191-How-can-I-reset-my-2-Factor-Authentication-2FA-'
target='_blank'
size='13px'
weight={500}
>
<Button data-e2e='linkToReset2fa' nature='light'>
<FormattedMessage id='scenes.help.reset' defaultMessage='Reset 2FA' />
</Button>
</Link>
</Right>
</Row>
<Footer>
<LinkContainer to='/login'>
<Button data-e2e='linkToLogin' nature='primary' height='56px' fullwidth>
<Text size='16px' color='white' weight={500}>
<FormattedMessage id='buttons.go_back' defaultMessage='Go Back' />
</Text>
</Button>
</Link>
</Right>
</Row>
<Footer>
<LinkContainer to='/login'>
<Button data-e2e='linkToLogin' nature='primary' height='56px' fullwidth>
<Text size='16px' color='white' weight={500}>
<FormattedMessage id='buttons.go_back' defaultMessage='Go Back' />
</LinkContainer>
<TextGroup inline>
<Text size='13px' color='grey800' weight={500}>
<FormattedMessage
id='scenes.help.contact.stillneedhelp'
defaultMessage='Still need help?'
/>
</Text>
</Button>
</LinkContainer>
<TextGroup inline>
<Text size='13px' color='grey800' weight={500}>
<FormattedMessage
id='scenes.help.contact.stillneedhelp'
defaultMessage='Still need help?'
/>
</Text>
<Link
href='https://exchange-support.blockchain.com/'
target='_blank'
size='13px'
weight={500}
>
<FormattedMessage id='buttons.contact_support' defaultMessage='Contact Support' />
</Link>
</TextGroup>
</Footer>
</Wrapper>
)
<Link
href='https://exchange-support.blockchain.com/'
target='_blank'
size='13px'
weight={500}
>
<FormattedMessage id='buttons.contact_support' defaultMessage='Contact Support' />
</Link>
</TextGroup>
</Footer>
</Wrapper>
) : // <ResetPassword />
null
}
}

type State = { showHelpOptions: boolean }

export default Help

0 comments on commit 794b1fb

Please sign in to comment.