Initial commit: 浼佷笟寰俊 AI 鏈哄櫒浜哄姪鐞?MVP

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
bujie9527
2026-02-05 16:36:32 +08:00
commit 59275ed4dc
126 changed files with 9120 additions and 0 deletions

160
docs/stage2.md Normal file
View File

@@ -0,0 +1,160 @@
# 阶段 2SQLAlchemy + Alembic + 用户登录体系
## 1. 数据库与迁移
- **连接**backend 通过环境变量 `DATABASE_URL`(异步 `postgresql+asyncpg://...`)连接 PostgreSQLAlembic 使用 `DATABASE_URL_SYNC`(同步 `postgresql://...`)。
- **表结构**
- **users**id (uuid)、username、password_hash、role、is_active、created_at
- **audit_logs**id (uuid)、actor_user_id (FK users)、action、meta_json (JSONB)、created_at
### 迁移流程说明
Alembic 会按版本顺序执行 `alembic/versions/` 下的迁移脚本,在数据库中创建或修改表,并在库中记录当前版本(表 `alembic_version`)。
执行时:
1. 读取 `backend/alembic.ini``backend/alembic/env.py`
2. `env.py``app.config.settings` 读取 `database_url_sync`(即环境变量 `DATABASE_URL_SYNC`),用该同步连接串连接 PostgreSQL。
3. 对比数据库中的 `alembic_version` 与本地迁移文件,将尚未执行的迁移按顺序执行(例如 `001_users_and_audit_logs.py` 会创建 `users``audit_logs` 表)。
---
### 方式 ADocker 启动时自动迁移
**步骤:**
1. 在项目根目录执行:
```bash
docker compose up -d
```
2. Compose 会先启动 `db`,等待健康检查通过后再启动 `backend`。
3. **backend 容器**的启动命令为:
```text
sh -c "alembic upgrade head && uvicorn app.main:app --host 0.0.0.0 --port 8000"
```
4. **迁移阶段**
- 容器内当前目录为 `/app`(即 backend 代码根目录),`PYTHONPATH=/app`。
- 执行 `alembic upgrade head` 时Alembic 在 `/app` 下找到 `alembic.ini`、`alembic/env.py` 和 `alembic/versions/`。
- 环境变量由 `docker-compose` 注入(含 `DATABASE_URL_SYNC=postgresql://wecom:wecom_secret@db:5432/wecom_ai`,注意主机名为 `db`)。
- `env.py` 通过 `app.config.settings` 读到该连接串,用**同步**驱动连接 PostgreSQL执行所有未执行的迁移如创建 `users`、`audit_logs`)。
5. **应用启动**:迁移成功后执行 `uvicorn ...`FastAPI 启动。
**注意**:若迁移失败(例如数据库未就绪、连接串错误),整条 CMD 会失败容器退出backend 不会起来。可查看日志:`docker compose logs backend`。
**一键迁移脚本Docker**:在项目根目录执行其一即可完成「起 db → 等就绪 → 执行 alembic upgrade head」
- **Windows PowerShell**`.\deploy\scripts\migrate.ps1`
- **Linux / macOS**`bash deploy/scripts/migrate.sh`
- **任意平台Python**`python deploy/scripts/migrate.py`(默认 Docker本机迁移用 `python deploy/scripts/migrate.py --local`
---
### 方式 B本机执行迁移
适用于在本机用 Python 直接跑迁移、数据库可在本机访问(本地 PostgreSQL 或已映射端口的 Docker 数据库)的情况。
**前提**
- 本机已安装 Python 3.12、PostgreSQL 客户端库(`psycopg2-binary`)。
- 数据库已存在(例如 Docker 只起 db`docker compose up -d db`),且已知连接信息。
**步骤:**
1. **进入 backend 目录**(迁移必须在 backend 根目录执行,以便找到 `alembic.ini` 和 `alembic/`
```bash
cd backend
```
2. **准备环境变量**(二选一):
- 在项目根目录已有 `.env` 时,可在 backend 下复制一份,让 `app.config` 自动读取:
```bash
cp ../.env .env
```
- 或直接设置连接串PowerShell 示例):
```powershell
$env:DATABASE_URL_SYNC = "postgresql://wecom:wecom_secret@localhost:5432/wecom_ai"
```
Linux/macOS
```bash
export DATABASE_URL_SYNC=postgresql://wecom:wecom_secret@localhost:5432/wecom_ai
```
若数据库在 Docker 且未改端口,主机填 `localhost`、端口 `5432` 即可。
3. **安装依赖**(若未装过):
```bash
pip install -r requirements.txt
```
4. **执行迁移**
```bash
alembic upgrade head
```
- Alembic 会读取当前目录下的 `alembic.ini` 和 `alembic/env.py`。
- `env.py` 里会 `from app.config import settings`、`from app.models import Base`,因此当前目录必须在 backend或设置 `PYTHONPATH` 指向 backend这样 `app` 才能正确解析。
- 执行后,数据库中会创建/更新表,并写入 `alembic_version`。
5. **验证**:连接数据库查看是否有 `users`、`audit_logs` 及 `alembic_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
```bash
# 确保 .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 存储**:使用 **localStorage**key 为 `"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://localhost 或 http://localhost:3000应跳转登录页。
4. 输入 admin / admin或你在 .env 里设置的 `ADMIN_USERNAME` / `ADMIN_PASSWORD`),提交后应跳转 Dashboard 并显示当前用户信息。
5. 点击退出后应回到登录页;再次访问 /dashboard 应被重定向到 /login。
直连 API 验证:
```bash
# 登录取 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
```