7.0 KiB
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。
- 若设置
DB_DSN:直接使用该完整 DSN(适合 CI、容器或临时切换)。 - 否则:用
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 目录下:
# 导入到 .env(或当前环境变量)指向的库
go run ./cmd/migrate --data-dir ./data
Windows 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(或 Querytoken):用户 CRUD、签到配置、注册策略与邀请码管理。
允许的 CORS 自定义头包含:Authorization、X-Admin-Token、X-Visit-Ip、X-Visit-Location、X-Auth-Client、X-Auth-Client-Name 等。
本地开发命令
cd sproutgate-backend
go mod tidy
go run .
默认监听 :8080。前端开发时请将 VITE_API_BASE 指向本服务(详见仓库根目录下 sproutgate-frontend/前端文档.md)。
安全提示
- 勿将生产
DB_DSN、SMTP 密码、真实admin令牌提交到版本库。 - 旧版
data/config/email.json等若含真实口令,迁移后应以环境或运维密钥管理为准,并限制数据库与 SMTP 账号权限。