Skip to content

Commit

Permalink
Add 'withAdmin' HOC
Browse files Browse the repository at this point in the history
  • Loading branch information
unmade committed Jun 7, 2021
1 parent f1abe3e commit d65df84
Show file tree
Hide file tree
Showing 10 changed files with 123 additions and 49 deletions.
9 changes: 6 additions & 3 deletions src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@ import { Switch, Route } from 'react-router-dom';

import * as routes from './routes';

import Files from './pages/Files';
import Trash from './pages/Trash';
import withAdmin from './hoc/withAdmin';

import SideBar from './containers/SideBar';

import Toast from './containers/Toast';
import ToastItem from './containers/ToastItem';

import Files from './pages/Files';
import Trash from './pages/Trash';
import UserManagement from './pages/admin/UserManagement';

function App() {
return (
<>
Expand All @@ -22,6 +24,7 @@ function App() {
<Switch>
<Route path={routes.FILES.route} component={Files} />
<Route path={routes.TRASH.route} component={Trash} />
<Route path={routes.USER_MANAGEMENT.route} component={withAdmin(UserManagement)} />
</Switch>
</div>
</div>
Expand Down
7 changes: 4 additions & 3 deletions src/components/SideBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,26 @@ import PropTypes from 'prop-types';
import { NavLink } from 'react-router-dom';

import * as icons from '../icons';
import * as routes from '../routes';

import AccountMenu from '../containers/AccountMenu';

export const menu = [
{
path: '/files',
path: routes.FILES.reverse({ path: '.' }),
title: 'Files',
icon: <icons.File className="flex-shrink-0 w-5 h-5 mr-3" />,
},
{
path: '/trash',
path: routes.TRASH.reverse({ path: '.' }),
title: 'Trash',
icon: <icons.TrashOutlined className="flex-shrink-0 w-5 h-5 mr-3" />,
},
];

const adminMenu = [
{
path: '/admin/users',
path: routes.USER_MANAGEMENT.reverse(),
title: 'User management',
icon: <icons.UsersOutline className="flex-shrink-0 w-5 h-5 mr-3" />,
},
Expand Down
38 changes: 0 additions & 38 deletions src/containers/withAuth.jsx

This file was deleted.

23 changes: 23 additions & 0 deletions src/hoc/withAdmin.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import React from 'react';

import { useSelector } from 'react-redux';

import { isAdmin } from '../store/reducers/accounts';

import Forbidden from '../pages/Forbidden';

export default function (Component) {
return function AdminComponent(props) {
const admin = useSelector(isAdmin);

if (admin) {
return (
// eslint-disable-next-line react/jsx-props-no-spreading
<Component {...props} />
);
}

// return null;
return <Forbidden />;
};
}
26 changes: 26 additions & 0 deletions src/hoc/withAuth.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from 'react';

import { useSelector } from 'react-redux';
import { useHistory, useLocation } from 'react-router-dom';

import { getIsAuthenticated } from '../store/reducers/auth';

export default function (Component) {
return function AuthenticatedComponent(props) {
const history = useHistory();
const location = useLocation();
const authenticated = useSelector(getIsAuthenticated);

React.useEffect(() => {
if (!authenticated) {
const nextLocation = (location.pathname !== '/') ? location.pathname : '/files';
history.push(`/signin?next=${nextLocation}`);
}
}, [authenticated, location.pathname, history]);

return (
// eslint-disable-next-line react/jsx-props-no-spreading
<Component {...props} />
);
};
}
15 changes: 10 additions & 5 deletions src/index.jsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
import React from 'react';

import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import './index.css';
import './tailwind.generated.css';
import App from './App';

import store from './store/store';

import withAuth from './hoc/withAuth';

import Login from './pages/Login';
import withAuth from './containers/withAuth';

import * as serviceWorker from './serviceWorker';
import App from './App';

import store from './store/store';
import './index.css';
import './tailwind.generated.css';

ReactDOM.render(
<React.StrictMode>
Expand Down
32 changes: 32 additions & 0 deletions src/pages/Forbidden.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import React from 'react';

import { useHistory } from 'react-router-dom';

import * as icons from '../icons';

import Button from '../components/ui/Button';

function Forbidden() {
const history = useHistory();

return (
<div className="fixed inset-0 bg-white z-50">
<div className="flex flex-col items-center justify-center min-h-screen space-y-8">
<h1 className="text-3xl">
Forbidden
</h1>
<Button
type="text"
size="lg"
icon={<icons.ArrowLeft />}
title="Go back"
onClick={() => history.push('/')}
>
Go home
</Button>
</div>
</div>
);
}

export default Forbidden;
11 changes: 11 additions & 0 deletions src/pages/admin/UserManagement.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import React from 'react';

function UserManagement() {
return (
<div>
User Management
</div>
);
}

export default UserManagement;
10 changes: 10 additions & 0 deletions src/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,14 @@ export const FILES = {

export const TRASH = {
route: '/trash/:dirPath*',
reverse({ path }) {
return join('/trash', path);
},
};

export const USER_MANAGEMENT = {
route: '/admin/user-management',
reverse() {
return this.route;
},
};
1 change: 1 addition & 0 deletions src/store/reducers/accounts.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,4 @@ export default combineReducers({
});

export const getCurrentAccount = (state) => state.accounts.currentAccount;
export const isAdmin = (state) => getCurrentAccount(state)?.superuser ?? false;

0 comments on commit d65df84

Please sign in to comment.