fix(auth): отобразить роль analyst в UserMenu, расширить Role union в useMe (#1237)

This commit is contained in:
Light1YT 2026-06-13 15:03:15 +05:00
parent 49d26b4696
commit d8a2ad7854
2 changed files with 19 additions and 5 deletions

View file

@ -5,7 +5,7 @@
*
* Avatar-кнопка с инициалом из username + dropdown:
* - текущий username
* - role badge («Админ» / «Пилот»)
* - role badge («Админ» / «Пилот» / «Аналитик»)
* - кнопка «Выйти» invalidate Caddy basic_auth cached creds в browser
*
* Используется в `TopNav.rightSlot`. Если /me грузится или 401 (dev без
@ -24,7 +24,18 @@ import { useEffect, useRef, useState } from "react";
import { LogOut } from "lucide-react";
import { useMe } from "@/lib/useMe";
import { useMe, type Role } from "@/lib/useMe";
/**
* Локализация ролей для badge. Должен покрывать все варианты `Role` из
* `lib/useMe.ts` TypeScript-проверка через `Record<Role, string>`
* сломает build, если backend добавит новую роль без обновления map.
*/
const ROLE_LABELS: Record<Role, string> = {
admin: "Админ",
pilot: "Пилот",
analyst: "Аналитик",
};
/**
* Logout invalidate basic_auth cache + reload.
@ -89,7 +100,7 @@ export function UserMenu() {
if (isLoading || error || !data) return null;
const initial = data.username[0]?.toUpperCase() ?? "?";
const roleLabel = data.role === "admin" ? "Админ" : "Пилот";
const roleLabel = ROLE_LABELS[data.role];
return (
<div ref={containerRef} style={{ position: "relative" }}>

View file

@ -4,7 +4,7 @@
* `useMe()` TanStack-хук для GET /api/v1/me.
*
* Backend возвращает `UserScope` (см. `backend/app/core/auth.py`):
* { username, role: "admin"|"pilot", allowed_paths: string[], deny_paths: string[] }
* { username, role: "admin"|"pilot"|"analyst", allowed_paths: string[], deny_paths: string[] }
*
* Failure modes:
* - 401 нет X-Authenticated-User (локально без Caddy basic_auth). Фронт
@ -26,7 +26,10 @@ import { apiFetchWithStatus, HTTPError } from "@/lib/api";
// статус через `error instanceof HTTPError` — это работает в runtime независимо
// от type-level decl.
export type Role = "admin" | "pilot";
// Должен совпадать с `Role` в `backend/app/core/auth.py` (Literal["admin", "pilot", "analyst"]).
// Источник правды — `auth/roles.yaml`; при добавлении новой роли расширить тут и
// `ROLE_LABELS` в `components/auth/UserMenu.tsx`.
export type Role = "admin" | "pilot" | "analyst";
export interface UserScope {
username: string;