Security Validation (enhance-security-validation): - JWT secret validation with entropy checking and pattern detection - CSRF protection middleware with token generation/validation - Frontend CSRF token auto-injection for DELETE/PUT/PATCH requests - MIME type validation with magic bytes detection for file uploads Error Resilience (add-error-resilience): - React ErrorBoundary component with fallback UI and retry functionality - ErrorBoundaryWithI18n wrapper for internationalization support - Page-level and section-level error boundaries in App.tsx Query Performance (optimize-query-performance): - Query monitoring utility with threshold warnings - N+1 query fixes using joinedload/selectinload - Optimized project members, tasks, and subtasks endpoints Bug Fixes: - WebSocket session management (P0): Return primitives instead of ORM objects - LIKE query injection (P1): Escape special characters in search queries Tests: 543 backend tests, 56 frontend tests passing Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
152 lines
4.3 KiB
TypeScript
152 lines
4.3 KiB
TypeScript
import { Routes, Route, Navigate } from 'react-router-dom'
|
|
import { useAuth } from './contexts/AuthContext'
|
|
import { Skeleton } from './components/Skeleton'
|
|
import { ErrorBoundary } from './components/ErrorBoundary'
|
|
import { SectionErrorBoundary } from './components/ErrorBoundaryWithI18n'
|
|
import Login from './pages/Login'
|
|
import Dashboard from './pages/Dashboard'
|
|
import Spaces from './pages/Spaces'
|
|
import Projects from './pages/Projects'
|
|
import Tasks from './pages/Tasks'
|
|
import ProjectSettings from './pages/ProjectSettings'
|
|
import MySettings from './pages/MySettings'
|
|
import AuditPage from './pages/AuditPage'
|
|
import WorkloadPage from './pages/WorkloadPage'
|
|
import ProjectHealthPage from './pages/ProjectHealthPage'
|
|
import ProtectedRoute from './components/ProtectedRoute'
|
|
import Layout from './components/Layout'
|
|
|
|
function App() {
|
|
const { isAuthenticated, loading } = useAuth()
|
|
|
|
if (loading) {
|
|
return (
|
|
<div className="container" style={{ padding: '24px', maxWidth: '1200px', margin: '0 auto' }}>
|
|
<Skeleton variant="rect" width="100%" height={60} style={{ marginBottom: '24px' }} />
|
|
<Skeleton variant="rect" width="100%" height={400} />
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<ErrorBoundary variant="page">
|
|
<Routes>
|
|
<Route
|
|
path="/login"
|
|
element={isAuthenticated ? <Navigate to="/" /> : <Login />}
|
|
/>
|
|
<Route
|
|
path="/"
|
|
element={
|
|
<ProtectedRoute>
|
|
<Layout>
|
|
<SectionErrorBoundary sectionName="Dashboard">
|
|
<Dashboard />
|
|
</SectionErrorBoundary>
|
|
</Layout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/spaces"
|
|
element={
|
|
<ProtectedRoute>
|
|
<Layout>
|
|
<SectionErrorBoundary sectionName="Spaces">
|
|
<Spaces />
|
|
</SectionErrorBoundary>
|
|
</Layout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/spaces/:spaceId"
|
|
element={
|
|
<ProtectedRoute>
|
|
<Layout>
|
|
<SectionErrorBoundary sectionName="Projects">
|
|
<Projects />
|
|
</SectionErrorBoundary>
|
|
</Layout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/projects/:projectId"
|
|
element={
|
|
<ProtectedRoute>
|
|
<Layout>
|
|
<SectionErrorBoundary sectionName="Tasks">
|
|
<Tasks />
|
|
</SectionErrorBoundary>
|
|
</Layout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/projects/:projectId/settings"
|
|
element={
|
|
<ProtectedRoute>
|
|
<Layout>
|
|
<SectionErrorBoundary sectionName="Project Settings">
|
|
<ProjectSettings />
|
|
</SectionErrorBoundary>
|
|
</Layout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/audit"
|
|
element={
|
|
<ProtectedRoute>
|
|
<Layout>
|
|
<SectionErrorBoundary sectionName="Audit">
|
|
<AuditPage />
|
|
</SectionErrorBoundary>
|
|
</Layout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/workload"
|
|
element={
|
|
<ProtectedRoute>
|
|
<Layout>
|
|
<SectionErrorBoundary sectionName="Workload">
|
|
<WorkloadPage />
|
|
</SectionErrorBoundary>
|
|
</Layout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/project-health"
|
|
element={
|
|
<ProtectedRoute>
|
|
<Layout>
|
|
<SectionErrorBoundary sectionName="Project Health">
|
|
<ProjectHealthPage />
|
|
</SectionErrorBoundary>
|
|
</Layout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
<Route
|
|
path="/my-settings"
|
|
element={
|
|
<ProtectedRoute>
|
|
<Layout>
|
|
<SectionErrorBoundary sectionName="Settings">
|
|
<MySettings />
|
|
</SectionErrorBoundary>
|
|
</Layout>
|
|
</ProtectedRoute>
|
|
}
|
|
/>
|
|
</Routes>
|
|
</ErrorBoundary>
|
|
)
|
|
}
|
|
|
|
export default App
|