Merge pull request #2382 from influxdata/fix/user-sign-out-login
Fix/user sign out loginpull/10616/head
commit
be299966aa
|
@ -1,13 +1,13 @@
|
|||
// Libraries
|
||||
import React, {ReactElement, PureComponent} from 'react'
|
||||
import {withRouter, WithRouterProps} from 'react-router'
|
||||
|
||||
// APIs
|
||||
import {trySources} from 'src/onboarding/apis'
|
||||
|
||||
// Components
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
import SigninPage from 'src/onboarding/containers/SigninPage'
|
||||
import Notifications from 'src/shared/components/notifications/Notifications'
|
||||
import {getMe} from 'src/shared/apis/v2/user'
|
||||
|
||||
// Types
|
||||
import {RemoteDataState} from 'src/types'
|
||||
|
@ -17,12 +17,17 @@ interface State {
|
|||
isUserSignedIn: boolean
|
||||
}
|
||||
|
||||
interface Props {
|
||||
interface OwnProps {
|
||||
children: ReactElement<any>
|
||||
}
|
||||
|
||||
type Props = OwnProps & WithRouterProps
|
||||
|
||||
const FETCH_WAIT = 60000
|
||||
|
||||
@ErrorHandling
|
||||
export class Signin extends PureComponent<Props, State> {
|
||||
private intervalID: NodeJS.Timer
|
||||
constructor(props: Props) {
|
||||
super(props)
|
||||
|
||||
|
@ -36,24 +41,23 @@ export class Signin extends PureComponent<Props, State> {
|
|||
const isSourcesAllowed = await trySources()
|
||||
const isUserSignedIn = isSourcesAllowed
|
||||
this.setState({loading: RemoteDataState.Done, isUserSignedIn})
|
||||
this.checkForLogin()
|
||||
this.intervalID = setInterval(this.checkForLogin, FETCH_WAIT)
|
||||
if (!isUserSignedIn) {
|
||||
this.props.router.push('/signin')
|
||||
}
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
clearInterval(this.intervalID)
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {isUserSignedIn} = this.state
|
||||
|
||||
if (this.isLoading) {
|
||||
return <div className="page-spinner" />
|
||||
}
|
||||
if (!isUserSignedIn) {
|
||||
return (
|
||||
<div className="chronograf-root">
|
||||
<Notifications inPresentationMode={true} />
|
||||
<SigninPage onSignInUser={this.handleSignInUser} />
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return this.props.children && React.cloneElement(this.props.children)
|
||||
}
|
||||
|
||||
return this.props.children && React.cloneElement(this.props.children)
|
||||
}
|
||||
|
||||
private get isLoading(): boolean {
|
||||
|
@ -64,9 +68,15 @@ export class Signin extends PureComponent<Props, State> {
|
|||
)
|
||||
}
|
||||
|
||||
private handleSignInUser = () => {
|
||||
this.setState({isUserSignedIn: true})
|
||||
private checkForLogin = async () => {
|
||||
try {
|
||||
await getMe()
|
||||
} catch (error) {
|
||||
clearInterval(this.intervalID)
|
||||
this.setState({isUserSignedIn: false})
|
||||
this.props.router.push('/signin')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Signin
|
||||
export default withRouter(Signin)
|
||||
|
|
|
@ -19,6 +19,7 @@ import SetActiveSource from 'src/shared/containers/SetActiveSource'
|
|||
import GetOrganizations from 'src/shared/containers/GetOrganizations'
|
||||
import Setup from 'src/Setup'
|
||||
import Signin from 'src/Signin'
|
||||
import SigninPage from 'src/onboarding/containers/SigninPage'
|
||||
import Logout from 'src/Logout'
|
||||
import TaskPage from 'src/tasks/containers/TaskPage'
|
||||
import TasksPage from 'src/tasks/containers/TasksPage'
|
||||
|
@ -89,6 +90,7 @@ class Root extends PureComponent {
|
|||
path="/onboarding/:stepID/:substepID"
|
||||
component={OnboardingWizardPage}
|
||||
/>
|
||||
<Route path="/signin" component={SigninPage} />
|
||||
<Route component={Signin}>
|
||||
<Route component={GetMe}>
|
||||
<Route component={GetOrganizations}>
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
// Libraries
|
||||
import React, {PureComponent, ChangeEvent} from 'react'
|
||||
import {withRouter, WithRouterProps} from 'react-router'
|
||||
import {connect} from 'react-redux'
|
||||
import _, {get} from 'lodash'
|
||||
|
||||
// Components
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
|
||||
import {
|
||||
Button,
|
||||
ComponentColor,
|
||||
ComponentSize,
|
||||
Input,
|
||||
InputType,
|
||||
Form,
|
||||
Grid,
|
||||
Columns,
|
||||
ButtonType,
|
||||
} from 'src/clockface'
|
||||
|
||||
// APIs
|
||||
import {signin} from 'src/onboarding/apis'
|
||||
|
||||
// Actions
|
||||
import {notify as notifyAction} from 'src/shared/actions/notifications'
|
||||
|
||||
// Constants
|
||||
import * as copy from 'src/shared/copy/notifications'
|
||||
|
||||
// Types
|
||||
import {Links} from 'src/types/v2/links'
|
||||
import {Notification, NotificationFunc} from 'src/types'
|
||||
|
||||
export interface OwnProps {
|
||||
links: Links
|
||||
notify: (message: Notification | NotificationFunc) => void
|
||||
}
|
||||
|
||||
interface State {
|
||||
username: string
|
||||
password: string
|
||||
}
|
||||
|
||||
type Props = OwnProps & WithRouterProps
|
||||
|
||||
@ErrorHandling
|
||||
class SigninForm extends PureComponent<Props, State> {
|
||||
public state: State = {
|
||||
username: '',
|
||||
password: '',
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {username, password} = this.state
|
||||
return (
|
||||
<Form onSubmit={this.handleSignIn}>
|
||||
<Grid>
|
||||
<Grid.Row>
|
||||
<Grid.Column widthXS={Columns.Twelve}>
|
||||
<Form.Element label="Username">
|
||||
<Input
|
||||
value={username}
|
||||
onChange={this.handleUsername}
|
||||
size={ComponentSize.Medium}
|
||||
autoFocus={true}
|
||||
/>
|
||||
</Form.Element>
|
||||
</Grid.Column>
|
||||
<Grid.Column widthXS={Columns.Twelve}>
|
||||
<Form.Element label="Password">
|
||||
<Input
|
||||
value={password}
|
||||
onChange={this.handlePassword}
|
||||
size={ComponentSize.Medium}
|
||||
type={InputType.Password}
|
||||
/>
|
||||
</Form.Element>
|
||||
</Grid.Column>
|
||||
<Grid.Column widthXS={Columns.Twelve}>
|
||||
<Form.Footer>
|
||||
<Button
|
||||
color={ComponentColor.Primary}
|
||||
text="Sign In"
|
||||
size={ComponentSize.Medium}
|
||||
type={ButtonType.Submit}
|
||||
/>
|
||||
</Form.Footer>
|
||||
</Grid.Column>
|
||||
</Grid.Row>
|
||||
</Grid>
|
||||
</Form>
|
||||
)
|
||||
}
|
||||
|
||||
private handleUsername = (e: ChangeEvent<HTMLInputElement>): void => {
|
||||
const username = e.target.value
|
||||
this.setState({username})
|
||||
}
|
||||
private handlePassword = (e: ChangeEvent<HTMLInputElement>): void => {
|
||||
const password = e.target.value
|
||||
this.setState({password})
|
||||
}
|
||||
|
||||
private handleSignIn = async (): Promise<void> => {
|
||||
const {notify, router} = this.props
|
||||
const {username, password} = this.state
|
||||
|
||||
try {
|
||||
await signin({username, password})
|
||||
router.push('/dashboards')
|
||||
} catch (error) {
|
||||
const message = get(error, 'data.msg', '')
|
||||
|
||||
if (!message) {
|
||||
return notify(copy.SigninError)
|
||||
}
|
||||
|
||||
notify({...copy.SigninError, message})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const mstp = ({links}) => ({
|
||||
links,
|
||||
})
|
||||
|
||||
const mdtp = {
|
||||
notify: notifyAction,
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mstp,
|
||||
mdtp
|
||||
)(withRouter(SigninForm))
|
|
@ -1,142 +1,25 @@
|
|||
// Libraries
|
||||
import React, {PureComponent, ChangeEvent} from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
import _, {get} from 'lodash'
|
||||
import React, {PureComponent} from 'react'
|
||||
import _ from 'lodash'
|
||||
|
||||
// Components
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
import SplashPage from 'src/shared/components/splash_page/SplashPage'
|
||||
|
||||
import {
|
||||
Button,
|
||||
ComponentColor,
|
||||
ComponentSize,
|
||||
Input,
|
||||
InputType,
|
||||
Form,
|
||||
Grid,
|
||||
Columns,
|
||||
ButtonType,
|
||||
} from 'src/clockface'
|
||||
|
||||
// APIs
|
||||
import {signin} from 'src/onboarding/apis'
|
||||
|
||||
// Actions
|
||||
import {notify as notifyAction} from 'src/shared/actions/notifications'
|
||||
|
||||
// Constants
|
||||
import * as copy from 'src/shared/copy/notifications'
|
||||
|
||||
// Types
|
||||
import {Links} from 'src/types/v2/links'
|
||||
import {Notification, NotificationFunc} from 'src/types'
|
||||
|
||||
export interface Props {
|
||||
links: Links
|
||||
notify: (message: Notification | NotificationFunc) => void
|
||||
onSignInUser: () => void
|
||||
}
|
||||
|
||||
interface State {
|
||||
username: string
|
||||
password: string
|
||||
}
|
||||
import SigninForm from 'src/onboarding/components/SigninForm'
|
||||
|
||||
@ErrorHandling
|
||||
class SigninPage extends PureComponent<Props, State> {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
this.state = {
|
||||
username: '',
|
||||
password: '',
|
||||
}
|
||||
}
|
||||
|
||||
class SigninPage extends PureComponent<{}> {
|
||||
public render() {
|
||||
const {username, password} = this.state
|
||||
return (
|
||||
<SplashPage panelWidthPixels={300}>
|
||||
<SplashPage.Panel>
|
||||
<SplashPage.Logo />
|
||||
<SplashPage.Header title="InfluxData" />
|
||||
<Form onSubmit={this.handleSignIn}>
|
||||
<Grid>
|
||||
<Grid.Row>
|
||||
<Grid.Column widthXS={Columns.Twelve}>
|
||||
<Form.Element label="Username">
|
||||
<Input
|
||||
value={username}
|
||||
onChange={this.handleUsername}
|
||||
size={ComponentSize.Medium}
|
||||
autoFocus={true}
|
||||
/>
|
||||
</Form.Element>
|
||||
</Grid.Column>
|
||||
<Grid.Column widthXS={Columns.Twelve}>
|
||||
<Form.Element label="Password">
|
||||
<Input
|
||||
value={password}
|
||||
onChange={this.handlePassword}
|
||||
size={ComponentSize.Medium}
|
||||
type={InputType.Password}
|
||||
/>
|
||||
</Form.Element>
|
||||
</Grid.Column>
|
||||
<Grid.Column widthXS={Columns.Twelve}>
|
||||
<Form.Footer>
|
||||
<Button
|
||||
color={ComponentColor.Primary}
|
||||
text="Sign In"
|
||||
size={ComponentSize.Medium}
|
||||
type={ButtonType.Submit}
|
||||
/>
|
||||
</Form.Footer>
|
||||
</Grid.Column>
|
||||
</Grid.Row>
|
||||
</Grid>
|
||||
</Form>
|
||||
<SigninForm />
|
||||
</SplashPage.Panel>
|
||||
</SplashPage>
|
||||
)
|
||||
}
|
||||
|
||||
private handleUsername = (e: ChangeEvent<HTMLInputElement>): void => {
|
||||
const username = e.target.value
|
||||
this.setState({username})
|
||||
}
|
||||
private handlePassword = (e: ChangeEvent<HTMLInputElement>): void => {
|
||||
const password = e.target.value
|
||||
this.setState({password})
|
||||
}
|
||||
|
||||
private handleSignIn = async (): Promise<void> => {
|
||||
const {notify, onSignInUser} = this.props
|
||||
const {username, password} = this.state
|
||||
try {
|
||||
await signin({username, password})
|
||||
onSignInUser()
|
||||
} catch (error) {
|
||||
const message = get(error, 'data.msg', '')
|
||||
|
||||
if (!message) {
|
||||
return notify(copy.SigninError)
|
||||
}
|
||||
|
||||
notify({...copy.SigninError, message})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const mstp = ({links}) => ({
|
||||
links,
|
||||
})
|
||||
|
||||
const mdtp = {
|
||||
notify: notifyAction,
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mstp,
|
||||
mdtp
|
||||
)(SigninPage)
|
||||
export default SigninPage
|
||||
|
|
Loading…
Reference in New Issue