fix: auto-fix code issues (cron)

- 修复重复导入/字段
- 修复异常处理
- 修复PEP8格式问题
- 添加类型注解
- 修复缺失的urllib.parse导入
This commit is contained in:
OpenClaw Bot
2026-02-28 06:03:09 +08:00
parent ff83cab6c7
commit fe3d64a1d2
41 changed files with 4501 additions and 1176 deletions

View File

@@ -23,6 +23,7 @@ from typing import Any
logger = logging.getLogger(__name__)
class TenantLimits:
"""租户资源限制常量"""
@@ -42,6 +43,7 @@ class TenantLimits:
UNLIMITED = -1
class TenantStatus(StrEnum):
"""租户状态"""
@@ -51,6 +53,7 @@ class TenantStatus(StrEnum):
EXPIRED = "expired" # 过期
PENDING = "pending" # 待激活
class TenantTier(StrEnum):
"""租户订阅层级"""
@@ -58,6 +61,7 @@ class TenantTier(StrEnum):
PRO = "pro" # 专业版
ENTERPRISE = "enterprise" # 企业版
class TenantRole(StrEnum):
"""租户角色"""
@@ -66,6 +70,7 @@ class TenantRole(StrEnum):
MEMBER = "member" # 成员
VIEWER = "viewer" # 查看者
class DomainStatus(StrEnum):
"""域名状态"""
@@ -74,6 +79,7 @@ class DomainStatus(StrEnum):
FAILED = "failed" # 验证失败
EXPIRED = "expired" # 已过期
@dataclass
class Tenant:
"""租户数据类"""
@@ -92,6 +98,7 @@ class Tenant:
resource_limits: dict[str, Any] # 资源限制
metadata: dict[str, Any] # 元数据
@dataclass
class TenantDomain:
"""租户域名数据类"""
@@ -109,6 +116,7 @@ class TenantDomain:
ssl_enabled: bool # SSL 是否启用
ssl_expires_at: datetime | None
@dataclass
class TenantBranding:
"""租户品牌配置数据类"""
@@ -126,6 +134,7 @@ class TenantBranding:
created_at: datetime
updated_at: datetime
@dataclass
class TenantMember:
"""租户成员数据类"""
@@ -142,6 +151,7 @@ class TenantMember:
last_active_at: datetime | None
status: str # active/pending/suspended
@dataclass
class TenantPermission:
"""租户权限定义数据类"""
@@ -156,6 +166,7 @@ class TenantPermission:
conditions: dict | None # 条件限制
created_at: datetime
class TenantManager:
"""租户管理器 - 多租户 SaaS 架构核心"""
@@ -199,8 +210,24 @@ class TenantManager:
# 角色权限映射
ROLE_PERMISSIONS = {
TenantRole.OWNER: ["tenant:*", "project:*", "member:*", "billing:*", "settings:*", "api:*", "export:*"],
TenantRole.ADMIN: ["tenant:read", "project:*", "member:*", "billing:read", "settings:*", "api:*", "export:*"],
TenantRole.OWNER: [
"tenant:*",
"project:*",
"member:*",
"billing:*",
"settings:*",
"api:*",
"export:*",
],
TenantRole.ADMIN: [
"tenant:read",
"project:*",
"member:*",
"billing:read",
"settings:*",
"api:*",
"export:*",
],
TenantRole.MEMBER: [
"tenant:read",
"project:create",
@@ -360,10 +387,18 @@ class TenantManager:
cursor.execute("CREATE INDEX IF NOT EXISTS idx_tenants_slug ON tenants(slug)")
cursor.execute("CREATE INDEX IF NOT EXISTS idx_tenants_owner ON tenants(owner_id)")
cursor.execute("CREATE INDEX IF NOT EXISTS idx_tenants_status ON tenants(status)")
cursor.execute("CREATE INDEX IF NOT EXISTS idx_domains_tenant ON tenant_domains(tenant_id)")
cursor.execute("CREATE INDEX IF NOT EXISTS idx_domains_domain ON tenant_domains(domain)")
cursor.execute("CREATE INDEX IF NOT EXISTS idx_domains_status ON tenant_domains(status)")
cursor.execute("CREATE INDEX IF NOT EXISTS idx_members_tenant ON tenant_members(tenant_id)")
cursor.execute(
"CREATE INDEX IF NOT EXISTS idx_domains_tenant ON tenant_domains(tenant_id)"
)
cursor.execute(
"CREATE INDEX IF NOT EXISTS idx_domains_domain ON tenant_domains(domain)"
)
cursor.execute(
"CREATE INDEX IF NOT EXISTS idx_domains_status ON tenant_domains(status)"
)
cursor.execute(
"CREATE INDEX IF NOT EXISTS idx_members_tenant ON tenant_members(tenant_id)"
)
cursor.execute("CREATE INDEX IF NOT EXISTS idx_members_user ON tenant_members(user_id)")
cursor.execute("CREATE INDEX IF NOT EXISTS idx_usage_tenant ON tenant_usage(tenant_id)")
cursor.execute("CREATE INDEX IF NOT EXISTS idx_usage_date ON tenant_usage(date)")
@@ -380,7 +415,12 @@ class TenantManager:
# ==================== 租户管理 ====================
def create_tenant(
self, name: str, owner_id: str, tier: str = "free", description: str | None = None, settings: dict | None = None
self,
name: str,
owner_id: str,
tier: str = "free",
description: str | None = None,
settings: dict | None = None,
) -> Tenant:
"""创建新租户"""
conn = self._get_connection()
@@ -389,8 +429,12 @@ class TenantManager:
slug = self._generate_slug(name)
# 获取对应层级的资源限制
tier_enum = TenantTier(tier) if tier in [t.value for t in TenantTier] else TenantTier.FREE
resource_limits = self.DEFAULT_LIMITS.get(tier_enum, self.DEFAULT_LIMITS[TenantTier.FREE])
tier_enum = (
TenantTier(tier) if tier in [t.value for t in TenantTier] else TenantTier.FREE
)
resource_limits = self.DEFAULT_LIMITS.get(
tier_enum, self.DEFAULT_LIMITS[TenantTier.FREE]
)
tenant = Tenant(
id=tenant_id,
@@ -544,7 +588,7 @@ class TenantManager:
cursor = conn.cursor()
cursor.execute(
f"""
UPDATE tenants SET {', '.join(updates)}
UPDATE tenants SET {", ".join(updates)}
WHERE id = ?
""",
params,
@@ -599,7 +643,11 @@ class TenantManager:
# ==================== 域名管理 ====================
def add_domain(
self, tenant_id: str, domain: str, is_primary: bool = False, verification_method: str = "dns"
self,
tenant_id: str,
domain: str,
is_primary: bool = False,
verification_method: str = "dns",
) -> TenantDomain:
"""为租户添加自定义域名"""
conn = self._get_connection()
@@ -752,7 +800,10 @@ class TenantManager:
"value": f"insightflow-verify={token}",
"ttl": 3600,
},
"file_verification": {"url": f"http://{domain}/.well-known/insightflow-verify.txt", "content": token},
"file_verification": {
"url": f"http://{domain}/.well-known/insightflow-verify.txt",
"content": token,
},
"instructions": [
f"DNS 验证: 添加 TXT 记录 _insightflow.{domain},值为 insightflow-verify={token}",
f"文件验证: 在网站根目录创建 .well-known/insightflow-verify.txt内容为 {token}",
@@ -873,7 +924,7 @@ class TenantManager:
cursor.execute(
f"""
UPDATE tenant_branding SET {', '.join(updates)}
UPDATE tenant_branding SET {", ".join(updates)}
WHERE tenant_id = ?
""",
params,
@@ -951,7 +1002,12 @@ class TenantManager:
# ==================== 成员与权限管理 ====================
def invite_member(
self, tenant_id: str, email: str, role: str, invited_by: str, permissions: list[str] | None = None
self,
tenant_id: str,
email: str,
role: str,
invited_by: str,
permissions: list[str] | None = None,
) -> TenantMember:
"""邀请成员加入租户"""
conn = self._get_connection()
@@ -959,7 +1015,9 @@ class TenantManager:
member_id = str(uuid.uuid4())
# 使用角色默认权限
role_enum = TenantRole(role) if role in [r.value for r in TenantRole] else TenantRole.MEMBER
role_enum = (
TenantRole(role) if role in [r.value for r in TenantRole] else TenantRole.MEMBER
)
default_permissions = self.ROLE_PERMISSIONS.get(role_enum, [])
final_permissions = permissions or default_permissions
@@ -1146,7 +1204,13 @@ class TenantManager:
result = []
for row in rows:
tenant = self._row_to_tenant(row)
result.append({**asdict(tenant), "member_role": row["role"], "member_status": row["member_status"]})
result.append(
{
**asdict(tenant),
"member_role": row["role"],
"member_status": row["member_status"],
}
)
return result
finally:
@@ -1253,14 +1317,21 @@ class TenantManager:
row["total_storage"] or 0, limits.get("max_storage_mb", 0) * 1024 * 1024
),
"transcription": self._calc_percentage(
row["total_transcription"] or 0, limits.get("max_transcription_minutes", 0) * 60
row["total_transcription"] or 0,
limits.get("max_transcription_minutes", 0) * 60,
),
"api_calls": self._calc_percentage(
row["total_api_calls"] or 0, limits.get("max_api_calls_per_day", 0)
),
"projects": self._calc_percentage(row["max_projects"] or 0, limits.get("max_projects", 0)),
"entities": self._calc_percentage(row["max_entities"] or 0, limits.get("max_entities", 0)),
"members": self._calc_percentage(row["max_members"] or 0, limits.get("max_team_members", 0)),
"projects": self._calc_percentage(
row["max_projects"] or 0, limits.get("max_projects", 0)
),
"entities": self._calc_percentage(
row["max_entities"] or 0, limits.get("max_entities", 0)
),
"members": self._calc_percentage(
row["max_members"] or 0, limits.get("max_team_members", 0)
),
},
}
@@ -1434,10 +1505,14 @@ class TenantManager:
status=row["status"],
owner_id=row["owner_id"],
created_at=(
datetime.fromisoformat(row["created_at"]) if isinstance(row["created_at"], str) else row["created_at"]
datetime.fromisoformat(row["created_at"])
if isinstance(row["created_at"], str)
else row["created_at"]
),
updated_at=(
datetime.fromisoformat(row["updated_at"]) if isinstance(row["updated_at"], str) else row["updated_at"]
datetime.fromisoformat(row["updated_at"])
if isinstance(row["updated_at"], str)
else row["updated_at"]
),
expires_at=(
datetime.fromisoformat(row["expires_at"])
@@ -1464,10 +1539,14 @@ class TenantManager:
else row["verified_at"]
),
created_at=(
datetime.fromisoformat(row["created_at"]) if isinstance(row["created_at"], str) else row["created_at"]
datetime.fromisoformat(row["created_at"])
if isinstance(row["created_at"], str)
else row["created_at"]
),
updated_at=(
datetime.fromisoformat(row["updated_at"]) if isinstance(row["updated_at"], str) else row["updated_at"]
datetime.fromisoformat(row["updated_at"])
if isinstance(row["updated_at"], str)
else row["updated_at"]
),
is_primary=bool(row["is_primary"]),
ssl_enabled=bool(row["ssl_enabled"]),
@@ -1492,10 +1571,14 @@ class TenantManager:
login_page_bg=row["login_page_bg"],
email_template=row["email_template"],
created_at=(
datetime.fromisoformat(row["created_at"]) if isinstance(row["created_at"], str) else row["created_at"]
datetime.fromisoformat(row["created_at"])
if isinstance(row["created_at"], str)
else row["created_at"]
),
updated_at=(
datetime.fromisoformat(row["updated_at"]) if isinstance(row["updated_at"], str) else row["updated_at"]
datetime.fromisoformat(row["updated_at"])
if isinstance(row["updated_at"], str)
else row["updated_at"]
),
)
@@ -1510,7 +1593,9 @@ class TenantManager:
permissions=json.loads(row["permissions"] or "[]"),
invited_by=row["invited_by"],
invited_at=(
datetime.fromisoformat(row["invited_at"]) if isinstance(row["invited_at"], str) else row["invited_at"]
datetime.fromisoformat(row["invited_at"])
if isinstance(row["invited_at"], str)
else row["invited_at"]
),
joined_at=(
datetime.fromisoformat(row["joined_at"])
@@ -1525,8 +1610,10 @@ class TenantManager:
status=row["status"],
)
# ==================== 租户上下文管理 ====================
class TenantContext:
"""租户上下文管理器 - 用于请求级别的租户隔离"""
@@ -1559,9 +1646,11 @@ class TenantContext:
cls._current_tenant_id = None
cls._current_user_id = None
# 全局租户管理器实例
tenant_manager = None
def get_tenant_manager(db_path: str = "insightflow.db") -> TenantManager:
"""获取租户管理器实例(单例模式)"""
global tenant_manager