refactor(api): introduce UserContext schema for API dependency injection

Replace direct User database model imports in API endpoints with UserContext
schema, following the architecture principle that API routes should not import
database models directly.

Changes:
- Create UserContext schema in models/schema/auth.py with from_user() factory
- Update app/api/deps.py to return UserContext from all auth dependencies
- Add _get_user_model() helper for functions needing User model access
- Update 58 API endpoint files to use UserContext instead of User
- Add noqa comments for 4 legitimate edge cases (enums, internal helpers)

Architecture validation: 0 errors (down from 61), 11 warnings remain

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-30 20:47:33 +01:00
parent 1ad30bd77e
commit cad862f469
60 changed files with 755 additions and 589 deletions

View File

@@ -32,7 +32,7 @@ from app.services.letzshop import (
VendorNotFoundError,
)
from app.tasks.letzshop_tasks import process_historical_import
from models.database.user import User
from models.schema.auth import UserContext
from app.modules.marketplace.schemas import (
FulfillmentOperationResponse,
LetzshopCachedVendorDetail,
@@ -96,7 +96,7 @@ def list_vendors_letzshop_status(
False, description="Only show vendors with Letzshop configured"
),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""
List all vendors with their Letzshop integration status.
@@ -130,7 +130,7 @@ def list_vendors_letzshop_status(
def get_vendor_credentials(
vendor_id: int = Path(..., description="Vendor ID"),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""Get Letzshop credentials for a vendor (API key is masked)."""
order_service = get_order_service(db)
@@ -173,7 +173,7 @@ def create_or_update_vendor_credentials(
vendor_id: int = Path(..., description="Vendor ID"),
credentials_data: LetzshopCredentialsCreate = ...,
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""Create or update Letzshop credentials for a vendor."""
order_service = get_order_service(db)
@@ -220,7 +220,7 @@ def update_vendor_credentials(
vendor_id: int = Path(..., description="Vendor ID"),
credentials_data: LetzshopCredentialsUpdate = ...,
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""Partially update Letzshop credentials for a vendor."""
order_service = get_order_service(db)
@@ -269,7 +269,7 @@ def update_vendor_credentials(
def delete_vendor_credentials(
vendor_id: int = Path(..., description="Vendor ID"),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""Delete Letzshop credentials for a vendor."""
order_service = get_order_service(db)
@@ -308,7 +308,7 @@ def delete_vendor_credentials(
def test_vendor_connection(
vendor_id: int = Path(..., description="Vendor ID"),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""Test the Letzshop connection for a vendor using stored credentials."""
order_service = get_order_service(db)
@@ -333,7 +333,7 @@ def test_vendor_connection(
def test_api_key(
test_request: LetzshopConnectionTestRequest,
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""Test a Letzshop API key without saving it."""
creds_service = get_credentials_service(db)
@@ -372,7 +372,7 @@ def list_all_letzshop_orders(
None, description="Search by order number, customer name, or email"
),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""
List Letzshop orders across all vendors (or for a specific vendor).
@@ -462,7 +462,7 @@ def list_vendor_letzshop_orders(
None, description="Search by order number, customer name, or email"
),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""List Letzshop orders for a vendor."""
order_service = get_order_service(db)
@@ -543,7 +543,7 @@ def list_vendor_letzshop_orders(
def get_letzshop_order_detail(
order_id: int = Path(..., description="Letzshop order ID"),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""Get detailed information for a single Letzshop order."""
order_service = get_order_service(db)
@@ -623,7 +623,7 @@ def trigger_vendor_sync(
vendor_id: int = Path(..., description="Vendor ID"),
sync_request: LetzshopSyncTriggerRequest = LetzshopSyncTriggerRequest(),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""
Trigger a sync operation for a vendor.
@@ -721,7 +721,7 @@ def list_all_letzshop_jobs(
skip: int = Query(0, ge=0),
limit: int = Query(20, ge=1, le=100),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""
Get unified list of all Letzshop-related jobs across all vendors.
@@ -753,7 +753,7 @@ def list_vendor_letzshop_jobs(
skip: int = Query(0, ge=0),
limit: int = Query(20, ge=1, le=100),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""
Get unified list of Letzshop-related jobs for a vendor.
@@ -794,7 +794,7 @@ def start_historical_import(
vendor_id: int = Path(..., description="Vendor ID"),
background_tasks: BackgroundTasks = None,
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""
Start historical order import from Letzshop as a background job.
@@ -861,7 +861,7 @@ def get_historical_import_status(
vendor_id: int = Path(..., description="Vendor ID"),
job_id: int = Path(..., description="Import job ID"),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""
Get status of a historical import job.
@@ -884,7 +884,7 @@ def get_historical_import_status(
def get_import_summary(
vendor_id: int = Path(..., description="Vendor ID"),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""
Get summary statistics for imported Letzshop orders.
@@ -919,7 +919,7 @@ def confirm_order(
vendor_id: int = Path(..., description="Vendor ID"),
order_id: int = Path(..., description="Order ID"),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""
Confirm all inventory units for a Letzshop order.
@@ -1004,7 +1004,7 @@ def reject_order(
vendor_id: int = Path(..., description="Vendor ID"),
order_id: int = Path(..., description="Order ID"),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""
Decline all inventory units for a Letzshop order.
@@ -1079,7 +1079,7 @@ def confirm_single_item(
order_id: int = Path(..., description="Order ID"),
item_id: str = Path(..., description="External Item ID (Letzshop inventory unit ID)"),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""
Confirm a single inventory unit in an order.
@@ -1144,7 +1144,7 @@ def decline_single_item(
order_id: int = Path(..., description="Order ID"),
item_id: str = Path(..., description="External Item ID (Letzshop inventory unit ID)"),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""
Decline a single inventory unit in an order.
@@ -1199,7 +1199,7 @@ def decline_single_item(
def sync_tracking_for_vendor(
vendor_id: int = Path(..., description="Vendor ID"),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""
Sync tracking information from Letzshop for confirmed orders.
@@ -1297,7 +1297,7 @@ def get_vendor_sync_service(db: Session) -> LetzshopVendorSyncService:
def trigger_vendor_directory_sync(
background_tasks: BackgroundTasks,
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
):
"""
Trigger a sync of the Letzshop vendor directory.
@@ -1351,7 +1351,7 @@ def trigger_vendor_directory_sync(
)
def get_vendor_directory_stats(
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
) -> LetzshopVendorDirectoryStatsResponse:
"""
Get statistics about the Letzshop vendor directory cache.
@@ -1377,7 +1377,7 @@ def list_cached_vendors(
page: int = Query(1, ge=1),
limit: int = Query(20, ge=1, le=100),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
) -> LetzshopCachedVendorListResponse:
"""
List cached Letzshop vendors with search and filtering.
@@ -1429,7 +1429,7 @@ def list_cached_vendors(
def get_cached_vendor_detail(
slug: str = Path(..., description="Letzshop vendor slug"),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
) -> LetzshopCachedVendorDetailResponse:
"""
Get detailed information about a cached Letzshop vendor.
@@ -1487,7 +1487,7 @@ def create_vendor_from_letzshop(
slug: str = Path(..., description="Letzshop vendor slug"),
company_id: int = Query(..., description="Company ID to create vendor under"),
db: Session = Depends(get_db),
current_admin: User = Depends(get_current_admin_api),
current_admin: UserContext = Depends(get_current_admin_api),
) -> LetzshopCreateVendorFromCacheResponse:
"""
Create a platform vendor from a cached Letzshop vendor.