From 87c64abf73c7783b9bf613a8aee24df090b94e2f Mon Sep 17 00:00:00 2001 From: Roberto Quezada Date: Mon, 18 Feb 2019 14:32:36 -0700 Subject: [PATCH 1/9] Refactor authenticated routes - add auth provider at top level of routes - add authenticated route component - fix login page temporarily being displayed on home component refresh - add proper redirect on forgot-password component if user logged in --- client/routes.jsx | 45 ++++++++----------- imports/ui/components/forgot_password.jsx | 8 +++- imports/ui/components/hoc/AuthProvider.jsx | 33 ++++++++++++++ .../ui/components/hoc/AuthenticatedRoute.jsx | 18 ++++++++ imports/ui/components/moderator.jsx | 2 +- 5 files changed, 77 insertions(+), 29 deletions(-) create mode 100644 imports/ui/components/hoc/AuthProvider.jsx create mode 100644 imports/ui/components/hoc/AuthenticatedRoute.jsx diff --git a/client/routes.jsx b/client/routes.jsx index 6e2762e..6e76864 100644 --- a/client/routes.jsx +++ b/client/routes.jsx @@ -9,46 +9,39 @@ import Apply from '../imports/ui/components/apply.jsx'; import ForgotPassword from '../imports/ui/components/forgot_password.jsx'; import SetPassword from '../imports/ui/components/set_password.jsx'; import Home from '../imports/ui/components/home.jsx'; -import Moderator from '../imports/ui/components/home.jsx'; -import withUser from '../imports/ui/components/hoc/with-user.jsx'; +import Moderator from '../imports/ui/components/moderator.jsx'; +import AuthenticatedRoute from '../imports/ui/components/hoc/AuthenticatedRoute'; +import { AuthProvider } from '../imports/ui/components/hoc/AuthProvider'; +import withUser from '../imports/ui/components/hoc/with-user'; export const renderRoutes = () => ( - + - - - - - - - - - - + + + + + + + + + + + + - + ); -// All routes where user supposed to be logged in -// If user is not logged in, redirect them to login page -const RouteWithUser = withUser(({ user, component: Component, ...rest }) => { - const { pathname } = window.location; - - if (user) { - return } />; - } else if (pathname !== '/login' && pathname === rest.path) { - return ; - } - return null; -}); const RouteWithOutUser = withUser(({ user, component: Component, ...rest }) => { const { pathname } = window.location; if (!user) { return } />; } else if (pathname !== '/home' && pathname === rest.path) { + console.log('getting redirected to home..') return ; } return null; diff --git a/imports/ui/components/forgot_password.jsx b/imports/ui/components/forgot_password.jsx index 64b4a4b..e193609 100644 --- a/imports/ui/components/forgot_password.jsx +++ b/imports/ui/components/forgot_password.jsx @@ -3,6 +3,8 @@ import { Link } from 'react-router-dom'; import { Alert, Card, Container, Button, Form, Row, Col } from 'react-bootstrap'; import { Accounts } from 'meteor/accounts-base'; import { EMAIL_REGEX } from '/imports/constants/regex'; +import { AuthContext } from './hoc/AuthProvider' +import { Redirect } from 'react-router-dom' class ForgotPassword extends React.Component { constructor(props) { @@ -37,8 +39,10 @@ class ForgotPassword extends React.Component { render() { const { validated, error, success, processing } = this.state; + const { isLoggedIn } = this.context return ( + isLoggedIn ? : @@ -68,7 +72,7 @@ class ForgotPassword extends React.Component { {error ? {error} : null} {success ? {success} : null} -
+
Login
@@ -77,5 +81,5 @@ class ForgotPassword extends React.Component { ); } } - +ForgotPassword.contextType = AuthContext export default ForgotPassword; diff --git a/imports/ui/components/hoc/AuthProvider.jsx b/imports/ui/components/hoc/AuthProvider.jsx new file mode 100644 index 0000000..f4f72d0 --- /dev/null +++ b/imports/ui/components/hoc/AuthProvider.jsx @@ -0,0 +1,33 @@ +import React from 'react' +import { Meteor } from 'meteor/meteor'; +import { Accounts } from 'meteor/accounts-base'; +const AuthContext = React.createContext() + +class AuthProvider extends React.Component { + constructor() { + super() + } + state = { + loggedIn: !!Meteor.userId(), + user: '' + } + + componentDidMount() { + Accounts.onLogout(_ => this.setState({ loggedIn: false })) + Accounts.onLogin(_ => this.setState({ loggedIn: true, user: Meteor.user() })) + } + + render() { + return ( + + {this.props.children} + + ) + } +} + +const AuthConsumer = AuthContext.Consumer + +export { AuthProvider, AuthConsumer, AuthContext } diff --git a/imports/ui/components/hoc/AuthenticatedRoute.jsx b/imports/ui/components/hoc/AuthenticatedRoute.jsx new file mode 100644 index 0000000..53e0dd4 --- /dev/null +++ b/imports/ui/components/hoc/AuthenticatedRoute.jsx @@ -0,0 +1,18 @@ +import React from 'react' +import { Route, Redirect } from 'react-router-dom' +import { AuthConsumer } from './AuthProvider' + +const AuthenticatedRoute = ({ component: Component, ...rest }) => ( + + {({ isLoggedIn, user }) => ( + + isLoggedIn ? : + } + {...rest} + /> + )} + +) + +export default AuthenticatedRoute diff --git a/imports/ui/components/moderator.jsx b/imports/ui/components/moderator.jsx index b69df74..272bfe7 100644 --- a/imports/ui/components/moderator.jsx +++ b/imports/ui/components/moderator.jsx @@ -20,4 +20,4 @@ const Moderator = props => { ) } -export default Home +export default Moderator From fb9e066251b1aafe9675e1931c2080c7f9ed5224 Mon Sep 17 00:00:00 2001 From: Roberto Quezada Date: Mon, 18 Feb 2019 21:13:31 -0700 Subject: [PATCH 2/9] Continue refactoring authenticated routes - update navbar component to leverage context API - delete unused withUser function - delete unused route components --- client/routes.jsx | 23 ++----- imports/ui/components/hoc/with-user.jsx | 25 -------- imports/ui/components/login.jsx | 5 ++ imports/ui/components/navbar.jsx | 83 +++++++++++++------------ 4 files changed, 53 insertions(+), 83 deletions(-) delete mode 100644 imports/ui/components/hoc/with-user.jsx diff --git a/client/routes.jsx b/client/routes.jsx index 6e76864..49dab99 100644 --- a/client/routes.jsx +++ b/client/routes.jsx @@ -12,7 +12,6 @@ import Home from '../imports/ui/components/home.jsx'; import Moderator from '../imports/ui/components/moderator.jsx'; import AuthenticatedRoute from '../imports/ui/components/hoc/AuthenticatedRoute'; import { AuthProvider } from '../imports/ui/components/hoc/AuthProvider'; -import withUser from '../imports/ui/components/hoc/with-user'; export const renderRoutes = () => ( @@ -21,28 +20,16 @@ export const renderRoutes = () => ( - + - - + + - - + + ); - - -const RouteWithOutUser = withUser(({ user, component: Component, ...rest }) => { - const { pathname } = window.location; - if (!user) { - return } />; - } else if (pathname !== '/home' && pathname === rest.path) { - console.log('getting redirected to home..') - return ; - } - return null; -}); diff --git a/imports/ui/components/hoc/with-user.jsx b/imports/ui/components/hoc/with-user.jsx deleted file mode 100644 index 19a61db..0000000 --- a/imports/ui/components/hoc/with-user.jsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react'; -import { Meteor } from 'meteor/meteor'; -import { Accounts } from 'meteor/accounts-base'; - -const WithUser = (Component) => { - return class extends React.Component { - constructor(props) { - super(props); - this.state = { - isLoggedin: !!Meteor.userId() - } - } - - componentDidMount() { - Accounts.onLogout(_ => this.setState({isLoggedin: false})) - Accounts.onLogin(_ => this.setState({isLoggedin: true})) - } - - render() { - return - } - } -} - -export default WithUser diff --git a/imports/ui/components/login.jsx b/imports/ui/components/login.jsx index d1fc69f..a95f975 100644 --- a/imports/ui/components/login.jsx +++ b/imports/ui/components/login.jsx @@ -3,6 +3,8 @@ import { Link } from 'react-router-dom'; import { Alert, Card, Container, Button, Form, Row, Col } from 'react-bootstrap'; import { Meteor } from 'meteor/meteor'; import { EMAIL_REGEX } from '/imports/constants/regex'; +import { AuthContext } from './hoc/AuthProvider' +import { Redirect } from 'react-router-dom' class Login extends React.Component { constructor(props) { @@ -33,8 +35,10 @@ class Login extends React.Component { render() { const { validated, error } = this.state; + const { isLoggedIn } = this.context return ( + isLoggedIn ? : @@ -78,5 +82,6 @@ class Login extends React.Component { ); } } +Login.contextType = AuthContext export default Login; diff --git a/imports/ui/components/navbar.jsx b/imports/ui/components/navbar.jsx index 633730a..b8d5f20 100644 --- a/imports/ui/components/navbar.jsx +++ b/imports/ui/components/navbar.jsx @@ -2,8 +2,7 @@ import React from 'react'; import { Link } from 'react-router-dom'; import { Navbar, Nav, Button, Container } from 'react-bootstrap'; import { Meteor } from 'meteor/meteor'; -import withUser from '/imports/ui/components/hoc/with-user.jsx'; - +import { AuthConsumer } from './hoc/AuthProvider' class NavbarWrapper extends React.Component { constructor(props) { super(props); @@ -18,48 +17,52 @@ class NavbarWrapper extends React.Component { console.log(this.props) return ( - - - - - CodeBuddies Connect - - -