# SproutGate（萌芽账户认证中心）

前后端分离的统一账户与轻量用户中心：注册登录、邮箱验证、找回密码、副邮箱、签到与资料管理；管理员可维护用户、签到与注册/邀请码策略。数据以 **JSON 文件落盘**（无传统数据库），适合自建与小规模部署。第三方站点（如万象口袋）通过 **OAuth 式查询参数** 与 **JWT / 校验接口** 接入，详见 [`sproutgate-backend/API_DOCS.md`](./sproutgate-backend/API_DOCS.md)。

---

## 架构总览

```mermaid
flowchart LR
  subgraph client [浏览器]
    FE[React + Vite SPA]
  end
  subgraph api [sproutgate-backend]
    Gin[Gin HTTP]
    H[handlers]
    S[storage JSON]
    J[auth JWT]
    Gin --> H --> S
    H --> J
  end
  FE -->|HTTPS /api| Gin
  S --> FS[(data/config + data/users)]
```

| 部分 | 技术栈 | 目录 | 说明 |
|------|--------|------|------|
| 前端 | React 18 + Vite 5 | [`sproutgate-frontend/`](./sproutgate-frontend/) | 无 `react-router`；由 [`App.jsx`](./sproutgate-frontend/src/App.jsx) 按 `pathname` 切换视图；`VITE_API_BASE` 指向后端 |
| 后端 | Go 1.20 + Gin | [`sproutgate-backend/`](./sproutgate-backend/) | 单体 REST；默认端口 `8080`；CORS 放行常用头（含 `Authorization`、`X-Admin-Token`、`X-Auth-Client*`） |
| 数据 | JSON 文件 | [`sproutgate-backend/data/`](./sproutgate-backend/data/) | `config/`（`admin.json`、`auth.json` 含 JWT 密钥、`email.json`、`checkin.json`、`registration.json` 等）、`users/`（用户记录） |

---

## 后端代码结构（`sproutgate-backend/`）

| 包 / 目录 | 职责 |
|-----------|------|
| [`main.go`](./sproutgate-backend/main.go) | 初始化 [`storage.Store`](./sproutgate-backend/internal/storage/storage.go)、注册路由、监听 `PORT` |
| [`internal/handlers/`](./sproutgate-backend/internal/handlers/) | HTTP 处理：`auth_login`、`auth_password`、`profile`、`checkin`、`admin`、`public_registration`、`registration_admin`、`secondary_email`、`auth_client` 等；[`handler.go`](./sproutgate-backend/internal/handlers/handler.go) 聚合依赖 |
| [`internal/storage/`](./sproutgate-backend/internal/storage/storage.go) | 数据目录布局、读写 JSON、待验证/重置令牌等 |
| [`internal/models/`](./sproutgate-backend/internal/models/) | `User`、`Activity`、待审核、副邮箱、接入方元数据等结构体 |
| [`internal/auth/jwt.go`](./sproutgate-backend/internal/auth/jwt.go) | JWT 签发与解析（HS256） |
| [`internal/email/mailer.go`](./sproutgate-backend/internal/email/mailer.go) | SMTP 发信（配置来自 `data/config/email.json`） |
| [`internal/clientgeo/`](./sproutgate-backend/internal/clientgeo/clientgeo.go) | 与访问来源等辅助逻辑配合（请求头见 `main.go` CORS） |

**API 前缀（与 [`main.go`](./sproutgate-backend/main.go) 一致）**

| 前缀 | 说明 |
|------|------|
| `/api/auth/*` | 登录、注册、邮箱验证、忘记/重置密码、副邮箱、`POST /verify`、`GET /me`、签到、`PUT /profile`；可带 `X-Auth-Client` / `X-Auth-Client-Name` 记录第三方应用 |
| `/api/public/*` | 公开用户资料、注册策略（是否强制邀请码等） |
| `/api/admin/*` | 需 [`AdminMiddleware`](./sproutgate-backend/internal/handlers/admin.go)：请求头 `X-Admin-Token` 或 Query `token`，与用户 JWT 分离 |

**运维与文档**：`GET /`、`GET /api`（JSON 服务说明）、`GET /api/health`、`GET /api/docs`（返回仓库内 `API_DOCS.md`）。

---

## 前端代码结构（`sproutgate-frontend/`）

| 路径 | 说明 |
|------|------|
| [`src/App.jsx`](./sproutgate-frontend/src/App.jsx) | 根组件：根据路径渲染门户 / 公开用户页 / 管理端；顶栏 **连点 Logo** 进入管理员流程 |
| [`src/config.js`](./sproutgate-frontend/src/config.js) | `VITE_API_BASE`、开发与生产默认 API 地址 |
| [`src/components/UserPortal.jsx`](./sproutgate-frontend/src/components/UserPortal.jsx) | `/`：登录、注册、邮件验证、`redirect_uri` 统一登录回跳等 |
| [`src/components/PublicUserPage.jsx`](./sproutgate-frontend/src/components/PublicUserPage.jsx) | `/user`、`/user/:account`：公开资料 |
| [`src/components/AdminPanel.jsx`](./sproutgate-frontend/src/components/AdminPanel.jsx) | `/admin`：用户与签到、注册策略管理 |

---

## 认证与安全（摘要）

1. **用户会话**：登录成功后签发 JWT（`Authorization: Bearer`）；受保护接口解析 JWT 后按 `account` 加载用户；封禁等状态见 handlers 内校验。
2. **令牌校验**：`POST /api/auth/verify` 供第三方后端校验用户 token（见 API 文档）。
3. **管理员**：与业务 JWT 独立，使用 **`X-Admin-Token`**（或 Query `token`）与 `data/config/admin.json` 比对。
4. **第三方统一登录门户**：入口 URL 查询参数 `redirect_uri`、`client_id`、`client_name` 等；前端通过 `sessionStorage` 与请求头 **`X-Auth-Client`** / **`X-Auth-Client-Name`** 与后端协同（CORS 已允许上述头）。

部署到公网前：**修改默认 JWT 密钥、管理员 Token、SMTP 密码**，且勿将含真实密钥的 `data/config` 提交到公开仓库。

---

## 环境要求

- **后端**：Go **1.20+**（以 [`sproutgate-backend/go.mod`](./sproutgate-backend/go.mod) 为准）
- **前端**：Node.js **18+**（建议 LTS）

---

## 快速开始

### 方式一：根目录脚本（推荐本地开发）

**Windows**

```bat
sproutgate.bat dev
```

**macOS / Linux**

```bash
chmod +x sproutgate.sh
./sproutgate.sh dev
```

会启动后端 `go run .` 与前端 `npm run dev`（前端默认 **5173**，后端默认 **8080**）。

仅构建前端：

```bat
sproutgate.bat build
```

```bash
./sproutgate.sh build
```

### 方式二：手动分别启动

**后端**

```bash
cd sproutgate-backend
go mod tidy
go run .
```

**前端**

```bash
cd sproutgate-frontend
npm install
npm run dev
```

### 前端连接后端

在 `sproutgate-frontend/.env`（自行创建）中设置：

```env
VITE_API_BASE=http://localhost:8080
```

生产环境改为实际 API 地址（如 `https://auth.api.example.com`）。

### 配置与安全

- 管理员 Token、JWT 密钥、邮件 SMTP 等位于 **`sproutgate-backend/data/config/`**（如 `admin.json`、`auth.json`、`email.json`）。**部署到公网前请务必修改默认值，且不要将真实密钥提交到仓库。**
- 进入管理员后台：在任意页面顶栏 **连续点击 Logo 五次**（约 2.6 秒内），在弹窗中输入与 `admin.json` 一致的 Token；也可直接使用 `http://localhost:5173/admin?token=<Token>`（Token 会写入本地后再请求接口）。

### 可选：Docker 仅跑后端 API

在 [`sproutgate-backend`](./sproutgate-backend) 目录：

```bash
docker compose up -d --build
```

默认将容器内 `8080` 映射到主机 **`28080`**（可通过环境变量 **`AUTH_API_PORT`** 修改）。数据目录通过卷挂载到 **`./data`**。

---

## 环境变量（后端）

| 变量 | 说明 |
|------|------|
| `PORT` | 监听端口，默认 `8080` |
| `DATA_DIR` | 数据根目录；不设置时使用仓库内相对路径下的 `data` 布局 |

---

## 相关文档

| 文档 | 内容 |
|------|------|
| [`sproutgate-backend/API_DOCS.md`](./sproutgate-backend/API_DOCS.md) | HTTP 接口契约（第三方接入主参考） |
| [`AGENTS.md`](./AGENTS.md) | 目录约定、协作与 PR 建议 |

---

## 许可证

若仓库未包含 `LICENSE` 文件，使用前请与维护者确认授权方式。
