Remove all V1 architecture components and promote V2 to primary: - Delete all paddle_ocr_* table models (export, ocr, translation, user) - Delete legacy routers (auth, export, ocr, translation) - Delete legacy schemas and services - Promote user_v2.py to user.py as primary user model - Update all imports and dependencies to use V2 models only - Update main.py version to 2.0.0 Database changes: - Fix SQLAlchemy reserved word: rename audit_log.metadata to extra_data - Add migration to drop all paddle_ocr_* tables - Update alembic env to only import V2 models Frontend fixes: - Fix Select component exports in TaskHistoryPage.tsx - Update to use simplified Select API with options prop - Fix AxiosInstance TypeScript import syntax 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
96 lines
3.0 KiB
Python
96 lines
3.0 KiB
Python
"""
|
|
Tool_OCR - Audit Log Model
|
|
Security audit logging for authentication and task operations
|
|
"""
|
|
|
|
from sqlalchemy import Column, Integer, String, DateTime, Text, ForeignKey
|
|
from sqlalchemy.orm import relationship
|
|
from datetime import datetime
|
|
|
|
from app.core.database import Base
|
|
|
|
|
|
class AuditLog(Base):
|
|
"""
|
|
Audit log model for security tracking
|
|
|
|
Records all important events including:
|
|
- Authentication events (login, logout, failures)
|
|
- Task operations (create, update, delete)
|
|
- Admin operations
|
|
"""
|
|
|
|
__tablename__ = "tool_ocr_audit_logs"
|
|
|
|
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
|
user_id = Column(
|
|
Integer,
|
|
ForeignKey("tool_ocr_users.id", ondelete="SET NULL"),
|
|
nullable=True,
|
|
index=True,
|
|
comment="User who performed the action (NULL for system events)"
|
|
)
|
|
event_type = Column(
|
|
String(50),
|
|
nullable=False,
|
|
index=True,
|
|
comment="Event type: auth_login, auth_logout, auth_failed, task_create, etc."
|
|
)
|
|
event_category = Column(
|
|
String(20),
|
|
nullable=False,
|
|
index=True,
|
|
comment="Category: authentication, task, admin, system"
|
|
)
|
|
description = Column(
|
|
Text,
|
|
nullable=False,
|
|
comment="Human-readable event description"
|
|
)
|
|
ip_address = Column(String(45), nullable=True, comment="Client IP address (IPv4/IPv6)")
|
|
user_agent = Column(String(500), nullable=True, comment="Client user agent")
|
|
resource_type = Column(
|
|
String(50),
|
|
nullable=True,
|
|
comment="Type of resource affected (task, user, session)"
|
|
)
|
|
resource_id = Column(
|
|
String(255),
|
|
nullable=True,
|
|
index=True,
|
|
comment="ID of affected resource"
|
|
)
|
|
success = Column(
|
|
Integer,
|
|
default=1,
|
|
nullable=False,
|
|
comment="1 for success, 0 for failure"
|
|
)
|
|
error_message = Column(Text, nullable=True, comment="Error details if failed")
|
|
extra_data = Column(Text, nullable=True, comment="Additional JSON metadata")
|
|
created_at = Column(DateTime, default=datetime.utcnow, nullable=False, index=True)
|
|
|
|
# Relationships
|
|
user = relationship("User", back_populates="audit_logs")
|
|
|
|
def __repr__(self):
|
|
return f"<AuditLog(id={self.id}, type='{self.event_type}', user_id={self.user_id})>"
|
|
|
|
def to_dict(self):
|
|
"""Convert audit log to dictionary"""
|
|
return {
|
|
"id": self.id,
|
|
"user_id": self.user_id,
|
|
"event_type": self.event_type,
|
|
"event_category": self.event_category,
|
|
"description": self.description,
|
|
"ip_address": self.ip_address,
|
|
"user_agent": self.user_agent,
|
|
"resource_type": self.resource_type,
|
|
"resource_id": self.resource_id,
|
|
"success": bool(self.success),
|
|
"error_message": self.error_message,
|
|
"extra_data": self.extra_data,
|
|
"created_at": self.created_at.isoformat() if self.created_at else None
|
|
}
|