Created
May 1, 2018 14:41
-
-
Save chrisabrams/a975867321238b37c90b5965902e2dd2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, {Component} from 'react' | |
import {Route, Redirect} from 'react-router-dom' | |
import userProvider from 'store/providers/user' | |
export default class ProtectedRoute extends Component { | |
constructor(props) { | |
super(props) | |
this.inProgress = false | |
/* | |
NOTE: Can't render a route with a both component & render property | |
*/ | |
this.rProps = Object.assign({}, props) | |
delete this.rProps.component | |
this.state = { | |
authed: false, | |
completed: false, | |
redirectPathname: this.props.redirectPathname || '/auth/login', // Default path to send on redirect | |
props: this.rProps | |
} | |
} | |
auth() { | |
this.inProgress = true | |
const user = userProvider.get() | |
if(!user.__loaded) { | |
return setTimeout(this.auth.bind(this), 100) | |
} | |
let authed = (user && user.id) ? true : false | |
if(this.props.roles instanceof Array) { | |
let roleAuthed = false | |
for(let i = 0, l = this.props.roles.length; i < l; i++) { | |
const role = this.props.roles[i] | |
if(user.roles && user.roles.includes(role)) { | |
roleAuthed = true | |
continue | |
} | |
} | |
if(!roleAuthed) { | |
authed = false | |
} | |
this.setState({ | |
authed, | |
completed: true, | |
redirectPathname: '/dashboard' | |
}) | |
} | |
else { | |
this.setState({ | |
authed, | |
completed: true | |
}) | |
} | |
this.inProgress = false | |
} | |
componentWillMount() { | |
this.auth() | |
} | |
componentWillReceiveProps(nextProps) { | |
/* | |
This is a Component that was mounted from another route; let the component know that the route has changed | |
*/ | |
if(this.state.completed && this.props.computedMatch.path != nextProps.computedMatch.path) { | |
this.setState({props: nextProps}) | |
} | |
} | |
redirect = (props, pathname) => { | |
const options = {pathname, state: {from: props.location}} | |
return <Redirect to={options} /> | |
} | |
renderComponent = (props) => { | |
const authed = this.state.authed | |
const Component = this.props.component | |
if(authed === true) { | |
return <Component {...props} /> | |
} | |
return this.redirect(props, this.state.redirectPathname) | |
} | |
render() { | |
// Can use this to create an optional spinner component while waiting for async function to complete | |
const spinner = null | |
return this.state.completed | |
? <Route | |
{...this.state.props} | |
ref='route' | |
render={this.renderComponent} | |
/> | |
: spinner | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment