Files
000-platform/backend/app/routers/tenant_wechat_apps.py
Admin 90d10537c2
All checks were successful
continuous-integration/drone/push Build is passing
fix: 增加列表接口 size 参数限制到 1000
修复下拉列表请求 size=1000 导致 422 验证错误的问题
2026-01-24 18:01:09 +08:00

199 lines
5.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""租户企业微信应用配置路由"""
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=1000),
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
}