Files
SproutGate/sproutgate-backend/后端文档.md

7.0 KiB
Raw Permalink Blame History

SproutGate 后端文档

技术栈

  • 语言Go 1.20+
  • Web 框架Gin跨域中间件 github.com/gin-contrib/cors
  • 数据存储MySQL通过 GORM + gorm.io/driver/mysql
  • JWTgithub.com/golang-jwt/jwt/v5
  • 密码哈希golang.org/x/crypto/bcrypt

业务数据与配置均保存在 MySQL 中,不再使用 data/users/*.jsondata/config/*.json 作为运行时数据源。仓库中的 data/ 仅可作迁移脚本输入或本地备份参考。

目录结构(要点)

路径 说明
main.go 入口:连接数据库、初始化 Store、注册路由
internal/database/ MySQL 连接(DB_DSNDB_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 拼接 DSNDB_HOST/DB_USER/DB_PASSWORD 三者缺一即报错退出;DB_PORT 默认 3306DB_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=3306DB_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 键值配置:adminauthemailcheckinregistrationJSON
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_configsinvite_codes)、data/users/*.json(写入 users)。对已存在主键执行 UPSERT:同账号、同配置键会更新为迁移文件中的值。

HTTP 路由速览

  • GET /GET /apiAPI 简要说明 JSONmain.go 内嵌字段,含 versionroutePrefixes 等)。当前未注册单独返回 Markdown 的 /api/docs 路由;对外长文档见仓库根目录 萌芽账户认证中心-第三方应用API接入文档.md
  • GET /api/health{ "status": "ok", "env": "<APP_ENV 或 development>" }
  • /api/auth/*:登录、注册、邮箱验证、忘记/重置密码、辅助邮箱、令牌校验、/me、签到、更新资料等;可选请求头 X-Auth-ClientX-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 自定义头包含:AuthorizationX-Admin-TokenX-Visit-IpX-Visit-LocationX-Auth-ClientX-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 账号权限。