Merge pull request #5 from apuc/authentication

Authentication
This commit is contained in:
kavalar 2021-08-05 16:45:32 +03:00 committed by GitHub
commit 3e66e373a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 105 additions and 23 deletions

8
package-lock.json generated
View File

@ -3216,6 +3216,14 @@
"resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.2.1.tgz", "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.2.1.tgz",
"integrity": "sha512-evY7DN8qSIbsW2H/TWQ1bX3sXN1d4MNb5Vb4n7BzPuCwRHdkZ1H2eNLuSh73EoQqkGKUtju2G2HCcjCfhvZIAA==" "integrity": "sha512-evY7DN8qSIbsW2H/TWQ1bX3sXN1d4MNb5Vb4n7BzPuCwRHdkZ1H2eNLuSh73EoQqkGKUtju2G2HCcjCfhvZIAA=="
}, },
"axios": {
"version": "0.21.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-0.21.1.tgz",
"integrity": "sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA==",
"requires": {
"follow-redirects": "^1.10.0"
}
},
"axobject-query": { "axobject-query": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz",

View File

@ -7,6 +7,7 @@
"@testing-library/jest-dom": "^5.12.0", "@testing-library/jest-dom": "^5.12.0",
"@testing-library/react": "^11.2.7", "@testing-library/react": "^11.2.7",
"@testing-library/user-event": "^12.8.3", "@testing-library/user-event": "^12.8.3",
"axios": "^0.21.1",
"bootstrap": "^4.6.0", "bootstrap": "^4.6.0",
"dotenv": "^10.0.0", "dotenv": "^10.0.0",
"eslint": "^7.27.0", "eslint": "^7.27.0",

View File

@ -16,18 +16,18 @@ const App = () => {
return ( return (
<Router> <Router>
<Switch> <Switch>
<Route path='/auth' exact> <Route path='/authdev' exact>
{/* <AuthPageForPartners /> */}
<AuthPageForDevelopers /> <AuthPageForDevelopers />
</Route> </Route>
<Route path='/auth' exact>
<AuthPageForPartners />
</Route>
<ProtectedRoute path='/' exact component={HomePage} /> <ProtectedRoute path='/' exact component={HomePage} />
<ProtectedRoute path='/candidate/:id' component={CandidatePage} /> <ProtectedRoute path='/candidate/:id' component={CandidatePage} />
<ProtectedRoute path='/calendar' component={CalendarPage} /> <ProtectedRoute path='/calendar' component={CalendarPage} />
<ProtectedRoute path='/form' component={FormPage} /> <ProtectedRoute path='/form' component={FormPage} />
<ProtectedRoute path='/report' component={ReportPage} /> <ProtectedRoute path='/report' component={ReportPage} />
<Route> <ProtectedRoute component={()=><div>Page not found</div>} />
<div>Page not found</div>
</Route>
</Switch> </Switch>
</Router> </Router>
) )

5
src/api/index.js Normal file
View File

@ -0,0 +1,5 @@
import axios from 'axios';
export default axios.create({
baseURL: process.env.REACT_APP_API_URL
});

View File

@ -16,7 +16,7 @@ import { fetchAuth } from '../../server/server'
import { useSelector } from 'react-redux' import { useSelector } from 'react-redux'
import { selectAuth } from '../../redux/outstaffingSlice'; import { selectAuth } from '../../redux/outstaffingSlice';
import { Redirect } from 'react-router-dom'; import { Redirect, Link } from 'react-router-dom';
const AuthForDevelopers = () => { const AuthForDevelopers = () => {
const dispatch = useDispatch() const dispatch = useDispatch()
@ -25,8 +25,6 @@ const AuthForDevelopers = () => {
const [username, setUsername] = useState('') const [username, setUsername] = useState('')
const [password, setPassword] = useState('') const [password, setPassword] = useState('')
console.log('i', isAuth)
if(isAuth) { if(isAuth) {
return <Redirect to='/' /> return <Redirect to='/' />
} }
@ -79,6 +77,10 @@ const AuthForDevelopers = () => {
> >
Войти Войти
</button> </button>
<button className={`${style.form__btn} ${style.auth__link}`}>
<Link to='/auth'>Для партнёров</Link>
</button>
</form> </form>
</div> </div>
</div> </div>

View File

@ -399,3 +399,16 @@
line-height: normal; line-height: normal;
margin-left: 24px; margin-left: 24px;
} }
.auth__link {
display: block;
margin-top: 1.3rem;
}
.auth__link a {
display: block;
width: 100%;
height: 100%;
color: #fff;
}

View File

@ -1,4 +1,4 @@
import React from 'react'; import React, { useState } from 'react';
import { useDispatch } from 'react-redux'; import { useDispatch } from 'react-redux';
import { auth } from '../../redux/outstaffingSlice'; import { auth } from '../../redux/outstaffingSlice';
import style from './AuthForPartners.module.css'; import style from './AuthForPartners.module.css';
@ -12,9 +12,22 @@ import phone from '../../images/phone.png';
import telegram from '../../images/telegram.png'; import telegram from '../../images/telegram.png';
import vector from '../../images/Vector_Smart_Object.png'; import vector from '../../images/Vector_Smart_Object.png';
import vectorBlack from '../../images/Vector_Smart_Object_black.png'; import vectorBlack from '../../images/Vector_Smart_Object_black.png';
import { fetchAuth } from '../../server/server'
import { useSelector } from 'react-redux'
import { selectAuth } from '../../redux/outstaffingSlice';
import { Redirect, Link } from 'react-router-dom';
const AuthForPartners = () => { const AuthForPartners = () => {
const dispatch = useDispatch(); const dispatch = useDispatch()
const isAuth = useSelector(selectAuth)
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
if(isAuth) {
return <Redirect to='/' />
}
return ( return (
<section className={style.partners}> <section className={style.partners}>
@ -34,14 +47,33 @@ const AuthForPartners = () => {
</div> </div>
<form className={style.partners__form}> <form className={style.partners__form}>
<label htmlFor="login">Ваш логин:</label> <label htmlFor="login">Ваш логин:</label>
<input id="login" type="text" placeholder="Логин" /> <input id="login" type="text" placeholder="Логин"
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
<label htmlFor="password">Пароль:</label> <label htmlFor="password">Пароль:</label>
<input id="password" type="password" placeholder="Пароль" /> <input id="password" type="password" placeholder="Пароль"
value={password}
onChange={(e) => setPassword(e.target.value)}
/>
<button className={style.form__btn} type="submit" onClick={() => dispatch(auth(true))}> <button className={style.form__btn}
onClick={(e) => {
e.preventDefault();
fetchAuth({
username,
password,
dispatch: ()=> dispatch(auth(true))
})
}
}>
Войти Войти
</button> </button>
<button className={`${style.form__btn} ${style.auth__link}`}>
<Link to='/authdev'>Для разработчиков</Link>
</button>
</form> </form>
</div> </div>
</div> </div>

View File

@ -400,3 +400,15 @@
line-height: normal; line-height: normal;
margin-left: 24px; margin-left: 24px;
} }
.auth__link {
display: block;
margin-top: 1.3rem;
}
.auth__link a {
display: block;
width: 100%;
height: 100%;
color: #fff;
}

View File

@ -18,7 +18,7 @@ const Candidate = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
useEffect(() => { useEffect(() => {
fetchItemsForId('https://guild.craft-group.xyz/api/profile/', Number(candidateId)).then((el) => fetchItemsForId(`${process.env.REACT_APP_API_URL}/api/profile/`, Number(candidateId)).then((el) =>
dispatch(currentCandidate(el)) dispatch(currentCandidate(el))
); );
}, [dispatch, candidateId]); }, [dispatch, candidateId]);

View File

@ -14,7 +14,7 @@ const Description = ({ onLoadMore }) => {
const [allCandidates, getAllCandidates] = useState([]); const [allCandidates, getAllCandidates] = useState([]);
useEffect(() => { useEffect(() => {
fetchProfile('https://guild.craft-group.xyz/api/profile?limit=', 1000).then((p) => getAllCandidates(p)); fetchProfile(`${process.env.REACT_APP_API_URL}/api/profile?limit=`, 1000).then((p) => getAllCandidates(p));
}, []); }, []);
return ( return (

View File

@ -30,7 +30,7 @@ const Form = () => {
formData.append('phone', data.phone); formData.append('phone', data.phone);
formData.append('comment', data.comment); formData.append('comment', data.comment);
fetchForm('https://guild.craft-group.xyz/api/profile/add-to-interview', formData); fetchForm(`${process.env.REACT_APP_API_URL}/api/profile/add-to-interview`, formData);
}; };
const goBack = () => { const goBack = () => {

View File

@ -11,11 +11,11 @@ const Home = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
useEffect(() => { useEffect(() => {
fetchProfile('https://guild.craft-group.xyz/api/profile?limit=', index).then((profileArr) => fetchProfile(`${process.env.REACT_APP_API_URL}/api/profile?limit=`, index).then((profileArr) =>
dispatch(profiles(profileArr)) dispatch(profiles(profileArr))
); );
fetchSkills('https://guild.craft-group.xyz/api/skills/skills-on-main-page').then((skills) => { fetchSkills(`${process.env.REACT_APP_API_URL}/api/skills/skills-on-main-page`).then((skills) => {
const keys = Object.keys(skills); const keys = Object.keys(skills);
const values = Object.values(skills); const values = Object.values(skills);

View File

@ -28,7 +28,7 @@ const Outstaffing = () => {
<div className="row"> <div className="row">
<div className="col-12 col-xl-4"> <div className="col-12 col-xl-4">
<OutstaffingBlock <OutstaffingBlock
dataTags={tagsArr.flat().filter((tag) => tag.name === 'skills_front')} dataTags={tagsArr && tagsArr.flat().filter((tag) => tag.name === 'skills_front')}
img={front} img={front}
header="Фронтенд" header="Фронтенд"
/> />

View File

@ -15,7 +15,7 @@ const TagSelect = () => {
const handleSubmit = () => { const handleSubmit = () => {
const filterItemsId = itemsArr.map((item) => item.id).join(); const filterItemsId = itemsArr.map((item) => item.id).join();
fetchItemsForId(`https://guild.craft-group.xyz/api/profile?skills=`, filterItemsId).then((el) => fetchItemsForId(`${process.env.REACT_APP_API_URL}/api/profile?skills=`, filterItemsId).then((el) =>
dispatch(filteredCandidates(el)) dispatch(filteredCandidates(el))
); );

View File

@ -2,7 +2,9 @@ export const fetchProfile = async (link, index) => {
try { try {
const response = await fetch(`${link}${index}`, { const response = await fetch(`${link}${index}`, {
headers: { headers: {
'Authorization': `Bearer ${localStorage.getItem('auth_token')}` 'Access-Control-Request-Headers': 'authorization',
'Authorization': `Bearer ${localStorage.getItem('auth_token')}`,
'Origin': `${process.env.REACT_APP_BASE_URL}`,
} }
}) })
let data = await response.json() let data = await response.json()
@ -15,7 +17,9 @@ export const fetchSkills = async (link) => {
try { try {
const response = await fetch(link, { const response = await fetch(link, {
headers: { headers: {
'Authorization': `Bearer ${localStorage.getItem('auth_token')}` 'Access-Control-Request-Headers': 'authorization',
'Authorization': `Bearer ${localStorage.getItem('auth_token')}`,
'Origin': `${process.env.REACT_APP_BASE_URL}`,
} }
}) })
let data = await response.json() let data = await response.json()
@ -25,10 +29,13 @@ export const fetchSkills = async (link) => {
} }
export const fetchItemsForId = async (link, id) => { export const fetchItemsForId = async (link, id) => {
console.log(`Bearer ${localStorage.getItem('auth_token')}`);
try { try {
const response = await fetch(`${link}${id}`, { const response = await fetch(`${link}${id}`, {
headers: { headers: {
'Authorization': `Bearer ${localStorage.getItem('auth_token')}` // 'Access-Control-Request-Headers': 'authorization',
'Authorization': `Bearer ${localStorage.getItem('auth_token')}`,
'Origin': `${process.env.REACT_APP_BASE_URL}`,
} }
}) })
let data = await response.json() let data = await response.json()
@ -42,7 +49,9 @@ export const fetchForm = async (link, info) => {
const response = await fetch(link, { const response = await fetch(link, {
method: 'POST', method: 'POST',
headers: { headers: {
'Access-Control-Request-Headers': 'authorization',
'Authorization': `Bearer ${localStorage.getItem('auth_token')}`, 'Authorization': `Bearer ${localStorage.getItem('auth_token')}`,
'Origin': `${process.env.REACT_APP_BASE_URL}`,
'Content-Type': 'multipart/form-data' 'Content-Type': 'multipart/form-data'
}, },
body: info body: info