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 (
-
-
-
-
-
- {isAdmin && (
-
- )}
-
- );
-}
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";
-}