fix: auto-fix code issues (cron)
- 修复重复导入/字段 - 修复异常处理 - 修复PEP8格式问题 - 添加类型注解 - 修复缺失的urllib.parse导入
This commit is contained in:
@@ -21,6 +21,7 @@ from typing import Any
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class SSOProvider(StrEnum):
|
||||
"""SSO 提供商类型"""
|
||||
|
||||
@@ -32,6 +33,7 @@ class SSOProvider(StrEnum):
|
||||
GOOGLE = "google" # Google Workspace
|
||||
CUSTOM_SAML = "custom_saml" # 自定义 SAML
|
||||
|
||||
|
||||
class SSOStatus(StrEnum):
|
||||
"""SSO 配置状态"""
|
||||
|
||||
@@ -40,6 +42,7 @@ class SSOStatus(StrEnum):
|
||||
ACTIVE = "active" # 已启用
|
||||
ERROR = "error" # 配置错误
|
||||
|
||||
|
||||
class SCIMSyncStatus(StrEnum):
|
||||
"""SCIM 同步状态"""
|
||||
|
||||
@@ -48,6 +51,7 @@ class SCIMSyncStatus(StrEnum):
|
||||
SUCCESS = "success" # 同步成功
|
||||
FAILED = "failed" # 同步失败
|
||||
|
||||
|
||||
class AuditLogExportFormat(StrEnum):
|
||||
"""审计日志导出格式"""
|
||||
|
||||
@@ -56,6 +60,7 @@ class AuditLogExportFormat(StrEnum):
|
||||
PDF = "pdf"
|
||||
XLSX = "xlsx"
|
||||
|
||||
|
||||
class DataRetentionAction(StrEnum):
|
||||
"""数据保留策略动作"""
|
||||
|
||||
@@ -63,6 +68,7 @@ class DataRetentionAction(StrEnum):
|
||||
DELETE = "delete" # 删除
|
||||
ANONYMIZE = "anonymize" # 匿名化
|
||||
|
||||
|
||||
class ComplianceStandard(StrEnum):
|
||||
"""合规标准"""
|
||||
|
||||
@@ -72,6 +78,7 @@ class ComplianceStandard(StrEnum):
|
||||
HIPAA = "hipaa"
|
||||
PCI_DSS = "pci_dss"
|
||||
|
||||
|
||||
@dataclass
|
||||
class SSOConfig:
|
||||
"""SSO 配置数据类"""
|
||||
@@ -104,6 +111,7 @@ class SSOConfig:
|
||||
last_tested_at: datetime | None
|
||||
last_error: str | None
|
||||
|
||||
|
||||
@dataclass
|
||||
class SCIMConfig:
|
||||
"""SCIM 配置数据类"""
|
||||
@@ -128,6 +136,7 @@ class SCIMConfig:
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
@dataclass
|
||||
class SCIMUser:
|
||||
"""SCIM 用户数据类"""
|
||||
@@ -147,6 +156,7 @@ class SCIMUser:
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
@dataclass
|
||||
class AuditLogExport:
|
||||
"""审计日志导出记录"""
|
||||
@@ -171,6 +181,7 @@ class AuditLogExport:
|
||||
completed_at: datetime | None
|
||||
error_message: str | None
|
||||
|
||||
|
||||
@dataclass
|
||||
class DataRetentionPolicy:
|
||||
"""数据保留策略"""
|
||||
@@ -198,6 +209,7 @@ class DataRetentionPolicy:
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
|
||||
@dataclass
|
||||
class DataRetentionJob:
|
||||
"""数据保留任务"""
|
||||
@@ -215,6 +227,7 @@ class DataRetentionJob:
|
||||
details: dict[str, Any]
|
||||
created_at: datetime
|
||||
|
||||
|
||||
@dataclass
|
||||
class SAMLAuthRequest:
|
||||
"""SAML 认证请求"""
|
||||
@@ -229,6 +242,7 @@ class SAMLAuthRequest:
|
||||
used: bool
|
||||
used_at: datetime | None
|
||||
|
||||
|
||||
@dataclass
|
||||
class SAMLAuthResponse:
|
||||
"""SAML 认证响应"""
|
||||
@@ -245,13 +259,24 @@ class SAMLAuthResponse:
|
||||
processed_at: datetime | None
|
||||
created_at: datetime
|
||||
|
||||
|
||||
class EnterpriseManager:
|
||||
"""企业级功能管理器"""
|
||||
|
||||
# 默认属性映射
|
||||
DEFAULT_ATTRIBUTE_MAPPING = {
|
||||
SSOProvider.WECHAT_WORK: {"email": "email", "name": "name", "department": "department", "position": "position"},
|
||||
SSOProvider.DINGTALK: {"email": "email", "name": "name", "department": "department", "job_title": "title"},
|
||||
SSOProvider.WECHAT_WORK: {
|
||||
"email": "email",
|
||||
"name": "name",
|
||||
"department": "department",
|
||||
"position": "position",
|
||||
},
|
||||
SSOProvider.DINGTALK: {
|
||||
"email": "email",
|
||||
"name": "name",
|
||||
"department": "department",
|
||||
"job_title": "title",
|
||||
},
|
||||
SSOProvider.FEISHU: {
|
||||
"email": "email",
|
||||
"name": "name",
|
||||
@@ -505,18 +530,42 @@ class EnterpriseManager:
|
||||
# 创建索引
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_sso_tenant ON sso_configs(tenant_id)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_sso_provider ON sso_configs(provider)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_saml_requests_config ON saml_auth_requests(sso_config_id)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_saml_requests_expires ON saml_auth_requests(expires_at)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_saml_responses_request ON saml_auth_responses(request_id)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_scim_config_tenant ON scim_configs(tenant_id)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_scim_users_tenant ON scim_users(tenant_id)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_scim_users_external ON scim_users(external_id)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_audit_export_tenant ON audit_log_exports(tenant_id)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_audit_export_status ON audit_log_exports(status)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_retention_tenant ON data_retention_policies(tenant_id)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_retention_type ON data_retention_policies(resource_type)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_retention_jobs_policy ON data_retention_jobs(policy_id)")
|
||||
cursor.execute("CREATE INDEX IF NOT EXISTS idx_retention_jobs_status ON data_retention_jobs(status)")
|
||||
cursor.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_saml_requests_config ON saml_auth_requests(sso_config_id)"
|
||||
)
|
||||
cursor.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_saml_requests_expires ON saml_auth_requests(expires_at)"
|
||||
)
|
||||
cursor.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_saml_responses_request ON saml_auth_responses(request_id)"
|
||||
)
|
||||
cursor.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_scim_config_tenant ON scim_configs(tenant_id)"
|
||||
)
|
||||
cursor.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_scim_users_tenant ON scim_users(tenant_id)"
|
||||
)
|
||||
cursor.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_scim_users_external ON scim_users(external_id)"
|
||||
)
|
||||
cursor.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_audit_export_tenant ON audit_log_exports(tenant_id)"
|
||||
)
|
||||
cursor.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_audit_export_status ON audit_log_exports(status)"
|
||||
)
|
||||
cursor.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_retention_tenant ON data_retention_policies(tenant_id)"
|
||||
)
|
||||
cursor.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_retention_type ON data_retention_policies(resource_type)"
|
||||
)
|
||||
cursor.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_retention_jobs_policy ON data_retention_jobs(policy_id)"
|
||||
)
|
||||
cursor.execute(
|
||||
"CREATE INDEX IF NOT EXISTS idx_retention_jobs_status ON data_retention_jobs(status)"
|
||||
)
|
||||
|
||||
conn.commit()
|
||||
logger.info("Enterprise tables initialized successfully")
|
||||
@@ -649,7 +698,9 @@ class EnterpriseManager:
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def get_tenant_sso_config(self, tenant_id: str, provider: str | None = None) -> SSOConfig | None:
|
||||
def get_tenant_sso_config(
|
||||
self, tenant_id: str, provider: str | None = None
|
||||
) -> SSOConfig | None:
|
||||
"""获取租户的 SSO 配置"""
|
||||
conn = self._get_connection()
|
||||
try:
|
||||
@@ -734,7 +785,7 @@ class EnterpriseManager:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
f"""
|
||||
UPDATE sso_configs SET {', '.join(updates)}
|
||||
UPDATE sso_configs SET {", ".join(updates)}
|
||||
WHERE id = ?
|
||||
""",
|
||||
params,
|
||||
@@ -943,7 +994,11 @@ class EnterpriseManager:
|
||||
"""解析 SAML 响应(简化实现)"""
|
||||
# 实际应该使用 python-saml 库解析
|
||||
# 这里返回模拟数据
|
||||
return {"email": "user@example.com", "name": "Test User", "session_index": f"_{uuid.uuid4().hex}"}
|
||||
return {
|
||||
"email": "user@example.com",
|
||||
"name": "Test User",
|
||||
"session_index": f"_{uuid.uuid4().hex}",
|
||||
}
|
||||
|
||||
def _generate_self_signed_cert(self) -> str:
|
||||
"""生成自签名证书(简化实现)"""
|
||||
@@ -1094,7 +1149,7 @@ class EnterpriseManager:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
f"""
|
||||
UPDATE scim_configs SET {', '.join(updates)}
|
||||
UPDATE scim_configs SET {", ".join(updates)}
|
||||
WHERE id = ?
|
||||
""",
|
||||
params,
|
||||
@@ -1175,7 +1230,9 @@ class EnterpriseManager:
|
||||
# GET {scim_base_url}/Users
|
||||
return []
|
||||
|
||||
def _upsert_scim_user(self, conn: sqlite3.Connection, tenant_id: str, user_data: dict[str, Any]) -> None:
|
||||
def _upsert_scim_user(
|
||||
self, conn: sqlite3.Connection, tenant_id: str, user_data: dict[str, Any]
|
||||
) -> None:
|
||||
"""插入或更新 SCIM 用户"""
|
||||
cursor = conn.cursor()
|
||||
|
||||
@@ -1352,7 +1409,9 @@ class EnterpriseManager:
|
||||
logs = self._apply_compliance_filter(logs, export.compliance_standard)
|
||||
|
||||
# 生成导出文件
|
||||
file_path, file_size, checksum = self._generate_export_file(export_id, logs, export.export_format)
|
||||
file_path, file_size, checksum = self._generate_export_file(
|
||||
export_id, logs, export.export_format
|
||||
)
|
||||
|
||||
now = datetime.now()
|
||||
|
||||
@@ -1386,7 +1445,12 @@ class EnterpriseManager:
|
||||
conn.close()
|
||||
|
||||
def _fetch_audit_logs(
|
||||
self, tenant_id: str, start_date: datetime, end_date: datetime, filters: dict[str, Any], db_manager=None
|
||||
self,
|
||||
tenant_id: str,
|
||||
start_date: datetime,
|
||||
end_date: datetime,
|
||||
filters: dict[str, Any],
|
||||
db_manager=None,
|
||||
) -> list[dict[str, Any]]:
|
||||
"""获取审计日志数据"""
|
||||
if db_manager is None:
|
||||
@@ -1396,7 +1460,9 @@ class EnterpriseManager:
|
||||
# 这里简化实现
|
||||
return []
|
||||
|
||||
def _apply_compliance_filter(self, logs: list[dict[str, Any]], standard: str) -> list[dict[str, Any]]:
|
||||
def _apply_compliance_filter(
|
||||
self, logs: list[dict[str, Any]], standard: str
|
||||
) -> list[dict[str, Any]]:
|
||||
"""应用合规标准字段过滤"""
|
||||
fields = self.COMPLIANCE_FIELDS.get(ComplianceStandard(standard), [])
|
||||
|
||||
@@ -1410,7 +1476,9 @@ class EnterpriseManager:
|
||||
|
||||
return filtered_logs
|
||||
|
||||
def _generate_export_file(self, export_id: str, logs: list[dict[str, Any]], format: str) -> tuple[str, int, str]:
|
||||
def _generate_export_file(
|
||||
self, export_id: str, logs: list[dict[str, Any]], format: str
|
||||
) -> tuple[str, int, str]:
|
||||
"""生成导出文件"""
|
||||
import hashlib
|
||||
import os
|
||||
@@ -1599,7 +1667,9 @@ class EnterpriseManager:
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
def list_retention_policies(self, tenant_id: str, resource_type: str | None = None) -> list[DataRetentionPolicy]:
|
||||
def list_retention_policies(
|
||||
self, tenant_id: str, resource_type: str | None = None
|
||||
) -> list[DataRetentionPolicy]:
|
||||
"""列出数据保留策略"""
|
||||
conn = self._get_connection()
|
||||
try:
|
||||
@@ -1667,7 +1737,7 @@ class EnterpriseManager:
|
||||
cursor = conn.cursor()
|
||||
cursor.execute(
|
||||
f"""
|
||||
UPDATE data_retention_policies SET {', '.join(updates)}
|
||||
UPDATE data_retention_policies SET {", ".join(updates)}
|
||||
WHERE id = ?
|
||||
""",
|
||||
params,
|
||||
@@ -1910,10 +1980,14 @@ class EnterpriseManager:
|
||||
default_role=row["default_role"],
|
||||
domain_restriction=json.loads(row["domain_restriction"] or "[]"),
|
||||
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"]
|
||||
),
|
||||
last_tested_at=(
|
||||
datetime.fromisoformat(row["last_tested_at"])
|
||||
@@ -1932,10 +2006,14 @@ class EnterpriseManager:
|
||||
request_id=row["request_id"],
|
||||
relay_state=row["relay_state"],
|
||||
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"]
|
||||
),
|
||||
expires_at=(
|
||||
datetime.fromisoformat(row["expires_at"]) if isinstance(row["expires_at"], str) else row["expires_at"]
|
||||
datetime.fromisoformat(row["expires_at"])
|
||||
if isinstance(row["expires_at"], str)
|
||||
else row["expires_at"]
|
||||
),
|
||||
used=bool(row["used"]),
|
||||
used_at=(
|
||||
@@ -1966,10 +2044,14 @@ class EnterpriseManager:
|
||||
attribute_mapping=json.loads(row["attribute_mapping"] or "{}"),
|
||||
sync_rules=json.loads(row["sync_rules"] or "{}"),
|
||||
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"]
|
||||
),
|
||||
)
|
||||
|
||||
@@ -1988,13 +2070,19 @@ class EnterpriseManager:
|
||||
groups=json.loads(row["groups"] or "[]"),
|
||||
raw_data=json.loads(row["raw_data"] or "{}"),
|
||||
synced_at=(
|
||||
datetime.fromisoformat(row["synced_at"]) if isinstance(row["synced_at"], str) else row["synced_at"]
|
||||
datetime.fromisoformat(row["synced_at"])
|
||||
if isinstance(row["synced_at"], str)
|
||||
else row["synced_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"]
|
||||
),
|
||||
)
|
||||
|
||||
@@ -2005,9 +2093,13 @@ class EnterpriseManager:
|
||||
tenant_id=row["tenant_id"],
|
||||
export_format=row["export_format"],
|
||||
start_date=(
|
||||
datetime.fromisoformat(row["start_date"]) if isinstance(row["start_date"], str) else row["start_date"]
|
||||
datetime.fromisoformat(row["start_date"])
|
||||
if isinstance(row["start_date"], str)
|
||||
else row["start_date"]
|
||||
),
|
||||
end_date=datetime.fromisoformat(row["end_date"]) if isinstance(row["end_date"], str) else row["end_date"],
|
||||
end_date=datetime.fromisoformat(row["end_date"])
|
||||
if isinstance(row["end_date"], str)
|
||||
else row["end_date"],
|
||||
filters=json.loads(row["filters"] or "{}"),
|
||||
compliance_standard=row["compliance_standard"],
|
||||
status=row["status"],
|
||||
@@ -2022,11 +2114,15 @@ class EnterpriseManager:
|
||||
else row["downloaded_at"]
|
||||
),
|
||||
expires_at=(
|
||||
datetime.fromisoformat(row["expires_at"]) if isinstance(row["expires_at"], str) else row["expires_at"]
|
||||
datetime.fromisoformat(row["expires_at"])
|
||||
if isinstance(row["expires_at"], str)
|
||||
else row["expires_at"]
|
||||
),
|
||||
created_by=row["created_by"],
|
||||
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"]
|
||||
),
|
||||
completed_at=(
|
||||
datetime.fromisoformat(row["completed_at"])
|
||||
@@ -2060,10 +2156,14 @@ class EnterpriseManager:
|
||||
),
|
||||
last_execution_result=row["last_execution_result"],
|
||||
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"]
|
||||
),
|
||||
)
|
||||
|
||||
@@ -2090,13 +2190,17 @@ class EnterpriseManager:
|
||||
error_count=row["error_count"],
|
||||
details=json.loads(row["details"] or "{}"),
|
||||
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"]
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
# 全局实例
|
||||
_enterprise_manager = None
|
||||
|
||||
|
||||
def get_enterprise_manager(db_path: str = "insightflow.db") -> EnterpriseManager:
|
||||
"""获取 EnterpriseManager 单例"""
|
||||
global _enterprise_manager
|
||||
|
||||
Reference in New Issue
Block a user