feat: enable audit logging for authentication and task operations
Add audit_service.log_event() calls to track key user activities: - auth_login: successful and failed login attempts with IP/user agent - auth_logout: single session and all sessions logout - task_delete: task deletion with user context - file_upload: file upload with filename, size, and type - admin_cleanup: manual cleanup trigger with statistics Each event captures client IP (from X-Forwarded-For/X-Real-IP headers), user agent, and relevant metadata for compliance and debugging. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -390,7 +390,7 @@ async def root():
|
||||
|
||||
# Include V2 API routers
|
||||
from app.routers import auth, tasks, admin, translate
|
||||
from fastapi import UploadFile, File, Depends, HTTPException, status
|
||||
from fastapi import UploadFile, File, Depends, HTTPException, status, Request
|
||||
from sqlalchemy.orm import Session
|
||||
import hashlib
|
||||
|
||||
@@ -399,6 +399,23 @@ from app.models.user import User
|
||||
from app.models.task import TaskFile
|
||||
from app.schemas.task import UploadResponse, TaskStatusEnum
|
||||
from app.services.task_service import task_service
|
||||
from app.services.audit_service import audit_service
|
||||
|
||||
|
||||
def get_client_ip(request: Request) -> str:
|
||||
"""Extract client IP address from request"""
|
||||
forwarded = request.headers.get("X-Forwarded-For")
|
||||
if forwarded:
|
||||
return forwarded.split(",")[0].strip()
|
||||
real_ip = request.headers.get("X-Real-IP")
|
||||
if real_ip:
|
||||
return real_ip
|
||||
return request.client.host if request.client else "unknown"
|
||||
|
||||
|
||||
def get_user_agent(request: Request) -> str:
|
||||
"""Extract user agent from request"""
|
||||
return request.headers.get("User-Agent", "unknown")[:500]
|
||||
|
||||
app.include_router(auth.router)
|
||||
app.include_router(tasks.router)
|
||||
@@ -409,6 +426,7 @@ app.include_router(translate.router)
|
||||
# File upload endpoint
|
||||
@app.post("/api/v2/upload", response_model=UploadResponse, tags=["Upload"], summary="Upload file for OCR")
|
||||
async def upload_file(
|
||||
request: Request,
|
||||
file: UploadFile = File(..., description="File to upload (PNG, JPG, PDF, etc.)"),
|
||||
db: Session = Depends(get_db),
|
||||
current_user: User = Depends(get_current_user)
|
||||
@@ -470,6 +488,25 @@ async def upload_file(
|
||||
|
||||
logger.info(f"Uploaded file {file.filename} ({file_size} bytes) for task {task.task_id}, user {current_user.email}")
|
||||
|
||||
# Log file upload event
|
||||
audit_service.log_event(
|
||||
db=db,
|
||||
event_type="file_upload",
|
||||
event_category="file",
|
||||
description=f"File uploaded: {file.filename} ({file_size} bytes)",
|
||||
user_id=current_user.id,
|
||||
ip_address=get_client_ip(request),
|
||||
user_agent=get_user_agent(request),
|
||||
resource_type="task",
|
||||
resource_id=task.task_id,
|
||||
success=True,
|
||||
metadata={
|
||||
"filename": file.filename,
|
||||
"file_size": file_size,
|
||||
"file_type": file.content_type
|
||||
}
|
||||
)
|
||||
|
||||
return {
|
||||
"task_id": task.task_id,
|
||||
"filename": file.filename,
|
||||
|
||||
Reference in New Issue
Block a user