feat: 添加飞书用户模块和订阅功能支持

- 新增feishu_users模块用于处理飞书用户身份验证和权限管理
- 新增subscriptions模块用于处理订阅相关功能
- 新增personalization模块用于个性化服务
- 在alembic迁移配置中注册新的模型模块
- 在API路由器中添加feishu_users和subscriptions路由
- 实现事件调度服务的改进,包括错误处理和状态更新优化
- 添加飞书命令处理的权限检查机制
- 实现飞书应用票据事件处理
- 改进审计日志记录功能
```
This commit is contained in:
2026-07-27 08:02:17 +08:00
parent db751f03b4
commit d7db84571d
148 changed files with 17110 additions and 765 deletions

60
tests/conftest.py Normal file
View File

@@ -0,0 +1,60 @@
import os
import sys
import tempfile
from pathlib import Path
_database_file = tempfile.NamedTemporaryFile(
prefix="company-ai-platform-tests-",
suffix=".db",
delete=False,
)
_database_file.close()
_database_path = Path(_database_file.name)
# This module is loaded before test modules are imported. Keep every suite run isolated
# from a developer's local .env, database, queues, and external AI/Feishu credentials.
os.environ.update(
{
"COMPANY_AI_DISABLE_DOTENV": "true",
"APP_ENV": "test",
"DATABASE_URL": f"sqlite:///{_database_path.as_posix()}",
"LEGACY_DATABASE_URL": "",
"LEGACY_ALLOWED_QUERIES": "{}",
"LEGACY_PROJECT_QUERY": "",
"LEGACY_TASK_QUERY": "",
"API_KEY": "test-key",
"API_KEYS": "[]",
"AUDIT_API_KEY": "audit-key",
"AUDIT_API_KEYS": "[]",
"AUDIT_API_ACTOR": "audit-manager",
"MODEL_PROVIDER": "noop",
"DIRECT_LLM_API_KEY": "",
"HERMES_API_KEY": "",
"OPENCLAW_API_KEY": "",
"OPENCLAW_GATEWAY_TOKEN": "",
"FEISHU_APP_ID": "",
"FEISHU_APP_SECRET": "",
"FEISHU_ENCRYPT_KEY": "",
"FEISHU_DEFAULT_CHAT_ID": "",
"FEISHU_VERIFICATION_TOKEN": "test-feishu-token",
"FEISHU_ADMIN_IDENTITIES": "",
"FEISHU_USER_FEATURES_ENABLED": "false",
"MARKET_DATA_TOKEN": "",
"SCHEDULER_ENABLED": "false",
"TASK_QUEUE_ENABLED": "false",
"TASK_QUEUE_ALWAYS_EAGER": "false",
"LEGACY_SYNC_ENABLED": "false",
}
)
def pytest_sessionfinish() -> None:
"""Remove the suite database after every test module has finished."""
database_module = sys.modules.get("app.core.database.session")
if database_module is not None:
database_module.engine.dispose()
if database_module.legacy_engine is not None:
database_module.legacy_engine.dispose()
_database_path.unlink(missing_ok=True)