Kyle Pope 21aa670a39 Extract real client IP from proxy headers instead of Docker bridge IP
Nginx already forwards X-Forwarded-For and X-Real-IP, but the backend
read request.client.host directly — always returning 172.18.0.x. Added
get_client_ip() helper to audit service; updated all 13 call sites.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 19:20:07 +08:00

36 lines
1.2 KiB
Python

import json
from fastapi import Request
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.audit_log import AuditLog
def get_client_ip(request: Request) -> str:
"""Extract the real client IP from proxy headers, falling back to direct connection."""
forwarded_for = request.headers.get("x-forwarded-for")
if forwarded_for:
# X-Forwarded-For can be a comma-separated list; first entry is the original client
return forwarded_for.split(",")[0].strip()
real_ip = request.headers.get("x-real-ip")
if real_ip:
return real_ip.strip()
return request.client.host if request.client else "unknown"
async def log_audit_event(
db: AsyncSession,
action: str,
actor_id: int | None = None,
target_id: int | None = None,
detail: dict | None = None,
ip: str | None = None,
) -> None:
"""Record an action in the audit log. Does NOT commit — caller handles transaction."""
entry = AuditLog(
actor_user_id=actor_id,
target_user_id=target_id,
action=action,
detail=json.dumps(detail) if detail else None,
ip_address=ip[:45] if ip else None,
)
db.add(entry)