Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Implement private route #47

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/Routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import CreatePage from './components/CreatePage';
import LoginPage from './components/LoginPage';
import DashboardPage from './components/DashboardPage';
import NotFoundPage from './components/errorsLoaders/NotFoundPage';
import PrivateRoute from './components/PrivateRoute';

const Routes = () => (
<>
Expand All @@ -20,7 +21,7 @@ const Routes = () => (
<Route exact path="/meeting/:showId/(respond|results)?" component={ShowPage} />
<Route exact path="/new" component={CreatePage} />
<Route exact path="/(login|signup)" component={LoginPage} />
<Route exact path="/dashboard" component={DashboardPage} />
<PrivateRoute exact path="/dashboard" component={DashboardPage} />
<Route path="*" component={NotFoundPage} />
</Switch>
<GoogleAnalytics />
Expand Down
19 changes: 3 additions & 16 deletions src/components/AuthenticatedQuery.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,17 @@ import React, { Component } from 'react';
import { Query } from 'react-apollo';
import { auth } from '../firebase';
import { getAuthInput } from '../utils/auth';
import { Redirect } from 'react-router-dom';

// Wrapper around the Query component that automatically injects an auth
// variable if it is present. If requiresAuth is true, the component will also
// not render anything if the user is logged out.
export default class AuthenticatedQuery extends Component {
state = {
auth: null,
authRefreshed: false,
};

refreshAuthInfo() {
getAuthInput().then((auth) => {
if (auth) {
this.setState({ auth, authRefreshed: true });
} else {
this.setState({ auth });
}
});
getAuthInput().then((auth) => this.setState({ auth }));
}

componentDidMount() {
Expand All @@ -36,18 +28,13 @@ export default class AuthenticatedQuery extends Component {

render() {
const { variables, requiresAuth } = this.props;
const { auth, authRefreshed } = this.state;
const { auth } = this.state;

// Render null if we require authentication
// TODO: Render something if not authenticated instead of just putting a
// blank screen. Maybe have a default blank component or take in a prop for
// this.
if (requiresAuth && !auth) {
if (authRefreshed === true) {
return <Redirect to="/login" />;
}
return null;
}
if (requiresAuth && !auth) return null;

const mergedVars = { auth, ...variables };
return <Query {...this.props} variables={mergedVars} />;
Expand Down
67 changes: 67 additions & 0 deletions src/components/PrivateRoute.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
import React, { Component } from 'react';
import { auth } from '../firebase';
import { getAuthInput } from '../utils/auth';
import { Redirect, Route } from 'react-router-dom';
import styles from './PrivateRoute.module.scss';
import Button from '@material/react-button';

// Wrapper around Routes components which require authentication, such as
// DashboardPage. Automatically redirects to Login if user is not authenticated.
// Pass in to Login component a path to redirect back on successful auth.
export default class PrivateRoute extends Component {
state = {
auth: null,
authRefreshed: false,
};

refreshAuthInfo() {
getAuthInput().then((auth) => {
if (auth) {
this.setState({ auth, authRefreshed: true });
} else {
this.setState({ auth });
}
});
}

componentDidMount() {
this.refreshAuthInfo();
// Necessary because if this page is loaded directly, getAuthInput will
// give you a null auth object.
auth().onAuthStateChanged(() => this.refreshAuthInfo());
}

componentWillUnmount() {
this.setState({ authRefreshed: false });
}

render() {
const { component: Component, ...rest } = this.props;
const { auth, authRefreshed } = this.state;
console.log(auth, authRefreshed);

// Redirect to /login when unauthorized
// Render component if authorized
// Render null if authentication is ongoing
return (
<Route
{...rest}
render={(props) => {
if (!auth && authRefreshed) {
return <Redirect to={{ pathname: '/login', state: { from: props.location } }} />;
} else if (auth) {
return <Component {...props} />;
}
return (
<section className={styles.container}>
<h2>Log in to see your meetings</h2>
<Button onClick={this.handleLogIn} outlined>
Log In or Sign Up
</Button>
</section>
);
}}
/>
);
}
}
19 changes: 19 additions & 0 deletions src/components/PrivateRoute.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
.container {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 85%;

display: flex;
flex-direction: column;
align-items: center;
justify-content: center;

text-align: center;
}

.buttonLink {
color: inherit;
text-decoration: none;
}