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.metadata 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)
|