"""租户企业微信应用配置路由""" import json from fastapi import APIRouter, Depends, HTTPException, Query from pydantic import BaseModel from typing import Optional, List from sqlalchemy.orm import Session from ..database import get_db from ..models.tenant_wechat_app import TenantWechatApp from .auth import get_current_user, require_operator from ..models.user import User from ..services.crypto import encrypt_config, decrypt_config router = APIRouter(prefix="/tenant-wechat-apps", tags=["租户企微应用"]) # Schemas class TenantWechatAppCreate(BaseModel): tenant_id: str name: str corp_id: str agent_id: str secret: Optional[str] = None # 明文,存储时加密 class TenantWechatAppUpdate(BaseModel): name: Optional[str] = None corp_id: Optional[str] = None agent_id: Optional[str] = None secret: Optional[str] = None status: Optional[int] = None # API Endpoints @router.get("") async def list_tenant_wechat_apps( page: int = Query(1, ge=1), size: int = Query(20, ge=1, le=100), tenant_id: Optional[str] = None, user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """获取租户企微应用列表""" query = db.query(TenantWechatApp) if tenant_id: query = query.filter(TenantWechatApp.tenant_id == tenant_id) total = query.count() apps = query.order_by(TenantWechatApp.id.desc()).offset((page - 1) * size).limit(size).all() return { "total": total, "page": page, "size": size, "items": [format_wechat_app(app) for app in apps] } @router.get("/by-tenant/{tenant_id}") async def list_by_tenant( tenant_id: str, user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """获取指定租户的所有企微应用(用于下拉选择)""" apps = db.query(TenantWechatApp).filter( TenantWechatApp.tenant_id == tenant_id, TenantWechatApp.status == 1 ).order_by(TenantWechatApp.id.asc()).all() return [{"id": app.id, "name": app.name, "corp_id": app.corp_id, "agent_id": app.agent_id} for app in apps] @router.get("/{app_id}") async def get_tenant_wechat_app( app_id: int, user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """获取企微应用详情""" app = db.query(TenantWechatApp).filter(TenantWechatApp.id == app_id).first() if not app: raise HTTPException(status_code=404, detail="企微应用不存在") return format_wechat_app(app) @router.post("") async def create_tenant_wechat_app( data: TenantWechatAppCreate, user: User = Depends(require_operator), db: Session = Depends(get_db) ): """创建企微应用""" # 加密 secret secret_encrypted = None if data.secret: secret_encrypted = encrypt_config(data.secret) app = TenantWechatApp( tenant_id=data.tenant_id, name=data.name, corp_id=data.corp_id, agent_id=data.agent_id, secret_encrypted=secret_encrypted, status=1 ) db.add(app) db.commit() db.refresh(app) return {"success": True, "id": app.id} @router.put("/{app_id}") async def update_tenant_wechat_app( app_id: int, data: TenantWechatAppUpdate, user: User = Depends(require_operator), db: Session = Depends(get_db) ): """更新企微应用""" app = db.query(TenantWechatApp).filter(TenantWechatApp.id == app_id).first() if not app: raise HTTPException(status_code=404, detail="企微应用不存在") update_data = data.model_dump(exclude_unset=True) # 处理 secret 加密 if 'secret' in update_data: if update_data['secret']: app.secret_encrypted = encrypt_config(update_data['secret']) del update_data['secret'] for key, value in update_data.items(): setattr(app, key, value) db.commit() return {"success": True} @router.delete("/{app_id}") async def delete_tenant_wechat_app( app_id: int, user: User = Depends(require_operator), db: Session = Depends(get_db) ): """删除企微应用""" app = db.query(TenantWechatApp).filter(TenantWechatApp.id == app_id).first() if not app: raise HTTPException(status_code=404, detail="企微应用不存在") # 检查是否有租户应用在使用 from ..models.tenant_app import TenantApp usage_count = db.query(TenantApp).filter(TenantApp.wechat_app_id == app_id).count() if usage_count > 0: raise HTTPException(status_code=400, detail=f"有 {usage_count} 个应用配置正在使用此企微应用,无法删除") db.delete(app) db.commit() return {"success": True} @router.get("/{app_id}/secret") async def get_wechat_secret( app_id: int, user: User = Depends(require_operator), db: Session = Depends(get_db) ): """获取解密的 secret(仅操作员以上)""" app = db.query(TenantWechatApp).filter(TenantWechatApp.id == app_id).first() if not app: raise HTTPException(status_code=404, detail="企微应用不存在") secret = None if app.secret_encrypted: secret = decrypt_config(app.secret_encrypted) return {"secret": secret} def format_wechat_app(app: TenantWechatApp) -> dict: """格式化企微应用数据""" return { "id": app.id, "tenant_id": app.tenant_id, "name": app.name, "corp_id": app.corp_id, "agent_id": app.agent_id, "has_secret": bool(app.secret_encrypted), "status": app.status, "created_at": app.created_at, "updated_at": app.updated_at }