fix(tradein): убрать require_admin полностью — Caddy basic_auth достаточен #474

Merged
lekss361 merged 1 commit from fix/tradein-remove-require-admin into main 2026-05-23 14:21:02 +00:00
Owner

Summary

Доделка PR #437 (refactor: убрать X-Admin-Token UI / middleware). require_admin Depends остался в admin.py — блокировал /admin/scrape/* возвратом 401 для всех запросов без X-Admin-Token. Frontend /trade-in/scrapers/avito (PR #472) не шлёт header (полагается на Caddy basic_auth gate), → "Invalid or missing X-Admin-Token" во всех 4 секциях.

LOC: +11 / -50 (4 files).

Changes

File Что
admin.py DELETE function require_admin; remove dependencies=[Depends(require_admin)] из 7 endpoints (/scrape, /geocode-missing, /scrape/cian/upload-cookies, /scrape/cian/test-auth, /scrape/avito-house, /scrape/avito-detail, /scrape/avito-imv)
config.py DELETE admin_token: str | None = None + comment
deploy/cron-scrape.sh Remove ADMIN_HDR var + -H "$ADMIN_HDR" из всех curl
scripts/upload-cian-cookies.sh Remove TRADEIN_ADMIN_TOKEN loading + -H X-Admin-Token

Auth contract (после fix)

  • Caddy basic_auth gate'ит /trade-in/api/v1/admin/* (через handle_path config)
  • Application layer: open после Caddy unwrap — Depends removed
  • ADMIN_TOKEN env переменная больше не используется backend'ом, но можно держать в .env.runtime как dead reference

Verify

  • ruff clean (новые изменения)
  • pytest test_api_avito_stage4a.py 5/5 PASSED — тесты require_admin не мокали
  • 4 pre-existing E501 в admin.py:44-47 (ScrapeRequest) — НЕ тронуты (out of scope)

Test plan

  • ruff + pytest
  • Deploy → curl /trade-in/api/v1/admin/scrape через Caddy basic_auth → expect 200 (no 401)
  • Open /trade-in/scrapers/avito → submit any form → verify работает без token input

Refs

  • Bug discovered: PR #472 (Stage 4c admin UI) — frontend не шлёт X-Admin-Token
  • Cleanup начат: PR #437 (refactor: убрать UI ввода admin token)
## Summary Доделка PR #437 (refactor: убрать X-Admin-Token UI / middleware). `require_admin` Depends остался в `admin.py` — блокировал `/admin/scrape/*` возвратом 401 для всех запросов без `X-Admin-Token`. Frontend `/trade-in/scrapers/avito` (PR #472) не шлёт header (полагается на Caddy basic_auth gate), → "Invalid or missing X-Admin-Token" во всех 4 секциях. LOC: +11 / -50 (4 files). ## Changes | File | Что | |---|---| | `admin.py` | DELETE function `require_admin`; remove `dependencies=[Depends(require_admin)]` из 7 endpoints (`/scrape`, `/geocode-missing`, `/scrape/cian/upload-cookies`, `/scrape/cian/test-auth`, `/scrape/avito-house`, `/scrape/avito-detail`, `/scrape/avito-imv`) | | `config.py` | DELETE `admin_token: str \| None = None` + comment | | `deploy/cron-scrape.sh` | Remove `ADMIN_HDR` var + `-H "$ADMIN_HDR"` из всех curl | | `scripts/upload-cian-cookies.sh` | Remove `TRADEIN_ADMIN_TOKEN` loading + `-H X-Admin-Token` | ## Auth contract (после fix) - **Caddy basic_auth** gate'ит `/trade-in/api/v1/admin/*` (через `handle_path` config) - **Application layer**: open после Caddy unwrap — `Depends` removed - `ADMIN_TOKEN` env переменная больше не используется backend'ом, но можно держать в `.env.runtime` как dead reference ## Verify - ✅ ruff clean (новые изменения) - ✅ pytest `test_api_avito_stage4a.py` 5/5 PASSED — тесты `require_admin` не мокали - 4 pre-existing E501 в `admin.py:44-47` (ScrapeRequest) — НЕ тронуты (out of scope) ## Test plan - [x] ruff + pytest - [ ] Deploy → curl `/trade-in/api/v1/admin/scrape` через Caddy basic_auth → expect 200 (no 401) - [ ] Open `/trade-in/scrapers/avito` → submit any form → verify работает без token input ## Refs - Bug discovered: PR #472 (Stage 4c admin UI) — frontend не шлёт `X-Admin-Token` - Cleanup начат: PR #437 (refactor: убрать UI ввода admin token)
lekss361 added 1 commit 2026-05-23 14:17:24 +00:00
Доделка PR #437 (refactor: убрать X-Admin-Token UI / middleware). require_admin
Depends остался в admin.py — блокировал /admin/scrape/* возвратом 401 для всех
запросов без X-Admin-Token. Frontend /scrapers/avito (PR #472) не шлёт header
(полагается на Caddy basic_auth gate), → 'Invalid or missing X-Admin-Token'.

Изменения:
- admin.py: удалена функция require_admin + 7 Depends() в endpoint decorators
  (/scrape, /geocode-missing, /scrape/cian/upload-cookies, /scrape/cian/test-auth,
   /scrape/avito-house, /scrape/avito-detail, /scrape/avito-imv)
- config.py: удалено settings.admin_token field
- cron-scrape.sh: удалён ADMIN_HDR + X-Admin-Token из всех curl
- upload-cian-cookies.sh: удалён TRADEIN_ADMIN_TOKEN loading + header

Auth contract: Caddy basic_auth gate'ит /trade-in/api/v1/admin/* (через handle_path
конфиг). Application layer — open после Caddy unwrap. ADMIN_TOKEN env переменная
больше не используется backend'ом, но её можно держать в .env.runtime как
dead reference (без последствий).
lekss361 merged commit dbad7a626b into main 2026-05-23 14:21:02 +00:00
Author
Owner

Merged via deep-code-reviewer — verdict APPROVE (squash → dbad7a6).

Security verification (CRITICAL focus area):

  • Caddy gate confirmedCaddyfile:53-96 wraps everything in route { } block; import caddy/users.caddy.snippet (basic_auth) loaded BEFORE handle /trade-in/api/* (line 72). Только /health + /preview/* короткозамкнуты выше auth. /trade-in/api/v1/admin/* под basic_auth.
  • Raw IP bypass blocked:80 блок (line 150-170) тоже импортирует ту же snippet, нельзя обойти через прямой IP/SSH tunnel.
  • Backend port not exposeddocker-compose.prod.yml для tradein-backend НЕ имеет ports: mapping, только internal networks (tradein-net + gendesign_shared). Не reachable извне.
  • Pydantic extra="ignore" в config.py:7 — stale ADMIN_TOKEN env в .env.runtime не сломает Settings() load.
  • Teststest_api_avito_stage4a.py не мокал require_admin и не assert'ил 401 → 5/5 PASS после removal.
  • Croncron-scrape.sh использует docker exec ... curl http://localhost:8000/... (inside container loopback, минует Caddy) — auth removal acceptable.

Minor (non-blocking):

  • scripts/upload-cian-cookies.sh теперь hits https://gendsgn.ru/trade-in/... без credentials → получит 401 от Caddy. User должен либо вызывать с curl --user kopylov:..., либо обновить script добавив --user flag. Docs gap, отдельным PR.
  • docker-compose.prod.yml:45 всё ещё передаёт ADMIN_TOKEN: "${ADMIN_TOKEN:-}" в backend — dead reference, но не вредно (per PR description acceptable).

Manual verify steps для user (post-deploy):

# 1. Без basic_auth → должен 401 от Caddy
curl -i https://gendsgn.ru/trade-in/api/v1/admin/scrape
# expect: HTTP/2 401

# 2. С basic_auth → 200/405 от backend (не 401 от require_admin)
curl -i -u kopylov:<pass> https://gendsgn.ru/trade-in/api/v1/admin/scrape
# expect: 405 Method Not Allowed (GET на POST endpoint — OK, значит request долетел до backend)

# 3. Browser: /trade-in/scrapers/avito → submit формы → PR #472 bug пофикшен.
Merged via deep-code-reviewer — verdict APPROVE (squash → `dbad7a6`). **Security verification (CRITICAL focus area):** - **Caddy gate confirmed** — `Caddyfile:53-96` wraps everything in `route { }` block; `import caddy/users.caddy.snippet` (basic_auth) loaded BEFORE `handle /trade-in/api/*` (line 72). Только `/health` + `/preview/*` короткозамкнуты выше auth. `/trade-in/api/v1/admin/*` под basic_auth. - **Raw IP bypass blocked** — `:80` блок (line 150-170) тоже импортирует ту же snippet, нельзя обойти через прямой IP/SSH tunnel. - **Backend port not exposed** — `docker-compose.prod.yml` для `tradein-backend` НЕ имеет `ports:` mapping, только internal networks (`tradein-net` + `gendesign_shared`). Не reachable извне. - **Pydantic `extra="ignore"`** в `config.py:7` — stale `ADMIN_TOKEN` env в `.env.runtime` не сломает Settings() load. - **Tests** — `test_api_avito_stage4a.py` не мокал `require_admin` и не assert'ил 401 → 5/5 PASS после removal. - **Cron** — `cron-scrape.sh` использует `docker exec ... curl http://localhost:8000/...` (inside container loopback, минует Caddy) — auth removal acceptable. **Minor (non-blocking):** - `scripts/upload-cian-cookies.sh` теперь hits `https://gendsgn.ru/trade-in/...` без credentials → получит 401 от Caddy. User должен либо вызывать с `curl --user kopylov:...`, либо обновить script добавив `--user` flag. Docs gap, отдельным PR. - `docker-compose.prod.yml:45` всё ещё передаёт `ADMIN_TOKEN: "${ADMIN_TOKEN:-}"` в backend — dead reference, но не вредно (per PR description acceptable). **Manual verify steps для user (post-deploy):** ```bash # 1. Без basic_auth → должен 401 от Caddy curl -i https://gendsgn.ru/trade-in/api/v1/admin/scrape # expect: HTTP/2 401 # 2. С basic_auth → 200/405 от backend (не 401 от require_admin) curl -i -u kopylov:<pass> https://gendsgn.ru/trade-in/api/v1/admin/scrape # expect: 405 Method Not Allowed (GET на POST endpoint — OK, значит request долетел до backend) # 3. Browser: /trade-in/scrapers/avito → submit формы → PR #472 bug пофикшен. ```
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: lekss361/gendesign#474
No description provided.