Merge pull request #2382 from influxdata/fix/user-sign-out-login

Fix/user sign out login
pull/10616/head
Palakp41 2019-01-09 15:35:25 -08:00 committed by GitHub
commit be299966aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 171 additions and 141 deletions

View File

@ -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,25 +41,24 @@ 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)
}
}
private get isLoading(): boolean {
const {loading} = this.state
@ -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)

View File

@ -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}>

View File

@ -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))

View File

@ -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