feat: Add JWT auth and nomenclature sync to data-entry-app
Integrate shared JWT authentication into data-entry-app: - Add Oracle pool initialization for auth service - Add AuthenticationMiddleware to protect API routes - Update all receipt endpoints to use CurrentUser from JWT - Add shared auth router (/api/auth/login, /api/auth/refresh) Add nomenclature synchronization feature: - Create SQLite models for synced suppliers, local suppliers, and cash registers - Add nomenclature router with sync triggers and CRUD endpoints - Add sync service for Oracle → SQLite nomenclature data - Update nomenclature_service to use synced SQLite data with fallbacks Create shared frontend components: - Add shared/frontend/ with LoginView.vue, auth store factory, login.css - Integrate shared login and auth into data-entry-app frontend - Add axios-based API service with token refresh interceptor 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,10 @@ import threading
|
||||
from pathlib import Path
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
# Load .env file BEFORE any imports that use os.getenv()
|
||||
from dotenv import load_dotenv
|
||||
load_dotenv()
|
||||
|
||||
from fastapi import FastAPI
|
||||
|
||||
# Configure logging to show INFO level messages
|
||||
@@ -24,6 +28,9 @@ sys.path.insert(0, str(project_root / "shared"))
|
||||
from app.config import settings
|
||||
from app.db.database import init_db
|
||||
|
||||
# Import Oracle pool for auth service
|
||||
from database.oracle_pool import oracle_pool
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
@@ -31,7 +38,15 @@ async def lifespan(app: FastAPI):
|
||||
# Startup
|
||||
print(f"Starting {settings.app_name} v{settings.app_version}")
|
||||
|
||||
# Initialize database
|
||||
# Initialize Oracle pool (required for authentication)
|
||||
try:
|
||||
await oracle_pool.initialize()
|
||||
print("Oracle pool initialized")
|
||||
except Exception as e:
|
||||
print(f"Warning: Oracle pool initialization failed: {e}")
|
||||
print("Authentication will not work without Oracle connection")
|
||||
|
||||
# Initialize SQLite database
|
||||
await init_db()
|
||||
print("Database initialized")
|
||||
|
||||
@@ -55,6 +70,11 @@ async def lifespan(app: FastAPI):
|
||||
|
||||
# Shutdown
|
||||
print("Shutting down...")
|
||||
try:
|
||||
await oracle_pool.close()
|
||||
print("Oracle pool closed")
|
||||
except Exception as e:
|
||||
print(f"Warning: Oracle pool close failed: {e}")
|
||||
|
||||
|
||||
# Create FastAPI app
|
||||
@@ -74,6 +94,14 @@ app.add_middleware(
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# Authentication middleware
|
||||
from auth.middleware import AuthenticationMiddleware
|
||||
|
||||
app.add_middleware(
|
||||
AuthenticationMiddleware,
|
||||
excluded_paths=["/docs", "/redoc", "/openapi.json", "/health", "/", "/api/auth/login", "/api/auth/refresh"]
|
||||
)
|
||||
|
||||
# Mount static files for uploads (optional - can serve through nginx in prod)
|
||||
uploads_path = Path(settings.upload_path)
|
||||
if uploads_path.exists():
|
||||
@@ -92,10 +120,17 @@ async def health_check():
|
||||
|
||||
|
||||
# Import and include routers
|
||||
from app.routers import receipts, ocr
|
||||
from app.routers import receipts, ocr, nomenclature
|
||||
|
||||
app.include_router(receipts.router, prefix="/api/receipts", tags=["receipts"])
|
||||
app.include_router(ocr.router, prefix="/api/ocr", tags=["ocr"])
|
||||
app.include_router(nomenclature.router, prefix="/api/nomenclature", tags=["nomenclature"])
|
||||
|
||||
# Auth router
|
||||
from auth.routes import create_auth_router
|
||||
|
||||
auth_router = create_auth_router(prefix="") # No prefix - we set it in include_router
|
||||
app.include_router(auth_router, prefix="/api/auth", tags=["auth"])
|
||||
|
||||
|
||||
# Root endpoint
|
||||
|
||||
Reference in New Issue
Block a user