Change to the recommended way of doing login-guarded pages.

It's also much cleaner in our case because the signup page is no longer
handled from inside the login page.
master
Tom Hacohen 4 years ago
parent 835367ba9f
commit 750eae59b4

@ -27,7 +27,6 @@ import { List, ListItem } from "./widgets/List";
import withSpin from "./widgets/withSpin"; import withSpin from "./widgets/withSpin";
import ErrorBoundary from "./components/ErrorBoundary"; import ErrorBoundary from "./components/ErrorBoundary";
import SideMenu from "./SideMenu"; import SideMenu from "./SideMenu";
import LoginGate from "./LoginGate";
import { RouteResolver } from "./routes"; import { RouteResolver } from "./routes";
import * as store from "./store"; import * as store from "./store";
@ -35,6 +34,7 @@ import * as actions from "./store/actions";
import { useCredentials } from "./credentials"; import { useCredentials } from "./credentials";
import { SyncManager } from "./sync/SyncManager"; import { SyncManager } from "./sync/SyncManager";
import MainRouter from "./MainRouter";
export const routeResolver = new RouteResolver({ export const routeResolver = new RouteResolver({
home: "", home: "",
@ -85,6 +85,8 @@ export const routeResolver = new RouteResolver({
new: "new", new: "new",
import: "import", import: "import",
}, },
login: {
},
signup: { signup: {
}, },
settings: { settings: {
@ -239,7 +241,7 @@ export default function App() {
</Drawer> </Drawer>
<ErrorBoundary> <ErrorBoundary>
<LoginGate /> <MainRouter />
</ErrorBoundary> </ErrorBoundary>
</div> </div>
</BrowserRouter> </BrowserRouter>

@ -7,7 +7,6 @@ import { useDispatch } from "react-redux";
import Container from "./widgets/Container"; import Container from "./widgets/Container";
import ExternalLink from "./widgets/ExternalLink"; import ExternalLink from "./widgets/ExternalLink";
import SyncGate from "./SyncGate";
import LoginForm from "./components/LoginForm"; import LoginForm from "./components/LoginForm";
import { login } from "./store/actions"; import { login } from "./store/actions";
@ -20,18 +19,30 @@ import SignedPagesBadge from "./images/signed-pages-badge.svg";
import { useCredentials } from "./credentials"; import { useCredentials } from "./credentials";
import LoadingIndicator from "./widgets/LoadingIndicator"; import LoadingIndicator from "./widgets/LoadingIndicator";
import { startTask } from "./helpers"; import { startTask } from "./helpers";
import { Switch, Route } from "react-router"; import { Redirect, useLocation } from "react-router";
import { routeResolver } from "./App"; import { routeResolver } from "./App";
import SignupPage from "./SignupPage";
import { Link } from "react-router-dom"; import { Link } from "react-router-dom";
interface LocationState {
from: {
pathname: string;
};
}
export default function LoginGate() { export default function LoginPage() {
const credentials = useCredentials(); const credentials = useCredentials();
const dispatch = useDispatch(); const dispatch = useDispatch();
const location = useLocation();
const [loading, setLoading] = React.useState(false); const [loading, setLoading] = React.useState(false);
const [fetchError, setFetchError] = React.useState<Error>(); const [fetchError, setFetchError] = React.useState<Error>();
const { from } = location.state as LocationState || { from: { pathname: routeResolver.getRoute("home") } };
if (credentials) {
return (
<Redirect to={from.pathname} />
);
}
async function onFormSubmit(username: string, password: string, serviceApiUrl?: string) { async function onFormSubmit(username: string, password: string, serviceApiUrl?: string) {
try { try {
setLoading(true); setLoading(true);
@ -56,7 +67,7 @@ export default function LoginGate() {
return ( return (
<LoadingIndicator /> <LoadingIndicator />
); );
} else if (credentials === null) { } else {
const style = { const style = {
isSafe: { isSafe: {
textDecoration: "none", textDecoration: "none",
@ -69,15 +80,6 @@ export default function LoginGate() {
}; };
return ( return (
<Switch>
<Route
path={routeResolver.getRoute("signup")}
exact
render={() => (
<SignupPage />
)}
/>
<Route>
<Container style={{ maxWidth: "30rem" }}> <Container style={{ maxWidth: "30rem" }}>
<h2 style={{ marginBottom: "0.1em" }}>Log In</h2> <h2 style={{ marginBottom: "0.1em" }}>Log In</h2>
<div style={{ fontSize: "90%" }}>or <Link to={routeResolver.getRoute("signup")}>create an account</Link></div> <div style={{ fontSize: "90%" }}>or <Link to={routeResolver.getRoute("signup")}>create an account</Link></div>
@ -100,12 +102,6 @@ export default function LoginGate() {
<li><ExternalLink style={style.isSafe} href={C.sourceCode}>Source code</ExternalLink></li> <li><ExternalLink style={style.isSafe} href={C.sourceCode}>Source code</ExternalLink></li>
</ul> </ul>
</Container> </Container>
</Route>
</Switch>
); );
} }
return (
<SyncGate />
);
} }

@ -0,0 +1,63 @@
// SPDX-FileCopyrightText: © 2017 EteSync Authors
// SPDX-License-Identifier: AGPL-3.0-only
import * as React from "react";
import { Route, Switch, Redirect, RouteProps } from "react-router";
import { useCredentials } from "./credentials";
import LoadingIndicator from "./widgets/LoadingIndicator";
import SyncGate from "./SyncGate";
import { routeResolver } from "./App";
import SignupPage from "./SignupPage";
import LoginPage from "./LoginPage";
export default function MainRouter() {
return (
<Switch>
<Route
path={routeResolver.getRoute("signup")}
exact
>
<SignupPage />
</Route>
<Route
path={routeResolver.getRoute("login")}
exact
>
<LoginPage />
</Route>
<PrivateRoute
path="*"
>
<SyncGate />
</PrivateRoute>
</Switch>
);
}
function PrivateRoute(props: Omit<RouteProps, "render">) {
const credentials = useCredentials();
const { children, ...rest } = props;
if (credentials === undefined) {
return (<LoadingIndicator style={{ display: "block", margin: "40px auto" }} />);
}
return (
<Route
{...rest}
render={({ location }) => (
(credentials) ? (
children
) : (
<Redirect
to={{
pathname: "/login",
state: { from: location },
}}
/>
)
)}
/>
);
}
Loading…
Cancel
Save