Files
docqube_backend/app/modules/auth/utils/device_utils.py
T
2026-09-08 11:00:05 +05:30

106 lines
3.3 KiB
Python

import hashlib
import uuid
from fastapi import Request
import re
import requests
import logging
logger = logging.getLogger(__name__)
def get_client_ip(request: Request) -> str:
client_host = request.client.host if request.client else "0.0.0.0"
is_trusted = client_host.startswith("10.") or client_host.startswith("172.") or client_host.startswith("192.168.") or client_host == "127.0.0.1"
if is_trusted:
x_forwarded_for = request.headers.get("X-Forwarded-For")
if x_forwarded_for:
return x_forwarded_for.split(",")[0].strip()
return client_host
def parse_user_agent(user_agent: str):
try:
from user_agents import parse
user_agent_parsed = parse(user_agent)
browser = user_agent_parsed.browser.family
os = user_agent_parsed.os.family
device_type = "Desktop"
if user_agent_parsed.is_mobile:
device_type = "Mobile"
elif user_agent_parsed.is_tablet:
device_type = "Tablet"
return browser, os, device_type
except ImportError:
browser = "Unknown"
os = "Unknown"
device_type = "Desktop"
ua_lower = user_agent.lower()
if "mobile" in ua_lower or "android" in ua_lower or "iphone" in ua_lower:
device_type = "Mobile"
if "tablet" in ua_lower or "ipad" in ua_lower:
device_type = "Tablet"
if "windows" in ua_lower:
os = "Windows"
elif "mac os" in ua_lower or "macos" in ua_lower:
os = "macOS"
elif "android" in ua_lower:
os = "Android"
elif "iphone" in ua_lower or "ipad" in ua_lower:
os = "iOS"
elif "linux" in ua_lower:
os = "Linux"
if "edg" in ua_lower:
browser = "Edge"
elif "opr" in ua_lower or "opera" in ua_lower:
browser = "Opera"
elif "chrome" in ua_lower:
browser = "Chrome"
elif "safari" in ua_lower:
browser = "Safari"
elif "firefox" in ua_lower:
browser = "Firefox"
return browser, os, device_type
def generate_device_fingerprint(request: Request) -> str:
device_id = request.cookies.get("docqube_device_id")
if device_id:
return device_id
new_device_id = str(uuid.uuid4())
request.state.new_device_id = new_device_id
return new_device_id
def get_location_from_ip(ip: str):
"""
Fetch approximate location from IP using free ip-api.com.
Returns (country, state, city, lat, lon)
"""
if not ip or ip in ("127.0.0.1", "0.0.0.0", "localhost"):
return "Unknown", "Unknown", "Unknown", None, None
try:
response = requests.get(f"http://ip-api.com/json/{ip}", timeout=3)
if response.status_code == 200:
data = response.json()
if data.get("status") == "success":
return (
data.get("country", "Unknown"),
data.get("regionName", "Unknown"),
data.get("city", "Unknown"),
data.get("lat"),
data.get("lon")
)
except Exception as e:
logger.warning(f"Failed to fetch location for IP")
return "Unknown", "Unknown", "Unknown", None, None