mirror of
https://github.com/pawelmalak/snippet-box.git
synced 2025-12-21 13:23:05 +01:00
Auth error handling. Auth redirecting
This commit is contained in:
@@ -2,19 +2,30 @@ import { Fragment, useContext, useEffect } from 'react';
|
||||
import { Switch, Route } from 'react-router-dom';
|
||||
import { Navbar } from './components/Navigation/Navbar';
|
||||
import { Editor, Home, Snippet, Snippets, Auth, Profile } from './containers';
|
||||
import { ProtectedRoute } from './utils';
|
||||
import { AuthContext } from './store';
|
||||
import { decodeToken, ProtectedRoute } from './utils';
|
||||
import { AuthContext, SnippetsContext } from './store';
|
||||
|
||||
export const App = () => {
|
||||
const { autoLogin } = useContext(AuthContext);
|
||||
const { autoLogin, logout } = useContext(AuthContext);
|
||||
const { getSnippets, countTags } = useContext(SnippetsContext);
|
||||
|
||||
useEffect(() => {
|
||||
// autoLogin();
|
||||
// const checker = setInterval(() => {
|
||||
// autoLogin();
|
||||
// console.log('cake');
|
||||
// }, 1000);
|
||||
// return () => window.clearInterval(checker);
|
||||
autoLogin();
|
||||
|
||||
getSnippets();
|
||||
countTags();
|
||||
|
||||
const checkTokenValidity = setInterval(() => {
|
||||
if (localStorage.token) {
|
||||
const { exp: expiresAt } = decodeToken(localStorage.token);
|
||||
|
||||
if (Date.now() > expiresAt * 1000) {
|
||||
logout();
|
||||
}
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
return () => window.clearInterval(checkTokenValidity);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { useContext, useEffect } from 'react';
|
||||
import { useHistory } from 'react-router';
|
||||
import { useHistory, useLocation } from 'react-router';
|
||||
import { AuthContext } from '../store';
|
||||
import { AuthForm } from '../components/Auth';
|
||||
import { Card, Layout } from '../components/UI';
|
||||
@@ -8,9 +8,13 @@ export const Auth = (): JSX.Element => {
|
||||
const { isAuthenticated } = useContext(AuthContext);
|
||||
const history = useHistory();
|
||||
|
||||
// Get previous location
|
||||
const location = useLocation<{ from: string }>();
|
||||
const { from } = location.state || '/';
|
||||
|
||||
useEffect(() => {
|
||||
if (isAuthenticated) {
|
||||
history.push('/');
|
||||
history.push(from);
|
||||
}
|
||||
}, [isAuthenticated]);
|
||||
|
||||
|
||||
@@ -10,6 +10,13 @@ export const ProtectedRoute = ({ ...rest }: RouteProps) => {
|
||||
if (isAuthenticated) {
|
||||
return <Route {...rest} />;
|
||||
} else {
|
||||
return <Redirect to='/auth' />;
|
||||
return (
|
||||
<Redirect
|
||||
to={{
|
||||
pathname: '/auth',
|
||||
state: { from: window.location.pathname }
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
20
client/src/utils/authErrorHandler.ts
Normal file
20
client/src/utils/authErrorHandler.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { errorHandler } from '.';
|
||||
import { UserWithRole } from '../typescript/interfaces';
|
||||
|
||||
interface Params {
|
||||
err: any;
|
||||
setIsAuthenticated: (v: React.SetStateAction<boolean>) => void;
|
||||
setUser: (v: React.SetStateAction<UserWithRole | null>) => void;
|
||||
}
|
||||
|
||||
export const authErrorHandler = (params: Params) => {
|
||||
const { err, setUser, setIsAuthenticated } = params;
|
||||
|
||||
errorHandler(err);
|
||||
|
||||
localStorage.removeItem('token');
|
||||
|
||||
setUser(null);
|
||||
|
||||
setIsAuthenticated(false);
|
||||
};
|
||||
@@ -11,5 +11,7 @@ export const errorHandler = (err: any) => {
|
||||
msg = 'Something went wrong';
|
||||
}
|
||||
|
||||
// todo: emit notification
|
||||
// redirect on error
|
||||
console.log(msg);
|
||||
};
|
||||
|
||||
@@ -3,4 +3,6 @@ export * from './badgeColor';
|
||||
export * from './findLanguage';
|
||||
export * from './searchParser';
|
||||
export * from './ProtectedRoute';
|
||||
export * from './authErrorHandler';
|
||||
export * from './errorHandler';
|
||||
export * from './decodeToken';
|
||||
|
||||
@@ -7,4 +7,6 @@ services:
|
||||
- /path/to/host/data:/app/data
|
||||
ports:
|
||||
- 5000:5000
|
||||
environment:
|
||||
- NODE_ENV: production
|
||||
restart: unless-stopped
|
||||
|
||||
13
list.md
Normal file
13
list.md
Normal file
@@ -0,0 +1,13 @@
|
||||
**Implemented**
|
||||
|
||||
- [x] Login / logout / register
|
||||
- [x] Auto login (token valid 14 days)
|
||||
- [x] Roles (admin, user)
|
||||
|
||||
**Planned features**
|
||||
|
||||
- [ ] Guest access (read and search access to snippets marked as public)
|
||||
- [ ] Generate token for raw snippet access
|
||||
- [ ] Admin panel (right now admin and users share the same view)
|
||||
|
||||
By default, admin account is created with login `admin@local.com` and password `snippet-admin`. If there are any snippets in the database, they will be assigned to the admin as the owner.
|
||||
@@ -11,6 +11,20 @@ export const errorHandler = (
|
||||
) => {
|
||||
logger.log(err.message, 'ERROR');
|
||||
|
||||
if (process.env.NODE_ENV == 'development') {
|
||||
console.log(err);
|
||||
}
|
||||
|
||||
const error = {
|
||||
...err
|
||||
};
|
||||
|
||||
if (err.message == 'Validation error') {
|
||||
// @ts-ignore
|
||||
error.message = err.errors[0].message;
|
||||
error.statusCode = 400;
|
||||
}
|
||||
|
||||
res.status(err.statusCode || 500).json({
|
||||
error: err.message || 'Internal Server Error'
|
||||
});
|
||||
|
||||
@@ -7,3 +7,4 @@ export * from './createAdmin';
|
||||
export * from './hashPassword';
|
||||
export * from './signToken';
|
||||
export * from './createAdmin';
|
||||
export * from './resourceExists';
|
||||
|
||||
17
src/utils/resourceExists.ts
Normal file
17
src/utils/resourceExists.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { NextFunction } from 'express';
|
||||
import { ErrorResponse } from '.';
|
||||
|
||||
export const resourceExists = (
|
||||
resource: any,
|
||||
name: string,
|
||||
id: number,
|
||||
next: NextFunction
|
||||
) => {
|
||||
if (!resource) {
|
||||
return next(
|
||||
new ErrorResponse(404, `${name} with the id of ${id} was not found`)
|
||||
);
|
||||
}
|
||||
|
||||
return;
|
||||
};
|
||||
Reference in New Issue
Block a user