Files
wecom-ai-assistant/docs/stage2.md
2026-02-05 16:36:32 +08:00

7.4 KiB
Raw Permalink Blame History

阶段 2SQLAlchemy + Alembic + 用户登录体系

1. 数据库与迁移

  • 连接backend 通过环境变量 DATABASE_URL(异步 postgresql+asyncpg://...)连接 PostgreSQLAlembic 使用 DATABASE_URL_SYNC(同步 postgresql://...)。
  • 表结构
    • usersid (uuid)、username、password_hash、role、is_active、created_at
    • audit_logsid (uuid)、actor_user_id (FK users)、action、meta_json (JSONB)、created_at

迁移流程说明

Alembic 会按版本顺序执行 alembic/versions/ 下的迁移脚本,在数据库中创建或修改表,并在库中记录当前版本(表 alembic_version)。
执行时:

  1. 读取 backend/alembic.inibackend/alembic/env.py
  2. env.pyapp.config.settings 读取 database_url_sync(即环境变量 DATABASE_URL_SYNC),用该同步连接串连接 PostgreSQL。
  3. 对比数据库中的 alembic_version 与本地迁移文件,将尚未执行的迁移按顺序执行(例如 001_users_and_audit_logs.py 会创建 usersaudit_logs 表)。

方式 ADocker 启动时自动迁移

步骤:

  1. 在项目根目录执行:
    docker compose up -d
    
  2. Compose 会先启动 db,等待健康检查通过后再启动 backend
  3. backend 容器的启动命令为:
    sh -c "alembic upgrade head && uvicorn app.main:app --host 0.0.0.0 --port 8000"
    
  4. 迁移阶段
    • 容器内当前目录为 /app(即 backend 代码根目录),PYTHONPATH=/app
    • 执行 alembic upgrade headAlembic 在 /app 下找到 alembic.inialembic/env.pyalembic/versions/
    • 环境变量由 docker-compose 注入(含 DATABASE_URL_SYNC=postgresql://wecom:wecom_secret@db:5432/wecom_ai,注意主机名为 db)。
    • env.py 通过 app.config.settings 读到该连接串,用同步驱动连接 PostgreSQL执行所有未执行的迁移如创建 usersaudit_logs)。
  5. 应用启动:迁移成功后执行 uvicorn ...FastAPI 启动。

注意:若迁移失败(例如数据库未就绪、连接串错误),整条 CMD 会失败容器退出backend 不会起来。可查看日志:docker compose logs backend

一键迁移脚本Docker:在项目根目录执行其一即可完成「起 db → 等就绪 → 执行 alembic upgrade head」

  • Windows PowerShell.\deploy\scripts\migrate.ps1
  • Linux / macOSbash deploy/scripts/migrate.sh
  • 任意平台Pythonpython deploy/scripts/migrate.py(默认 Docker本机迁移用 python deploy/scripts/migrate.py --local

方式 B本机执行迁移

适用于在本机用 Python 直接跑迁移、数据库可在本机访问(本地 PostgreSQL 或已映射端口的 Docker 数据库)的情况。

前提

  • 本机已安装 Python 3.12、PostgreSQL 客户端库(psycopg2-binary)。
  • 数据库已存在(例如 Docker 只起 dbdocker compose up -d db),且已知连接信息。

步骤:

  1. 进入 backend 目录(迁移必须在 backend 根目录执行,以便找到 alembic.inialembic/

    cd backend
    
  2. 准备环境变量(二选一):

    • 在项目根目录已有 .env 时,可在 backend 下复制一份,让 app.config 自动读取:
      cp ../.env .env
      
    • 或直接设置连接串PowerShell 示例):
      $env:DATABASE_URL_SYNC = "postgresql://wecom:wecom_secret@localhost:5432/wecom_ai"
      
      Linux/macOS
      export DATABASE_URL_SYNC=postgresql://wecom:wecom_secret@localhost:5432/wecom_ai
      
      若数据库在 Docker 且未改端口,主机填 localhost、端口 5432 即可。
  3. 安装依赖(若未装过):

    pip install -r requirements.txt
    
  4. 执行迁移

    alembic upgrade head
    
    • Alembic 会读取当前目录下的 alembic.inialembic/env.py
    • env.py 里会 from app.config import settingsfrom app.models import Base,因此当前目录必须在 backend或设置 PYTHONPATH 指向 backend这样 app 才能正确解析。
    • 执行后,数据库中会创建/更新表,并写入 alembic_version
  5. 验证:连接数据库查看是否有 usersaudit_logsalembic_version 表。

本机常见问题

  • 报错 No module named 'app':未在 backend 目录执行,或未设置 PYTHONPATH。解决:cd backend 再执行,或 PYTHONPATH=backend alembic -c backend/alembic.ini upgrade head(在项目根目录时)。
  • 连接被拒绝:检查 DATABASE_URL_SYNC 的主机、端口、用户名、密码、数据库名是否与真实 PostgreSQL 一致Docker 时主机为 localhost,端口一般为 5432)。

2. 如何创建管理员

使用 seed 脚本(从 项目根目录 执行,依赖已安装的 Python 和 .env

# 确保 .env 存在,且 DATABASE_URL_SYNC 指向数据库Docker 时用 localhost:5432
pip install python-dotenv bcrypt psycopg2-binary sqlalchemy

python deploy/scripts/seed.py

可选环境变量(在 .env 或导出):

  • ADMIN_USERNAME:默认 admin
  • ADMIN_PASSWORD:默认 admin
  • DATABASE_URL_SYNC同步连接串Docker 时一般为 postgresql://wecom:wecom_secret@localhost:5432/wecom_ai

脚本会检查 users 表是否存在;若不存在会提示先执行迁移。若用户名已存在则跳过创建。

3. Auth API

  • POST /api/auth/login

    • Body: {"username":"admin","password":"admin"}
    • 成功200{"access_token":"...","token_type":"bearer"}
    • 失败401/403
  • GET /api/auth/me

    • Header: Authorization: Bearer <access_token>
    • 成功200当前用户信息id、username、role、is_active、created_at
    • 失败401/403

4. 管理后台

  • Token 存储:使用 localStoragekey 为 "token"。实现见 admin/lib/api.ts 注释。生产环境可改为 httpOnly Cookie 由后端 Set-Cookie。
  • 登录页 /login:表单提交后调用 POST /api/auth/login,成功则写入 localStorage 并跳转 /dashboard
  • Dashboard /dashboard:需登录;进入时请求 GET /api/auth/me,失败则清除 token 并跳转 /login;成功则展示当前用户信息与退出按钮。
  • 根路径 /:有 token 则跳转 /dashboard,否则跳转 /login

5. 安全

  • 密码bcryptpasslib + bcrypt 4.1.2)。
  • JWT:有过期时间,由 JWT_EXPIRE_MINUTES 控制(默认 60 分钟);密钥 JWT_SECRET 需在生产环境修改。

6. 如何登录验证

  1. 启动:docker compose up -d(自动执行迁移)。
  2. 创建管理员:python deploy/scripts/seed.py(见上文)。
  3. 打开 http://localhosthttp://localhost:3000应跳转登录页
  4. 输入 admin / admin或你在 .env 里设置的 ADMIN_USERNAME / ADMIN_PASSWORD),提交后应跳转 Dashboard 并显示当前用户信息。
  5. 点击退出后应回到登录页;再次访问 /dashboard 应被重定向到 /login。

直连 API 验证:

# 登录取 token
TOKEN=$(curl -s -X POST http://localhost:8000/api/auth/login -H "Content-Type: application/json" -d '{"username":"admin","password":"admin"}' | jq -r .access_token)
# 当前用户
curl -s -H "Authorization: Bearer $TOKEN" http://localhost:8000/api/auth/me