71 lines
1.9 KiB
Python
71 lines
1.9 KiB
Python
import json
|
||
from datetime import datetime
|
||
from fastapi import Request
|
||
from sqlalchemy.ext.asyncio import AsyncSession
|
||
from models import LoginLog, OperationLog
|
||
|
||
|
||
def get_client_ip(request: Request) -> str:
|
||
"""从请求中提取客户端IP地址,支持代理转发"""
|
||
xff = request.headers.get("X-Forwarded-For")
|
||
if xff:
|
||
return xff.split(",")[0].strip()
|
||
xri = request.headers.get("X-Real-IP")
|
||
if xri:
|
||
return xri.strip()
|
||
return request.client.host if request.client else "unknown"
|
||
|
||
|
||
def get_user_agent(request: Request) -> str:
|
||
"""从请求中提取 User-Agent"""
|
||
return request.headers.get("User-Agent", "")
|
||
|
||
|
||
async def save_login_log(
|
||
db: AsyncSession,
|
||
username: str,
|
||
ip_address: str,
|
||
user_agent: str,
|
||
status: str,
|
||
failure_reason: str | None = None,
|
||
):
|
||
"""保存登录日志(独立提交,确保失败记录不丢失)"""
|
||
log = LoginLog(
|
||
username=username,
|
||
login_time=datetime.utcnow(),
|
||
ip_address=ip_address,
|
||
user_agent=user_agent,
|
||
status=status,
|
||
failure_reason=failure_reason,
|
||
)
|
||
db.add(log)
|
||
await db.commit()
|
||
|
||
|
||
async def create_operation_log(
|
||
db: AsyncSession,
|
||
user_id: int,
|
||
username: str,
|
||
action_type: str,
|
||
target_type: str,
|
||
target_id: int | None = None,
|
||
target_name: str | None = None,
|
||
detail: dict | None = None,
|
||
ip_address: str = "",
|
||
user_agent: str = "",
|
||
):
|
||
"""创建操作日志(不提交,由调用方事务统一提交)"""
|
||
log = OperationLog(
|
||
user_id=user_id,
|
||
username=username,
|
||
action_type=action_type,
|
||
target_type=target_type,
|
||
target_id=target_id,
|
||
target_name=target_name,
|
||
detail=json.dumps(detail, ensure_ascii=False) if detail else None,
|
||
ip_address=ip_address,
|
||
user_agent=user_agent,
|
||
createtime=datetime.utcnow(),
|
||
)
|
||
db.add(log)
|