feat(security): JWT required on every API route, gated dev fallback, role checks
- main.py: global get_current_user dependency on all routers except /auth/login and /health; prod fail-fast startup guard rejects wildcard CORS, default credentials, DEV_LOGIN_ENABLED - inventory/pm: X-User-Role header identity fallback now only active when PROCUREMENT_DEV_LOGIN_ENABLED=true (was unconditional in production) - item_decisions writes + attachment deletes: require_role( procurement_manager, admin) — require_role was defined but never used - config.py: ENVIRONMENT flag, comma-separated CORS_ORIGINS, no default Casdoor client secret/admin password, DEV_LOGIN_ENABLED=false - frontend: authenticated file downloads (Bearer + blob) — <a href> links cannot send the token; FileList/QuoteDetail/AcceptModal/EditModal/ PurchaseHistory converted; DEV_LOGIN_ENABLED build arg defaults false - smoke tests authenticate via POST /auth/login (SMOKE_USER/SMOKE_PASSWORD) - traefik: security headers, API rate limit, 12MB body cap (prod overlay) - nginx client_max_body_size aligned to 12MB
This commit is contained in:
@@ -19,6 +19,17 @@ def check(name, ok, extra=""):
|
||||
|
||||
c = httpx.Client(base_url=BASE, timeout=30)
|
||||
|
||||
# ---------- auth: every endpoint now requires a Casdoor JWT ----------
|
||||
import os
|
||||
|
||||
r = c.post("/auth/login", json={
|
||||
"username": os.environ.get("SMOKE_USER", "tester"),
|
||||
"password": os.environ.get("SMOKE_PASSWORD", "123456"),
|
||||
})
|
||||
check("POST /auth/login", r.status_code == 200, r.text[:200])
|
||||
if r.status_code == 200:
|
||||
c.headers["Authorization"] = f"Bearer {r.json()['data']['access_token']}"
|
||||
|
||||
# ---------- units ----------
|
||||
r = c.post("/units", json={"code": "test-unit", "name_fa": "واحد تست", "dimension": "count", "si_factor": 1.0})
|
||||
check("POST /units", r.status_code == 201 and r.json()["data"]["id"] > 19, r.text[:200])
|
||||
|
||||
Reference in New Issue
Block a user