From 654ce7b6c80bb23099c5adc4abd095d488bf79a8 Mon Sep 17 00:00:00 2001 From: bot-frontend Date: Sat, 30 May 2026 21:18:19 +0300 Subject: [PATCH] =?UTF-8?q?fix(frontend):=20pilot-only=20=D1=8E=D0=B7?= =?UTF-8?q?=D0=B5=D1=80=20=E2=86=92=20auto-redirect=20=D0=BD=D0=B0=20/trad?= =?UTF-8?q?e-in/=20=D0=B2=D0=BC=D0=B5=D1=81=D1=82=D0=BE=20=C2=AB=D0=94?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D1=83=D0=BF=D0=B0=20=D0=BD=D0=B5=D1=82=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RouteGuard: при denied path главного фронта (корень / и пр.) если у роли единственная рабочая зона — trade-in (isPathAllowed(/trade-in/)=true) → window.location.replace('/trade-in/') вместо дед-энда NoAccessScreen. Guard от петли: не редиректить если путь уже под /trade-in. admin/multi-scope с разрешённым / не затронуты. Вариант 2 из issue (без Caddy/backend). Refs #799 --- frontend/src/components/auth/RouteGuard.tsx | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/frontend/src/components/auth/RouteGuard.tsx b/frontend/src/components/auth/RouteGuard.tsx index a4891e04..2d8ae184 100644 --- a/frontend/src/components/auth/RouteGuard.tsx +++ b/frontend/src/components/auth/RouteGuard.tsx @@ -61,6 +61,21 @@ export function RouteGuard({ children }: RouteGuardProps) { // Path-level guard на прямой URL. Backend всё равно 403 на /api/v1/admin/*, // но мы не хотим показать «битый admin UI» — лучше сразу stop. if (!isPathAllowed(data.allowed_paths, data.deny_paths, pathname)) { + // #799: pilot-only юзер (единственная доступная зона — trade-in) на + // запрещённом пути главного фронта (корень `/` и пр.) → авто-redirect в + // /trade-in/ вместо дед-энда «Доступа нет». Условия: + // - текущий путь НЕ под /trade-in (иначе цикл; /trade-in — отдельный + // bundle за Caddy, этот гард его не обслуживает, но guard на всякий); + // - у роли есть доступ к /trade-in/ (т.е. trade-in — её рабочая зона). + // admin / multi-scope с разрешённым `/` сюда не попадают (isPathAllowed=true). + if ( + typeof window !== "undefined" && + !pathname.startsWith("/trade-in") && + isPathAllowed(data.allowed_paths, data.deny_paths, "/trade-in/") + ) { + window.location.replace("/trade-in/"); + return null; + } return ; }