from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from typing import List, Optional from database import get_db from models.company_r2_config import CompanyR2Config from models.company import Company from models.user import User from schemas.product import ( CompanyR2ConfigResponse, CompanyR2ConfigCreate, CompanyR2ConfigUpdate ) from routers.auth import get_current_user, is_admin_user from utils.r2_uploader import set_cached_config, clear_cached_config, R2Config router = APIRouter() def verify_superadmin(current_user: User): """验证用户是否为超级管理员或admin用户""" if not current_user.is_superadmin and not is_admin_user(current_user): raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Only superadmin can access this endpoint" ) @router.get("/all", response_model=List[CompanyR2ConfigResponse]) async def get_all_r2_configs( current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """获取所有公司的 R2 配置(仅超管)""" verify_superadmin(current_user) configs = db.query(CompanyR2Config).all() result = [] for config in configs: company = db.query(Company).filter( Company.company_code == config.company_code ).first() config_dict = { 'id': config.id, 'company_code': config.company_code, 'company_name': company.name if company else None, 'r2_account_id': config.r2_account_id, 'r2_access_key_id': config.r2_access_key_id, 'r2_secret_access_key': config.r2_secret_access_key, 'r2_bucket_name': config.r2_bucket_name, 'r2_public_url': config.r2_public_url, 'r2_enabled': config.r2_enabled, 'created_at': config.created_at, 'updated_at': config.updated_at } result.append(config_dict) return result @router.get("/config/{company_code}", response_model=Optional[CompanyR2ConfigResponse]) async def get_r2_config_by_company( company_code: str, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """获取指定公司的 R2 配置(仅超管)""" verify_superadmin(current_user) config = db.query(CompanyR2Config).filter( CompanyR2Config.company_code == company_code ).first() if config: r2_config = R2Config({ 'r2_account_id': config.r2_account_id, 'r2_access_key_id': config.r2_access_key_id, 'r2_secret_access_key': config.r2_secret_access_key, 'r2_bucket_name': config.r2_bucket_name, 'r2_public_url': config.r2_public_url, 'r2_enabled': config.r2_enabled }) set_cached_config(company_code, r2_config) company = db.query(Company).filter( Company.company_code == config.company_code ).first() config_dict = { 'id': config.id, 'company_code': config.company_code, 'company_name': company.name if company else None, 'r2_account_id': config.r2_account_id, 'r2_access_key_id': config.r2_access_key_id, 'r2_secret_access_key': config.r2_secret_access_key, 'r2_bucket_name': config.r2_bucket_name, 'r2_public_url': config.r2_public_url, 'r2_enabled': config.r2_enabled, 'created_at': config.created_at, 'updated_at': config.updated_at } return config_dict return config @router.post("/config/{company_code}", response_model=CompanyR2ConfigResponse, status_code=status.HTTP_201_CREATED) async def create_r2_config_for_company( company_code: str, config_data: CompanyR2ConfigCreate, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """为指定公司创建或更新 R2 配置(仅超管)""" verify_superadmin(current_user) existing_config = db.query(CompanyR2Config).filter( CompanyR2Config.company_code == company_code ).first() if existing_config: update_data = config_data.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(existing_config, field, value) db.commit() db.refresh(existing_config) config = existing_config else: config_dict = config_data.model_dump() config_dict['company_code'] = company_code config = CompanyR2Config(**config_dict) db.add(config) db.commit() db.refresh(config) clear_cached_config(company_code) r2_config = R2Config({ 'r2_account_id': config.r2_account_id, 'r2_access_key_id': config.r2_access_key_id, 'r2_secret_access_key': config.r2_secret_access_key, 'r2_bucket_name': config.r2_bucket_name, 'r2_public_url': config.r2_public_url, 'r2_enabled': config.r2_enabled }) set_cached_config(company_code, r2_config) company = db.query(Company).filter( Company.company_code == config.company_code ).first() config_dict = { 'id': config.id, 'company_code': config.company_code, 'company_name': company.name if company else None, 'r2_account_id': config.r2_account_id, 'r2_access_key_id': config.r2_access_key_id, 'r2_secret_access_key': config.r2_secret_access_key, 'r2_bucket_name': config.r2_bucket_name, 'r2_public_url': config.r2_public_url, 'r2_enabled': config.r2_enabled, 'created_at': config.created_at, 'updated_at': config.updated_at } return config_dict @router.put("/config/{company_code}", response_model=CompanyR2ConfigResponse) async def update_r2_config_for_company( company_code: str, config_update: CompanyR2ConfigUpdate, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """更新指定公司的 R2 配置(仅超管)""" verify_superadmin(current_user) config = db.query(CompanyR2Config).filter( CompanyR2Config.company_code == company_code ).first() if config is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="R2 config not found" ) update_data = config_update.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(config, field, value) db.commit() db.refresh(config) clear_cached_config(company_code) r2_config = R2Config({ 'r2_account_id': config.r2_account_id, 'r2_access_key_id': config.r2_access_key_id, 'r2_secret_access_key': config.r2_secret_access_key, 'r2_bucket_name': config.r2_bucket_name, 'r2_public_url': config.r2_public_url, 'r2_enabled': config.r2_enabled }) set_cached_config(company_code, r2_config) company = db.query(Company).filter( Company.company_code == config.company_code ).first() config_dict = { 'id': config.id, 'company_code': config.company_code, 'company_name': company.name if company else None, 'r2_account_id': config.r2_account_id, 'r2_access_key_id': config.r2_access_key_id, 'r2_secret_access_key': config.r2_secret_access_key, 'r2_bucket_name': config.r2_bucket_name, 'r2_public_url': config.r2_public_url, 'r2_enabled': config.r2_enabled, 'created_at': config.created_at, 'updated_at': config.updated_at } return config_dict @router.delete("/config/{company_code}", status_code=status.HTTP_204_NO_CONTENT) async def delete_r2_config_for_company( company_code: str, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """删除指定公司的 R2 配置(仅超管)""" verify_superadmin(current_user) config = db.query(CompanyR2Config).filter( CompanyR2Config.company_code == company_code ).first() if config is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="R2 config not found" ) db.delete(config) db.commit() clear_cached_config(company_code) return None @router.get("/config", response_model=Optional[CompanyR2ConfigResponse]) async def get_company_r2_config( current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """获取当前公司的 R2 配置""" config = db.query(CompanyR2Config).filter( CompanyR2Config.company_code == current_user.company_code ).first() if config: r2_config = R2Config({ 'r2_account_id': config.r2_account_id, 'r2_access_key_id': config.r2_access_key_id, 'r2_secret_access_key': config.r2_secret_access_key, 'r2_bucket_name': config.r2_bucket_name, 'r2_public_url': config.r2_public_url, 'r2_enabled': config.r2_enabled }) set_cached_config(current_user.company_code, r2_config) return config @router.post("/config", response_model=CompanyR2ConfigResponse, status_code=status.HTTP_201_CREATED) async def create_company_r2_config( config_data: CompanyR2ConfigCreate, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """创建或更新当前公司的 R2 配置""" existing_config = db.query(CompanyR2Config).filter( CompanyR2Config.company_code == current_user.company_code ).first() if existing_config: update_data = config_data.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(existing_config, field, value) db.commit() db.refresh(existing_config) config = existing_config else: config_dict = config_data.model_dump() config_dict['company_code'] = current_user.company_code config = CompanyR2Config(**config_dict) db.add(config) db.commit() db.refresh(config) clear_cached_config(current_user.company_code) r2_config = R2Config({ 'r2_account_id': config.r2_account_id, 'r2_access_key_id': config.r2_access_key_id, 'r2_secret_access_key': config.r2_secret_access_key, 'r2_bucket_name': config.r2_bucket_name, 'r2_public_url': config.r2_public_url, 'r2_enabled': config.r2_enabled }) set_cached_config(current_user.company_code, r2_config) return config @router.put("/config", response_model=CompanyR2ConfigResponse) async def update_company_r2_config( config_update: CompanyR2ConfigUpdate, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """更新当前公司的 R2 配置""" config = db.query(CompanyR2Config).filter( CompanyR2Config.company_code == current_user.company_code ).first() if config is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="R2 config not found" ) update_data = config_update.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(config, field, value) db.commit() db.refresh(config) clear_cached_config(current_user.company_code) r2_config = R2Config({ 'r2_account_id': config.r2_account_id, 'r2_access_key_id': config.r2_access_key_id, 'r2_secret_access_key': config.r2_secret_access_key, 'r2_bucket_name': config.r2_bucket_name, 'r2_public_url': config.r2_public_url, 'r2_enabled': config.r2_enabled }) set_cached_config(current_user.company_code, r2_config) return config @router.delete("/config", status_code=status.HTTP_204_NO_CONTENT) async def delete_company_r2_config( current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """删除当前公司的 R2 配置""" config = db.query(CompanyR2Config).filter( CompanyR2Config.company_code == current_user.company_code ).first() if config is None: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="R2 config not found" ) db.delete(config) db.commit() clear_cached_config(current_user.company_code) return None @router.post("/config/clear-cache", status_code=status.HTTP_200_OK) async def clear_r2_config_cache( current_user: User = Depends(get_current_user) ): """清除当前公司的 R2 配置缓存""" clear_cached_config(current_user.company_code) return {"message": "Cache cleared successfully"}