# -*- coding: utf-8 -*- """ 租户管理蓝图 处理租户 CRUD 的 API 路由 """ import json import logging from flask import Blueprint, request, jsonify from src.core.database import db_manager from src.core.models import Tenant, DEFAULT_TENANT logger = logging.getLogger(__name__) tenants_bp = Blueprint('tenants', __name__, url_prefix='/api/tenants') def _ensure_default_tenant(): """确保 default 租户存在""" try: with db_manager.get_session() as session: existing = session.query(Tenant).filter(Tenant.tenant_id == DEFAULT_TENANT).first() if not existing: session.add(Tenant( tenant_id=DEFAULT_TENANT, name="默认租户", description="系统默认租户" )) session.commit() except Exception as e: logger.error(f"确保默认租户失败: {e}") @tenants_bp.route('', methods=['GET']) def list_tenants(): """获取所有租户列表""" try: with db_manager.get_session() as session: tenants = session.query(Tenant).order_by(Tenant.created_at).all() return jsonify([t.to_dict() for t in tenants]) except Exception as e: logger.error(f"获取租户列表失败: {e}") return jsonify({"error": str(e)}), 500 @tenants_bp.route('', methods=['POST']) def create_tenant(): """创建新租户""" try: data = request.get_json() if not data or not data.get('tenant_id') or not data.get('name'): return jsonify({"error": "tenant_id 和 name 为必填项"}), 400 tenant_id = data['tenant_id'].strip() name = data['name'].strip() if not tenant_id or not name: return jsonify({"error": "tenant_id 和 name 不能为空"}), 400 with db_manager.get_session() as session: existing = session.query(Tenant).filter(Tenant.tenant_id == tenant_id).first() if existing: return jsonify({"error": f"租户 '{tenant_id}' 已存在"}), 409 tenant = Tenant( tenant_id=tenant_id, name=name, description=data.get('description', ''), config=json.dumps(data.get('config', {})) ) session.add(tenant) session.commit() # 重新查询以获取完整数据 tenant = session.query(Tenant).filter(Tenant.tenant_id == tenant_id).first() return jsonify({"success": True, "tenant": tenant.to_dict()}), 201 except Exception as e: logger.error(f"创建租户失败: {e}") return jsonify({"error": str(e)}), 500 @tenants_bp.route('/', methods=['PUT']) def update_tenant(tenant_id): """更新租户信息(重命名等)""" try: data = request.get_json() if not data: return jsonify({"error": "请求体不能为空"}), 400 with db_manager.get_session() as session: tenant = session.query(Tenant).filter(Tenant.tenant_id == tenant_id).first() if not tenant: return jsonify({"error": f"租户 '{tenant_id}' 不存在"}), 404 if 'name' in data: tenant.name = data['name'].strip() if 'description' in data: tenant.description = data['description'] if 'config' in data: tenant.config = json.dumps(data['config']) if 'is_active' in data: tenant.is_active = data['is_active'] session.commit() tenant = session.query(Tenant).filter(Tenant.tenant_id == tenant_id).first() return jsonify({"success": True, "tenant": tenant.to_dict()}) except Exception as e: logger.error(f"更新租户失败: {e}") return jsonify({"error": str(e)}), 500 @tenants_bp.route('/', methods=['DELETE']) def delete_tenant(tenant_id): """删除租户(不允许删除 default)""" try: if tenant_id == DEFAULT_TENANT: return jsonify({"error": "不能删除默认租户"}), 403 with db_manager.get_session() as session: tenant = session.query(Tenant).filter(Tenant.tenant_id == tenant_id).first() if not tenant: return jsonify({"error": f"租户 '{tenant_id}' 不存在"}), 404 session.delete(tenant) session.commit() return jsonify({"success": True, "message": f"租户 '{tenant_id}' 已删除"}) except Exception as e: logger.error(f"删除租户失败: {e}") return jsonify({"error": str(e)}), 500