сделал провайдер и защищенные роуты
This commit is contained in:
parent
00ce8fa980
commit
e2958b9de6
@ -8,7 +8,7 @@ class UserEntity(BaseModel):
|
|||||||
first_name: str = Field(..., example='Ivan')
|
first_name: str = Field(..., example='Ivan')
|
||||||
last_name: str = Field(..., example='Ivanov')
|
last_name: str = Field(..., example='Ivanov')
|
||||||
patronymic: Optional[str] = Field(None, example='Ivanov')
|
patronymic: Optional[str] = Field(None, example='Ivanov')
|
||||||
login: str = Field(..., example='user@example.com')
|
login: str = Field(..., example='ivanov74')
|
||||||
|
|
||||||
role_id: int = Field(..., example=1)
|
role_id: int = Field(..., example=1)
|
||||||
|
|
||||||
|
|||||||
4
web-app/package-lock.json
generated
4
web-app/package-lock.json
generated
@ -12,6 +12,7 @@
|
|||||||
"@react-buddy/palette-antd": "^5.3.0",
|
"@react-buddy/palette-antd": "^5.3.0",
|
||||||
"antd": "^5.23.1",
|
"antd": "^5.23.1",
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
|
"prop-types": "^15.8.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-router-dom": "^7.1.1"
|
"react-router-dom": "^7.1.1"
|
||||||
@ -3617,7 +3618,6 @@
|
|||||||
"version": "4.1.1",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
|
||||||
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
@ -3888,7 +3888,6 @@
|
|||||||
"version": "15.8.1",
|
"version": "15.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
|
||||||
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"loose-envify": "^1.4.0",
|
"loose-envify": "^1.4.0",
|
||||||
@ -4552,7 +4551,6 @@
|
|||||||
"version": "16.13.1",
|
"version": "16.13.1",
|
||||||
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
|
||||||
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/react-router": {
|
"node_modules/react-router": {
|
||||||
|
|||||||
@ -10,13 +10,14 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@react-buddy/ide-toolbox": "^2.4.0",
|
||||||
|
"@react-buddy/palette-antd": "^5.3.0",
|
||||||
"antd": "^5.23.1",
|
"antd": "^5.23.1",
|
||||||
"axios": "^1.7.9",
|
"axios": "^1.7.9",
|
||||||
|
"prop-types": "^15.8.1",
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-router-dom": "^7.1.1",
|
"react-router-dom": "^7.1.1"
|
||||||
"@react-buddy/ide-toolbox": "^2.4.0",
|
|
||||||
"@react-buddy/palette-antd": "^5.3.0"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@eslint/js": "^9.17.0",
|
"@eslint/js": "^9.17.0",
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
function App() {
|
import {BrowserRouter as Router} from "react-router-dom";
|
||||||
|
import AppRouter from "./AppRouter.jsx";
|
||||||
|
import {AuthProvider} from "./AuthContext.jsx";
|
||||||
|
|
||||||
return (
|
const App = () => (
|
||||||
<>
|
<AuthProvider>
|
||||||
<p>1234</p>
|
<Router>
|
||||||
</>
|
<AppRouter/>
|
||||||
)
|
</Router>
|
||||||
}
|
</AuthProvider>
|
||||||
|
);
|
||||||
|
|
||||||
export default App
|
export default App
|
||||||
|
|||||||
15
web-app/src/AppRouter.jsx
Normal file
15
web-app/src/AppRouter.jsx
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import {Routes, Route} from "react-router-dom";
|
||||||
|
import PrivateRoute from "./components/PrivateRoute.jsx";
|
||||||
|
|
||||||
|
|
||||||
|
const AppRouter = () => (
|
||||||
|
<Routes>
|
||||||
|
<Route path="/login"/>
|
||||||
|
|
||||||
|
<Route element={<PrivateRoute/>}>
|
||||||
|
|
||||||
|
</Route>
|
||||||
|
</Routes>
|
||||||
|
)
|
||||||
|
|
||||||
|
export default AppRouter;
|
||||||
45
web-app/src/AuthContext.jsx
Normal file
45
web-app/src/AuthContext.jsx
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import {createContext, useState, useContext, useEffect} from "react";
|
||||||
|
import PropTypes from "prop-types";
|
||||||
|
import {loginUser} from "./api/LoginRequest.jsx";
|
||||||
|
|
||||||
|
const AuthContext = createContext(undefined);
|
||||||
|
|
||||||
|
export const AuthProvider = ({children}) => {
|
||||||
|
const [user, setUser] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const token = localStorage.getItem("access_token");
|
||||||
|
if (token) {
|
||||||
|
setUser({token});
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const login = async (loginData) => {
|
||||||
|
try {
|
||||||
|
const token = await loginUser(loginData);
|
||||||
|
localStorage.setItem("access_token", token);
|
||||||
|
setUser({ token });
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Login failed", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const logout = () => {
|
||||||
|
localStorage.removeItem("access_token");
|
||||||
|
setUser(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<AuthContext.Provider value={{user, login, logout}}>
|
||||||
|
{children}
|
||||||
|
</AuthContext.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
AuthProvider.propTypes = {
|
||||||
|
children: PropTypes.node.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useAuth = () => {
|
||||||
|
return useContext(AuthContext);
|
||||||
|
};
|
||||||
13
web-app/src/api/LoginRequest.jsx
Normal file
13
web-app/src/api/LoginRequest.jsx
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
import axios from "axios";
|
||||||
|
import CONFIG from "../core/Config.jsx";
|
||||||
|
|
||||||
|
export const loginUser = async (loginData) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`${CONFIG.BASE_URL}/login/`, loginData, {
|
||||||
|
withCredentials: true,
|
||||||
|
});
|
||||||
|
return response.data.access_token;
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error("Login failed: " + error.message);
|
||||||
|
}
|
||||||
|
};
|
||||||
14
web-app/src/components/PrivateRoute.jsx
Normal file
14
web-app/src/components/PrivateRoute.jsx
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import {Navigate, Outlet} from "react-router-dom";
|
||||||
|
import {useAuth} from "../AuthContext.jsx";
|
||||||
|
|
||||||
|
const PrivateRoute = () => {
|
||||||
|
const {user} = useAuth();
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
return <Navigate to="/login"/>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return <Outlet/>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PrivateRoute;
|
||||||
5
web-app/src/core/Config.jsx
Normal file
5
web-app/src/core/Config.jsx
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
const CONFIG = {
|
||||||
|
BASE_URL: 'http://localhost:8080/api/v1/',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CONFIG;
|
||||||
Loading…
x
Reference in New Issue
Block a user