add auth redirect, public 404 page

This commit is contained in:
Sidney Alcantara
2021-09-16 13:00:04 +10:00
parent 7e297f3141
commit 4b6a79dbbf
9 changed files with 110 additions and 55 deletions

View File

@@ -1,16 +1,14 @@
import { lazy, Suspense } from "react";
import { Route, Switch, Link, Redirect } from "react-router-dom";
import { Route, Switch, Redirect } from "react-router-dom";
import LocalizationProvider from "@mui/lab/LocalizationProvider";
import AdapterDateFns from "@mui/lab/AdapterDateFns";
import { StyledEngineProvider } from "@mui/material/styles";
import { Button } from "@mui/material";
import "./space-grotesk.css";
import CustomBrowserRouter from "utils/CustomBrowserRouter";
import PrivateRoute from "utils/PrivateRoute";
import ErrorBoundary from "components/ErrorBoundary";
import EmptyState from "components/EmptyState";
import Loading from "components/Loading";
import Navigation from "components/Navigation";
import Logo from "assets/Logo";
@@ -22,10 +20,11 @@ import { SnackbarProvider } from "contexts/SnackbarContext";
import { SnackLogProvider } from "contexts/SnackLogContext";
import routes from "constants/routes";
import AuthView from "pages/Auth";
import SignOutView from "pages/Auth/SignOut";
import TestView from "pages/Test";
import RowyRunTestView from "pages/RowyRunTest";
import AuthPage from "pages/Auth";
import SignOutPage from "pages/Auth/SignOut";
import TestPage from "pages/Test";
import RowyRunTestPage from "pages/RowyRunTest";
import PageNotFound from "pages/PageNotFound";
import Favicon from "assets/Favicon";
import "analytics";
@@ -67,7 +66,7 @@ export default function App() {
<Route
exact
path={routes.auth}
render={() => <AuthView />}
render={() => <AuthPage />}
/>
<Route
exact
@@ -82,7 +81,7 @@ export default function App() {
<Route
exact
path={routes.signOut}
render={() => <SignOutView />}
render={() => <SignOutPage />}
/>
<Route
exact
@@ -93,7 +92,7 @@ export default function App() {
<Route
exact
path={"/test"}
render={() => <TestView />}
render={() => <TestPage />}
/>
<PrivateRoute
@@ -120,7 +119,7 @@ export default function App() {
<Route
exact
path={routes.rowyRunTest}
render={() => <RowyRunTestView />}
render={() => <RowyRunTestPage />}
/>
<PrivateRoute
exact
@@ -189,30 +188,12 @@ export default function App() {
)}
/>
<PrivateRoute
render={() => (
<Navigation
title="Page Not Found"
titleComponent={<div />}
>
<EmptyState
message="Page Not Found"
description={
<Button
component={Link}
to={routes.home}
variant="outlined"
style={{ marginTop: 8 }}
>
Go Home
</Button>
}
fullScreen
style={{ marginTop: -64 }}
/>
</Navigation>
)}
<Route
exact
path={routes.pageNotFound}
render={() => <PageNotFound />}
/>
<Route render={() => <PageNotFound />} />
</Switch>
</Suspense>
</CustomBrowserRouter>

View File

@@ -6,6 +6,7 @@ export enum routes {
signOut = "/signOut",
authSetup = "/authSetup",
setup = "/setup",
pageNotFound = "/404",
table = "/table",
tableWithId = "/table/:id",

View File

@@ -24,6 +24,7 @@ export const projectId = process.env.REACT_APP_FIREBASE_PROJECT_ID!;
export const WEBHOOK_URL = `https://${(functions as any).region_}-${
appConfig.projectId
}.cloudfunctions.net/webhook`;
export const googleProvider =
new firebase.auth.GoogleAuthProvider().setCustomParameters({
prompt: "select_account",

View File

@@ -49,7 +49,7 @@ export default function ImpersonatorAuthPage() {
return (
<AuthLayout loading={loading}>
<div>
<Typography variant="h6" component="h2" gutterBottom>
<Typography variant="h6" component="h1" gutterBottom>
Admin Authentication
</Typography>
<Typography gutterBottom>

View File

@@ -28,7 +28,7 @@ export default function JwtAuthPage() {
return (
<AuthLayout loading={loading}>
<Typography variant="h6" component="h2">
<Typography variant="h6" component="h1">
Test Authentication
</Typography>

View File

@@ -18,13 +18,7 @@ export default function SignOutPage() {
<EmptyState
message="Signed Out"
description={
<Button
component={Link}
to="/auth"
variant="outlined"
color="primary"
style={{ marginTop: 24 }}
>
<Button component={Link} to="/auth" variant="outlined" sx={{ mt: 3 }}>
Sign In Again
</Button>
}

View File

@@ -1,10 +1,21 @@
import { useLocation } from "react-router-dom";
import queryString from "query-string";
import AuthLayout from "components/Auth/AuthLayout";
import FirebaseUi from "components/Auth/FirebaseUi";
export default function AuthPage() {
const { search } = useLocation();
const parsed = queryString.parse(search);
const uiConfig: firebaseui.auth.Config = {};
if (typeof parsed.redirect === "string" && parsed.redirect.length > 0) {
uiConfig.signInSuccessUrl = parsed.redirect;
}
return (
<AuthLayout>
<FirebaseUi />
<FirebaseUi uiConfig={uiConfig} />
</AuthLayout>
);
}

View File

@@ -0,0 +1,58 @@
import { Link } from "react-router-dom";
import { Button } from "@mui/material";
import GoIcon from "assets/icons/Go";
import HomeIcon from "@mui/icons-material/HomeOutlined";
import AuthLayout from "components/Auth/AuthLayout";
import Navigation, { APP_BAR_HEIGHT } from "components/Navigation";
import EmptyState from "components/EmptyState";
import { homepage } from "@root/package.json";
import { useAppContext } from "contexts/AppContext";
import routes from "constants/routes";
export interface IPageNotFoundProps {}
export default function PageNotFound() {
const { currentUser } = useAppContext();
if (!currentUser)
return (
<AuthLayout>
<EmptyState
message="Page Not Found"
description={
<Button
variant="outlined"
sx={{ mt: 3 }}
href={homepage}
endIcon={<GoIcon style={{ margin: "0 -0.33em" }} />}
>
{homepage.split("//")[1].replace(/\//g, "")}
</Button>
}
/>
</AuthLayout>
);
return (
<Navigation title="Page Not Found" titleComponent={<div />}>
<EmptyState
message="Page Not Found"
description={
<Button
variant="outlined"
sx={{ mt: 3 }}
component={Link}
to={routes.home}
startIcon={<HomeIcon />}
>
Home
</Button>
}
fullScreen
style={{ marginTop: -APP_BAR_HEIGHT }}
/>
</Navigation>
);
}

View File

@@ -1,26 +1,35 @@
import React, { useContext } from "react";
import { Route, RouteProps, Redirect } from "react-router-dom";
import { AppContext } from "contexts/AppContext";
import Loading from "../components/Loading";
import { useAppContext } from "contexts/AppContext";
import Loading from "components/Loading";
import routes from "constants/routes";
interface IPrivateRouteProps extends RouteProps {
render: NonNullable<RouteProps["render"]>;
}
const PrivateRoute: React.FC<IPrivateRouteProps> = ({ render, ...rest }) => {
const { currentUser } = useContext(AppContext);
export default function PrivateRoute({ render, ...props }: IPrivateRouteProps) {
const { currentUser } = useAppContext();
if (!!currentUser) return <Route {...rest} render={render} />;
if (!!currentUser) return <Route {...props} render={render} />;
if (currentUser === null) return <Redirect to="/auth" />;
const redirect =
(props.location?.pathname ?? "") + (props.location?.search ?? "");
if (currentUser === null)
return (
<Redirect
to={{
pathname: routes.auth,
search: redirect ? `?redirect=${encodeURIComponent(redirect)}` : "",
}}
/>
);
return (
<Route
{...rest}
{...props}
render={() => <Loading message="Authenticating" fullScreen />}
/>
);
};
export default PrivateRoute;
}