refactor: complete V1 to V2 migration and remove legacy architecture

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>
This commit is contained in:
egg
2025-11-14 21:27:39 +08:00
parent ad2b832fb6
commit fd98018ddd
34 changed files with 554 additions and 3787 deletions

View File

@@ -1,6 +1,6 @@
"""
Tool_OCR - FastAPI Dependencies
Authentication and database session dependencies
Tool_OCR - FastAPI Dependencies (V2)
Authentication and database session dependencies with external authentication
"""
from typing import Generator, Optional
@@ -13,7 +13,6 @@ from sqlalchemy.orm import Session
from app.core.database import SessionLocal
from app.core.security import decode_access_token
from app.models.user import User
from app.models.user_v2 import User as UserV2
from app.models.session import Session as UserSession
from app.services.admin_service import admin_service
@@ -44,7 +43,7 @@ def get_current_user(
db: Session = Depends(get_db)
) -> User:
"""
Get current authenticated user from JWT token
Get current authenticated user from JWT token (External Authentication)
Args:
credentials: HTTP Bearer credentials
@@ -65,110 +64,6 @@ def get_current_user(
# Extract token
token = credentials.credentials
# Decode token
payload = decode_access_token(token)
if payload is None:
raise credentials_exception
# Extract user ID from token (convert from string to int)
user_id_str: Optional[str] = payload.get("sub")
if user_id_str is None:
raise credentials_exception
try:
user_id: int = int(user_id_str)
except (ValueError, TypeError):
raise credentials_exception
# Query user from database
user = db.query(User).filter(User.id == user_id).first()
if user is None:
raise credentials_exception
# Check if user is active
if not user.is_active:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Inactive user"
)
return user
def get_current_active_user(
current_user: User = Depends(get_current_user)
) -> User:
"""
Get current active user
Args:
current_user: Current user from get_current_user
Returns:
User: Current active user
Raises:
HTTPException: If user is inactive
"""
if not current_user.is_active:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Inactive user"
)
return current_user
def get_current_admin_user(
current_user: User = Depends(get_current_user)
) -> User:
"""
Get current admin user
Args:
current_user: Current user from get_current_user
Returns:
User: Current admin user
Raises:
HTTPException: If user is not admin
"""
if not current_user.is_admin:
raise HTTPException(
status_code=status.HTTP_403_FORBIDDEN,
detail="Not enough privileges"
)
return current_user
# ===== V2 Dependencies for External Authentication =====
def get_current_user_v2(
credentials: HTTPAuthorizationCredentials = Depends(security),
db: Session = Depends(get_db)
) -> UserV2:
"""
Get current authenticated user from JWT token (V2 with external auth)
Args:
credentials: HTTP Bearer credentials
db: Database session
Returns:
UserV2: Current user object
Raises:
HTTPException: If token is invalid or user not found
"""
credentials_exception = HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
# Extract token
token = credentials.credentials
# Decode token
payload = decode_access_token(token)
if payload is None:
@@ -187,10 +82,10 @@ def get_current_user_v2(
# Extract session ID from token (optional)
session_id: Optional[int] = payload.get("session_id")
# Query user from database (using V2 model)
user = db.query(UserV2).filter(UserV2.id == user_id).first()
# Query user from database
user = db.query(User).filter(User.id == user_id).first()
if user is None:
logger.warning(f"User {user_id} not found in V2 table")
logger.warning(f"User {user_id} not found")
raise credentials_exception
# Check if user is active
@@ -234,17 +129,17 @@ def get_current_user_v2(
return user
def get_current_active_user_v2(
current_user: UserV2 = Depends(get_current_user_v2)
) -> UserV2:
def get_current_active_user(
current_user: User = Depends(get_current_user)
) -> User:
"""
Get current active user (V2)
Get current active user
Args:
current_user: Current user from get_current_user_v2
current_user: Current user from get_current_user
Returns:
UserV2: Current active user
User: Current active user
Raises:
HTTPException: If user is inactive
@@ -257,17 +152,17 @@ def get_current_active_user_v2(
return current_user
def get_current_admin_user_v2(
current_user: UserV2 = Depends(get_current_user_v2)
) -> UserV2:
def get_current_admin_user(
current_user: User = Depends(get_current_user)
) -> User:
"""
Get current admin user (V2)
Get current admin user
Args:
current_user: Current user from get_current_user_v2
current_user: Current user from get_current_user
Returns:
UserV2: Current admin user
User: Current admin user
Raises:
HTTPException: If user is not admin