- D-11: replace get_client_ip body with trusted-proxy CIDR check (127/8, 172.16/12,
192.168/16, ::1/128); untrusted peers always return their own IP, preventing XFF
spoofing by external callers
- D-12: create services/rate_limiting.py with _account_key() keyed by user.id
(falls back to peer IP when no authenticated user in request.state); exports
account_limiter = Limiter(key_func=_account_key)
- Wire: auth.py switches from get_remote_address to get_client_ip; main.py imports
account_limiter; all 9 documents.py endpoints and 7 cloud.py endpoints decorated
@account_limiter.limit("100/minute") with request.state.current_user = current_user
as the first handler statement (A1 ordering invariant)
- Promote all 8 xfail stubs to real assertions; add autouse fixture in conftest.py
to reset MemoryStorage between tests preventing cross-test 429 contamination
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
18 lines
458 B
Python
18 lines
458 B
Python
"""Per-account rate limiter shared across document and cloud routers (D-12)."""
|
|
from __future__ import annotations
|
|
|
|
from fastapi import Request
|
|
from slowapi import Limiter
|
|
|
|
|
|
def _account_key(request: Request) -> str:
|
|
user = getattr(request.state, "current_user", None)
|
|
if user is not None:
|
|
return str(user.id)
|
|
if request.client:
|
|
return request.client.host
|
|
return "anonymous"
|
|
|
|
|
|
account_limiter = Limiter(key_func=_account_key)
|