feat(auth): minimal login/logout + ProtectedRoute (B-LOGOUT)

- api/client.js: apiFetch подставляет Bearer-токен, выставляет
  Content-Type: application/json для не-FormData тел, ловит 401 -> событие
- context/AuthContext: валидация токена через /auth/me, loading-гейт,
  logout(), подписка на 401
- components/ProtectedRoute: guard с ролями и заглушкой на время проверки
- pages/Login: форма входа (OAuth2 form-urlencoded), редирект на from
- App.js: AuthProvider, /login, ProtectedRoute на /sar /desktop
  /analysis /admin (admin -> roles=[admin]) /mobile
- AdminDashboard/CaseForm/AnalysisResult: переход на apiFetch
- AdminDashboard: кнопка "Выйти" в шапке (useAuth().logout)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
root
2026-08-20 16:04:05 +00:00
parent c2ad5c1915
commit bef93d159c
10 changed files with 443 additions and 25 deletions
@@ -1,6 +1,7 @@
import React, { useState, useEffect } from "react";
import { useParams } from "react-router-dom";
import SearchMap from '../../components/SearchMap';
import { apiFetch } from "../../api/client";
import "./AnalysisResult.css";
const AnalysisResult = () => {
@@ -16,7 +17,7 @@ const AnalysisResult = () => {
setLoading(true);
setError(null);
const caseResponse = await fetch(`/api/v1/cases/${caseId}`);
const caseResponse = await apiFetch(`/api/v1/cases/${caseId}`);
if (!caseResponse.ok) {
throw new Error("Не удалось загрузить карточку");
}