mirror of
https://github.com/serty2005/rmser.git
synced 2026-02-04 19:02:33 -06:00
авторизация fixed
This commit is contained in:
@@ -9,8 +9,8 @@ import { DraftsList } from "./pages/DraftsList";
|
||||
import { SettingsPage } from "./pages/SettingsPage";
|
||||
import { UNAUTHORIZED_EVENT } from "./services/api";
|
||||
|
||||
// Компонент заглушки для 401 ошибки
|
||||
const UnauthorizedScreen = () => (
|
||||
// Компонент-заглушка для внешних браузеров
|
||||
const NotInTelegramScreen = () => (
|
||||
<div
|
||||
style={{
|
||||
height: "100vh",
|
||||
@@ -18,15 +18,16 @@ const UnauthorizedScreen = () => (
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
background: "#fff",
|
||||
padding: 20,
|
||||
}}
|
||||
>
|
||||
<Result
|
||||
status="403"
|
||||
title="Доступ запрещен"
|
||||
subTitle="Мы не нашли вас в базе данных. Пожалуйста, запустите бота и настройте сервер."
|
||||
status="warning"
|
||||
title="Доступ ограничен"
|
||||
subTitle="Пожалуйста, откройте это приложение через официального Telegram бота @RmserBot для корректной работы."
|
||||
extra={
|
||||
<Button type="primary" href="https://t.me/RmserBot" target="_blank">
|
||||
Перейти в бота @RmserBot
|
||||
Перейти в бота
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
@@ -35,20 +36,47 @@ const UnauthorizedScreen = () => (
|
||||
|
||||
function App() {
|
||||
const [isUnauthorized, setIsUnauthorized] = useState(false);
|
||||
const tg = window.Telegram?.WebApp;
|
||||
|
||||
// Проверяем, есть ли данные от Telegram
|
||||
const isInTelegram = !!tg?.initData;
|
||||
|
||||
useEffect(() => {
|
||||
const handleUnauthorized = () => setIsUnauthorized(true);
|
||||
|
||||
// Подписываемся на событие из api.ts
|
||||
window.addEventListener(UNAUTHORIZED_EVENT, handleUnauthorized);
|
||||
|
||||
if (tg) {
|
||||
tg.expand(); // Расширяем приложение на все окно
|
||||
}
|
||||
|
||||
return () => {
|
||||
window.removeEventListener(UNAUTHORIZED_EVENT, handleUnauthorized);
|
||||
};
|
||||
}, []);
|
||||
}, [tg]);
|
||||
|
||||
// Если открыто не в Telegram — блокируем всё
|
||||
if (!isInTelegram) {
|
||||
return <NotInTelegramScreen />;
|
||||
}
|
||||
|
||||
// Если бэкенд вернул 401
|
||||
if (isUnauthorized) {
|
||||
return <UnauthorizedScreen />;
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
height: "100vh",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<Result
|
||||
status="403"
|
||||
title="Ошибка доступа"
|
||||
subTitle="Не удалось подтвердить вашу личность. Попробуйте обновить страницу внутри Telegram."
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -56,14 +84,11 @@ function App() {
|
||||
<BrowserRouter>
|
||||
<Routes>
|
||||
<Route path="/" element={<AppLayout />}>
|
||||
{/* Если Dashboard удален, можно сделать редирект на invoices */}
|
||||
<Route index element={<Navigate to="/invoices" replace />} />
|
||||
|
||||
<Route path="ocr" element={<OcrLearning />} />
|
||||
<Route path="invoices" element={<DraftsList />} />
|
||||
<Route path="invoice/:id" element={<InvoiceDraftPage />} />
|
||||
<Route path="settings" element={<SettingsPage />} />
|
||||
|
||||
<Route path="*" element={<Navigate to="/" replace />} />
|
||||
</Route>
|
||||
</Routes>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import axios from 'axios';
|
||||
import { notification } from 'antd';
|
||||
import type {
|
||||
CatalogItem,
|
||||
CreateInvoiceRequest,
|
||||
@@ -30,9 +31,6 @@ const API_URL = import.meta.env.VITE_API_URL || 'http://localhost:8080/api';
|
||||
// Телеграм объект
|
||||
const tg = window.Telegram?.WebApp;
|
||||
|
||||
// ID для локальной разработки (Fallback)
|
||||
const DEBUG_USER_ID = 665599275;
|
||||
|
||||
// Событие для глобальной обработки 401
|
||||
export const UNAUTHORIZED_EVENT = 'rms_unauthorized';
|
||||
|
||||
@@ -43,31 +41,42 @@ const apiClient = axios.create({
|
||||
},
|
||||
});
|
||||
|
||||
// --- Request Interceptor (Авторизация) ---
|
||||
// --- Request Interceptor (Авторизация через initData) ---
|
||||
apiClient.interceptors.request.use((config) => {
|
||||
// 1. Пробуем взять ID из Telegram WebApp
|
||||
// 2. Ищем в URL параметрах (удобно для тестов в браузере: ?_tg_id=123)
|
||||
// 3. Используем хардкод для локальной разработки
|
||||
const urlParams = new URLSearchParams(window.location.search);
|
||||
const paramId = urlParams.get('_tg_id');
|
||||
|
||||
const userId = tg?.initDataUnsafe?.user?.id || paramId || DEBUG_USER_ID;
|
||||
const initData = tg?.initData;
|
||||
|
||||
if (userId) {
|
||||
config.headers['X-Telegram-User-ID'] = userId.toString();
|
||||
// Если initData пустая — мы не в Telegram. Блокируем запрос.
|
||||
if (!initData) {
|
||||
console.error('Запрос заблокирован: приложение запущено вне Telegram.');
|
||||
return Promise.reject(new Error('MISSING_TELEGRAM_DATA'));
|
||||
}
|
||||
|
||||
// Устанавливаем заголовок согласно новым требованиям
|
||||
config.headers['Authorization'] = `Bearer ${initData}`;
|
||||
|
||||
return config;
|
||||
});
|
||||
|
||||
// --- Response Interceptor (Обработка ошибок) ---
|
||||
// --- Response Interceptor (Обработка ошибок и уведомления) ---
|
||||
apiClient.interceptors.response.use(
|
||||
(response) => response,
|
||||
(error) => {
|
||||
if (error.response && error.response.status === 401) {
|
||||
// Генерируем кастомное событие, которое поймает App.tsx
|
||||
// Глобальное уведомление об ошибке авторизации
|
||||
notification.error({
|
||||
message: 'Ошибка авторизации',
|
||||
description: 'Ваша сессия в Telegram истекла или данные неверны. Попробуйте перезапустить бота.',
|
||||
placement: 'top',
|
||||
});
|
||||
|
||||
window.dispatchEvent(new Event(UNAUTHORIZED_EVENT));
|
||||
}
|
||||
|
||||
// Если запрос был отменен нами (нет initData), не выводим стандартную ошибку API
|
||||
if (error.message === 'MISSING_TELEGRAM_DATA') {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
console.error('API Error:', error);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
|
||||
4
rmser-view/src/vite-env.d.ts
vendored
4
rmser-view/src/vite-env.d.ts
vendored
@@ -1,7 +1,7 @@
|
||||
/// <reference types="vite/client" />
|
||||
|
||||
interface TelegramWebApp {
|
||||
initData: string;
|
||||
initData: string; // Сырая строка с параметрами и хешем
|
||||
initDataUnsafe: {
|
||||
user?: {
|
||||
id: number;
|
||||
@@ -10,11 +10,9 @@ interface TelegramWebApp {
|
||||
username?: string;
|
||||
language_code?: string;
|
||||
};
|
||||
// ... другие поля по необходимости
|
||||
};
|
||||
close: () => void;
|
||||
expand: () => void;
|
||||
// ... другие методы
|
||||
}
|
||||
|
||||
interface Window {
|
||||
|
||||
Reference in New Issue
Block a user