Skip to content

Commit 4ae2ecb

Browse files
authored
Merge pull request #980 from oskarhane/pw-change-retry
Retry reconnection on pw-change
2 parents 80f4c98 + 7f8c59d commit 4ae2ecb

File tree

9 files changed

+189
-47
lines changed

9 files changed

+189
-47
lines changed

src/browser/modules/Frame/FrameSuccess.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import React from 'react'
2121
const FrameSuccess = props => {
2222
if (!props || !props.message) return null
23-
return <span style={{ color: 'green' }}>{props.message}</span>
23+
return <span className='statusbar--success'>{props.message}</span>
2424
}
2525

2626
export default FrameSuccess

src/browser/modules/Frame/styled.jsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,12 @@ export const StyledFrameStatusbar = styled.div`
126126
display: flex;
127127
flex-direction: row;
128128
flex: none;
129+
align-items: center;
130+
padding-left: 10px;
131+
132+
.statusbar--success {
133+
color: ${props => props.theme.success};
134+
}
129135
`
130136

131137
export const StyledFrameSidebar = styled.ul`

src/browser/modules/Stream/Auth/ChangePasswordForm.jsx

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,13 @@ export default class ChangePasswordForm extends Component {
8585
}
8686
render () {
8787
const indexStart = this.props.showExistingPasswordInput ? 1 : 0
88+
const { isLoading } = this.props
89+
const classNames = []
90+
if (isLoading) {
91+
classNames.push('isLoading')
92+
}
8893
return (
89-
<StyledConnectionForm>
94+
<StyledConnectionForm className={classNames.join(' ')}>
9095
<InputEnterStepping
9196
steps={this.props.showExistingPasswordInput ? 3 : 2}
9297
submitAction={this.validateSame}
@@ -108,7 +113,8 @@ export default class ChangePasswordForm extends Component {
108113
type: 'password',
109114
onChange: this.onExistingPasswordChange,
110115
value: this.state.password,
111-
ref: ref => setRefForIndex(0, ref)
116+
ref: ref => setRefForIndex(0, ref),
117+
disabled: isLoading
112118
})}
113119
/>
114120
</StyledConnectionFormEntry>
@@ -122,7 +128,8 @@ export default class ChangePasswordForm extends Component {
122128
type: 'password',
123129
onChange: this.onNewPasswordChange,
124130
value: this.state.newPassword,
125-
ref: ref => setRefForIndex(indexStart, ref)
131+
ref: ref => setRefForIndex(indexStart, ref),
132+
disabled: isLoading
126133
})}
127134
/>
128135
</StyledConnectionFormEntry>
@@ -136,15 +143,20 @@ export default class ChangePasswordForm extends Component {
136143
type: 'password',
137144
onChange: this.onNewPasswordChange2,
138145
value: this.state.newPassword2,
139-
ref: ref => setRefForIndex(indexStart + 1, ref)
146+
ref: ref => setRefForIndex(indexStart + 1, ref),
147+
disabled: isLoading
140148
})}
141149
/>
142150
</StyledConnectionFormEntry>
143-
<FormButton
144-
data-testid='changePassword'
145-
label='Change password'
146-
{...getSubmitProps()}
147-
/>
151+
<Render if={!isLoading}>
152+
<FormButton
153+
data-testid='changePassword'
154+
label='Change password'
155+
disabled={isLoading}
156+
{...getSubmitProps()}
157+
/>
158+
</Render>
159+
<Render if={isLoading}>Please wait...</Render>
148160
</React.Fragment>
149161
)
150162
}}

src/browser/modules/Stream/Auth/ChangePasswordFrame.jsx

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
*/
2020

2121
import React, { Component } from 'react'
22+
import { connect } from 'react-redux'
2223

2324
import ConnectionForm from './ConnectionForm'
2425
import FrameTemplate from '../../Frame/FrameTemplate'
@@ -27,6 +28,7 @@ import Render from 'browser-components/Render'
2728
import { H3 } from 'browser-components/headers'
2829
import { Lead } from 'browser-components/Text'
2930
import { StyledConnectionAside } from './styled'
31+
import { getActiveConnection } from 'shared/modules/connections/connectionsDuck'
3032

3133
export class ChangePasswordFrame extends Component {
3234
constructor (props) {
@@ -56,22 +58,25 @@ export class ChangePasswordFrame extends Component {
5658
<H3>Password change</H3>
5759
<Render if={!this.state.success}>
5860
<Lead>
59-
Enter your current password and the new twice to change your
60-
password.
61+
{this.props.activeConnection
62+
? 'Enter your current password and the new twice to change your password.'
63+
: 'Please connect to a database to change the password.'}
6164
</Lead>
6265
</Render>
6366
<Render if={this.state.success}>
6467
<Lead>Password change successful</Lead>
6568
</Render>
6669
</StyledConnectionAside>
6770

68-
<ConnectionForm
69-
{...this.props}
70-
error={this.error}
71-
onSuccess={this.onSuccess}
72-
forcePasswordChange
73-
showExistingPasswordInput
74-
/>
71+
<Render if={this.props.activeConnection}>
72+
<ConnectionForm
73+
{...this.props}
74+
error={this.error}
75+
onSuccess={this.onSuccess}
76+
forcePasswordChange
77+
showExistingPasswordInput
78+
/>
79+
</Render>
7580
</React.Fragment>
7681
)
7782
return (
@@ -88,4 +93,14 @@ export class ChangePasswordFrame extends Component {
8893
)
8994
}
9095
}
91-
export default ChangePasswordFrame
96+
97+
const mapStateToProps = state => {
98+
return {
99+
activeConnection: getActiveConnection(state)
100+
}
101+
}
102+
103+
export default connect(
104+
mapStateToProps,
105+
() => ({})
106+
)(ChangePasswordFrame)

src/browser/modules/Stream/Auth/ConnectionForm.jsx

Lines changed: 72 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ import {
2626
getActiveConnection,
2727
setActiveConnection,
2828
updateConnection,
29-
CONNECT
29+
CONNECT,
30+
VERIFY_CREDENTIALS
3031
} from 'shared/modules/connections/connectionsDuck'
3132
import { getInitCmd } from 'shared/modules/settings/settingsDuck'
3233
import { executeSystemCommand } from 'shared/modules/commands/commandsDuck'
@@ -49,6 +50,7 @@ export class ConnectionForm extends Component {
4950
this.state = {
5051
...connection,
5152
isConnected: isConnected,
53+
isLoading: false,
5254
passwordChangeNeeded: props.passwordChangeNeeded || false,
5355
forcePasswordChange: props.forcePasswordChange || false,
5456
successCallback: props.onSuccess || (() => {}),
@@ -57,24 +59,41 @@ export class ConnectionForm extends Component {
5759
}
5860
tryConnect = (password, doneFn) => {
5961
this.props.error({})
60-
this.props.bus.self(CONNECT, { ...this.state, password }, res => {
61-
doneFn(res)
62-
})
62+
this.props.bus.self(
63+
VERIFY_CREDENTIALS,
64+
{ ...this.state, password },
65+
res => {
66+
doneFn(res)
67+
}
68+
)
6369
}
64-
connect = (doneFn = () => {}) => {
70+
connect = (
71+
doneFn = () => {},
72+
onError = null,
73+
noResetConnectionOnFail = false
74+
) => {
6575
this.props.error({})
66-
this.props.bus.self(CONNECT, this.state, res => {
67-
doneFn()
68-
if (res.success) {
69-
this.saveAndStart()
70-
} else {
71-
if (res.error.code === 'Neo.ClientError.Security.CredentialsExpired') {
72-
this.setState({ passwordChangeNeeded: true })
76+
this.props.bus.self(
77+
CONNECT,
78+
{ ...this.state, noResetConnectionOnFail },
79+
res => {
80+
doneFn()
81+
if (res.success) {
82+
this.saveAndStart()
7383
} else {
74-
this.props.error(res.error)
84+
if (
85+
res.error.code === 'Neo.ClientError.Security.CredentialsExpired'
86+
) {
87+
this.setState({ passwordChangeNeeded: true })
88+
} else {
89+
if (onError) {
90+
return onError(res)
91+
}
92+
this.props.error(res.error)
93+
}
7594
}
7695
}
77-
})
96+
)
7897
}
7998
onUsernameChange (event) {
8099
const username = event.target.value
@@ -98,10 +117,13 @@ export class ConnectionForm extends Component {
98117
this.props.error({})
99118
}
100119
onChangePassword ({ newPassword, error }) {
120+
this.setState({ isLoading: true })
101121
if (error && error.code) {
122+
this.setState({ isLoading: false })
102123
return this.props.error(error)
103124
}
104125
if (this.state.password === null) {
126+
this.setState({ isLoading: false })
105127
return this.props.error({ message: 'Please set existing password' })
106128
}
107129
this.props.error({})
@@ -117,9 +139,38 @@ export class ConnectionForm extends Component {
117139
response => {
118140
if (response.success) {
119141
return this.setState({ password: newPassword }, () => {
120-
this.connect()
142+
let retries = 5
143+
const retryFn = res => {
144+
// New password not accepted yet, initiate retry
145+
if (res.error.code === 'Neo.ClientError.Security.Unauthorized') {
146+
retries--
147+
if (retries > 0) {
148+
setTimeout(
149+
() =>
150+
this.connect(
151+
() => {
152+
this.setState({ isLoading: false })
153+
},
154+
retryFn,
155+
true
156+
),
157+
200
158+
)
159+
}
160+
} else {
161+
this.props.error(res.error)
162+
}
163+
}
164+
this.connect(
165+
() => {
166+
this.setState({ isLoading: false })
167+
},
168+
retryFn,
169+
true
170+
)
121171
})
122172
}
173+
this.setState({ isLoading: false })
123174
this.props.error(response.error)
124175
}
125176
)
@@ -160,7 +211,12 @@ export class ConnectionForm extends Component {
160211
showExistingPasswordInput={this.props.showExistingPasswordInput}
161212
onChangePasswordClick={this.onChangePassword.bind(this)}
162213
onChange={this.onChangePasswordChange.bind(this)}
163-
tryConnect={this.tryConnect}
214+
tryConnect={(password, doneFn) => {
215+
this.setState({ isLoading: true }, () =>
216+
this.tryConnect(password, doneFn)
217+
)
218+
}}
219+
isLoading={this.state.isLoading}
164220
>
165221
{this.props.children}
166222
</ChangePasswordForm>

src/browser/modules/Stream/Auth/styled.jsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ import { StyledFrameAside } from '../../Frame/styled'
2424

2525
export const StyledConnectionForm = styled.form`
2626
padding: 0 15px;
27+
28+
&.isLoading {
29+
opacity: 0.5;
30+
}
2731
`
2832
export const StyledConnectionAside = styled(StyledFrameAside)``
2933
export const StyledConnectionFormEntry = styled.div`

0 commit comments

Comments
 (0)