.
This commit is contained in:
@@ -1,30 +1,18 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
/*
|
|
||||||
const axiosInstance = axios.create({
|
|
||||||
baseURL: '/api',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
const axiosInstance = axios.create({
|
const axiosInstance = axios.create({
|
||||||
baseURL: 'https://api.testsite.deinedorfapp.de/api',
|
baseURL: 'https://api.testsite.deinedorfapp.de/api',
|
||||||
//baseURL: 'http://localhost:5173/api',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
});
|
withCredentials: true
|
||||||
|
|
||||||
axiosInstance.interceptors.request.use((config) => {
|
|
||||||
const token = localStorage.getItem('jwt_token');
|
|
||||||
if (token) {
|
|
||||||
config.headers.Authorization = `Bearer ${token}`;
|
|
||||||
}
|
|
||||||
return config;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
axiosInstance.interceptors.response.use(
|
axiosInstance.interceptors.response.use(
|
||||||
(response) => response,
|
(response) => response,
|
||||||
(error) => {
|
(error) => {
|
||||||
if (error.response?.status === 401) {
|
const isAuthCheck = error.config?.url?.includes('/auth/me');
|
||||||
localStorage.removeItem('jwt_token');
|
const isLogin = error.config?.url?.includes('/auth/login');
|
||||||
|
|
||||||
|
if (error.response?.status === 401 && !isAuthCheck && !isLogin) {
|
||||||
window.location.href = '/login';
|
window.location.href = '/login';
|
||||||
}
|
}
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
import { Navigate } from 'react-router-dom';
|
import { Navigate } from 'react-router-dom';
|
||||||
import { useAuth } from '../context/AuthContext';
|
import { useAuth } from '../context/AuthContext';
|
||||||
|
import { CircularProgress, Box } from '@mui/material';
|
||||||
|
|
||||||
export default function PrivateRoute({ children, allowedRoles }) {
|
export default function PrivateRoute({ children, allowedRoles }) {
|
||||||
const { isAuthenticated, role } = useAuth();
|
const { isAuthenticated, role, loading } = useAuth();
|
||||||
|
|
||||||
|
if (loading) return (
|
||||||
|
<Box display="flex" justifyContent="center" alignItems="center" minHeight="100vh">
|
||||||
|
<CircularProgress />
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
|
||||||
if (!isAuthenticated) return <Navigate to="/login" replace />;
|
if (!isAuthenticated) return <Navigate to="/login" replace />;
|
||||||
if (allowedRoles && !allowedRoles.includes(role)) return <Navigate to="/unauthorized" replace />;
|
if (allowedRoles && !allowedRoles.includes(role)) return <Navigate to="/unauthorized" replace />;
|
||||||
|
|||||||
@@ -1,37 +1,50 @@
|
|||||||
import { createContext, useContext, useState } from 'react';
|
import { createContext, useContext, useState, useEffect } from 'react';
|
||||||
import axiosInstance from '../api/axiosInstance';
|
import axiosInstance from '../api/axiosInstance';
|
||||||
import { jwtDecode } from 'jwt-decode';
|
|
||||||
import { SettingsRemoteOutlined } from '@mui/icons-material';
|
|
||||||
|
|
||||||
const AuthContext = createContext(null);
|
const AuthContext = createContext(null);
|
||||||
|
|
||||||
export function AuthProvider({ children }) {
|
export function AuthProvider({ children }) {
|
||||||
const [token, setToken] = useState(() => localStorage.getItem('jwt_token'));
|
const [role, setRole] = useState(null);
|
||||||
const [role, setRole] = useState(() => {
|
const [isAuthenticated, setIsAuthenticated] = useState(false);
|
||||||
const t = localStorage.getItem('jwt_token');
|
const [loading, setLoading] = useState(true);
|
||||||
return t ? jwtDecode(t).role : null;
|
|
||||||
});
|
useEffect(() => {
|
||||||
|
axiosInstance.get('/auth/me')
|
||||||
|
.then(({ data }) => {
|
||||||
|
setRole(data.role.replace('ROLE_', ''));
|
||||||
|
setIsAuthenticated(true);
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setRole(null);
|
||||||
|
setIsAuthenticated(false);
|
||||||
|
})
|
||||||
|
.finally(() => setLoading(false));
|
||||||
|
}, []);
|
||||||
|
|
||||||
const login = async (email, password) => {
|
const login = async (email, password) => {
|
||||||
// Endpunkt ggf. anpassen
|
|
||||||
const { data } = await axiosInstance.post('/auth/login', { email, password });
|
const { data } = await axiosInstance.post('/auth/login', { email, password });
|
||||||
localStorage.setItem('jwt_token', data.token);
|
setRole(data.role.replace('ROLE_', ''));
|
||||||
const decoded = jwtDecode(data.token);
|
setIsAuthenticated(true);
|
||||||
setToken(data.token);
|
|
||||||
setRole(decoded.role)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const logout = () => {
|
const logout = async () => {
|
||||||
localStorage.removeItem('jwt_token');
|
try {
|
||||||
setToken(null);
|
await axiosInstance.post('/auth/logout');
|
||||||
setRole(null)
|
} finally {
|
||||||
|
setRole(null);
|
||||||
|
setIsAuthenticated(false);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<AuthContext.Provider value={{ token, login, logout, isAuthenticated: !!token, role }}>
|
<AuthContext.Provider value={{ login, logout, isAuthenticated, role, loading }}>
|
||||||
{children}
|
{children}
|
||||||
</AuthContext.Provider>
|
</AuthContext.Provider>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useAuth = () => useContext(AuthContext);
|
export const useAuth = () => {
|
||||||
|
const context = useContext(AuthContext);
|
||||||
|
if (!context) throw new Error('useAuth muss innerhalb eines AuthProviders verwendet werden');
|
||||||
|
return context;
|
||||||
|
};
|
||||||
Reference in New Issue
Block a user