Skip to content

Commit 3fceb58

Browse files
committed
Fix router logic to account for logged out users; closes pterodactyl#4085
Middleware was removed from the `/` route to redirect users without authentication, so now we need to handle this on the front-end properly.
1 parent b051718 commit 3fceb58

File tree

5 files changed

+99
-61
lines changed

5 files changed

+99
-61
lines changed

resources/scripts/components/App.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import tw, { GlobalStyles as TailwindGlobalStyles } from 'twin.macro';
1313
import GlobalStylesheet from '@/assets/css/GlobalStylesheet';
1414
import { history } from '@/components/history';
1515
import { setupInterceptors } from '@/api/interceptors';
16+
import AuthenticatedRoute from '@/components/elements/AuthenticatedRoute';
17+
import { ServerContext } from '@/state/server';
1618

1719
interface ExtendedWindow extends Window {
1820
SiteConfiguration?: SiteSettings;
@@ -60,10 +62,20 @@ const App = () => {
6062
<div css={tw`mx-auto w-auto`}>
6163
<Router history={history}>
6264
<Switch>
63-
<Route path="/server/:id" component={ServerRouter}/>
64-
<Route path="/auth" component={AuthenticationRouter}/>
65-
<Route path="/" component={DashboardRouter}/>
66-
<Route path={'*'} component={NotFound}/>
65+
<Route path={'/auth'}>
66+
<AuthenticationRouter/>
67+
</Route>
68+
<AuthenticatedRoute path={'/server/:id'}>
69+
<ServerContext.Provider>
70+
<ServerRouter/>
71+
</ServerContext.Provider>
72+
</AuthenticatedRoute>
73+
<AuthenticatedRoute path={'/'}>
74+
<DashboardRouter/>
75+
</AuthenticatedRoute>
76+
<Route path={'*'}>
77+
<NotFound/>
78+
</Route>
6779
</Switch>
6880
</Router>
6981
</div>
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
import { Redirect, Route, RouteProps } from 'react-router';
3+
import { useStoreState } from '@/state/hooks';
4+
5+
export default ({ children, ...props }: Omit<RouteProps, 'render'>) => {
6+
const isAuthenticated = useStoreState(state => !!state.user.data?.uuid);
7+
8+
return (
9+
<Route
10+
{...props}
11+
render={({ location }) => (
12+
isAuthenticated ? children : <Redirect to={{ pathname: '/auth/login', state: { from: location } }}/>
13+
)}
14+
/>
15+
);
16+
};
Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,29 @@
11
import React from 'react';
2-
import { Route, RouteComponentProps, Switch } from 'react-router-dom';
2+
import { Route, Switch, useRouteMatch } from 'react-router-dom';
33
import LoginContainer from '@/components/auth/LoginContainer';
44
import ForgotPasswordContainer from '@/components/auth/ForgotPasswordContainer';
55
import ResetPasswordContainer from '@/components/auth/ResetPasswordContainer';
66
import LoginCheckpointContainer from '@/components/auth/LoginCheckpointContainer';
77
import { NotFound } from '@/components/elements/ScreenBlock';
8+
import { useHistory, useLocation } from 'react-router';
89

9-
export default ({ location, history, match }: RouteComponentProps) => (
10-
<div className={'pt-8 xl:pt-32'}>
11-
<Switch location={location}>
12-
<Route path={`${match.path}/login`} component={LoginContainer} exact/>
13-
<Route path={`${match.path}/login/checkpoint`} component={LoginCheckpointContainer}/>
14-
<Route path={`${match.path}/password`} component={ForgotPasswordContainer} exact/>
15-
<Route path={`${match.path}/password/reset/:token`} component={ResetPasswordContainer}/>
16-
<Route path={`${match.path}/checkpoint`}/>
17-
<Route path={'*'}>
18-
<NotFound onBack={() => history.push('/auth/login')}/>
19-
</Route>
20-
</Switch>
21-
</div>
22-
);
10+
export default () => {
11+
const history = useHistory();
12+
const location = useLocation();
13+
const { path } = useRouteMatch();
14+
15+
return (
16+
<div className={'pt-8 xl:pt-32'}>
17+
<Switch location={location}>
18+
<Route path={`${path}/login`} component={LoginContainer} exact/>
19+
<Route path={`${path}/login/checkpoint`} component={LoginCheckpointContainer}/>
20+
<Route path={`${path}/password`} component={ForgotPasswordContainer} exact/>
21+
<Route path={`${path}/password/reset/:token`} component={ResetPasswordContainer}/>
22+
<Route path={`${path}/checkpoint`}/>
23+
<Route path={'*'}>
24+
<NotFound onBack={() => history.push('/auth/login')}/>
25+
</Route>
26+
</Switch>
27+
</div>
28+
);
29+
};
Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import React from 'react';
2-
import { NavLink, Route, RouteComponentProps, Switch } from 'react-router-dom';
2+
import { NavLink, Route, Switch } from 'react-router-dom';
33
import AccountOverviewContainer from '@/components/dashboard/AccountOverviewContainer';
44
import NavigationBar from '@/components/NavigationBar';
55
import DashboardContainer from '@/components/dashboard/DashboardContainer';
@@ -8,37 +8,42 @@ import { NotFound } from '@/components/elements/ScreenBlock';
88
import TransitionRouter from '@/TransitionRouter';
99
import SubNavigation from '@/components/elements/SubNavigation';
1010
import AccountSSHContainer from '@/components/dashboard/ssh/AccountSSHContainer';
11+
import { useLocation } from 'react-router';
1112

12-
export default ({ location }: RouteComponentProps) => (
13-
<>
14-
<NavigationBar/>
15-
{location.pathname.startsWith('/account') &&
16-
<SubNavigation>
17-
<div>
18-
<NavLink to={'/account'} exact>Settings</NavLink>
19-
<NavLink to={'/account/api'}>API Credentials</NavLink>
20-
<NavLink to={'/account/ssh'}>SSH Keys</NavLink>
21-
</div>
22-
</SubNavigation>
23-
}
24-
<TransitionRouter>
25-
<Switch location={location}>
26-
<Route path={'/'} exact>
27-
<DashboardContainer/>
28-
</Route>
29-
<Route path={'/account'} exact>
30-
<AccountOverviewContainer/>
31-
</Route>
32-
<Route path={'/account/api'} exact>
33-
<AccountApiContainer/>
34-
</Route>
35-
<Route path={'/account/ssh'} exact>
36-
<AccountSSHContainer/>
37-
</Route>
38-
<Route path={'*'}>
39-
<NotFound/>
40-
</Route>
41-
</Switch>
42-
</TransitionRouter>
43-
</>
44-
);
13+
export default () => {
14+
const location = useLocation();
15+
16+
return (
17+
<>
18+
<NavigationBar/>
19+
{location.pathname.startsWith('/account') &&
20+
<SubNavigation>
21+
<div>
22+
<NavLink to={'/account'} exact>Settings</NavLink>
23+
<NavLink to={'/account/api'}>API Credentials</NavLink>
24+
<NavLink to={'/account/ssh'}>SSH Keys</NavLink>
25+
</div>
26+
</SubNavigation>
27+
}
28+
<TransitionRouter>
29+
<Switch location={location}>
30+
<Route path={'/'} exact>
31+
<DashboardContainer/>
32+
</Route>
33+
<Route path={'/account'} exact>
34+
<AccountOverviewContainer/>
35+
</Route>
36+
<Route path={'/account/api'} exact>
37+
<AccountApiContainer/>
38+
</Route>
39+
<Route path={'/account/ssh'} exact>
40+
<AccountSSHContainer/>
41+
</Route>
42+
<Route path={'*'}>
43+
<NotFound/>
44+
</Route>
45+
</Switch>
46+
</TransitionRouter>
47+
</>
48+
);
49+
};

resources/scripts/routers/ServerRouter.tsx

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import TransferListener from '@/components/server/TransferListener';
22
import React, { useEffect, useState } from 'react';
3-
import { NavLink, Route, RouteComponentProps, Switch } from 'react-router-dom';
3+
import { NavLink, Route, Switch, useRouteMatch } from 'react-router-dom';
44
import NavigationBar from '@/components/NavigationBar';
55
import ServerConsole from '@/components/server/ServerConsole';
66
import TransitionRouter from '@/TransitionRouter';
@@ -31,6 +31,7 @@ import RequireServerPermission from '@/hoc/RequireServerPermission';
3131
import ServerInstallSvg from '@/assets/images/server_installing.svg';
3232
import ServerRestoreSvg from '@/assets/images/server_restore.svg';
3333
import ServerErrorSvg from '@/assets/images/server_error.svg';
34+
import { useLocation } from 'react-router';
3435

3536
const ConflictStateRenderer = () => {
3637
const status = ServerContext.useStoreState(state => state.server.data?.status || null);
@@ -59,7 +60,10 @@ const ConflictStateRenderer = () => {
5960
);
6061
};
6162

62-
const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>) => {
63+
export default () => {
64+
const match = useRouteMatch<{ id: string }>();
65+
const location = useLocation();
66+
6367
const rootAdmin = useStoreState(state => state.user.data!.rootAdmin);
6468
const [ error, setError ] = useState('');
6569

@@ -194,9 +198,3 @@ const ServerRouter = ({ match, location }: RouteComponentProps<{ id: string }>)
194198
</React.Fragment>
195199
);
196200
};
197-
198-
export default (props: RouteComponentProps<any>) => (
199-
<ServerContext.Provider>
200-
<ServerRouter {...props}/>
201-
</ServerContext.Provider>
202-
);

0 commit comments

Comments
 (0)