|
All checks were successful
CI Trade-In / changes (pull_request) Successful in 23s
CI / changes (pull_request) Successful in 23s
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / backend-tests (pull_request) Has been skipped
CI / frontend-tests (pull_request) Successful in 2m18s
CI / openapi-codegen-check (pull_request) Successful in 3m48s
CRUD именованных профилей POI-весов был недостижим никому без DevTools. Панель отпирала его значением `admin_token` из localStorage, а записать это значение было нечем: инпут удалили в #442. Поле «User ID» тоже не показывалось — оно само стояло за `{!!adminToken && ...}`. Признак, за которым была заперта фича, ничего не решал. Сервер перестал читать `X-Admin-Token` в #437, последний `verify_admin_token` удалён в #2775. Проверено живым запросом на проде: GET weight-profiles с корректным токеном, с мусорным и без заголовка вовсе дают один и тот же 200. Настоящая защита — два других слоя, тоже прод-проверенных: Caddy basic_auth (без кред 401 на периметре, клиентский X-Authenticated-User не проходит) и rbac_guard (`role != admin` → 403 admin only для pilot и analyst). Поэтому мёртвый механизм убран целиком, а не наполовину: гейт `!!adminToken`, оба чтения localStorage, отправка заголовка во всех четырёх хуках и пропсы `userId`/`adminToken` панели. Владельца профилей панель берёт из `/api/v1/me` — там же, где его берут RouteGuard и Topbar (тот же queryKey, лишнего запроса нет). Профили и так per-user, а единственный сохранённый на проде профиль лежит под `user_id='admin'` — ровно под именем basic_auth-аккаунта, так что миграции нет. Заодно чинится вторая оборванная проводка на том же пути. `analyze` отправлял `profile_id` без `profile_user_id`, а `resolve_weights()` ищет профиль как `get_profile(db, user_id, profile_id)` — при `user_id=None` веса молча падали на системные, при этом ответ рапортовал `weights_profile.source = "profile"`. Проверено на проде: `profile_id=1` без `profile_user_id` → `tram_stop −0.5` вместо `−0.4` из профиля. Без этой правки выбор профиля в разблокированном дропдауне показывал бы одни ползунки, а score считался бы по другим весам. Ветка вынесена в `buildAnalyzeOptions()` — она дублировалась в двух местах. Микрокопия: «Укажите User ID и Admin Token для сохранения профилей» обещала поле, которого нет. Текст называет причину, а не действие, и в проде вообще недостижим — без входа страницу не отдаёт Caddy. Refs #2782 |
||
|---|---|---|
| .. | ||
| public | ||
| src | ||
| .dockerignore | ||
| .env.example | ||
| .eslintrc.json | ||
| Dockerfile | ||
| next-env.d.ts | ||
| next.config.ts | ||
| package-lock.json | ||
| package.json | ||
| sentry.client.config.ts | ||
| sentry.edge.config.ts | ||
| sentry.server.config.ts | ||
| tsconfig.json | ||
| vitest-env.d.ts | ||
| vitest.config.ts | ||
| vitest.setup.ts | ||