Files
app-service/backend/app/api/v1/audit.py
matteoscrugli 8c4a555b88 Add comprehensive backend features and mobile UI improvements
Backend:
- Add 2FA authentication with TOTP support
- Add API keys management system
- Add audit logging for security events
- Add file upload/management system
- Add notifications system with preferences
- Add session management
- Add webhooks integration
- Add analytics endpoints
- Add export functionality
- Add password policy enforcement
- Add new database migrations for core tables

Frontend:
- Add module position system (top/bottom sidebar sections)
- Add search and notifications module configuration tabs
- Add mobile logo replacing hamburger menu
- Center page title absolutely when no tabs present
- Align sidebar footer toggles with navigation items
- Add lighter icon color in dark theme for mobile
- Add API keys management page
- Add notifications page with context
- Add admin analytics and audit logs pages

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 22:27:32 +01:00

163 lines
4.2 KiB
Python

"""Audit log API endpoints."""
from datetime import datetime
from typing import Optional
from fastapi import APIRouter, Depends, Query, HTTPException, status
from sqlalchemy.orm import Session
from app.dependencies import get_db, get_current_superuser
from app.models.user import User
from app import crud
from app.schemas.audit_log import (
AuditLog,
AuditLogList,
AuditLogFilter,
AuditLogStats
)
router = APIRouter()
@router.get("", response_model=AuditLogList)
def get_audit_logs(
db: Session = Depends(get_db),
current_user: User = Depends(get_current_superuser),
page: int = Query(1, ge=1),
page_size: int = Query(50, ge=1, le=100),
user_id: Optional[str] = None,
username: Optional[str] = None,
action: Optional[str] = None,
resource_type: Optional[str] = None,
resource_id: Optional[str] = None,
status_filter: Optional[str] = Query(None, alias="status"),
start_date: Optional[datetime] = None,
end_date: Optional[datetime] = None,
):
"""
Get paginated audit logs with optional filtering.
Requires superuser authentication.
"""
filters = AuditLogFilter(
user_id=user_id,
username=username,
action=action,
resource_type=resource_type,
resource_id=resource_id,
status=status_filter,
start_date=start_date,
end_date=end_date
)
skip = (page - 1) * page_size
items, total = crud.audit_log.get_multi(
db, skip=skip, limit=page_size, filters=filters
)
total_pages = (total + page_size - 1) // page_size
return AuditLogList(
items=items,
total=total,
page=page,
page_size=page_size,
total_pages=total_pages
)
@router.get("/stats", response_model=AuditLogStats)
def get_audit_stats(
db: Session = Depends(get_db),
current_user: User = Depends(get_current_superuser),
):
"""
Get audit log statistics.
Requires superuser authentication.
"""
return crud.audit_log.get_stats(db)
@router.get("/actions")
def get_distinct_actions(
db: Session = Depends(get_db),
current_user: User = Depends(get_current_superuser),
):
"""
Get list of distinct action types for filtering.
"""
return {"actions": crud.audit_log.get_distinct_actions(db)}
@router.get("/resource-types")
def get_distinct_resource_types(
db: Session = Depends(get_db),
current_user: User = Depends(get_current_superuser),
):
"""
Get list of distinct resource types for filtering.
"""
return {"resource_types": crud.audit_log.get_distinct_resource_types(db)}
@router.get("/user/{user_id}", response_model=AuditLogList)
def get_user_audit_logs(
user_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_superuser),
page: int = Query(1, ge=1),
page_size: int = Query(50, ge=1, le=100),
):
"""
Get audit logs for a specific user.
Requires superuser authentication.
"""
filters = AuditLogFilter(user_id=user_id)
skip = (page - 1) * page_size
items, total = crud.audit_log.get_multi(
db, skip=skip, limit=page_size, filters=filters
)
total_pages = (total + page_size - 1) // page_size
return AuditLogList(
items=items,
total=total,
page=page,
page_size=page_size,
total_pages=total_pages
)
@router.get("/{log_id}", response_model=AuditLog)
def get_audit_log(
log_id: str,
db: Session = Depends(get_db),
current_user: User = Depends(get_current_superuser),
):
"""
Get a specific audit log entry.
Requires superuser authentication.
"""
log = crud.audit_log.get(db, id=log_id)
if not log:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Audit log not found"
)
return log
@router.delete("/cleanup")
def cleanup_old_logs(
db: Session = Depends(get_db),
current_user: User = Depends(get_current_superuser),
days: int = Query(90, ge=1, le=365),
):
"""
Delete audit logs older than specified days.
Requires superuser authentication.
Default: 90 days.
"""
deleted = crud.audit_log.delete_old(db, days=days)
return {"deleted": deleted, "days_threshold": days}