Skip to content

Instantly share code, notes, and snippets.

@jackmccloy
Created August 11, 2016 19:34
Show Gist options
  • Save jackmccloy/3cb07e8c2a57299586a86c2eb7e484b5 to your computer and use it in GitHub Desktop.
Save jackmccloy/3cb07e8c2a57299586a86c2eb7e484b5 to your computer and use it in GitHub Desktop.
import React from 'react';
import { connect } from 'react-redux';
import { push, replace } from 'redux-router';
export function requireLoggedIn(Component) {
// a wrapper that requires a user be logged in. You can decide what 'logged in' means - in this example,
// a user is considered to be logged in if usersStore.meta.self !== null
class AuthComponent extends React.Component {
static displayName = 'AuthComponent';
static propTypes = {
dispatch: React.PropTypes.func,
location: React.PropTypes.object,
usersStore: React.PropTypes.object,
};
componentWillMount() {
// the check happens before the component mounts
if (this.props.usersStore.meta.self === null) {
// redirect to login and add next param so we can redirect again after login
this.props.dispatch(push(`/login?next=${this.props.location.pathname}`));
}
}
render() {
// if a user isn't logged in, they'll never get this far. if they are, the component that is
// passed to this wrapper will be rendered
return (
<Component {...this.props} />
);
}
}
function mapStateToProps(state) {
return {
usersStore: state.usersStore,
};
}
return connect(mapStateToProps)(AuthComponent);
}
export function requireLoggedOut(Component) {
// requireLoggedOut is similar to requireLoggedIn, but but if a user is
// logged in will redirect them to this.props.location.query.next (or to
// the site's homepage if this.props.location.query.next is undefined)
class AuthComponent extends React.Component {
static displayName = 'AuthComponent';
static propTypes = {
dispatch: React.PropTypes.func,
location: React.PropTypes.object,
usersStore: React.PropTypes.object,
};
componentWillMount() {
if (this.props.usersStore.meta.self !== null) {
if (this.props.location.query.next !== undefined) {
// redirects to next page
this.props.dispatch(replace(this.props.location.query.next));
} else {
// redirect to home
this.props.dispatch(replace('/'));
}
}
}
componentDidUpdate() {
this.componentWillMount();
}
render() {
return (
// render the component that requires the user be logged out (passed to this wrapper)
<Component {...this.props} />
);
}
}
function mapStateToProps(state) {
return {
usersStore: state.usersStore,
};
}
return connect(mapStateToProps)(AuthComponent);
}
export function requireSuperUser(Component) {
// You've probably got the idea by now, but here's how it might look if you want to
// restrict access to superusers
class AuthComponent extends React.Component {
static displayName = 'AuthComponent';
static propTypes = {
dispatch: React.PropTypes.func,
location: React.PropTypes.object,
usersStore: React.PropTypes.object,
};
componentWillMount() {
const usersStore = this.props.usersStore;
if (usersStore.meta.self === null) {
// redirect to login and add next param so we can redirect again after login
this.props.dispatch(push(`/login?next=${this.props.location.pathname}`));
} else if (usersStore.list.items[usersStore.meta.self].isSuperuser === false) {
// redirect to home
this.props.dispatch(push('/'));
}
}
render() {
// render the component that requires the user be logged out (passed to this wrapper)
return (
<Component {...this.props} />
);
}
}
function mapStateToProps(state) {
return {
usersStore: state.usersStore,
};
}
return connect(mapStateToProps)(AuthComponent);
}
// Then, when you export a component that you want to be permission restricted, wrap the exported component in your permission wrapper. The export method for the profile page on a site I built looks like this:
/*
module.exports = {
getComponent(location, callback) {
callback(null, requireLoggedIn(
connect(mapStateToProps)(Radium(Profile))
));
},
path: 'profile',
};
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment