fix(tradein/auth): honest 401/error screens in RouteGuard instead of misleading text
All checks were successful
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI / changes (pull_request) Successful in 7s
CI Trade-In / changes (pull_request) Successful in 7s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Successful in 1m1s
All checks were successful
CI / frontend-tests (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Has been skipped
CI / changes (pull_request) Successful in 7s
CI Trade-In / changes (pull_request) Successful in 7s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Successful in 1m1s
Session-expired (401) screen already existed but its CTA button was
mislabeled "Выйти" (logout) and called logout() with no reload alternative;
generic non-401/403 errors (500 / network fail) reused variant="user"
whose copy ("аккаунт не привязан к роли") is wrong for a technical failure.
- NoAccessScreen: session variant now shows "Войти снова" button that does
window.location.reload() (basic_auth top-level nav reload re-triggers the
browser's auth challenge on rejected creds) instead of full logout.
- New "error" variant for non-401/403 useMe() failures — honest copy +
"Обновить страницу" reload CTA, replacing the misleading "user" text.
- RouteGuard: generic catch-all error branch now routes to variant="error".
- trial (role=expired) and 403 (variant="user") screens unchanged.
This commit is contained in:
parent
5647c2b40e
commit
b176b1bc44
2 changed files with 61 additions and 29 deletions
|
|
@ -12,7 +12,7 @@
|
|||
import { logout } from "@/lib/logout";
|
||||
|
||||
interface NoAccessScreenProps {
|
||||
variant: "user" | "path" | "session" | "trial";
|
||||
variant: "user" | "path" | "session" | "trial" | "error";
|
||||
path?: string;
|
||||
}
|
||||
|
||||
|
|
@ -22,16 +22,20 @@ export function NoAccessScreen({ variant, path }: NoAccessScreenProps) {
|
|||
? "Сессия истекла"
|
||||
: variant === "trial"
|
||||
? "Пробный доступ закончился"
|
||||
: "Доступа нет";
|
||||
: variant === "error"
|
||||
? "Не удалось проверить доступ"
|
||||
: "Доступа нет";
|
||||
|
||||
const subtitle =
|
||||
variant === "session"
|
||||
? "Сессия истекла или вы не авторизованы. Обновите страницу, чтобы войти снова."
|
||||
: variant === "user"
|
||||
? "Учётная запись не привязана к роли. Обратитесь к администратору GenDesign — kopylov."
|
||||
: variant === "path"
|
||||
? "У вашей роли нет доступа к этому разделу. Вернитесь на главную или обратитесь к администратору."
|
||||
: null;
|
||||
? "Сессия истекла или вы не авторизованы. Нажмите «Войти снова», чтобы пройти авторизацию заново."
|
||||
: variant === "error"
|
||||
? "Возникла техническая проблема при проверке доступа. Проверьте подключение к интернету и обновите страницу. Если ошибка повторяется — обратитесь к администратору GenDesign."
|
||||
: variant === "user"
|
||||
? "Учётная запись не привязана к роли. Обратитесь к администратору GenDesign — kopylov."
|
||||
: variant === "path"
|
||||
? "У вашей роли нет доступа к этому разделу. Вернитесь на главную или обратитесь к администратору."
|
||||
: null;
|
||||
|
||||
return (
|
||||
<main
|
||||
|
|
@ -118,26 +122,51 @@ export function NoAccessScreen({ variant, path }: NoAccessScreenProps) {
|
|||
{path}
|
||||
</p>
|
||||
) : null}
|
||||
{/* Always-available logout — иначе locked/no-access юзер заперт:
|
||||
UserMenu (где обычно «Выйти») на этом экране не рендерится. */}
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => logout()}
|
||||
style={{
|
||||
marginTop: 20,
|
||||
background: "var(--accent)",
|
||||
color: "#FFFFFF",
|
||||
border: "none",
|
||||
borderRadius: 8,
|
||||
padding: "10px 16px",
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
cursor: "pointer",
|
||||
fontFamily: "inherit",
|
||||
}}
|
||||
>
|
||||
Выйти
|
||||
</button>
|
||||
{/* Always-available primary action — иначе locked/no-access юзер заперт:
|
||||
UserMenu (где обычно «Выйти») на этом экране не рендерится.
|
||||
session/error — сбой временный (истёкшая сессия / сетевой сбой),
|
||||
поэтому CTA — повторить попытку через reload, а не logout.
|
||||
basic_auth Caddy: reload на top-level navigation триггерит
|
||||
повторный auth-challenge браузера при отклонённых creds. */}
|
||||
{variant === "session" || variant === "error" ? (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => window.location.reload()}
|
||||
style={{
|
||||
marginTop: 20,
|
||||
background: "var(--accent)",
|
||||
color: "#FFFFFF",
|
||||
border: "none",
|
||||
borderRadius: 8,
|
||||
padding: "10px 16px",
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
cursor: "pointer",
|
||||
fontFamily: "inherit",
|
||||
}}
|
||||
>
|
||||
{variant === "session" ? "Войти снова" : "Обновить страницу"}
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => logout()}
|
||||
style={{
|
||||
marginTop: 20,
|
||||
background: "var(--accent)",
|
||||
color: "#FFFFFF",
|
||||
border: "none",
|
||||
borderRadius: 8,
|
||||
padding: "10px 16px",
|
||||
fontSize: 14,
|
||||
fontWeight: 500,
|
||||
cursor: "pointer",
|
||||
fontFamily: "inherit",
|
||||
}}
|
||||
>
|
||||
Выйти
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
|
|
|
|||
|
|
@ -58,7 +58,10 @@ export function RouteGuard({ children }: RouteGuardProps) {
|
|||
}
|
||||
|
||||
if (error) {
|
||||
return <NoAccessScreen variant="user" />;
|
||||
// Не 401/403 — 500 / сетевой сбой / таймаут. НЕ переиспользуем variant="user"
|
||||
// (текст «аккаунт не привязан к роли» вводит в заблуждение при техническом
|
||||
// сбое) — отдельный экран с честной формулировкой + reload CTA.
|
||||
return <NoAccessScreen variant="error" />;
|
||||
}
|
||||
|
||||
if (!data) return null;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue