113 lines
3.9 KiB
Python
113 lines
3.9 KiB
Python
from datetime import datetime
|
|
from typing import Optional, List
|
|
from uuid import UUID
|
|
|
|
from sqlalchemy import func, select
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from app.domain.schemas.audit import AuditLogResponse
|
|
from app.infra.db.metadb import models
|
|
|
|
|
|
class AuditRepository:
|
|
"""审计日志数据访问层(system_hub)"""
|
|
|
|
def __init__(self, session: AsyncSession):
|
|
self.session = session
|
|
|
|
async def create_log(
|
|
self,
|
|
action: str,
|
|
user_id: Optional[UUID] = None,
|
|
project_id: Optional[UUID] = None,
|
|
resource_type: Optional[str] = None,
|
|
resource_id: Optional[str] = None,
|
|
ip_address: Optional[str] = None,
|
|
request_method: Optional[str] = None,
|
|
request_path: Optional[str] = None,
|
|
request_data: Optional[dict] = None,
|
|
response_status: Optional[int] = None,
|
|
) -> AuditLogResponse:
|
|
log = models.AuditLog(
|
|
user_id=user_id,
|
|
project_id=project_id,
|
|
action=action,
|
|
resource_type=resource_type,
|
|
resource_id=resource_id,
|
|
ip_address=ip_address,
|
|
request_method=request_method,
|
|
request_path=request_path,
|
|
request_data=request_data,
|
|
response_status=response_status,
|
|
timestamp=datetime.utcnow(),
|
|
)
|
|
self.session.add(log)
|
|
await self.session.commit()
|
|
await self.session.refresh(log)
|
|
return AuditLogResponse.model_validate(log)
|
|
|
|
async def get_logs(
|
|
self,
|
|
user_id: Optional[UUID] = None,
|
|
project_id: Optional[UUID] = None,
|
|
action: Optional[str] = None,
|
|
resource_type: Optional[str] = None,
|
|
start_time: Optional[datetime] = None,
|
|
end_time: Optional[datetime] = None,
|
|
skip: int = 0,
|
|
limit: int = 100,
|
|
) -> List[AuditLogResponse]:
|
|
conditions = []
|
|
if user_id is not None:
|
|
conditions.append(models.AuditLog.user_id == user_id)
|
|
if project_id is not None:
|
|
conditions.append(models.AuditLog.project_id == project_id)
|
|
if action:
|
|
conditions.append(models.AuditLog.action == action)
|
|
if resource_type:
|
|
conditions.append(models.AuditLog.resource_type == resource_type)
|
|
if start_time:
|
|
conditions.append(models.AuditLog.timestamp >= start_time)
|
|
if end_time:
|
|
conditions.append(models.AuditLog.timestamp <= end_time)
|
|
|
|
stmt = (
|
|
select(models.AuditLog)
|
|
.where(*conditions)
|
|
.order_by(models.AuditLog.timestamp.desc())
|
|
.offset(skip)
|
|
.limit(limit)
|
|
)
|
|
result = await self.session.execute(stmt)
|
|
return [
|
|
AuditLogResponse.model_validate(log)
|
|
for log in result.scalars().all()
|
|
]
|
|
|
|
async def get_log_count(
|
|
self,
|
|
user_id: Optional[UUID] = None,
|
|
project_id: Optional[UUID] = None,
|
|
action: Optional[str] = None,
|
|
resource_type: Optional[str] = None,
|
|
start_time: Optional[datetime] = None,
|
|
end_time: Optional[datetime] = None,
|
|
) -> int:
|
|
conditions = []
|
|
if user_id is not None:
|
|
conditions.append(models.AuditLog.user_id == user_id)
|
|
if project_id is not None:
|
|
conditions.append(models.AuditLog.project_id == project_id)
|
|
if action:
|
|
conditions.append(models.AuditLog.action == action)
|
|
if resource_type:
|
|
conditions.append(models.AuditLog.resource_type == resource_type)
|
|
if start_time:
|
|
conditions.append(models.AuditLog.timestamp >= start_time)
|
|
if end_time:
|
|
conditions.append(models.AuditLog.timestamp <= end_time)
|
|
|
|
stmt = select(func.count()).select_from(models.AuditLog).where(*conditions)
|
|
result = await self.session.execute(stmt)
|
|
return int(result.scalar() or 0)
|