124 lines
7.0 KiB
Markdown
124 lines
7.0 KiB
Markdown
# SproutGate 后端文档
|
||
|
||
## 技术栈
|
||
|
||
- **语言**:Go 1.20+
|
||
- **Web 框架**:Gin;跨域中间件 **`github.com/gin-contrib/cors`**
|
||
- **数据存储**:MySQL(通过 GORM + `gorm.io/driver/mysql`)
|
||
- **JWT**:`github.com/golang-jwt/jwt/v5`
|
||
- **密码哈希**:`golang.org/x/crypto/bcrypt`
|
||
|
||
业务数据与配置均保存在 MySQL 中,**不再使用** `data/users/*.json` 与 `data/config/*.json` 作为运行时数据源。仓库中的 `data/` 仅可作迁移脚本输入或本地备份参考。
|
||
|
||
## 目录结构(要点)
|
||
|
||
| 路径 | 说明 |
|
||
|------|------|
|
||
| `main.go` | 入口:连接数据库、初始化 `Store`、注册路由 |
|
||
| `internal/database/` | MySQL 连接(`DB_DSN` 或 `DB_HOST`/`DB_USER`/`DB_PASSWORD`/`DB_NAME`/`DB_PORT`,支持 `.env` 本地加载) |
|
||
| `internal/handlers/` | HTTP 处理:认证、资料、签到、公开页、管理端等 |
|
||
| `internal/models/` | 领域模型(用户、待激活、重置密码、辅助邮箱等) |
|
||
| `internal/storage/` | 持久化:`Store` + GORM 模型与业务方法 |
|
||
| `internal/auth/` | JWT 签发与校验 |
|
||
| `internal/email/` | 发信 |
|
||
| `cmd/migrate/` | 一次性工具:将旧版 JSON `data/` 导入 MySQL |
|
||
|
||
## 环境与数据库
|
||
|
||
代码中**不再内置任何数据库地址或账号密码**,连接参数完全来自环境变量,连接字符串优先级:**`DB_DSN` > `DB_HOST`/`DB_PORT`/`DB_USER`/`DB_PASSWORD`/`DB_NAME`**。
|
||
|
||
1. **若设置 `DB_DSN`**:直接使用该完整 DSN(适合 CI、容器或临时切换)。
|
||
2. **否则**:用 `DB_HOST`/`DB_USER`/`DB_PASSWORD` 拼接 DSN,`DB_HOST`/`DB_USER`/`DB_PASSWORD` 三者缺一即报错退出;`DB_PORT` 默认 `3306`,`DB_NAME` 默认 `sproutgate`(开发、生产统一用这个库名,仅 host/账号不同)。
|
||
|
||
本地开发时,在 `sproutgate-backend/.env`(已在 `.gitignore` 中忽略,不会提交)里写:
|
||
|
||
```
|
||
DB_HOST=10.1.1.100
|
||
DB_PORT=3306
|
||
DB_USER=sproutgate-test
|
||
DB_PASSWORD=sproutgate-test
|
||
DB_NAME=sproutgate
|
||
```
|
||
|
||
`go run .` / `go run ./cmd/migrate` 启动时会自动从当前目录读取并加载 `.env`(已存在的环境变量不会被覆盖);生产部署通过容器/`docker-compose` 环境变量注入,不依赖 `.env` 文件。
|
||
|
||
其它常用环境变量:
|
||
|
||
| 变量 | 说明 | 默认 |
|
||
|------|------|------|
|
||
| `PORT` | HTTP 监听端口 | `8080` |
|
||
| `APP_ENV` | 仅影响 `/api/health` 返回的 `env` 字段,不再决定数据库选择 | 空则 health 中为 `development` |
|
||
| `GIN_MODE` | `release` 时 GORM 日志级别更安静(警告级) | debug 模式 |
|
||
| `DB_DSN` | 完整 MySQL DSN,覆盖 `DB_HOST` 等单项配置 | 未设置 |
|
||
| `DB_HOST` / `DB_PORT` / `DB_USER` / `DB_PASSWORD` / `DB_NAME` | MySQL 连接参数;`DB_HOST`/`DB_USER`/`DB_PASSWORD` 必填,无内置默认值 | `DB_PORT=3306`,`DB_NAME=sproutgate` |
|
||
| `GEO_LOOKUP_URL` | `GET /api/auth/me` 未带 `X-Visit-Location` 时,服务端按 IP 请求该基址反查展示地理位置(实现见 `internal/clientgeo`,会拼接 `?ip=`) | 默认 `https://cf-ip-geo.smyhub.com/api` |
|
||
|
||
**建议**:生产部署通过 `docker-compose.yml` 旁的 `.env`(同样被 `.gitignore` 忽略)注入 `DB_HOST`/`DB_USER`/`DB_PASSWORD`,不要把真实账号密码写进任何会提交到仓库的文件。
|
||
|
||
## 数据库表(AutoMigrate)
|
||
|
||
应用启动与 `migrate` 工具均会同步下列表结构(GORM `AutoMigrate`):
|
||
|
||
| 表名 | 用途 |
|
||
|------|------|
|
||
| `users` | 用户主数据;签到/访问时间列表、`auth_clients` 等以 JSON 文本列存储 |
|
||
| `pending_users` | 注册邮箱验证流程中的待激活用户 |
|
||
| `password_resets` | 忘记密码验证码 |
|
||
| `secondary_email_verifications` | 绑定辅助邮箱验证码 |
|
||
| `app_configs` | 键值配置:`admin`、`auth`、`email`、`checkin`、`registration`(JSON) |
|
||
| `invite_codes` | 注册邀请码 |
|
||
| `profile_likes` | 公开用户主页点赞明细(点赞者、被赞者、自然日等) |
|
||
| `profile_like_daily_quota` | 点赞者当日已用额度(与代码常量 `MaxProfileLikesPerDay` 配合) |
|
||
|
||
管理员令牌、JWT Secret、邮件 SMTP、签到奖励、是否强制邀请码等,均从 `app_configs` / `invite_codes` 读写,首次无记录时由 `Store` 按逻辑补全默认项。
|
||
|
||
## 从旧 JSON 迁移到 MySQL
|
||
|
||
在 **`sproutgate-backend`** 目录下:
|
||
|
||
```bash
|
||
# 导入到 .env(或当前环境变量)指向的库
|
||
go run ./cmd/migrate --data-dir ./data
|
||
```
|
||
|
||
Windows PowerShell 示例(临时指定生产库连接参数):
|
||
|
||
```powershell
|
||
$env:DB_HOST = "192.168.1.100"
|
||
$env:DB_USER = "sproutgate"
|
||
$env:DB_PASSWORD = "<生产密码>"
|
||
go run ./cmd/migrate --data-dir ./data
|
||
Remove-Item Env:DB_HOST, Env:DB_USER, Env:DB_PASSWORD # 可选:清除变量,避免影响本机其它命令
|
||
```
|
||
|
||
迁移内容:`data/config/*.json`(写入 `app_configs` 与 `invite_codes`)、`data/users/*.json`(写入 `users`)。对已存在主键执行 **UPSERT**:同账号、同配置键会更新为迁移文件中的值。
|
||
|
||
## HTTP 路由速览
|
||
|
||
- **`GET /`**、**`GET /api`**:API 简要说明 JSON(`main.go` 内嵌字段,含 `version`、`routePrefixes` 等)。**当前未注册**单独返回 Markdown 的 `/api/docs` 路由;对外长文档见仓库根目录 **`萌芽账户认证中心-第三方应用API接入文档.md`**。
|
||
- **`GET /api/health`**:`{ "status": "ok", "env": "<APP_ENV 或 development>" }`。
|
||
- **`/api/auth/*`**:登录、注册、邮箱验证、忘记/重置密码、辅助邮箱、令牌校验、`/me`、签到、更新资料等;可选请求头 `X-Auth-Client`、`X-Auth-Client-Name`(记录第三方应用接入)。
|
||
- **`/api/public/*`**:
|
||
- **`GET /api/public/users`**:公开用户目录(未封禁;默认按 `createdAt` 升序)。
|
||
- **`GET /api/public/users/:account`**:公开资料 + 累计赞数;若带合法 Bearer,可附加「是否已赞今日」「当日剩余可点赞人数」等浏览者上下文。
|
||
- **`POST /api/public/users/:account/like`**:登录用户给指定主页点赞(不能赞自己;每人每主页每日一次;每自然日每名用户最多给 **5** 位不同用户点赞,常量见 `internal/storage/profile_likes.go`)。
|
||
- **`GET /api/public/registration-policy`**:是否强制邀请码等。
|
||
- **`/api/admin/*`**:需 **`X-Admin-Token`**(或 Query `token`):用户 CRUD、签到配置、注册策略与邀请码管理。
|
||
|
||
允许的 CORS 自定义头包含:`Authorization`、`X-Admin-Token`、`X-Visit-Ip`、`X-Visit-Location`、`X-Auth-Client`、`X-Auth-Client-Name` 等。
|
||
|
||
## 本地开发命令
|
||
|
||
```bash
|
||
cd sproutgate-backend
|
||
go mod tidy
|
||
go run .
|
||
```
|
||
|
||
默认监听 `:8080`。前端开发时请将 `VITE_API_BASE` 指向本服务(详见仓库根目录下 `sproutgate-frontend/前端文档.md`)。
|
||
|
||
## 安全提示
|
||
|
||
- 勿将生产 `DB_DSN`、SMTP 密码、真实 `admin` 令牌提交到版本库。
|
||
- 旧版 `data/config/email.json` 等若含真实口令,迁移后应以环境或运维密钥管理为准,并限制数据库与 SMTP 账号权限。
|