Skip to content

Commit

Permalink
Merge pull request #980 from oskarhane/pw-change-retry
Browse files Browse the repository at this point in the history
Retry reconnection on pw-change
  • Loading branch information
oskarhane authored Nov 8, 2019
2 parents 80f4c98 + 7f8c59d commit 4ae2ecb
Show file tree
Hide file tree
Showing 9 changed files with 189 additions and 47 deletions.
2 changes: 1 addition & 1 deletion src/browser/modules/Frame/FrameSuccess.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import React from 'react'
const FrameSuccess = props => {
if (!props || !props.message) return null
return <span style={{ color: 'green' }}>{props.message}</span>
return <span className='statusbar--success'>{props.message}</span>
}

export default FrameSuccess
6 changes: 6 additions & 0 deletions src/browser/modules/Frame/styled.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,12 @@ export const StyledFrameStatusbar = styled.div`
display: flex;
flex-direction: row;
flex: none;
align-items: center;
padding-left: 10px;
.statusbar--success {
color: ${props => props.theme.success};
}
`

export const StyledFrameSidebar = styled.ul`
Expand Down
30 changes: 21 additions & 9 deletions src/browser/modules/Stream/Auth/ChangePasswordForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,13 @@ export default class ChangePasswordForm extends Component {
}
render () {
const indexStart = this.props.showExistingPasswordInput ? 1 : 0
const { isLoading } = this.props
const classNames = []
if (isLoading) {
classNames.push('isLoading')
}
return (
<StyledConnectionForm>
<StyledConnectionForm className={classNames.join(' ')}>
<InputEnterStepping
steps={this.props.showExistingPasswordInput ? 3 : 2}
submitAction={this.validateSame}
Expand All @@ -108,7 +113,8 @@ export default class ChangePasswordForm extends Component {
type: 'password',
onChange: this.onExistingPasswordChange,
value: this.state.password,
ref: ref => setRefForIndex(0, ref)
ref: ref => setRefForIndex(0, ref),
disabled: isLoading
})}
/>
</StyledConnectionFormEntry>
Expand All @@ -122,7 +128,8 @@ export default class ChangePasswordForm extends Component {
type: 'password',
onChange: this.onNewPasswordChange,
value: this.state.newPassword,
ref: ref => setRefForIndex(indexStart, ref)
ref: ref => setRefForIndex(indexStart, ref),
disabled: isLoading
})}
/>
</StyledConnectionFormEntry>
Expand All @@ -136,15 +143,20 @@ export default class ChangePasswordForm extends Component {
type: 'password',
onChange: this.onNewPasswordChange2,
value: this.state.newPassword2,
ref: ref => setRefForIndex(indexStart + 1, ref)
ref: ref => setRefForIndex(indexStart + 1, ref),
disabled: isLoading
})}
/>
</StyledConnectionFormEntry>
<FormButton
data-testid='changePassword'
label='Change password'
{...getSubmitProps()}
/>
<Render if={!isLoading}>
<FormButton
data-testid='changePassword'
label='Change password'
disabled={isLoading}
{...getSubmitProps()}
/>
</Render>
<Render if={isLoading}>Please wait...</Render>
</React.Fragment>
)
}}
Expand Down
35 changes: 25 additions & 10 deletions src/browser/modules/Stream/Auth/ChangePasswordFrame.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
*/

import React, { Component } from 'react'
import { connect } from 'react-redux'

import ConnectionForm from './ConnectionForm'
import FrameTemplate from '../../Frame/FrameTemplate'
Expand All @@ -27,6 +28,7 @@ import Render from 'browser-components/Render'
import { H3 } from 'browser-components/headers'
import { Lead } from 'browser-components/Text'
import { StyledConnectionAside } from './styled'
import { getActiveConnection } from 'shared/modules/connections/connectionsDuck'

export class ChangePasswordFrame extends Component {
constructor (props) {
Expand Down Expand Up @@ -56,22 +58,25 @@ export class ChangePasswordFrame extends Component {
<H3>Password change</H3>
<Render if={!this.state.success}>
<Lead>
Enter your current password and the new twice to change your
password.
{this.props.activeConnection
? 'Enter your current password and the new twice to change your password.'
: 'Please connect to a database to change the password.'}
</Lead>
</Render>
<Render if={this.state.success}>
<Lead>Password change successful</Lead>
</Render>
</StyledConnectionAside>

<ConnectionForm
{...this.props}
error={this.error}
onSuccess={this.onSuccess}
forcePasswordChange
showExistingPasswordInput
/>
<Render if={this.props.activeConnection}>
<ConnectionForm
{...this.props}
error={this.error}
onSuccess={this.onSuccess}
forcePasswordChange
showExistingPasswordInput
/>
</Render>
</React.Fragment>
)
return (
Expand All @@ -88,4 +93,14 @@ export class ChangePasswordFrame extends Component {
)
}
}
export default ChangePasswordFrame

const mapStateToProps = state => {
return {
activeConnection: getActiveConnection(state)
}
}

export default connect(
mapStateToProps,
() => ({})
)(ChangePasswordFrame)
88 changes: 72 additions & 16 deletions src/browser/modules/Stream/Auth/ConnectionForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ import {
getActiveConnection,
setActiveConnection,
updateConnection,
CONNECT
CONNECT,
VERIFY_CREDENTIALS
} from 'shared/modules/connections/connectionsDuck'
import { getInitCmd } from 'shared/modules/settings/settingsDuck'
import { executeSystemCommand } from 'shared/modules/commands/commandsDuck'
Expand All @@ -49,6 +50,7 @@ export class ConnectionForm extends Component {
this.state = {
...connection,
isConnected: isConnected,
isLoading: false,
passwordChangeNeeded: props.passwordChangeNeeded || false,
forcePasswordChange: props.forcePasswordChange || false,
successCallback: props.onSuccess || (() => {}),
Expand All @@ -57,24 +59,41 @@ export class ConnectionForm extends Component {
}
tryConnect = (password, doneFn) => {
this.props.error({})
this.props.bus.self(CONNECT, { ...this.state, password }, res => {
doneFn(res)
})
this.props.bus.self(
VERIFY_CREDENTIALS,
{ ...this.state, password },
res => {
doneFn(res)
}
)
}
connect = (doneFn = () => {}) => {
connect = (
doneFn = () => {},
onError = null,
noResetConnectionOnFail = false
) => {
this.props.error({})
this.props.bus.self(CONNECT, this.state, res => {
doneFn()
if (res.success) {
this.saveAndStart()
} else {
if (res.error.code === 'Neo.ClientError.Security.CredentialsExpired') {
this.setState({ passwordChangeNeeded: true })
this.props.bus.self(
CONNECT,
{ ...this.state, noResetConnectionOnFail },
res => {
doneFn()
if (res.success) {
this.saveAndStart()
} else {
this.props.error(res.error)
if (
res.error.code === 'Neo.ClientError.Security.CredentialsExpired'
) {
this.setState({ passwordChangeNeeded: true })
} else {
if (onError) {
return onError(res)
}
this.props.error(res.error)
}
}
}
})
)
}
onUsernameChange (event) {
const username = event.target.value
Expand All @@ -98,10 +117,13 @@ export class ConnectionForm extends Component {
this.props.error({})
}
onChangePassword ({ newPassword, error }) {
this.setState({ isLoading: true })
if (error && error.code) {
this.setState({ isLoading: false })
return this.props.error(error)
}
if (this.state.password === null) {
this.setState({ isLoading: false })
return this.props.error({ message: 'Please set existing password' })
}
this.props.error({})
Expand All @@ -117,9 +139,38 @@ export class ConnectionForm extends Component {
response => {
if (response.success) {
return this.setState({ password: newPassword }, () => {
this.connect()
let retries = 5
const retryFn = res => {
// New password not accepted yet, initiate retry
if (res.error.code === 'Neo.ClientError.Security.Unauthorized') {
retries--
if (retries > 0) {
setTimeout(
() =>
this.connect(
() => {
this.setState({ isLoading: false })
},
retryFn,
true
),
200
)
}
} else {
this.props.error(res.error)
}
}
this.connect(
() => {
this.setState({ isLoading: false })
},
retryFn,
true
)
})
}
this.setState({ isLoading: false })
this.props.error(response.error)
}
)
Expand Down Expand Up @@ -160,7 +211,12 @@ export class ConnectionForm extends Component {
showExistingPasswordInput={this.props.showExistingPasswordInput}
onChangePasswordClick={this.onChangePassword.bind(this)}
onChange={this.onChangePasswordChange.bind(this)}
tryConnect={this.tryConnect}
tryConnect={(password, doneFn) => {
this.setState({ isLoading: true }, () =>
this.tryConnect(password, doneFn)
)
}}
isLoading={this.state.isLoading}
>
{this.props.children}
</ChangePasswordForm>
Expand Down
4 changes: 4 additions & 0 deletions src/browser/modules/Stream/Auth/styled.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ import { StyledFrameAside } from '../../Frame/styled'

export const StyledConnectionForm = styled.form`
padding: 0 15px;
&.isLoading {
opacity: 0.5;
}
`
export const StyledConnectionAside = styled(StyledFrameAside)``
export const StyledConnectionFormEntry = styled.div`
Expand Down
Loading

0 comments on commit 4ae2ecb

Please sign in to comment.