From 1fbec06c232ec01fc56e1d2febe6ef802be7b7fc Mon Sep 17 00:00:00 2001 From: "MH.Dmitrii" Date: Wed, 30 Sep 2026 16:18:36 +0300 Subject: [PATCH] revert the front --- frontend/src/App.css | 4 ++ frontend/src/App.tsx | 8 +-- frontend/src/api/LoginAPI/Auth.ts | 10 +-- frontend/src/api/UserAPI/User.ts | 9 --- frontend/src/api/token.ts | 52 +------------- .../components/RedirectIfAuthenticated.tsx | 12 ---- frontend/src/components/RequirePermission.tsx | 13 ---- frontend/src/context/AuthContext.ts | 12 ---- frontend/src/context/AuthProvider.tsx | 67 ------------------- .../auth/components/AuthComponent.tsx | 10 +-- frontend/src/hooks/useAuth.ts | 8 --- frontend/src/layouts/AuthLayout.css | 3 - frontend/src/main.tsx | 5 +- frontend/src/pages/DashboardPage.tsx | 22 ------ frontend/src/utils/permissions/Permissions.ts | 8 --- frontend/src/utils/rememberMe.ts | 13 ---- 16 files changed, 13 insertions(+), 243 deletions(-) delete mode 100644 frontend/src/api/UserAPI/User.ts delete mode 100644 frontend/src/components/RedirectIfAuthenticated.tsx delete mode 100644 frontend/src/components/RequirePermission.tsx delete mode 100644 frontend/src/context/AuthContext.ts delete mode 100644 frontend/src/context/AuthProvider.tsx delete mode 100644 frontend/src/hooks/useAuth.ts delete mode 100644 frontend/src/pages/DashboardPage.tsx delete mode 100644 frontend/src/utils/permissions/Permissions.ts delete mode 100644 frontend/src/utils/rememberMe.ts diff --git a/frontend/src/App.css b/frontend/src/App.css index ba3535a..3fc8113 100644 --- a/frontend/src/App.css +++ b/frontend/src/App.css @@ -1,3 +1,7 @@ #root { height: 100%; + box-shadow: 1px 1px 20px 1px rgba(68, 68, 68, 0.5); + border-radius: 40px; + border: 1px solid #444; + overflow: hidden; } \ No newline at end of file diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 5607d28..411f6b1 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -2,16 +2,12 @@ import './App.css' import { Route, Routes } from "react-router-dom"; import { LoginPage } from "./pages/LoginPage"; import { ForgotPasswordPage } from "./pages/ForgotPasswordPage"; -import { DashboardPage } from "./pages/DashboardPage"; -import { RequirePermission } from "./components/RequirePermission"; -import { RedirectIfAuthenticated } from "./components/RedirectIfAuthenticated"; function App() { return ( - } /> - } /> - } /> + } /> + } /> ); } diff --git a/frontend/src/api/LoginAPI/Auth.ts b/frontend/src/api/LoginAPI/Auth.ts index d4c87ea..97935c9 100644 --- a/frontend/src/api/LoginAPI/Auth.ts +++ b/frontend/src/api/LoginAPI/Auth.ts @@ -1,18 +1,14 @@ -import { API_URL, authFetch, setAccessToken } from "../token"; +import { API_URL, setAccessToken } from "../token"; export async function login(email: string, password: string) { const body = new URLSearchParams({ username: email, password }); const res = await fetch(`${API_URL}/protected/token`, { method: "POST", - body, - credentials: "include", + body, + credentials: "include", }); if (!res.ok) throw new Error("Неверный email или пароль"); const data = await res.json(); setAccessToken(data.access_token); return data; } - -export async function logout() { - return authFetch("/protected/logout"); -} diff --git a/frontend/src/api/UserAPI/User.ts b/frontend/src/api/UserAPI/User.ts deleted file mode 100644 index 5b45847..0000000 --- a/frontend/src/api/UserAPI/User.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { UserOut } from "../../types/UserTypes"; -import { authFetch } from "../token"; - - -export async function fetchCurrentUser(): Promise { - const res = await authFetch("/protected/me"); - if (!res.ok) throw new Error("Не удалось получить данные пользователя"); - return res.json(); -} \ No newline at end of file diff --git a/frontend/src/api/token.ts b/frontend/src/api/token.ts index 439a0b1..14bcfce 100644 --- a/frontend/src/api/token.ts +++ b/frontend/src/api/token.ts @@ -10,58 +10,8 @@ export function getAccessToken() { return accessToken; } -async function requestRefresh(): Promise<{ access_token: string } | null> { - const res = await fetch(`${API_URL}/protected/refresh`, { - method: "POST", - credentials: "include", - }); - if (!res.ok) return null; - return res.json(); -} - -let refreshInFlight: Promise | null = null; - -export function refreshAccessToken(): Promise { - if (refreshInFlight) return refreshInFlight; - - refreshInFlight = (async () => { - try { - // refresh_token в cookie одноразовый (ротация): если другая вкладка - // или повторный вызов уже успели обменять его на новый ровно перед - // нашим запросом, наш "старый" токен уже отозван и сервер ответит - // 404/401, хотя сессия на самом деле жива. Одна короткая повторная - // попытка подхватит уже обновлённую браузером cookie и не даст - // разлогинить валидного пользователя из-за проигранной гонки. - let data = await requestRefresh(); - if (!data) { - await new Promise((resolve) => setTimeout(resolve, 300)); - data = await requestRefresh(); - } - if (!data) { - setAccessToken(null); - return false; - } - setAccessToken(data.access_token); - return true; - } finally { - refreshInFlight = null; - } - })(); - - return refreshInFlight; -} - export async function authFetch(path: string, init: RequestInit = {}) { const headers = new Headers(init.headers); if (accessToken) headers.set("Authorization", `Bearer ${accessToken}`); - - const res = await fetch(`${API_URL}${path}`, { ...init, headers, credentials: "include" }); - if (res.status !== 401) return res; - - const refreshed = await refreshAccessToken(); - if (!refreshed) return res; - - const retryHeaders = new Headers(init.headers); - if (accessToken) retryHeaders.set("Authorization", `Bearer ${accessToken}`); - return fetch(`${API_URL}${path}`, { ...init, headers: retryHeaders, credentials: "include" }); + return fetch(`${API_URL}${path}`, { ...init, headers, credentials: "include" }); } diff --git a/frontend/src/components/RedirectIfAuthenticated.tsx b/frontend/src/components/RedirectIfAuthenticated.tsx deleted file mode 100644 index 695cc82..0000000 --- a/frontend/src/components/RedirectIfAuthenticated.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import type { ReactNode } from "react"; -import { Navigate } from "react-router-dom"; -import { useAuth } from "../hooks/useAuth"; - -export function RedirectIfAuthenticated({ children }: { children: ReactNode }) { - const { user, loading } = useAuth(); - - if (loading) return null; - if (user) return ; - - return children; -} diff --git a/frontend/src/components/RequirePermission.tsx b/frontend/src/components/RequirePermission.tsx deleted file mode 100644 index b023157..0000000 --- a/frontend/src/components/RequirePermission.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import type { ReactNode } from "react"; -import { Navigate } from "react-router-dom"; -import { useAuth } from "../hooks/useAuth"; - -export function RequirePermission({ permission, children }: { permission?: string; children: ReactNode }) { - const { user, permissions, loading } = useAuth(); - - if (loading) return null; - if (!user) return ; - if (permission && !permissions.has(permission)) return ; - - return children; -} diff --git a/frontend/src/context/AuthContext.ts b/frontend/src/context/AuthContext.ts deleted file mode 100644 index 2137587..0000000 --- a/frontend/src/context/AuthContext.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { createContext } from "react"; -import type { UserOut } from "../types/UserTypes"; - -export type AuthState = { - user: UserOut | null; - permissions: Set; - loading: boolean; - refreshUser: () => Promise>; - logout: () => Promise; -}; - -export const AuthContext = createContext(null); diff --git a/frontend/src/context/AuthProvider.tsx b/frontend/src/context/AuthProvider.tsx deleted file mode 100644 index 00b8e97..0000000 --- a/frontend/src/context/AuthProvider.tsx +++ /dev/null @@ -1,67 +0,0 @@ -import { useCallback, useEffect, useRef, useState, type ReactNode } from "react"; -import { fetchCurrentUser } from "../api/UserAPI/User"; -import { logout as apiLogout } from "../api/LoginAPI/Auth"; -import { refreshAccessToken, setAccessToken } from "../api/token"; -import { getEffectivePermissions } from "../utils/permissions/Permissions"; -import { getRememberMe, setRememberMe } from "../utils/rememberMe"; -import { AuthContext, type AuthState } from "./AuthContext"; - -export function AuthProvider({ children }: { children: ReactNode }) { - const [state, setState] = useState>({ - user: null, - permissions: new Set(), - loading: true, - }); - - const refreshUser = useCallback(async () => { - setState((s) => ({ ...s, loading: true })); - try { - const user = await fetchCurrentUser(); - const permissions = getEffectivePermissions(user); - setState({ user, permissions, loading: false }); - return permissions; - } catch { - setState({ user: null, permissions: new Set(), loading: false }); - return new Set(); - } - }, []); - - const logout = useCallback(async () => { - try { - await apiLogout(); - } catch { - // ошибку сети/сервера игнорируем — состояние всё равно чистим ниже - } finally { - setAccessToken(null); - setRememberMe(false); - setState({ user: null, permissions: new Set(), loading: false }); - } - }, []); - - const started = useRef(false); - - useEffect(() => { - if (started.current) return; - started.current = true; - - if (!getRememberMe()) { - setState({ user: null, permissions: new Set(), loading: false }); - return; - } - - (async () => { - const ok = await refreshAccessToken(); - if (ok) { - await refreshUser(); - } else { - setState({ user: null, permissions: new Set(), loading: false }); - } - })(); - }, [refreshUser]); - - return ( - - {children} - - ); -} diff --git a/frontend/src/features/auth/components/AuthComponent.tsx b/frontend/src/features/auth/components/AuthComponent.tsx index 6942d5d..cfbd8f7 100644 --- a/frontend/src/features/auth/components/AuthComponent.tsx +++ b/frontend/src/features/auth/components/AuthComponent.tsx @@ -1,13 +1,9 @@ import { useState, type SubmitEvent, type ReactElement } from "react"; -import { Link, useNavigate } from "react-router-dom"; +import { Link } from "react-router-dom"; import styles from "./AuthComponent.module.css"; import { login } from "../../../api/LoginAPI/Auth"; -import { useAuth } from "../../../hooks/useAuth"; -import { setRememberMe as persistRememberMe } from "../../../utils/rememberMe"; export function Auth():ReactElement { - const { refreshUser } = useAuth(); - const navigate = useNavigate(); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); const [rememberMe, setRememberMe] = useState(false); @@ -30,9 +26,7 @@ export function Auth():ReactElement { try { await login(email, password); - persistRememberMe(rememberMe); - await refreshUser(); - navigate("/dashboard"); + window.location.href = "http://localhost:8000/docs"; } catch (err) { console.error(err); setErrors({ password: "Неверный email или пароль" }); diff --git a/frontend/src/hooks/useAuth.ts b/frontend/src/hooks/useAuth.ts deleted file mode 100644 index 504d97f..0000000 --- a/frontend/src/hooks/useAuth.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { useContext } from "react"; -import { AuthContext } from "../context/AuthContext"; - -export function useAuth() { - const ctx = useContext(AuthContext); - if (!ctx) throw new Error("useAuth must be used inside AuthProvider"); - return ctx; -} diff --git a/frontend/src/layouts/AuthLayout.css b/frontend/src/layouts/AuthLayout.css index 60bdf9e..1cfbfec 100644 --- a/frontend/src/layouts/AuthLayout.css +++ b/frontend/src/layouts/AuthLayout.css @@ -5,9 +5,6 @@ width: 100%; overflow: hidden; height: 100%; - box-shadow: 1px 1px 20px 1px rgba(68, 68, 68, 0.5); - border-radius: 40px; - border: 1px solid #444; } .left_side { width: 60%; diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 24269be..ade9d64 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -3,14 +3,11 @@ import { createRoot } from 'react-dom/client' import { BrowserRouter } from 'react-router-dom' import './index.css' import App from './App.tsx' -import { AuthProvider } from './context/AuthProvider.tsx' createRoot(document.getElementById('root')!).render( - - - + , ) diff --git a/frontend/src/pages/DashboardPage.tsx b/frontend/src/pages/DashboardPage.tsx deleted file mode 100644 index bce1fff..0000000 --- a/frontend/src/pages/DashboardPage.tsx +++ /dev/null @@ -1,22 +0,0 @@ -import { useAuth } from "../hooks/useAuth"; - -export function DashboardPage() { - const { permissions, logout } = useAuth(); - const isAdmin = permissions.has("admin"); - - return ( -
-
-

User

-
- - - - {isAdmin && ( -
-

Admin

-
- )} -
- ); -} diff --git a/frontend/src/utils/permissions/Permissions.ts b/frontend/src/utils/permissions/Permissions.ts deleted file mode 100644 index f2ae736..0000000 --- a/frontend/src/utils/permissions/Permissions.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { UserOut } from "../../types/UserTypes"; - - -export function getEffectivePermissions(user: UserOut): Set { - const direct = user.direct_permissions.map(p => p.permission); - const fromGroups = user.group.flatMap(g => g.permissions.map(p => p.permission)); - return new Set([...direct, ...fromGroups]); -} \ No newline at end of file diff --git a/frontend/src/utils/rememberMe.ts b/frontend/src/utils/rememberMe.ts deleted file mode 100644 index fa8ef2f..0000000 --- a/frontend/src/utils/rememberMe.ts +++ /dev/null @@ -1,13 +0,0 @@ -const REMEMBER_ME_KEY = "rememberMe"; - -export function setRememberMe(value: boolean) { - if (value) { - localStorage.setItem(REMEMBER_ME_KEY, "1"); - } else { - localStorage.removeItem(REMEMBER_ME_KEY); - } -} - -export function getRememberMe(): boolean { - return localStorage.getItem(REMEMBER_ME_KEY) === "1"; -}