From e4ec5fd091f5ea9c44ea328362c84e4d2550c71b Mon Sep 17 00:00:00 2001 From: kurpfish Date: Wed, 4 Aug 2021 13:04:05 +0300 Subject: [PATCH] added server auth and protected routes --- src/App.js | 76 ++++------- src/components/Auth/AuthForDevelopers.js | 124 +++++++++++------- src/components/Calendar/Calendar.js | 2 +- .../ProtectedRoute/ProtectedRoute.js | 23 ++++ src/redux/outstaffingSlice.js | 2 +- src/server/server.js | 67 +++++++--- 6 files changed, 181 insertions(+), 113 deletions(-) create mode 100644 src/components/ProtectedRoute/ProtectedRoute.js diff --git a/src/App.js b/src/App.js index 25f0d0d2..73aa3273 100644 --- a/src/App.js +++ b/src/App.js @@ -1,60 +1,40 @@ -import React, { Suspense, lazy } from 'react'; -import { HashRouter as Router, Route, Switch } from 'react-router-dom'; -import { useSelector } from 'react-redux'; -import 'bootstrap/dist/css/bootstrap.min.css'; -import './fonts/stylesheet.css'; -import { selectAuth } from './redux/outstaffingSlice'; +import React, { Suspense, lazy } from 'react' +import { BrowserRouter as Router, Route, Switch } from 'react-router-dom' +import 'bootstrap/dist/css/bootstrap.min.css' +import './fonts/stylesheet.css' +import { ProtectedRoute } from './components/ProtectedRoute/ProtectedRoute'; -const AuthPageForDevelopers = lazy(() => import('./pages/AuthPageForDevelopers')); -// const AuthPageForPartners = lazy(() => import('./pages/AuthPageForPartners')); -const HomePage = lazy(() => import('./pages/HomePage')); -const CandidatePage = lazy(() => import('./pages/CandidatePage')); -const CalendarPage = lazy(() => import('./pages/CalendarPage')); -const ReportPage = lazy(() => import('./pages/ReportFormPage.js')); -const FormPage = lazy(() => import('./pages/FormPage.js')); +const AuthPageForDevelopers = lazy(() => + import('./pages/AuthPageForDevelopers') +) +const AuthPageForPartners = lazy(() => import('./pages/AuthPageForPartners')) +const HomePage = lazy(() => import('./pages/HomePage')) +const CandidatePage = lazy(() => import('./pages/CandidatePage')) +const CalendarPage = lazy(() => import('./pages/CalendarPage')) +const ReportPage = lazy(() => import('./pages/ReportFormPage.js')) +const FormPage = lazy(() => import('./pages/FormPage.js')) const App = () => { - const isAuth = useSelector(selectAuth); - // const [candidateForCalendar, setCandidateForCalendar] = useState([]); - - // const getCandidateForCalendar = (candidate) => { - // console.log('candidate ', candidate); - // setCandidateForCalendar(candidate); - // }; - return ( Loading...}> - {isAuth ? ( - - - - - - - - - - - - - - - - - -
Not found page
-
-
- ) : ( - + + {/* */} - )} + + + + + + +
Page not found
+
+
- ); -}; + ) +} -export default App; +export default App diff --git a/src/components/Auth/AuthForDevelopers.js b/src/components/Auth/AuthForDevelopers.js index d4e2e26d..5b37bcbd 100644 --- a/src/components/Auth/AuthForDevelopers.js +++ b/src/components/Auth/AuthForDevelopers.js @@ -1,56 +1,83 @@ -import React from 'react'; -import { useDispatch } from 'react-redux'; -import { auth } from '../../redux/outstaffingSlice'; -import style from './AuthForDevelopers.module.css'; -import ellipse from '../../images/ellipse.png'; -import arrow from '../../images/arrow__login_page.png'; -import authImg from '../../images/auth_img.png'; -import cross from '../../images/cross.png'; -import text from '../../images/Body_Text.png'; -import align from '../../images/align-left.png'; -import phone from '../../images/phone.png'; -import telegram from '../../images/telegram.png'; -import vector from '../../images/Vector_Smart_Object.png'; -import vectorBlack from '../../images/Vector_Smart_Object_black.png'; +import React, { useState } from 'react' +import { useDispatch } from 'react-redux' +import { auth } from '../../redux/outstaffingSlice' +import style from './AuthForDevelopers.module.css' +import ellipse from '../../images/ellipse.png' +import arrow from '../../images/arrow__login_page.png' +import authImg from '../../images/auth_img.png' +import cross from '../../images/cross.png' +import text from '../../images/Body_Text.png' +import align from '../../images/align-left.png' +import phone from '../../images/phone.png' +import telegram from '../../images/telegram.png' +import vector from '../../images/Vector_Smart_Object.png' +import vectorBlack from '../../images/Vector_Smart_Object_black.png' +import { fetchAuth } from '../../server/server' const AuthForDevelopers = () => { - const dispatch = useDispatch(); + const dispatch = useDispatch() + + const [username, setUsername] = useState('') + const [password, setPassword] = useState('') + return (
- - -
-
-
+ + +
+
+

Войти в систему

- + Для разработчиков
- - + + setUsername(e.target.value)} + /> - - + + setPassword(e.target.value)} + /> -
-
- +
+
-
+
- +

Управление
командой @@ -60,7 +87,7 @@ const AuthForDevelopers = () => {
- +
{/* */} @@ -69,39 +96,44 @@ const AuthForDevelopers = () => {
    -
  • Рабочее пространство
  • -
  • Управление задачами
  • +
  • + Рабочее пространство +
  • +
  • + Управление задачами +
- +

-
-
+
+
- +
- © Адвего — биржа контента №1. Копирайтинг, рерайтинг, переводы, работа на дому: поставщик - уникального контента. 2021{' '} + © Адвего — биржа контента №1. Копирайтинг, рерайтинг, + переводы, работа на дому: поставщик уникального контента. + 2021{' '}
-
+
- - + +
-
+

+7 495 156 78 98

Будни с 9:00 до 21:00

@@ -111,7 +143,7 @@ const AuthForDevelopers = () => {
- ); -}; + ) +} -export default AuthForDevelopers; +export default AuthForDevelopers diff --git a/src/components/Calendar/Calendar.js b/src/components/Calendar/Calendar.js index 2aca5077..55493358 100644 --- a/src/components/Calendar/Calendar.js +++ b/src/components/Calendar/Calendar.js @@ -19,7 +19,7 @@ const Calendar = () => { const { name, skillsName } = candidateForCalendar; - const abbreviatedName = name.substring(0, name.lastIndexOf(' ')); + const abbreviatedName = name && name.substring(0, name.lastIndexOf(' ')); return (
diff --git a/src/components/ProtectedRoute/ProtectedRoute.js b/src/components/ProtectedRoute/ProtectedRoute.js new file mode 100644 index 00000000..bc5b8234 --- /dev/null +++ b/src/components/ProtectedRoute/ProtectedRoute.js @@ -0,0 +1,23 @@ +import React from 'react'; +import { useSelector } from 'react-redux' +import { Route, Redirect } from 'react-router-dom'; +import { selectAuth } from '../../redux/outstaffingSlice'; + +export const ProtectedRoute = ({ component: Component, ...rest }) => { + const isAuth = useSelector(selectAuth) + const existingToken = localStorage.getItem('auth_token') + const expiresAt = localStorage.getItem('access_token_expired_at') + + const isTokenAlive = (existingToken && expiresAt && new Date(expiresAt).getTime() > (new Date()).getTime()); + + return ( + + ( isAuth || isTokenAlive) ? ( + + ) : + } + /> + ); + } \ No newline at end of file diff --git a/src/redux/outstaffingSlice.js b/src/redux/outstaffingSlice.js index 09de6405..a2e893f9 100644 --- a/src/redux/outstaffingSlice.js +++ b/src/redux/outstaffingSlice.js @@ -6,7 +6,7 @@ const initialState = { filteredCandidates: [], selectedItems: [], currentCandidate: {}, - auth: true, + auth: false, }; export const outstaffingSlice = createSlice({ diff --git a/src/server/server.js b/src/server/server.js index 18fc8516..9b7a5678 100644 --- a/src/server/server.js +++ b/src/server/server.js @@ -1,40 +1,73 @@ export const fetchProfile = async (link, index) => { try { - const response = await fetch(`${link}${index}`); - let data = await response.json(); + const response = await fetch(`${link}${index}`) + let data = await response.json() - return data; + return data } catch (error) {} -}; +} export const fetchSkills = async (link) => { try { - const response = await fetch(link); - let data = await response.json(); + const response = await fetch(link) + let data = await response.json() - return data; + return data } catch (error) {} -}; +} export const fetchItemsForId = async (link, id) => { try { - const response = await fetch(`${link}${id}`); - let data = await response.json(); + const response = await fetch(`${link}${id}`) + let data = await response.json() - return data; + return data } catch (error) {} -}; +} export const fetchForm = async (link, info) => { try { const response = await fetch(link, { method: 'POST', headers: { - 'Content-Type': 'multipart/form-data', + 'Content-Type': 'multipart/form-data' }, - body: info, - }); + body: info + }) - return response; + return response } catch (error) {} -}; +} + +export const fetchAuth = async ({ username, password, dispatch }) => { + try { + const response = await fetch( + 'https://guild.craft-group.xyz/api/user/login', + { + method: 'POST', + mode: 'cors', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + username, + password + }) + } + ) + + if(!response.ok) { + return response.statusText; + } + + response + .json() + .then((resJSON) => { + localStorage.setItem('auth_token', resJSON.access_token) + localStorage.setItem('access_token_expired_at', resJSON.access_token_expired_at) + dispatch(); + }) + } catch (error) { + console.error('Error occured: ', error) + } +}