Files
wecom_it_smart_desk/backend/app/config.py
T
Simon 364e688382 chore(release): v0.5.0-beta 发版准备
主要改动:

backend 业务:
- feat(error-codes): 统一错误码表 E1011/E1012 拆码
  - E1011 AUTH_PASSWORD_WRONG: 本地密码错误
  - E1012 AUTH_FIRST_LOGIN_PASSWORD_REQUIRED: 首次登录请先设置密码
  - E1015 AUTH_OLD_PASSWORD_REQUIRED: 改密需要旧密码
  - E1016 AUTH_OLD_PASSWORD_WRONG: 旧密码错误
- fix(agents): P0 降级放行时,如坐席已注册但未设密码,正确 raise 1012
  (修复前会撞 1011 本地密码错误,与场景不符)
- feat(approval): 审批模块 (T审批/A审批)
- feat(config): approval_template_resource / approval_template_device 配置
- feat(main): /ready, /metrics, /version 端点(K8s 友好)

backend 测试:
- test(agents): 新增 test_agents.py — 3 个 Fix-4 降级登录测试
  - 错误密码拒绝
  - 缺密码拒绝
  - 正确密码通过
  pytest tests/test_agents.py → 3/3 通过
- test(conftest): 模块级 mock + slowapi 限流重置 + UTF-8 patch
  解决 Windows pytest GBK 读 .env 失败 + 降级路径无法测试

仓库治理:
- chore(gitignore): 排除 .workbuddy/memory/(workbuddy 本地记忆)
- chore(docs): 重命名两份 IT 文档(前缀加智能区分版本)

部署与文档:
- docs: RELEASE_NOTES_v0.5.0-beta.md / dashboard.html / 需求-发版预览页面
- docs: 部署、架构、PRD、安全、评审报告等同步 v0.5.0-beta
- deploy-server: 打包脚本、nginx、docker-compose 版本号 bump

前端 (frontend-h5 / frontend-agent / frontend-admin / frontend-portal):
- index.html / package.json 版本号与构建号 bump

自动验收(RELEASE_NOTES L100-104):
- [x] pytest tests/test_agents.py -v → 3 passed
- [x] grep Bs7ucT backend frontend-h5 frontend-agent → 无输出
- [x] grep AppException(101[123]) backend → 仅 1 处(登录场景 1012)
- [ ] npm run build (frontend-h5 / frontend-agent) → 合并后跑

后续: 合并 feature/t-1-t4-merge → main,tag v0.5.0-beta
2026-06-15 14:14:58 +08:00

155 lines
7.0 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.
# =============================================================================
# 企微IT智能服务台 — 配置管理模块
# =============================================================================
# 说明:使用 pydantic-settings 从环境变量读取所有配置项
# 优先级:环境变量 > .env 文件 > 默认值
# 所有配置项集中管理,避免散落在代码各处
# =============================================================================
from typing import List
import redis.asyncio as aioredis
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
"""应用配置类。
使用 pydantic-settings 自动从环境变量读取配置值。
支持 .env 文件自动加载(开发环境便利)。
Attributes:
wecom_corp_id: 企业微信企业ID
wecom_agent_id: 企业微信应用AgentId
wecom_secret: 企业微信应用Secret
wecom_token: 企业微信回调Token
wecom_encoding_aes_key: 企业微信回调EncodingAESKey43位)
database_url: PostgreSQL 数据库连接地址
redis_url: Redis 连接地址
backend_host: 后端监听地址
backend_port: 后端监听端口
cors_origins: CORS 允许的源地址(逗号分隔)
"""
# ----------------------------------------------------------------------
# 企微自建应用配置
# ----------------------------------------------------------------------
# 企业ID(在企微管理后台 > 我的企业 > 企业信息 中查看)
wecom_corp_id: str = "ww1234567890abcdef"
# 应用AgentId(在企微管理后台 > 应用管理 > 自建应用 中查看)
wecom_agent_id: str = "1000002"
# 应用Secret(在企微管理后台 > 应用管理 > 自建应用 中查看)
wecom_secret: str = "your-agent-secret"
# 回调Token(在企微管理后台 > 应用管理 > 接收消息 中设置)
wecom_token: str = "your-callback-token"
# 回调EncodingAESKey43位字符串,用于消息加解密)
wecom_encoding_aes_key: str = "your-aes-key-43-characters-long-encoding-key"
# ----------------------------------------------------------------------
# 数据库配置
# ----------------------------------------------------------------------
# PostgreSQL 连接地址
# Docker 环境使用容器名 postgres,本地开发使用 localhost
database_url: str = "postgresql://wecom:wecom_secret@localhost:5432/wecom_it_desk"
# ----------------------------------------------------------------------
# Redis 配置
# ----------------------------------------------------------------------
# Redis 连接地址
# Docker 环境使用容器名 redis,本地开发使用 localhost
redis_url: str = "redis://localhost:6379/0"
# ----------------------------------------------------------------------
# 服务配置
# ----------------------------------------------------------------------
# 后端监听地址(0.0.0.0 表示监听所有网卡)
backend_host: str = "0.0.0.0"
# 后端监听端口
backend_port: int = 8000
# CORS 允许的源地址(逗号分隔的字符串)
cors_origins: str = "http://localhost:5173,http://localhost:5174,http://localhost:5175"
# ----------------------------------------------------------------------
# AI 服务配置(Dify
# ----------------------------------------------------------------------
# Dify API 端点(兼容 OpenAI Chat Completions 格式)
# 必须通过环境变量 DIFY_API_URL 配置,不设置默认值(防止凭据泄露)
dify_api_url: str = ""
# Dify API Key(格式:base_url|app_id|app_name
# 必须通过环境变量 DIFY_API_KEY 配置,不设置默认值(防止凭据泄露)
dify_api_key: str = ""
# Dify API 请求超时(秒),在网络慢时可调大
dify_timeout: int = 30
# ----------------------------------------------------------------------
# AI Wingman 服务配置(Dify Agent 2 — 坐席端辅助)
# ----------------------------------------------------------------------
# 坐席端 Wingman 专用 Dify API 端点(与员工端 Agent 分开)
# 留空则禁用 Wingman 功能(不影响主流程)
dify_wingman_api_url: str = ""
# 坐席端 Wingman Dify API Key(需要新建 Agent 后填入,留空则禁用)
# 格式:base_url|app_id|app_name(与 dify_api_key 相同格式)
dify_wingman_api_key: str = ""
# Wingman API 请求超时(秒)
dify_wingman_timeout: int = 30
# ----------------------------------------------------------------------
# Mock 登录配置(测试阶段使用,跳过企微 OAuth2)
# ----------------------------------------------------------------------
# 是否启用 Mock 登录(默认 false,生产环境必须关闭)
mock_login_enabled: bool = False
# ----------------------------------------------------------------------
# 审批模板配置(企微审批应用)
# ----------------------------------------------------------------------
# 资源申请审批模板ID(在企微审批应用设置中获取)
approval_template_resource: str = ""
# 设备申请审批模板ID(在企微审批应用设置中获取)
approval_template_device: str = ""
# ----------------------------------------------------------------------
# Pydantic-settings 配置
# ----------------------------------------------------------------------
model_config = SettingsConfigDict(
# 自动从 .env 文件加载环境变量
env_file=".env",
# .env 文件编码
env_file_encoding="utf-8",
# 环境变量名大小写不敏感
case_sensitive=False,
# 额外字段不允许(防止拼写错误的配置被忽略)
extra="ignore",
)
@property
def cors_origins_list(self) -> List[str]:
"""将 CORS 源地址字符串解析为列表。
将逗号分隔的字符串(如 "http://a,http://b"
转换为列表(如 ["http://a", "http://b"]),
方便 FastAPI 的 CORSMiddleware 使用。
Returns:
List[str]: CORS 允许的源地址列表
"""
# 去除每项的前后空格,过滤空字符串
return [origin.strip() for origin in self.cors_origins.split(",") if origin.strip()]
def create_redis_client(self) -> aioredis.Redis:
"""创建 Redis 异步客户端实例。
自动附加 protocol=2 参数,强制使用 RESP2 协议。
原因:Windows 版 Redis 3.x 不支持 RESP3 协议(HELLO 命令),
而 redis-py 8.0+ 默认使用 RESP3,会导致连接失败。
全项目统一使用此方法创建 Redis 客户端,避免协议不匹配。
Returns:
aioredis.Redis: 配置好的 Redis 异步客户端
"""
return aioredis.from_url(self.redis_url, protocol=2)
# 创建全局配置实例
# 整个应用通过 from app.config import settings 使用同一个实例
settings = Settings()