Files
opencloud-backend/README.md
T
2026-07-18 20:32:51 +08:00

188 lines
5.9 KiB
Markdown
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.
# OpenCloud Backend
OpenCloud 的 FastAPI 后端,替代原项目中的 Supabase Database、Auth 和 Storage。后端提供邮箱密码认证、可撤销刷新会话、云图上传与缩略图、地图/画廊查询、图鉴解锁、个人主页和管理员审核。
## 技术栈
- Python 3.13、FastAPI、Pydantic
- PostgreSQL 17、SQLAlchemy 2(异步)、Alembic
- Argon2 密码哈希、JWT Access Token、数据库 Refresh Session
- 本地持久化图片目录、Pillow 图片验证和缩略图生成
- SMTP 邮箱确认与密码重置
## 本地启动
复制配置并生成开发密钥:
```bash
cp .env.example .env
openssl rand -hex 32
```
把生成值写入 `.env``SECRET_KEY`,然后安装依赖:
```bash
uv sync
```
准备一个可访问的 PostgreSQL 数据库,并在 `.env` 中填写实际连接信息:
```dotenv
DATABASE_URL=postgresql+asyncpg://用户名:密码@主机:5432/数据库名
```
应用和 Alembic 都只从 `.env` 读取数据库连接,不需要在其他配置文件中重复填写。
创建表并写入十种云类型、可选初始管理员:
```bash
uv run alembic upgrade head
uv run python -m app.seed
```
启动开发服务器:
```bash
uv run uvicorn app.main:app --reload
```
- API`http://localhost:8000/api/v1`
- Swagger`http://localhost:8000/docs`
- 健康检查:`http://localhost:8000/api/v1/health`
## 认证约定
登录成功后响应包含有效期较短的 `access_token`。前端在请求头中发送:
```text
Authorization: Bearer <access_token>
```
Refresh Token 只保存在 HttpOnly Cookie 中。前端调用 `/api/v1/auth/refresh``/api/v1/auth/logout` 时必须允许 Cookie
```ts
fetch(url, { credentials: 'include' })
```
开发环境默认 `EMAIL_DELIVERY_MODE=console`,邮箱确认和密码重置链接会输出到后端日志。如需真实发信,请在 `.env` 中配置 SMTP 参数并将 `EMAIL_DELIVERY_MODE` 改为 `smtp`
## 主要接口
### 认证
- `POST /api/v1/auth/register`
- `POST /api/v1/auth/resend-confirmation`
- `POST /api/v1/auth/confirm-email`
- `POST /api/v1/auth/login`
- `POST /api/v1/auth/refresh`
- `POST /api/v1/auth/logout`
- `GET /api/v1/auth/me`
- `POST /api/v1/auth/forgot-password`
- `POST /api/v1/auth/reset-password`
- `PATCH /api/v1/auth/password`
### 云图和图鉴
- `GET/POST /api/v1/clouds`
- `GET /api/v1/clouds/map`
- `GET/PATCH/DELETE /api/v1/clouds/{id}`
- `POST /api/v1/clouds/batch-delete`
- `GET /api/v1/cloud-types`
- `GET /api/v1/cloud-types/{id}/clouds`
- `GET /api/v1/collections/me`
上传使用 `multipart/form-data`,文件字段为 `image`;服务端自行验证、重编码原图并生成 JPEG 缩略图。新图片状态始终为 `pending``user_id` 从 Access Token 获取,经纬度在服务端保留两位小数。
### 用户和管理后台
- `GET /api/v1/profiles/{user_id}`
- `PATCH /api/v1/profiles/me`
- `GET /api/v1/profiles/{user_id}/clouds`
- `GET /api/v1/admin/stats`
- `GET/PATCH /api/v1/admin/users`
- `GET /api/v1/admin/clouds`
- `PATCH /api/v1/admin/clouds/status`
- `PATCH /api/v1/admin/clouds/visibility`
- `POST /api/v1/admin/clouds/batch-delete`
精确的请求和响应模型以 Swagger/OpenAPI 为准。
## 环境变量
所有可调配置均可在 `.env.example` 中找到。首次运行先复制该文件:
```bash
cp .env.example .env
```
其中关键配置包括:
- `DATABASE_URL`:异步 SQLAlchemy 连接串,PostgreSQL 使用 `postgresql+asyncpg://`
- `SECRET_KEY`:JWT 签名密钥,生产环境至少 32 个字符
- `FRONTEND_URL`:认证邮件中的前端地址
- `PUBLIC_BASE_URL`API 和图片公开地址
- `CORS_ORIGINS`:逗号分隔的前端来源
- `UPLOAD_DIR`:持久化图片目录
- `EMAIL_DELIVERY_MODE``console``smtp`
- `ADMIN_EMAIL``ADMIN_PASSWORD`:执行 seed 时可选创建管理员
生产环境还必须设置 `ENVIRONMENT=production``COOKIE_SECURE=true`,并通过 HTTPS 访问。
## 数据库迁移(Alembic
Alembic 用于管理数据库结构版本,作用类似于数据库结构的 Git。它会记录建表、增加字段、创建索引等变更,使不同环境中的数据库结构与代码保持一致,但不会负责启动 PostgreSQL 服务。
项目中的相关文件:
- `app/models.py`SQLAlchemy 数据模型,也是当前期望的数据库结构
- `alembic/versions/`:按版本保存数据库迁移脚本
- `alembic/env.py`:加载模型,并通过 `.env` 获取 `DATABASE_URL`
- `alembic.ini`:Alembic 的基础配置,不保存数据库账号或密码
首次初始化数据库或拉取到新的迁移后,升级到最新版本:
```bash
uv run alembic upgrade head
```
修改 SQLAlchemy 模型后,先生成迁移脚本并检查生成内容,再执行升级:
```bash
uv run alembic revision --autogenerate -m "describe change"
uv run alembic upgrade head
```
查看当前数据库版本和迁移历史:
```bash
uv run alembic current
uv run alembic history
```
回退最近一次迁移:
```bash
uv run alembic downgrade -1
```
回退操作可能导致字段或数据被删除,执行前应先检查迁移脚本并备份数据库。
应用使用 SQLAlchemy 连接池,所有外键和主要画廊、地图、个人主页、审核查询均有对应索引。应用数据库账号不应使用 PostgreSQL 超级用户。
## 验证
```bash
uv run pytest -q
uv run python -m compileall -q app main.py
uv run alembic upgrade head --sql
```
测试覆盖注册、邮箱确认、登录、资料修改、上传、缩略图、图鉴解锁、管理员审核、画廊、地图和删除的完整流程。
## 部署注意事项
- `data/uploads` 必须挂载到持久化磁盘并纳入备份。
- PostgreSQL 和上传目录需要分别制定备份与恢复方案。
- 单机部署可由 FastAPI 提供 `/media`;高流量部署建议由 Nginx/Caddy 直接服务该目录。
- `is_hidden` 与原 Supabase 公共 bucket 行为一致,只阻止页面发现,知道图片 URL 的人仍可直接访问。若需要真正私密图片,应改为鉴权下载或短期签名 URL。