This commit is contained in:
2026-04-17 20:16:51 +02:00
parent c3c05e8af4
commit adb797e709
3 changed files with 47 additions and 39 deletions

View File

@@ -1,30 +1,18 @@
import axios from 'axios';
/*
const axiosInstance = axios.create({
baseURL: '/api',
headers: { 'Content-Type': 'application/json' },
});
*/
const axiosInstance = axios.create({
baseURL: 'https://api.testsite.deinedorfapp.de/api',
//baseURL: 'http://localhost:5173/api',
headers: { 'Content-Type': 'application/json' },
});
axiosInstance.interceptors.request.use((config) => {
const token = localStorage.getItem('jwt_token');
if (token) {
config.headers.Authorization = `Bearer ${token}`;
}
return config;
withCredentials: true
});
axiosInstance.interceptors.response.use(
(response) => response,
(error) => {
if (error.response?.status === 401) {
localStorage.removeItem('jwt_token');
const isAuthCheck = error.config?.url?.includes('/auth/me');
const isLogin = error.config?.url?.includes('/auth/login');
if (error.response?.status === 401 && !isAuthCheck && !isLogin) {
window.location.href = '/login';
}
return Promise.reject(error);

View File

@@ -1,8 +1,15 @@
import { Navigate } from 'react-router-dom';
import { useAuth } from '../context/AuthContext';
import { CircularProgress, Box } from '@mui/material';
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 (allowedRoles && !allowedRoles.includes(role)) return <Navigate to="/unauthorized" replace />;

View File

@@ -1,37 +1,50 @@
import { createContext, useContext, useState } from 'react';
import { createContext, useContext, useState, useEffect } from 'react';
import axiosInstance from '../api/axiosInstance';
import { jwtDecode } from 'jwt-decode';
import { SettingsRemoteOutlined } from '@mui/icons-material';
const AuthContext = createContext(null);
export function AuthProvider({ children }) {
const [token, setToken] = useState(() => localStorage.getItem('jwt_token'));
const [role, setRole] = useState(() => {
const t = localStorage.getItem('jwt_token');
return t ? jwtDecode(t).role : null;
});
const [role, setRole] = useState(null);
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [loading, setLoading] = useState(true);
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) => {
// Endpunkt ggf. anpassen
const { data } = await axiosInstance.post('/auth/login', { email, password });
localStorage.setItem('jwt_token', data.token);
const decoded = jwtDecode(data.token);
setToken(data.token);
setRole(decoded.role)
setRole(data.role.replace('ROLE_', ''));
setIsAuthenticated(true);
};
const logout = () => {
localStorage.removeItem('jwt_token');
setToken(null);
setRole(null)
const logout = async () => {
try {
await axiosInstance.post('/auth/logout');
} finally {
setRole(null);
setIsAuthenticated(false);
}
};
return (
<AuthContext.Provider value={{ token, login, logout, isAuthenticated: !!token, role }}>
{children}
</AuthContext.Provider>
<AuthContext.Provider value={{ login, logout, isAuthenticated, role, loading }}>
{children}
</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;
};