Some checks failed
Move all auth schemas (UserContext, UserLogin, LoginResponse, etc.) from legacy models/schema/auth.py to app/modules/tenancy/schemas/auth.py per MOD-019. Update 84 import sites across 14 modules. Legacy file now re-exports for backwards compatibility. Add missing tenancy service methods for cross-module consumers: - merchant_service.get_merchant_by_owner_id() - merchant_service.get_merchant_count_for_owner() - admin_service.get_user_by_id() (public, was private-only) - platform_service.get_active_store_count() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
139 lines
4.1 KiB
Python
139 lines
4.1 KiB
Python
# app/modules/cms/routes/api/admin_media.py
|
|
"""
|
|
Admin media management endpoints for store media libraries.
|
|
|
|
Allows admins to manage media files on behalf of stores.
|
|
"""
|
|
|
|
import logging
|
|
|
|
from fastapi import APIRouter, Depends, File, Query, UploadFile
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.api.deps import get_current_admin_api
|
|
from app.core.database import get_db
|
|
from app.modules.cms.schemas.media import (
|
|
MediaDetailResponse,
|
|
MediaItemResponse,
|
|
MediaListResponse,
|
|
MediaUploadResponse,
|
|
)
|
|
from app.modules.cms.services.media_service import media_service
|
|
from app.modules.tenancy.schemas.auth import UserContext
|
|
|
|
admin_media_router = APIRouter(prefix="/media")
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@admin_media_router.get("/stores/{store_id}", response_model=MediaListResponse)
|
|
def get_store_media_library(
|
|
store_id: int,
|
|
skip: int = Query(0, ge=0),
|
|
limit: int = Query(100, ge=1, le=1000),
|
|
media_type: str | None = Query(None, description="image, video, document"),
|
|
folder: str | None = Query(None, description="Filter by folder"),
|
|
search: str | None = Query(None),
|
|
current_admin: UserContext = Depends(get_current_admin_api),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""
|
|
Get media library for a specific store.
|
|
|
|
Admin can browse any store's media library.
|
|
"""
|
|
media_files, total = media_service.get_media_library(
|
|
db=db,
|
|
store_id=store_id,
|
|
skip=skip,
|
|
limit=limit,
|
|
media_type=media_type,
|
|
folder=folder,
|
|
search=search,
|
|
)
|
|
|
|
return MediaListResponse(
|
|
media=[MediaItemResponse.model_validate(m) for m in media_files],
|
|
total=total,
|
|
skip=skip,
|
|
limit=limit,
|
|
)
|
|
|
|
|
|
@admin_media_router.post("/stores/{store_id}/upload", response_model=MediaUploadResponse)
|
|
async def upload_store_media(
|
|
store_id: int,
|
|
file: UploadFile = File(...),
|
|
folder: str | None = Query("products", description="products, general, etc."),
|
|
current_admin: UserContext = Depends(get_current_admin_api),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""
|
|
Upload media file for a specific store.
|
|
|
|
Admin can upload media on behalf of any store.
|
|
Files are stored in store-specific directories.
|
|
"""
|
|
# Read file content
|
|
file_content = await file.read()
|
|
|
|
# Upload using service
|
|
media_file = await media_service.upload_file(
|
|
db=db,
|
|
store_id=store_id,
|
|
file_content=file_content,
|
|
filename=file.filename or "unnamed",
|
|
folder=folder or "products",
|
|
)
|
|
|
|
logger.info(f"Admin uploaded media for store {store_id}: {media_file.id}")
|
|
|
|
return MediaUploadResponse(
|
|
success=True,
|
|
message="File uploaded successfully",
|
|
media=MediaItemResponse.model_validate(media_file),
|
|
)
|
|
|
|
|
|
@admin_media_router.get("/stores/{store_id}/{media_id}", response_model=MediaDetailResponse)
|
|
def get_store_media_detail(
|
|
store_id: int,
|
|
media_id: int,
|
|
current_admin: UserContext = Depends(get_current_admin_api),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""
|
|
Get detailed info about a specific media file.
|
|
"""
|
|
media_file = media_service.get_media_by_id(db=db, media_id=media_id)
|
|
|
|
# Verify media belongs to the specified store
|
|
if media_file.store_id != store_id:
|
|
from app.modules.cms.exceptions import MediaNotFoundException
|
|
raise MediaNotFoundException(media_id)
|
|
|
|
return MediaDetailResponse.model_validate(media_file)
|
|
|
|
|
|
@admin_media_router.delete("/stores/{store_id}/{media_id}")
|
|
def delete_store_media(
|
|
store_id: int,
|
|
media_id: int,
|
|
current_admin: UserContext = Depends(get_current_admin_api),
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""
|
|
Delete a media file for a store.
|
|
"""
|
|
media_file = media_service.get_media_by_id(db=db, media_id=media_id)
|
|
|
|
# Verify media belongs to the specified store
|
|
if media_file.store_id != store_id:
|
|
from app.modules.cms.exceptions import MediaNotFoundException
|
|
raise MediaNotFoundException(media_id)
|
|
|
|
media_service.delete_media(db=db, media_id=media_id)
|
|
|
|
logger.info(f"Admin deleted media {media_id} for store {store_id}")
|
|
|
|
return {"success": True, "message": "Media deleted successfully"}
|