nex_docus/backend/app/services/log_service.py

139 lines
4.0 KiB
Python

"""
操作日志服务
"""
from sqlalchemy.ext.asyncio import AsyncSession
from fastapi import Request
from typing import Optional
import json
from app.models.log import OperationLog
from app.models.user import User
from app.core.enums import OperationType, ResourceType
class LogService:
"""操作日志服务"""
@staticmethod
async def log_operation(
db: AsyncSession,
operation_type: OperationType,
resource_type: ResourceType,
user: Optional[User] = None,
resource_id: Optional[int] = None,
detail: Optional[dict] = None,
request: Optional[Request] = None,
status: int = 1,
error_message: Optional[str] = None,
):
"""
记录操作日志
Args:
db: 数据库会话
operation_type: 操作类型
resource_type: 资源类型
user: 操作用户
resource_id: 资源ID
detail: 操作详情(字典格式)
request: FastAPI Request对象
status: 状态 0-失败 1-成功
error_message: 错误信息
"""
# 获取IP和User-Agent
ip_address = None
user_agent = None
if request:
ip_address = request.client.host if request.client else None
user_agent = request.headers.get("user-agent", "")
# 创建日志记录
log = OperationLog(
user_id=user.id if user else None,
username=user.username if user else "匿名",
operation_type=operation_type.value,
resource_type=resource_type.value,
resource_id=resource_id,
detail=json.dumps(detail, ensure_ascii=False) if detail else None,
ip_address=ip_address,
user_agent=user_agent,
status=status,
error_message=error_message,
)
db.add(log)
await db.commit()
@staticmethod
async def log_project_operation(
db: AsyncSession,
operation_type: OperationType,
project_id: int,
user: User,
detail: Optional[dict] = None,
request: Optional[Request] = None,
):
"""记录项目相关操作"""
await LogService.log_operation(
db=db,
operation_type=operation_type,
resource_type=ResourceType.PROJECT,
user=user,
resource_id=project_id,
detail=detail,
request=request,
)
@staticmethod
async def log_file_operation(
db: AsyncSession,
operation_type: OperationType,
project_id: int,
file_path: str,
user: User,
detail: Optional[dict] = None,
request: Optional[Request] = None,
):
"""记录文件相关操作"""
file_detail = {"project_id": project_id, "file_path": file_path}
if detail:
file_detail.update(detail)
await LogService.log_operation(
db=db,
operation_type=operation_type,
resource_type=ResourceType.FILE,
user=user,
resource_id=project_id, # 将project_id作为resource_id
detail=file_detail,
request=request,
)
@staticmethod
async def log_member_operation(
db: AsyncSession,
operation_type: OperationType,
project_id: int,
target_user_id: int,
user: User,
detail: Optional[dict] = None,
request: Optional[Request] = None,
):
"""记录成员相关操作"""
member_detail = {"project_id": project_id, "target_user_id": target_user_id}
if detail:
member_detail.update(detail)
await LogService.log_operation(
db=db,
operation_type=operation_type,
resource_type=ResourceType.MEMBER,
user=user,
resource_id=project_id,
detail=member_detail,
request=request,
)
log_service = LogService()