- Create FastAPI application with async I/O - Implement Redis session storage (fixes session loss on restart) - Add JWT authentication with refresh tokens - Add Microsoft SSO support via MSAL - Copy all processors from src/ (100% reused, no changes) - Create file upload/download endpoints - Create metadata update endpoints - Create template CRUD endpoints - Add SQLAlchemy async database models - Add Docker Compose configuration with Redis Solves critical issues: - Session management: Redis replaces in-memory dicts - Scalability: Async FastAPI + microservices architecture - File handling: Persistent storage with auto-cleanup Key files: - backend/app/main.py - FastAPI entry point - backend/app/core/redis_client.py - Session store - backend/app/core/auth.py - JWT authentication - backend/app/api/* - All REST endpoints - backend/app/processors/ - Reused from src/ Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
60 lines
1.6 KiB
Python
60 lines
1.6 KiB
Python
"""Base class for all metadata updaters."""
|
|
|
|
from abc import ABC, abstractmethod
|
|
from typing import Dict, Optional
|
|
|
|
class BaseUpdater(ABC):
|
|
"""Abstract base class for metadata updaters."""
|
|
|
|
@abstractmethod
|
|
def update_metadata(self, file_path: str, metadata: Dict[str, str], backup: bool = True) -> bool:
|
|
"""
|
|
Update file metadata.
|
|
|
|
Args:
|
|
file_path: Path to the file
|
|
metadata: Dictionary of metadata to update
|
|
backup: Whether to create backup before updating
|
|
|
|
Returns:
|
|
True if successful, False otherwise
|
|
"""
|
|
pass
|
|
|
|
@abstractmethod
|
|
def verify_metadata(self, file_path: str, expected_metadata: Dict[str, str]) -> bool:
|
|
"""
|
|
Verify metadata was written correctly.
|
|
|
|
Args:
|
|
file_path: Path to the file
|
|
expected_metadata: Expected metadata values
|
|
|
|
Returns:
|
|
True if metadata matches expected values
|
|
"""
|
|
pass
|
|
|
|
def validate_metadata(self, metadata: Dict[str, str]) -> bool:
|
|
"""
|
|
Validate metadata before writing.
|
|
|
|
Args:
|
|
metadata: Metadata dictionary
|
|
|
|
Returns:
|
|
True if valid
|
|
"""
|
|
# Check for required fields
|
|
required_fields = ['title']
|
|
for field in required_fields:
|
|
if field not in metadata or not metadata[field]:
|
|
return False
|
|
|
|
# Check field lengths
|
|
if len(metadata.get('title', '')) > 200:
|
|
return False
|
|
if len(metadata.get('keywords', '')) > 500:
|
|
return False
|
|
|
|
return True
|