fix: безопасность и UX лендингов — 16 исправлений

- CRITICAL: усиленная CSS-санитизация (escape-последовательности, at-rules)
- CRITICAL: очистка setTimeout при unmount
- HIGH: useMutation для создания покупки (вместо ручного fetch)
- HIGH: DOMPurify + rel="noopener noreferrer" на ссылках
- HIGH: ErrorBoundary для публичных страниц покупки
- MEDIUM: стабильные UUID для DnD элементов
- MEDIUM: race condition в delete timeout
- MEDIUM: клиентская валидация формы лендинга
- MEDIUM: staleTime для админ-запросов
- MEDIUM: общая утилита getApiErrorMessage
- MEDIUM: уведомление о таймауте поллинга
- LOW: ARIA роли для radio-карточек и форм
- LOW: дедупликация иконок в LandingIcons.tsx
- LOW: cn() вместо template literals
This commit is contained in:
Fringg
2026-03-06 07:23:11 +03:00
parent 8b5d777f0a
commit 3cea48235f
11 changed files with 389 additions and 217 deletions

View File

@@ -9,6 +9,7 @@ import {
ChannelSubscriptionScreen,
BlacklistedScreen,
} from './components/blocking';
import { ErrorBoundary } from './components/ErrorBoundary';
import { PermissionRoute } from '@/components/auth/PermissionRoute';
import { saveReturnUrl } from './utils/token';
import { useAnalyticsCounters } from './hooks/useAnalyticsCounters';
@@ -201,17 +202,21 @@ function App() {
<Route
path="/buy/success/:token"
element={
<LazyPage>
<PurchaseSuccess />
</LazyPage>
<ErrorBoundary level="app">
<LazyPage>
<PurchaseSuccess />
</LazyPage>
</ErrorBoundary>
}
/>
<Route
path="/buy/:slug"
element={
<LazyPage>
<QuickPurchase />
</LazyPage>
<ErrorBoundary level="app">
<LazyPage>
<QuickPurchase />
</LazyPage>
</ErrorBoundary>
}
/>