auth token

parent 09d90b26
import React from 'react'; import React from 'react';
import { BrowserRouter, Routes, Route, Outlet } from 'react-router-dom'; import { BrowserRouter, Routes, Route, Navigate, Outlet } from 'react-router-dom';
import { useSelector } from 'react-redux';
import { RootState } from '../src/main';
import Header from './components/Header/Header'; import Header from './components/Header/Header';
import AuthPage from './pages/AuthPage/AuthPage'; import AuthPage from './pages/AuthPage/AuthPage';
import HomePage from './pages/HomePage/HomePage'; import HomePage from './pages/HomePage/HomePage';
import RequestPage from './pages/RequestPage/RequestPage'; import RequestPage from './pages/RequestPage/RequestPage';
import AddPage from './pages/(crudPages)/AddPage'; import AddPage from './pages/(crudPages)/AddPage';
import EditPage from './pages/(crudPages)/EditPage'; import EditPage from './pages/(crudPages)/EditPage';
import 'react-material-symbols/rounded';
import './App.css'; import './App.css';
const AuthLayout = () => { const AuthLayout: React.FC = () => {
return ( return (
<> <>
<Header /> <Header />
<Outlet /> <Outlet />
</> </>
) );
} };
const App: React.FC = () => { const App: React.FC = () => {
const token = useSelector((state: RootState) => state.auth.token);
return ( return (
<BrowserRouter> <BrowserRouter>
<Routes> <Routes>
{!token ? (
<>
<Route path="/auth" element={<AuthPage />} /> <Route path="/auth" element={<AuthPage />} />
<Route element={<AuthLayout />} > <Route path="/*" element={<Navigate to="/auth" />} />
</>
) : (
<Route element={<AuthLayout />}>
<Route path="/" element={<HomePage />} /> <Route path="/" element={<HomePage />} />
<Route path="/add" element={<AddPage />} /> <Route path="/add" element={<AddPage />} />
<Route path="/edit/:id" element={<EditPage />} /> <Route path="/edit/:id" element={<EditPage />} />
<Route path="/requests" element={<RequestPage />} /> <Route path="/requests" element={<RequestPage />} />
<Route path="/*" element={<Navigate to="/" />} />
</Route> </Route>
)}
</Routes> </Routes>
</BrowserRouter> </BrowserRouter>
); );
......
import React, { useState } from 'react'; import React, { useState } from 'react';
import { MaterialSymbol } from 'react-material-symbols'; import { MaterialSymbol } from 'react-material-symbols';
import { Link } from 'react-router-dom'; import { Link, useNavigate } from 'react-router-dom';
import { Menu, Button, Drawer } from 'antd'; import { Menu, Button, Drawer } from 'antd';
import { useDispatch } from 'react-redux';
import { clearToken } from '../../store/store';
import type { MenuProps } from 'antd'; import type { MenuProps } from 'antd';
import './Header.css'; import './Header.css';
type MenuItem = Required<MenuProps>['items'][number]; type MenuItem = Required<MenuProps>['items'][number];
const items: MenuItem[] = [ const items: MenuItem[] = [
{ key: '1', icon: <MaterialSymbol icon='list' size={24} color='#fff'/>, label: <Link to="/">Список организаций</Link> }, { key: '1', icon: <MaterialSymbol icon='list' size={24} color='#fff' />, label: <Link to="/">Список организаций</Link> },
{ key: '2', icon: <MaterialSymbol icon='developer_guide' size={24} color='#fff'/>, label: <Link to="/">Справочники</Link> }, { key: '2', icon: <MaterialSymbol icon='developer_guide' size={24} color='#fff' />, label: <Link to="/">Справочники</Link> },
{ key: '3', icon: <MaterialSymbol icon='info' size={24} color='#fff'/>, label: <Link to="/requests">Информация о запросах</Link> }, { key: '3', icon: <MaterialSymbol icon='info' size={24} color='#fff' />, label: <Link to="/requests">Информация о запросах</Link> },
]; ];
const Header: React.FC = () => { const Header: React.FC = () => {
const [openMenu, setOpenMenu] = useState<boolean>(false); const [openMenu, setOpenMenu] = useState<boolean>(false);
const dispatch = useDispatch();
const navigate = useNavigate();
const handleLogout = () => {
dispatch(clearToken());
navigate('/auth');
};
return ( return (
<header className="header"> <header className="header">
...@@ -34,7 +43,7 @@ const Header: React.FC = () => { ...@@ -34,7 +43,7 @@ const Header: React.FC = () => {
}} }}
placement='left' placement='left'
className='custom-drawer' className='custom-drawer'
title="ЕСУТД" title="ЕСУТДjh"
> >
<Menu <Menu
theme='dark' theme='dark'
...@@ -49,11 +58,11 @@ const Header: React.FC = () => { ...@@ -49,11 +58,11 @@ const Header: React.FC = () => {
</Drawer> </Drawer>
<h1 className="header_title">ЕСУТД</h1> <h1 className="header_title">ЕСУТД</h1>
</div> </div>
<Button type='text' className="header_logout"> <Button type='text' className="header_logout" onClick={handleLogout}>
<MaterialSymbol icon='logout' size={24} color='#fff' /> <MaterialSymbol icon='logout' size={24} color='#fff' />
</Button> </Button>
</header> </header>
) )
} }
export default Header export default Header;
import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react'; import { createApi, fetchBaseQuery } from '@reduxjs/toolkit/query/react';
import { RootState } from '../../main'; // Add this import to get the RootState
interface Organization { interface Organization {
id: number; id: number;
...@@ -13,16 +14,16 @@ interface Organization { ...@@ -13,16 +14,16 @@ interface Organization {
host: string; host: string;
} }
export const apiSlice = createApi({ export const apiSlice = createApi({
reducerPath: 'api', reducerPath: 'api',
baseQuery: fetchBaseQuery({ baseQuery: fetchBaseQuery({
baseUrl: "/esutd/api/organizations", baseUrl: "/esutd/api/organizations",
prepareHeaders: (headers) => { prepareHeaders: (headers, { getState }) => {
const accessToken = `OTA3MTEzNzctYzA3YS00NzRkLTkyNDgtNzk4ZmEzMzViNzlj`; const state = getState() as RootState;
const accessToken = state.auth.token;
if (accessToken) { if (accessToken) {
headers.set("Authorization", `Bearer Token ${accessToken}`); headers.set("Authorization", `Bearer ${accessToken}`);
} }
headers.set("Accept", "*/*"); headers.set("Accept", "*/*");
...@@ -53,7 +54,7 @@ export const apiSlice = createApi({ ...@@ -53,7 +54,7 @@ export const apiSlice = createApi({
method: 'PUT', method: 'PUT',
body: rest, body: rest,
}), }),
invalidatesTags: ["organizations"] invalidatesTags: ["organizations"],
}), }),
deleteOrganization: builder.mutation<{ success: boolean; id: number }, number>({ deleteOrganization: builder.mutation<{ success: boolean; id: number }, number>({
query: (orgId) => ({ query: (orgId) => ({
......
...@@ -5,6 +5,8 @@ import { Provider } from 'react-redux'; ...@@ -5,6 +5,8 @@ import { Provider } from 'react-redux';
import './index.css'; import './index.css';
import store from '../src/store/store.ts'; import store from '../src/store/store.ts';
export type RootState = ReturnType<typeof store.getState>;
ReactDOM.createRoot(document.getElementById('root')!).render( ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode> <React.StrictMode>
<Provider store={store}> <Provider store={store}>
......
import React from 'react'; import React, { useState } from 'react';
import { Input, Typography, Button } from 'antd'; import { Input, Typography, Button, notification } from 'antd';
import { useNavigate } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { setToken } from '../../store/store';
import styles from './AuthPage.module.css'; import styles from './AuthPage.module.css';
// import { useGetOrganizationsQuery } from '../../features/api/apiSlice';
const AuthPage: React.FC = () => { const AuthPage: React.FC = () => {
const [token, setTokenInput] = useState('');
const navigate = useNavigate();
const dispatch = useDispatch();
const handleLogin = async () => {
try {
const response = await fetch('http://77.243.80.217:8080/esutd/api/organizations/list', {
headers: {
'Authorization': `Bearer ${token}`,
},
});
if (response.status === 200) {
dispatch(setToken(token));
navigate('/');
} else if (response.status === 403) {
notification.error({
message: 'Access Denied',
description: 'You do not have permission to access this resource.',
});
} else {
notification.error({
message: 'Login Failed',
description: 'An error occurred while trying to login.',
});
}
} catch (error) {
notification.error({
message: 'Login Error',
description: 'An error occurred while trying to login.',
});
}
};
return ( return (
<div className={styles.wrapper}> <div className={styles.wrapper}>
<div className={styles.form}> <div className={styles.form}>
...@@ -10,8 +48,10 @@ const AuthPage: React.FC = () => { ...@@ -10,8 +48,10 @@ const AuthPage: React.FC = () => {
<Input <Input
placeholder="введите токен" placeholder="введите токен"
className={styles.input_controller} className={styles.input_controller}
value={token}
onChange={(e) => setTokenInput(e.target.value)}
/> />
<Button className={styles.form_btn} type="primary">Войти</Button> <Button className={styles.form_btn} type="primary" onClick={handleLogin}>Войти</Button>
</div> </div>
</div> </div>
); );
......
import { configureStore, Store } from '@reduxjs/toolkit'; import { configureStore, Store, createSlice, PayloadAction } from '@reduxjs/toolkit';
import { apiSlice } from '../features/api/apiSlice'; import { apiSlice } from '../features/api/apiSlice';
import mainPaginationReducer from '../features/pagination/mainPagination'; import mainPaginationReducer from '../features/pagination/mainPagination';
interface AuthState {
token: string | null;
}
const initialState: AuthState = {
token: localStorage.getItem('token'),
};
const authSlice = createSlice({
name: 'auth',
initialState,
reducers: {
setToken: (state, action: PayloadAction<string>) => {
state.token = action.payload;
localStorage.setItem('token', action.payload);
},
clearToken: (state) => {
state.token = null;
localStorage.removeItem('token');
},
},
});
export const { setToken, clearToken } = authSlice.actions;
const store: Store = configureStore({ const store: Store = configureStore({
reducer: { reducer: {
auth: authSlice.reducer,
mainPagination: mainPaginationReducer, mainPagination: mainPaginationReducer,
[apiSlice.reducerPath]: apiSlice.reducer, [apiSlice.reducerPath]: apiSlice.reducer,
}, },
...@@ -12,3 +38,4 @@ const store: Store = configureStore({ ...@@ -12,3 +38,4 @@ const store: Store = configureStore({
}); });
export default store; export default store;
...@@ -8,7 +8,7 @@ export default defineConfig({ ...@@ -8,7 +8,7 @@ export default defineConfig({
'/api': { '/api': {
target: 'http://77.243.80.217:8080', target: 'http://77.243.80.217:8080',
changeOrigin: true, changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api/, ''), rewrite: (path) => path.replace(/^\/api/, ''),
secure: false, secure: false,
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment