feat: 更新SproutGate前后端代码

This commit is contained in:
2026-04-01 22:04:01 +08:00
parent 90590c7cb0
commit 650e1c7707
49 changed files with 3609 additions and 768 deletions

View File

@@ -0,0 +1,110 @@
# 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` / `APP_ENV` |
| `internal/handlers/` | HTTP 处理:认证、资料、签到、公开页、管理端等 |
| `internal/models/` | 领域模型(用户、待激活、重置密码、辅助邮箱等) |
| `internal/storage/` | 持久化:`Store` + GORM 模型与业务方法 |
| `internal/auth/` | JWT 签发与校验 |
| `internal/email/` | 发信 |
| `cmd/migrate/` | 一次性工具:将旧版 JSON `data/` 导入 MySQL |
## 环境与数据库
连接字符串优先级:**`DB_DSN` > 内置规则**。
1. **若设置 `DB_DSN`**:直接使用该完整 DSN适合 CI、容器或临时切换
2. **否则**:根据 `APP_ENV` 选择内置库:
- `APP_ENV=production``prod` → 生产库:`192.168.1.100:3306` / 库名 `sproutgate` / 用户 `sproutgate`
- 未设置或其它值 → 开发/测试库:`10.1.1.100:3306` / 库名 `sproutgate-test` / 用户 `sproutgate-test`
其它常用环境变量:
| 变量 | 说明 | 默认 |
|------|------|------|
| `PORT` | HTTP 监听端口 | `8080` |
| `APP_ENV` | 影响默认 MySQL 选择与 `/api/health` 返回的 `env` | 空则 health 中为 `development` |
| `GIN_MODE` | `release` 时 GORM 日志级别更安静(警告级) | debug 模式 |
| `DB_DSN` | 完整 MySQL DSN覆盖上述内置地址 | 未设置 |
| `GEO_LOOKUP_URL` | `GET /api/auth/me` 未带 `X-Visit-Location` 时,服务端按 IP 请求该基址反查展示地理位置(实现见 `internal/clientgeo`,会拼接 `?ip=` | 默认 `https://cf-ip-geo.smyhub.com/api` |
**建议**:生产部署时设置 `APP_ENV=production`,并确保 MySQL 防火墙与账号权限正确;敏感连接信息也可只通过 `DB_DSN` 注入,无需改代码。
## 数据库表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
# 导入到当前环境对应的库(默认开发库,除非设置 APP_ENV 或 DB_DSN
go run ./cmd/migrate --data-dir ./data
```
Windows PowerShell 示例(写入生产库):
```powershell
$env:APP_ENV = "production"
go run ./cmd/migrate --data-dir ./data
Remove-Item Env:APP_ENV # 可选:清除变量,避免影响本机其它命令
```
迁移内容:`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 账号权限。