Merge commit '026c837b919ab4380e8a6e6c052364bbf9bbe8a3' as 'core'
This commit is contained in:
76
core/backend/app/api/v1/audit.py
Normal file
76
core/backend/app/api/v1/audit.py
Normal file
@@ -0,0 +1,76 @@
|
||||
from fastapi import APIRouter, Depends, Query
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select, func
|
||||
from datetime import datetime
|
||||
from app.core.database import get_db
|
||||
from app.core.deps import get_current_user, require_roles
|
||||
from app.models.user import User, AuditLog
|
||||
|
||||
router = APIRouter(prefix="/audit", tags=["审计日志"])
|
||||
|
||||
|
||||
@router.get("/logs")
|
||||
async def list_audit_logs(
|
||||
user_id: int | None = None,
|
||||
action: str | None = None,
|
||||
resource: str | None = None,
|
||||
start_time: str | None = None,
|
||||
end_time: str | None = None,
|
||||
page: int = Query(1, ge=1),
|
||||
page_size: int = Query(20, ge=1, le=100),
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: User = Depends(require_roles("admin", "energy_manager")),
|
||||
):
|
||||
"""Return paginated audit logs with optional filters."""
|
||||
query = select(
|
||||
AuditLog.id,
|
||||
AuditLog.user_id,
|
||||
User.username,
|
||||
AuditLog.action,
|
||||
AuditLog.resource,
|
||||
AuditLog.detail,
|
||||
AuditLog.ip_address,
|
||||
AuditLog.created_at,
|
||||
).outerjoin(User, AuditLog.user_id == User.id)
|
||||
|
||||
if user_id is not None:
|
||||
query = query.where(AuditLog.user_id == user_id)
|
||||
if action:
|
||||
query = query.where(AuditLog.action == action)
|
||||
if resource:
|
||||
query = query.where(AuditLog.resource == resource)
|
||||
if start_time:
|
||||
try:
|
||||
st = datetime.fromisoformat(start_time)
|
||||
query = query.where(AuditLog.created_at >= st)
|
||||
except ValueError:
|
||||
pass
|
||||
if end_time:
|
||||
try:
|
||||
et = datetime.fromisoformat(end_time)
|
||||
query = query.where(AuditLog.created_at <= et)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
# Count
|
||||
count_q = select(func.count()).select_from(query.subquery())
|
||||
total = (await db.execute(count_q)).scalar()
|
||||
|
||||
# Paginate
|
||||
query = query.order_by(AuditLog.created_at.desc()).offset((page - 1) * page_size).limit(page_size)
|
||||
result = await db.execute(query)
|
||||
|
||||
items = []
|
||||
for row in result.all():
|
||||
items.append({
|
||||
"id": row.id,
|
||||
"user_id": row.user_id,
|
||||
"username": row.username or "-",
|
||||
"action": row.action,
|
||||
"resource": row.resource,
|
||||
"detail": row.detail,
|
||||
"ip_address": row.ip_address,
|
||||
"created_at": str(row.created_at) if row.created_at else None,
|
||||
})
|
||||
|
||||
return {"total": total, "items": items}
|
||||
Reference in New Issue
Block a user