Use real IP everywhere

This commit is contained in:
2025-11-09 19:18:05 +03:00
Unverified
parent 8f94dda4c3
commit 08c9a7cab7
3 changed files with 33 additions and 10 deletions
+3 -2
View File
@@ -9,6 +9,7 @@ from routes import account, messaging, profile, push, webrtc, devices, moderatio
import logging import logging
from models import User from models import User
from constants import OWNER_USERNAME from constants import OWNER_USERNAME
from utils import get_client_ip
from db import POOL_CONFIG, SessionLocal from db import POOL_CONFIG, SessionLocal
from logging_config import access_logger # noqa: F401 - ensure loggers configured from logging_config import access_logger # noqa: F401 - ensure loggers configured
@@ -87,7 +88,7 @@ async def access_logging_middleware(request: Request, call_next):
path=request.url.path, path=request.url.path,
status="error", status="error",
user=getattr(user, "username", None), user=getattr(user, "username", None),
ip=request.client.host if request.client else None, ip=get_client_ip(request),
duration=f"{duration:.3f}s", duration=f"{duration:.3f}s",
error=str(exc), error=str(exc),
) )
@@ -101,7 +102,7 @@ async def access_logging_middleware(request: Request, call_next):
path=request.url.path, path=request.url.path,
status=response.status_code, status=response.status_code,
user=getattr(user, "username", None), user=getattr(user, "username", None),
ip=request.headers.get("x-forwarded-for") or (request.client.host if request.client else None), ip=get_client_ip(request),
duration=f"{duration:.3f}s", duration=f"{duration:.3f}s",
) )
return response return response
+5 -6
View File
@@ -11,7 +11,7 @@ from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from constants import OWNER_USERNAME from constants import OWNER_USERNAME
from dependencies import get_current_user, get_db from dependencies import get_current_user, get_db
from models import LoginRequest, RegisterRequest, ChangePasswordRequest, User, CryptoPublicKey, CryptoBackup, DeviceSession from models import LoginRequest, RegisterRequest, ChangePasswordRequest, User, CryptoPublicKey, CryptoBackup, DeviceSession
from utils import create_token, get_password_hash, verify_password from utils import create_token, get_password_hash, verify_password, get_client_ip
from validation import is_valid_password, is_valid_username, is_valid_display_name from validation import is_valid_password, is_valid_username, is_valid_display_name
import os import os
@@ -67,8 +67,7 @@ def check_auth(current_user: User = Depends(get_current_user)):
@router.post("/login") @router.post("/login")
def login(request: LoginRequest, http: Request, db: Session = Depends(get_db)): def login(request: LoginRequest, http: Request, db: Session = Depends(get_db)):
username = request.username.strip() username = request.username.strip()
x_forwarded_for = http.headers.get("x-forwarded-for") if http else None client_ip = get_client_ip(http)
client_ip = x_forwarded_for.split(",")[0].strip() if x_forwarded_for else (http.client.host if http and http.client else None)
user = db.query(User).filter(User.username == username).first() user = db.query(User).filter(User.username == username).first()
@@ -168,7 +167,7 @@ def register(request: RegisterRequest, http: Request, db: Session = Depends(get_
display_name = request.display_name.strip() display_name = request.display_name.strip()
password = request.password.strip() password = request.password.strip()
confirm_password = request.confirm_password.strip() confirm_password = request.confirm_password.strip()
client_ip = http.client.host if http.client else None client_ip = get_client_ip(http)
# Determine if owner already exists # Determine if owner already exists
owner_exists = db.query(User).filter(User.username == OWNER_USERNAME).first() is not None owner_exists = db.query(User).filter(User.username == OWNER_USERNAME).first() is not None
@@ -396,7 +395,7 @@ def logout(
current_user.last_seen = datetime.now() current_user.last_seen = datetime.now()
db.commit() db.commit()
client_ip = http.client.host if http.client else None client_ip = get_client_ip(http)
log_security( log_security(
"logout", "logout",
username=current_user.username, username=current_user.username,
@@ -440,7 +439,7 @@ def change_password(
).update({DeviceSession.revoked: True}) ).update({DeviceSession.revoked: True})
db.commit() db.commit()
client_ip = http.client.host if http.client else None client_ip = get_client_ip(http)
log_security( log_security(
"password_changed", "password_changed",
username=current_user.username, username=current_user.username,
+24 -1
View File
@@ -1,6 +1,7 @@
from datetime import datetime, timedelta from datetime import datetime, timedelta
from fastapi import Request
import jwt import jwt
from typing import Optional from typing import Optional, Any
import bcrypt import bcrypt
from constants import * from constants import *
@@ -32,3 +33,25 @@ def verify_password(plain_password: str, hashed_password: str) -> bool:
def get_password_hash(password: str) -> str: def get_password_hash(password: str) -> str:
return bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()).decode("utf-8") return bcrypt.hashpw(password.encode("utf-8"), bcrypt.gensalt()).decode("utf-8")
def get_client_ip(request: Request) -> Optional[str]:
if not request:
return None
headers = request.headers
forwarded = headers.get("x-forwarded-for") or headers.get("X-Forwarded-For")
if forwarded:
candidate = forwarded.split(",")[0].strip()
if candidate:
return candidate
if request.client and request.client.host:
return request.client.host
if isinstance(request.scope, dict):
client_info = request.scope.get("client")
if isinstance(client_info, (list, tuple)) and client_info:
return client_info[0]
return None