fix(frontend): pilot-only юзер → auto-redirect на /trade-in/ вместо «Доступа нет»

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
This commit is contained in:
bot-frontend 2026-05-30 21:18:19 +03:00
parent ae820d3bd9
commit 654ce7b6c8

View file

@ -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 <NoAccessScreen variant="path" path={pathname} />;
}