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

@ -7,7 +7,6 @@ import { useDispatch } from "react-redux";
import Container from "./widgets/Container";
import ExternalLink from "./widgets/ExternalLink";
import SyncGate from "./SyncGate";
import LoginForm from "./components/LoginForm";
import { login } from "./store/actions";
@ -20,18 +19,30 @@ import SignedPagesBadge from "./images/signed-pages-badge.svg";
import { useCredentials } from "./credentials";
import LoadingIndicator from "./widgets/LoadingIndicator";
import { startTask } from "./helpers";
import { Switch, Route } from "react-router";
import { Redirect, useLocation } from "react-router";
import { routeResolver } from "./App";
import SignupPage from "./SignupPage";
import { Link } from "react-router-dom";
interface LocationState {
from: {
pathname: string;
};
}
export default function LoginGate() {
export default function LoginPage() {
const credentials = useCredentials();
const dispatch = useDispatch();
const location = useLocation();
const [loading, setLoading] = React.useState(false);
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) {
try {
setLoading(true);
@ -56,7 +67,7 @@ export default function LoginGate() {
return (
<LoadingIndicator />
);
} else if (credentials === null) {
} else {
const style = {
isSafe: {
textDecoration: "none",
@ -69,43 +80,28 @@ export default function LoginGate() {
};
return (
<Switch>
<Route
path={routeResolver.getRoute("signup")}
exact
render={() => (
<SignupPage />
)}
<Container style={{ maxWidth: "30rem" }}>
<h2 style={{ marginBottom: "0.1em" }}>Log In</h2>
<div style={{ fontSize: "90%" }}>or <Link to={routeResolver.getRoute("signup")}>create an account</Link></div>
<LoginForm
onSubmit={onFormSubmit}
loading={loading}
error={fetchError}
/>
<Route>
<Container style={{ maxWidth: "30rem" }}>
<h2 style={{ marginBottom: "0.1em" }}>Log In</h2>
<div style={{ fontSize: "90%" }}>or <Link to={routeResolver.getRoute("signup")}>create an account</Link></div>
<LoginForm
onSubmit={onFormSubmit}
loading={loading}
error={fetchError}
/>
<hr style={style.divider} />
<ExternalLink style={style.isSafe} href="https://www.etesync.com/faq/#signed-pages">
<img alt="SignedPgaes badge" src={SignedPagesBadge} />
</ExternalLink>
<ul>
<li><ExternalLink style={style.isSafe} href={C.homePage}>
The EteSync Website
</ExternalLink></li>
<li><ExternalLink style={style.isSafe} href={C.faq + "#web-client"}>
Is the web client safe to use?
</ExternalLink></li>
<li><ExternalLink style={style.isSafe} href={C.sourceCode}>Source code</ExternalLink></li>
</ul>
</Container>
</Route>
</Switch>
<hr style={style.divider} />
<ExternalLink style={style.isSafe} href="https://www.etesync.com/faq/#signed-pages">
<img alt="SignedPgaes badge" src={SignedPagesBadge} />
</ExternalLink>
<ul>
<li><ExternalLink style={style.isSafe} href={C.homePage}>
The EteSync Website
</ExternalLink></li>
<li><ExternalLink style={style.isSafe} href={C.faq + "#web-client"}>
Is the web client safe to use?
</ExternalLink></li>
<li><ExternalLink style={style.isSafe} href={C.sourceCode}>Source code</ExternalLink></li>
</ul>
</Container>
);
}
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