mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-11 09:46:37 +08:00
[优化] 更新认证机制,使用 OPENFLARE_TOKEN 替代 Bearer Token
This commit is contained in:
@@ -91,7 +91,7 @@ docker run -d \
|
|||||||
启动参数说明:
|
启动参数说明:
|
||||||
* **`-p 3000:3000`**:映射宿主机 `3000` 端口到容器内 `3000` 端口。
|
* **`-p 3000:3000`**:映射宿主机 `3000` 端口到容器内 `3000` 端口。
|
||||||
* **`-v $(pwd)/openflare-data:/data`**:挂载本地目录到容器的 `/data`,确保数据库文件 `openflare.db` 在重启或重建容器时不丢失。
|
* **`-v $(pwd)/openflare-data:/data`**:挂载本地目录到容器的 `/data`,确保数据库文件 `openflare.db` 在重启或重建容器时不丢失。
|
||||||
* **`SESSION_SECRET`**:必须配置的 Session 密钥签名哈希。
|
* **`SESSION_SECRET`**:建议配置的临时 Session 签名密钥,主要用于 OAuth 状态等非管理端 API 鉴权流程;管理端 API 登录凭证通过 `OPENFLARE_TOKEN` 请求头传递。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ Agent 本地 Pages 部署目录
|
|||||||
|
|
||||||
* Gin 提供 HTTP 服务。
|
* Gin 提供 HTTP 服务。
|
||||||
* GORM 访问 SQLite 或 PostgreSQL。
|
* GORM 访问 SQLite 或 PostgreSQL。
|
||||||
* 现有登录体系提供管理端 Session。
|
* 现有登录体系签发管理端用户 Token,管理端 API 通过 `OPENFLARE_TOKEN` 请求头鉴权。
|
||||||
* 认证源与外部账号绑定支持 GitHub OAuth 和标准 OIDC。
|
* 认证源与外部账号绑定支持 GitHub OAuth 和标准 OIDC。
|
||||||
* Go Server 托管 `openflare_server/web` 静态构建产物。
|
* Go Server 托管 `openflare_server/web` 静态构建产物。
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
| 现象 | 先看哪里 |
|
| 现象 | 先看哪里 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 管理端打不开 | Server 容器或进程日志、端口监听 |
|
| 管理端打不开 | Server 容器或进程日志、端口监听 |
|
||||||
| 登录异常 | 默认账号、Session Secret、浏览器请求、Server 日志 |
|
| 登录异常 | 默认账号、OPENFLARE_TOKEN、浏览器请求、Server 日志 |
|
||||||
| 数据无法保存 | 数据库连接、SQLite 文件权限、PostgreSQL 健康状态 |
|
| 数据无法保存 | 数据库连接、SQLite 文件权限、PostgreSQL 健康状态 |
|
||||||
| Agent 离线 | Agent 日志、Token、Server 地址、网络连通性 |
|
| Agent 离线 | Agent 日志、Token、Server 地址、网络连通性 |
|
||||||
| 发布后节点未更新 | 激活版本、节点 heartbeat、应用记录 |
|
| 发布后节点未更新 | 激活版本、节点 heartbeat、应用记录 |
|
||||||
@@ -85,8 +85,8 @@ NEXT_DEV_BACKEND_URL=http://127.0.0.1:3000 pnpm dev
|
|||||||
|
|
||||||
1. 确认连接的是预期数据库,避免 `SQLITE_PATH` 或 `DSN` 指向了另一个环境。
|
1. 确认连接的是预期数据库,避免 `SQLITE_PATH` 或 `DSN` 指向了另一个环境。
|
||||||
2. 查看 Server 日志中使用的是 `sqlite` 还是 `postgres`。
|
2. 查看 Server 日志中使用的是 `sqlite` 还是 `postgres`。
|
||||||
3. 如果部署在多副本或反向代理后,确认 `SESSION_SECRET` 固定且各实例一致。
|
3. 在浏览器开发者工具中确认管理端 API 请求携带 `OPENFLARE_TOKEN` 请求头。
|
||||||
4. 清理浏览器 Cookie 后重新登录。
|
4. 清理浏览器本地存储中的旧 `openflare_token` 后重新登录。
|
||||||
|
|
||||||
### 应急重置管理员密码
|
### 应急重置管理员密码
|
||||||
|
|
||||||
|
|||||||
@@ -167,19 +167,19 @@ v1-v7 视为历史初始基线,不再维护逐版本升级文件。v8-v17 是
|
|||||||
- Client 心跳返回 tunnel 配置版本摘要。
|
- Client 心跳返回 tunnel 配置版本摘要。
|
||||||
- Client 可拉取完整配置(relay 列表 + frpc 代理定义)。
|
- Client 可拉取完整配置(relay 列表 + frpc 代理定义)。
|
||||||
- Client 上报配置应用结果。
|
- Client 上报配置应用结果。
|
||||||
* **Admin Tunnel 管理 API** - `/api/tunnels/*`,要求 Admin Session。
|
* **Admin Tunnel 管理 API** - `/api/tunnels/*`,要求管理端 `OPENFLARE_TOKEN`。
|
||||||
- CRUD tunnel 实体(创建、查询、更新、删除)。
|
- CRUD tunnel 实体(创建、查询、更新、删除)。
|
||||||
- Token 管理(生成、轮换)。
|
- Token 管理(生成、轮换)。
|
||||||
- 强制同步(触发 Client 立即拉取新配置)。
|
- 强制同步(触发 Client 立即拉取新配置)。
|
||||||
* **Admin Pages 管理 API** - `/api/pages/*`,要求 Admin Session。
|
* **Admin Pages 管理 API** - `/api/pages/*`,要求管理端 `OPENFLARE_TOKEN`。
|
||||||
- CRUD Pages 项目,包括 SPA fallback 启用状态与回退路径。
|
- CRUD Pages 项目,包括 SPA fallback 启用状态与回退路径。
|
||||||
- 上传 zip 部署包、查看部署历史、激活部署、删除非激活部署。
|
- 上传 zip 部署包、查看部署历史、激活部署、删除非激活部署。
|
||||||
* **Agent Pages 下载 API** - `/api/agent/pages/*`,使用 `X-Agent-Token` 认证。
|
* **Agent Pages 下载 API** - `/api/agent/pages/*`,使用 `X-Agent-Token` 认证。
|
||||||
- Agent 仅能按激活配置引用的部署 ID 拉取静态部署包,不提供任意文件读取或远程命令入口。
|
- Agent 仅能按激活配置引用的部署 ID 拉取静态部署包,不提供任意文件读取或远程命令入口。
|
||||||
* 总览与节点详情优先使用专用聚合接口。
|
* 总览与节点详情优先使用专用聚合接口。
|
||||||
* 管理端变更类接口统一使用 `POST`;只读接口使用 `GET`。
|
* 管理端变更类接口统一使用 `POST`;只读接口使用 `GET`。
|
||||||
* 管理端继续复用现有登录、角色与 Session。
|
* 管理端登录成功后返回用户 token;管理端 API 只允许从 `OPENFLARE_TOKEN` 请求头读取登录凭证,不得通过 Cookie Session 放行。
|
||||||
* 第三方登录统一通过认证源 API 进入,认证源管理接口必须要求 Root Session。
|
* 第三方登录统一通过认证源 API 进入,认证源管理接口必须要求 Root 级 `OPENFLARE_TOKEN`。
|
||||||
* `/api/status` 只能返回已启用认证源的公开字段,不得返回 Client Secret。
|
* `/api/status` 只能返回已启用认证源的公开字段,不得返回 Client Secret。
|
||||||
* 第三方账号未绑定且注册关闭时,应提供绑定已有账号流程,不得自动创建用户。
|
* 第三方账号未绑定且注册关闭时,应提供绑定已有账号流程,不得自动创建用户。
|
||||||
* Agent/Relay/Client 正式请求统一使用对应的专属 token(`agent_token` / `relay_token`(即 agent_token) / `tunnel_token`)。
|
* Agent/Relay/Client 正式请求统一使用对应的专属 token(`agent_token` / `relay_token`(即 agent_token) / `tunnel_token`)。
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ OpenFlare 的管理端 API 与 Agent API 都使用 JSON。
|
|||||||
|
|
||||||
| 类型 | 约定 |
|
| 类型 | 约定 |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| 管理端 API | 由管理端 Session 鉴权 |
|
| 管理端 API | 由 `OPENFLARE_TOKEN` 请求头鉴权 |
|
||||||
| Agent API | 固定放在 `/api/agent/*` |
|
| Agent API | 固定放在 `/api/agent/*` |
|
||||||
| Relay API | 固定放在 `/api/relay/*`,使用 `X-Agent-Token` 鉴权(与 Agent 复用同一 token) |
|
| Relay API | 固定放在 `/api/relay/*`,使用 `X-Agent-Token` 鉴权(与 Agent 复用同一 token) |
|
||||||
| OpenFlared API | 固定放在 `/api/flared/*`,使用 `X-Tunnel-Token` 鉴权(独立的 tunnel_token) |
|
| OpenFlared API | 固定放在 `/api/flared/*`,使用 `X-Tunnel-Token` 鉴权(独立的 tunnel_token) |
|
||||||
@@ -29,7 +29,7 @@ OpenFlare 的管理端 API 与 Agent API 都使用 JSON。
|
|||||||
|
|
||||||
## WAF IP 组接口
|
## WAF IP 组接口
|
||||||
|
|
||||||
管理端 WAF IP 组接口统一要求管理端 Session 鉴权:
|
管理端 WAF IP 组接口统一要求管理端 `OPENFLARE_TOKEN` 鉴权:
|
||||||
|
|
||||||
| 方法 | 路径 | 说明 |
|
| 方法 | 路径 | 说明 |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
@@ -47,7 +47,13 @@ IP 组 `type` 支持 `manual`、`automatic`、`subscription`。自动型 IP 组
|
|||||||
|
|
||||||
## 鉴权
|
## 鉴权
|
||||||
|
|
||||||
管理端继续复用现有登录、角色与 Session。
|
管理端登录成功后返回用户 token,后续所有管理端 API 必须在请求头中携带:
|
||||||
|
|
||||||
|
```http
|
||||||
|
OPENFLARE_TOKEN: <token>
|
||||||
|
```
|
||||||
|
|
||||||
|
Server 只从 `OPENFLARE_TOKEN` 读取管理端登录凭证,不再通过 Cookie Session 放行管理端 API。角色和用户状态仍以数据库中的当前用户记录为准。
|
||||||
|
|
||||||
Agent 正式请求统一使用节点专属 `agent_token`,首次接入可使用全局 `discovery_token`。Agent 请求头固定为:
|
Agent 正式请求统一使用节点专属 `agent_token`,首次接入可使用全局 `discovery_token`。Agent 请求头固定为:
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ go run . --port 3000 --log-dir ./logs
|
|||||||
| `PORT` | Server 监听端口 | `3000` |
|
| `PORT` | Server 监听端口 | `3000` |
|
||||||
| `GIN_MODE` | Gin 运行模式 | 非 `debug` 时按 release |
|
| `GIN_MODE` | Gin 运行模式 | 非 `debug` 时按 release |
|
||||||
| `LOG_LEVEL` | 日志等级 | `info` |
|
| `LOG_LEVEL` | 日志等级 | `info` |
|
||||||
| `SESSION_SECRET` | Session 签名密钥 | 启动时随机生成 |
|
| `SESSION_SECRET` | 临时 Session 签名密钥,主要用于 OAuth 状态等非管理端 API 鉴权流程 | 启动时随机生成 |
|
||||||
| `SQLITE_PATH` | SQLite 数据库文件路径 | `openflare.db` |
|
| `SQLITE_PATH` | SQLite 数据库文件路径 | `openflare.db` |
|
||||||
| `DSN` | PostgreSQL DSN,设置后优先于 SQLite | 空 |
|
| `DSN` | PostgreSQL DSN,设置后优先于 SQLite | 空 |
|
||||||
| `SQL_DSN` | 兼容旧命名的 PostgreSQL DSN,优先级低于 `DSN` | 空 |
|
| `SQL_DSN` | 兼容旧命名的 PostgreSQL DSN,优先级低于 `DSN` | 空 |
|
||||||
@@ -76,7 +76,7 @@ go run . --port 3000 --log-dir ./logs
|
|||||||
* `DSN` 与 `SQL_DSN` 同时存在时优先使用 `DSN`。
|
* `DSN` 与 `SQL_DSN` 同时存在时优先使用 `DSN`。
|
||||||
* `DSN` 或 `SQL_DSN` 与 `SQLITE_PATH` 同时存在时优先使用 PostgreSQL。
|
* `DSN` 或 `SQL_DSN` 与 `SQLITE_PATH` 同时存在时优先使用 PostgreSQL。
|
||||||
* 当目标 PostgreSQL 数据库为空且本地 `SQLITE_PATH` 文件存在时,Server 启动阶段会自动迁移 SQLite 数据,并在日志中输出按表迁移进度。
|
* 当目标 PostgreSQL 数据库为空且本地 `SQLITE_PATH` 文件存在时,Server 启动阶段会自动迁移 SQLite 数据,并在日志中输出按表迁移进度。
|
||||||
* `SESSION_SECRET` 生产环境必须显式配置。
|
* `SESSION_SECRET` 生产环境建议显式配置,避免 OAuth 授权状态等临时会话在重启后失效;管理端 API 登录凭证不再通过 Cookie Session 传递,而是使用 `OPENFLARE_TOKEN` 请求头。
|
||||||
* `REDIS_CONN_STRING` 未配置时,相关能力回退为进程内实现。
|
* `REDIS_CONN_STRING` 未配置时,相关能力回退为进程内实现。
|
||||||
|
|
||||||
## 运行时 Option
|
## 运行时 Option
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
// @Summary List access logs
|
// @Summary List access logs
|
||||||
// @Tags AccessLogs
|
// @Tags AccessLogs
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param node_id query string false "Node ID"
|
// @Param node_id query string false "Node ID"
|
||||||
// @Param remote_addr query string false "Remote address"
|
// @Param remote_addr query string false "Remote address"
|
||||||
// @Param host query string false "Host"
|
// @Param host query string false "Host"
|
||||||
@@ -35,7 +35,7 @@ func GetAccessLogs(c *gin.Context) {
|
|||||||
// @Summary List folded access logs
|
// @Summary List folded access logs
|
||||||
// @Tags AccessLogs
|
// @Tags AccessLogs
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param node_id query string false "Node ID"
|
// @Param node_id query string false "Node ID"
|
||||||
// @Param remote_addr query string false "Remote address"
|
// @Param remote_addr query string false "Remote address"
|
||||||
// @Param host query string false "Host"
|
// @Param host query string false "Host"
|
||||||
@@ -62,7 +62,7 @@ func GetFoldedAccessLogs(c *gin.Context) {
|
|||||||
// @Summary List folded access log IP summaries
|
// @Summary List folded access log IP summaries
|
||||||
// @Tags AccessLogs
|
// @Tags AccessLogs
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param node_id query string false "Node ID"
|
// @Param node_id query string false "Node ID"
|
||||||
// @Param remote_addr query string false "Remote address"
|
// @Param remote_addr query string false "Remote address"
|
||||||
// @Param host query string false "Host"
|
// @Param host query string false "Host"
|
||||||
@@ -99,7 +99,7 @@ func GetFoldedAccessLogIPs(c *gin.Context) {
|
|||||||
// @Summary List access log IP summaries
|
// @Summary List access log IP summaries
|
||||||
// @Tags AccessLogs
|
// @Tags AccessLogs
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param node_id query string false "Node ID"
|
// @Param node_id query string false "Node ID"
|
||||||
// @Param remote_addr query string false "Remote address"
|
// @Param remote_addr query string false "Remote address"
|
||||||
// @Param host query string false "Host"
|
// @Param host query string false "Host"
|
||||||
@@ -130,7 +130,7 @@ func GetAccessLogIPSummaries(c *gin.Context) {
|
|||||||
// @Summary Get access log IP trend
|
// @Summary Get access log IP trend
|
||||||
// @Tags AccessLogs
|
// @Tags AccessLogs
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param node_id query string false "Node ID"
|
// @Param node_id query string false "Node ID"
|
||||||
// @Param remote_addr query string true "Remote address"
|
// @Param remote_addr query string true "Remote address"
|
||||||
// @Param host query string false "Host"
|
// @Param host query string false "Host"
|
||||||
@@ -158,7 +158,7 @@ func GetAccessLogIPTrend(c *gin.Context) {
|
|||||||
// @Tags AccessLogs
|
// @Tags AccessLogs
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/access-logs/cleanup [post]
|
// @Router /api/access-logs/cleanup [post]
|
||||||
func CleanupAccessLogs(c *gin.Context) {
|
func CleanupAccessLogs(c *gin.Context) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
// @Summary Get default ACME account
|
// @Summary Get default ACME account
|
||||||
// @Tags AcmeAccounts
|
// @Tags AcmeAccounts
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/acme-accounts/default [get]
|
// @Router /api/acme-accounts/default [get]
|
||||||
func GetDefaultAcmeAccount(c *gin.Context) {
|
func GetDefaultAcmeAccount(c *gin.Context) {
|
||||||
|
|||||||
@@ -296,7 +296,7 @@ func handleAgentWSStatus(c *gin.Context, node *model.Node, message service.Agent
|
|||||||
// @Summary List nodes
|
// @Summary List nodes
|
||||||
// @Tags Nodes
|
// @Tags Nodes
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/nodes/ [get]
|
// @Router /api/nodes/ [get]
|
||||||
func GetNodes(c *gin.Context) {
|
func GetNodes(c *gin.Context) {
|
||||||
@@ -312,7 +312,7 @@ func GetNodes(c *gin.Context) {
|
|||||||
// @Summary List apply logs
|
// @Summary List apply logs
|
||||||
// @Tags ApplyLogs
|
// @Tags ApplyLogs
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param node_id query string false "Node ID"
|
// @Param node_id query string false "Node ID"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/apply-logs/ [get]
|
// @Router /api/apply-logs/ [get]
|
||||||
@@ -334,7 +334,7 @@ func GetApplyLogs(c *gin.Context) {
|
|||||||
// @Tags ApplyLogs
|
// @Tags ApplyLogs
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/apply-logs/cleanup [post]
|
// @Router /api/apply-logs/cleanup [post]
|
||||||
func CleanupApplyLogs(c *gin.Context) {
|
func CleanupApplyLogs(c *gin.Context) {
|
||||||
|
|||||||
@@ -199,10 +199,8 @@ func OAuthCallback(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
var currentUserID *int
|
var currentUserID *int
|
||||||
if value := session.Get("id"); value != nil {
|
if currentUser := currentUserFromOpenFlareToken(c); currentUser != nil {
|
||||||
if idValue, ok := value.(int); ok {
|
currentUserID = ¤tUser.Id
|
||||||
currentUserID = &idValue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
result, pending, err := service.CompleteOAuthLogin(source, profile, currentUserID)
|
result, pending, err := service.CompleteOAuthLogin(source, profile, currentUserID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -224,7 +222,7 @@ func OAuthCallback(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if result.User != nil {
|
if result.User != nil {
|
||||||
cleanUser, err := setLoginSession(result.User, c)
|
cleanUser, err := setLoginToken(result.User)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondFailure(c, "无法保存会话信息,请重试")
|
respondFailure(c, "无法保存会话信息,请重试")
|
||||||
return
|
return
|
||||||
@@ -261,7 +259,7 @@ func LinkExistingOAuthAccount(c *gin.Context) {
|
|||||||
respondFailure(c, "无法更新会话信息,请重试")
|
respondFailure(c, "无法更新会话信息,请重试")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cleanUser, err := setLoginSession(user, c)
|
cleanUser, err := setLoginToken(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondFailure(c, "无法保存会话信息,请重试")
|
respondFailure(c, "无法保存会话信息,请重试")
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
// @Summary List config versions
|
// @Summary List config versions
|
||||||
// @Tags ConfigVersions
|
// @Tags ConfigVersions
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/config-versions/ [get]
|
// @Router /api/config-versions/ [get]
|
||||||
func GetConfigVersions(c *gin.Context) {
|
func GetConfigVersions(c *gin.Context) {
|
||||||
@@ -26,7 +26,7 @@ func GetConfigVersions(c *gin.Context) {
|
|||||||
// @Summary Get config version detail
|
// @Summary Get config version detail
|
||||||
// @Tags ConfigVersions
|
// @Tags ConfigVersions
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Version ID"
|
// @Param id path int true "Version ID"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
@@ -48,7 +48,7 @@ func GetConfigVersion(c *gin.Context) {
|
|||||||
// @Summary Get active config version
|
// @Summary Get active config version
|
||||||
// @Tags ConfigVersions
|
// @Tags ConfigVersions
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/config-versions/active [get]
|
// @Router /api/config-versions/active [get]
|
||||||
func GetActiveConfigVersion(c *gin.Context) {
|
func GetActiveConfigVersion(c *gin.Context) {
|
||||||
@@ -64,7 +64,7 @@ func GetActiveConfigVersion(c *gin.Context) {
|
|||||||
// @Summary Preview config rendering
|
// @Summary Preview config rendering
|
||||||
// @Tags ConfigVersions
|
// @Tags ConfigVersions
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/config-versions/preview [get]
|
// @Router /api/config-versions/preview [get]
|
||||||
func PreviewConfigVersion(c *gin.Context) {
|
func PreviewConfigVersion(c *gin.Context) {
|
||||||
@@ -80,7 +80,7 @@ func PreviewConfigVersion(c *gin.Context) {
|
|||||||
// @Summary Diff current draft against active version
|
// @Summary Diff current draft against active version
|
||||||
// @Tags ConfigVersions
|
// @Tags ConfigVersions
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/config-versions/diff [get]
|
// @Router /api/config-versions/diff [get]
|
||||||
func DiffConfigVersion(c *gin.Context) {
|
func DiffConfigVersion(c *gin.Context) {
|
||||||
@@ -96,7 +96,7 @@ func DiffConfigVersion(c *gin.Context) {
|
|||||||
// @Summary Publish a new config version
|
// @Summary Publish a new config version
|
||||||
// @Tags ConfigVersions
|
// @Tags ConfigVersions
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/config-versions/publish [post]
|
// @Router /api/config-versions/publish [post]
|
||||||
func PublishConfigVersion(c *gin.Context) {
|
func PublishConfigVersion(c *gin.Context) {
|
||||||
@@ -114,7 +114,7 @@ func PublishConfigVersion(c *gin.Context) {
|
|||||||
// @Summary Activate an existing config version
|
// @Summary Activate an existing config version
|
||||||
// @Tags ConfigVersions
|
// @Tags ConfigVersions
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Version ID"
|
// @Param id path int true "Version ID"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
@@ -140,7 +140,7 @@ type CleanupConfigVersionRequest struct {
|
|||||||
// @Summary Cleanup old config versions
|
// @Summary Cleanup old config versions
|
||||||
// @Tags ConfigVersions
|
// @Tags ConfigVersions
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param request body CleanupConfigVersionRequest true "Cleanup request"
|
// @Param request body CleanupConfigVersionRequest true "Cleanup request"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ type dashboardTrendsPayload struct {
|
|||||||
// @Summary Get dashboard overview
|
// @Summary Get dashboard overview
|
||||||
// @Tags Dashboard
|
// @Tags Dashboard
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
// @Router /api/dashboard/overview [get]
|
// @Router /api/dashboard/overview [get]
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
// @Tags Options
|
// @Tags Options
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/option/database/cleanup [post]
|
// @Router /api/option/database/cleanup [post]
|
||||||
func CleanupDatabaseObservability(c *gin.Context) {
|
func CleanupDatabaseObservability(c *gin.Context) {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ type DnsAccountInput struct {
|
|||||||
// @Summary List DNS accounts
|
// @Summary List DNS accounts
|
||||||
// @Tags DnsAccounts
|
// @Tags DnsAccounts
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/dns-accounts/ [get]
|
// @Router /api/dns-accounts/ [get]
|
||||||
func GetDnsAccounts(c *gin.Context) {
|
func GetDnsAccounts(c *gin.Context) {
|
||||||
@@ -33,7 +33,7 @@ func GetDnsAccounts(c *gin.Context) {
|
|||||||
// @Tags DnsAccounts
|
// @Tags DnsAccounts
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param payload body DnsAccountInput true "DNS account payload"
|
// @Param payload body DnsAccountInput true "DNS account payload"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/dns-accounts/ [post]
|
// @Router /api/dns-accounts/ [post]
|
||||||
@@ -62,7 +62,7 @@ func CreateDnsAccount(c *gin.Context) {
|
|||||||
// @Tags DnsAccounts
|
// @Tags DnsAccounts
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "DNS Account ID"
|
// @Param id path int true "DNS Account ID"
|
||||||
// @Param payload body DnsAccountInput true "DNS account payload"
|
// @Param payload body DnsAccountInput true "DNS account payload"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
@@ -100,7 +100,7 @@ func UpdateDnsAccount(c *gin.Context) {
|
|||||||
// @Summary Delete DNS account
|
// @Summary Delete DNS account
|
||||||
// @Tags DnsAccounts
|
// @Tags DnsAccounts
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "DNS Account ID"
|
// @Param id path int true "DNS Account ID"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/dns-accounts/{id}/delete [post]
|
// @Router /api/dns-accounts/{id}/delete [post]
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"openflare/model"
|
"openflare/model"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gin-contrib/sessions"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -79,9 +78,7 @@ func getGitHubUserInfoByCode(code string) (*GitHubUser, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GitHubOAuth(c *gin.Context) {
|
func GitHubOAuth(c *gin.Context) {
|
||||||
session := sessions.Default(c)
|
if currentUserFromOpenFlareToken(c) != nil {
|
||||||
username := session.Get("username")
|
|
||||||
if username != nil {
|
|
||||||
GitHubBind(c)
|
GitHubBind(c)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -135,10 +132,12 @@ func GitHubBind(c *gin.Context) {
|
|||||||
respondFailure(c, "该 GitHub 账户已被绑定")
|
respondFailure(c, "该 GitHub 账户已被绑定")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
session := sessions.Default(c)
|
currentUser := currentUserFromOpenFlareToken(c)
|
||||||
id := session.Get("id")
|
if currentUser == nil {
|
||||||
// id := c.GetInt("id") // critical bug!
|
respondFailure(c, "无权进行此操作,未登录或 token 无效")
|
||||||
user.Id = id.(int)
|
return
|
||||||
|
}
|
||||||
|
user.Id = currentUser.Id
|
||||||
err = user.FillUserById()
|
err = user.FillUserById()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondFailure(c, err.Error())
|
respondFailure(c, err.Error())
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
// @Summary List managed domains
|
// @Summary List managed domains
|
||||||
// @Tags ManagedDomains
|
// @Tags ManagedDomains
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/managed-domains/ [get]
|
// @Router /api/managed-domains/ [get]
|
||||||
func GetManagedDomains(c *gin.Context) {
|
func GetManagedDomains(c *gin.Context) {
|
||||||
@@ -28,7 +28,7 @@ func GetManagedDomains(c *gin.Context) {
|
|||||||
// @Tags ManagedDomains
|
// @Tags ManagedDomains
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param payload body service.ManagedDomainInput true "Managed domain payload"
|
// @Param payload body service.ManagedDomainInput true "Managed domain payload"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
@@ -51,7 +51,7 @@ func CreateManagedDomain(c *gin.Context) {
|
|||||||
// @Tags ManagedDomains
|
// @Tags ManagedDomains
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Managed domain ID"
|
// @Param id path int true "Managed domain ID"
|
||||||
// @Param payload body service.ManagedDomainInput true "Managed domain payload"
|
// @Param payload body service.ManagedDomainInput true "Managed domain payload"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
@@ -78,7 +78,7 @@ func UpdateManagedDomain(c *gin.Context) {
|
|||||||
// @Summary Delete managed domain
|
// @Summary Delete managed domain
|
||||||
// @Tags ManagedDomains
|
// @Tags ManagedDomains
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Managed domain ID"
|
// @Param id path int true "Managed domain ID"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
@@ -99,7 +99,7 @@ func DeleteManagedDomain(c *gin.Context) {
|
|||||||
// @Summary Match certificate for domain
|
// @Summary Match certificate for domain
|
||||||
// @Tags ManagedDomains
|
// @Tags ManagedDomains
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param domain query string true "Domain"
|
// @Param domain query string true "Domain"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/managed-domains/match [get]
|
// @Router /api/managed-domains/match [get]
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ type nodeObservabilityQuery struct {
|
|||||||
// @Tags Nodes
|
// @Tags Nodes
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param payload body service.NodeInput true "Node payload"
|
// @Param payload body service.NodeInput true "Node payload"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
@@ -44,7 +44,7 @@ func CreateNode(c *gin.Context) {
|
|||||||
// @Summary Get global discovery token
|
// @Summary Get global discovery token
|
||||||
// @Tags Nodes
|
// @Tags Nodes
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/nodes/bootstrap-token [get]
|
// @Router /api/nodes/bootstrap-token [get]
|
||||||
func GetNodeBootstrapToken(c *gin.Context) {
|
func GetNodeBootstrapToken(c *gin.Context) {
|
||||||
@@ -60,7 +60,7 @@ func GetNodeBootstrapToken(c *gin.Context) {
|
|||||||
// @Summary Rotate global discovery token
|
// @Summary Rotate global discovery token
|
||||||
// @Tags Nodes
|
// @Tags Nodes
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/nodes/bootstrap-token/rotate [post]
|
// @Router /api/nodes/bootstrap-token/rotate [post]
|
||||||
func RotateNodeBootstrapToken(c *gin.Context) {
|
func RotateNodeBootstrapToken(c *gin.Context) {
|
||||||
@@ -77,7 +77,7 @@ func RotateNodeBootstrapToken(c *gin.Context) {
|
|||||||
// @Tags Nodes
|
// @Tags Nodes
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Node ID"
|
// @Param id path int true "Node ID"
|
||||||
// @Param payload body service.NodeInput true "Node payload"
|
// @Param payload body service.NodeInput true "Node payload"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
@@ -106,7 +106,7 @@ func UpdateNode(c *gin.Context) {
|
|||||||
// @Summary Delete node
|
// @Summary Delete node
|
||||||
// @Tags Nodes
|
// @Tags Nodes
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Node ID"
|
// @Param id path int true "Node ID"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
@@ -128,7 +128,7 @@ func DeleteNode(c *gin.Context) {
|
|||||||
// @Summary Request agent self-update on node
|
// @Summary Request agent self-update on node
|
||||||
// @Tags Nodes
|
// @Tags Nodes
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Node ID"
|
// @Param id path int true "Node ID"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
@@ -162,7 +162,7 @@ func RequestNodeAgentUpdate(c *gin.Context) {
|
|||||||
// @Summary Request openresty restart on node
|
// @Summary Request openresty restart on node
|
||||||
// @Tags Nodes
|
// @Tags Nodes
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Node ID"
|
// @Param id path int true "Node ID"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
@@ -185,7 +185,7 @@ func RequestNodeOpenrestyRestart(c *gin.Context) {
|
|||||||
// @Summary Request force sync config on node
|
// @Summary Request force sync config on node
|
||||||
// @Tags Nodes
|
// @Tags Nodes
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Node ID"
|
// @Param id path int true "Node ID"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
@@ -208,7 +208,7 @@ func RequestNodeForceSync(c *gin.Context) {
|
|||||||
// @Summary Check latest agent release for node
|
// @Summary Check latest agent release for node
|
||||||
// @Tags Nodes
|
// @Tags Nodes
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Node ID"
|
// @Param id path int true "Node ID"
|
||||||
// @Param channel query string false "stable or preview"
|
// @Param channel query string false "stable or preview"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
@@ -232,7 +232,7 @@ func GetNodeAgentRelease(c *gin.Context) {
|
|||||||
// @Summary Get node observability details
|
// @Summary Get node observability details
|
||||||
// @Tags Nodes
|
// @Tags Nodes
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Node ID"
|
// @Param id path int true "Node ID"
|
||||||
// @Param hours query int false "Lookback window in hours"
|
// @Param hours query int false "Lookback window in hours"
|
||||||
// @Param limit query int false "Max records per section"
|
// @Param limit query int false "Max records per section"
|
||||||
@@ -266,7 +266,7 @@ func GetNodeObservability(c *gin.Context) {
|
|||||||
// @Summary Cleanup node health events
|
// @Summary Cleanup node health events
|
||||||
// @Tags Nodes
|
// @Tags Nodes
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Node ID"
|
// @Param id path int true "Node ID"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
// @Summary List proxy routes
|
// @Summary List proxy routes
|
||||||
// @Tags ProxyRoutes
|
// @Tags ProxyRoutes
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/proxy-routes/ [get]
|
// @Router /api/proxy-routes/ [get]
|
||||||
func GetProxyRoutes(c *gin.Context) {
|
func GetProxyRoutes(c *gin.Context) {
|
||||||
@@ -26,7 +26,7 @@ func GetProxyRoutes(c *gin.Context) {
|
|||||||
// @Summary Get proxy route detail
|
// @Summary Get proxy route detail
|
||||||
// @Tags ProxyRoutes
|
// @Tags ProxyRoutes
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Route ID"
|
// @Param id path int true "Route ID"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
@@ -49,7 +49,7 @@ func GetProxyRoute(c *gin.Context) {
|
|||||||
// @Tags ProxyRoutes
|
// @Tags ProxyRoutes
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param payload body service.ProxyRouteInput true "Proxy route payload"
|
// @Param payload body service.ProxyRouteInput true "Proxy route payload"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
@@ -72,7 +72,7 @@ func CreateProxyRoute(c *gin.Context) {
|
|||||||
// @Tags ProxyRoutes
|
// @Tags ProxyRoutes
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Route ID"
|
// @Param id path int true "Route ID"
|
||||||
// @Param payload body service.ProxyRouteInput true "Proxy route payload"
|
// @Param payload body service.ProxyRouteInput true "Proxy route payload"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
@@ -99,7 +99,7 @@ func UpdateProxyRoute(c *gin.Context) {
|
|||||||
// @Summary Delete proxy route
|
// @Summary Delete proxy route
|
||||||
// @Tags ProxyRoutes
|
// @Tags ProxyRoutes
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Route ID"
|
// @Param id path int true "Route ID"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
// @Summary List TLS certificates
|
// @Summary List TLS certificates
|
||||||
// @Tags TLSCertificates
|
// @Tags TLSCertificates
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/tls-certificates/ [get]
|
// @Router /api/tls-certificates/ [get]
|
||||||
func GetTLSCertificates(c *gin.Context) {
|
func GetTLSCertificates(c *gin.Context) {
|
||||||
@@ -26,7 +26,7 @@ func GetTLSCertificates(c *gin.Context) {
|
|||||||
// @Summary Get TLS certificate detail
|
// @Summary Get TLS certificate detail
|
||||||
// @Tags TLSCertificates
|
// @Tags TLSCertificates
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Certificate ID"
|
// @Param id path int true "Certificate ID"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
@@ -49,7 +49,7 @@ func GetTLSCertificate(c *gin.Context) {
|
|||||||
// @Summary Get TLS certificate PEM content
|
// @Summary Get TLS certificate PEM content
|
||||||
// @Tags TLSCertificates
|
// @Tags TLSCertificates
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Certificate ID"
|
// @Param id path int true "Certificate ID"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
@@ -73,7 +73,7 @@ func GetTLSCertificateContent(c *gin.Context) {
|
|||||||
// @Tags TLSCertificates
|
// @Tags TLSCertificates
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param payload body service.TLSCertificateInput true "TLS certificate payload"
|
// @Param payload body service.TLSCertificateInput true "TLS certificate payload"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
@@ -96,7 +96,7 @@ func CreateTLSCertificate(c *gin.Context) {
|
|||||||
// @Tags TLSCertificates
|
// @Tags TLSCertificates
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Certificate ID"
|
// @Param id path int true "Certificate ID"
|
||||||
// @Param payload body service.TLSCertificateInput true "TLS certificate payload"
|
// @Param payload body service.TLSCertificateInput true "TLS certificate payload"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
@@ -126,7 +126,7 @@ func UpdateTLSCertificate(c *gin.Context) {
|
|||||||
// @Tags TLSCertificates
|
// @Tags TLSCertificates
|
||||||
// @Accept multipart/form-data
|
// @Accept multipart/form-data
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param name formData string true "Certificate name"
|
// @Param name formData string true "Certificate name"
|
||||||
// @Param remark formData string false "Remark"
|
// @Param remark formData string false "Remark"
|
||||||
// @Param cert_file formData file true "Certificate file"
|
// @Param cert_file formData file true "Certificate file"
|
||||||
@@ -159,7 +159,7 @@ func ImportTLSCertificateFile(c *gin.Context) {
|
|||||||
// @Summary Delete TLS certificate
|
// @Summary Delete TLS certificate
|
||||||
// @Tags TLSCertificates
|
// @Tags TLSCertificates
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Certificate ID"
|
// @Param id path int true "Certificate ID"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
@@ -181,7 +181,7 @@ func DeleteTLSCertificate(c *gin.Context) {
|
|||||||
// @Tags TLSCertificates
|
// @Tags TLSCertificates
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param payload body service.TLSApplyInput true "TLS apply payload"
|
// @Param payload body service.TLSApplyInput true "TLS apply payload"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
@@ -204,7 +204,7 @@ func ApplyTLSCertificate(c *gin.Context) {
|
|||||||
// @Tags TLSCertificates
|
// @Tags TLSCertificates
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Certificate ID"
|
// @Param id path int true "Certificate ID"
|
||||||
// @Param payload body service.TLSApplyInput true "TLS apply payload"
|
// @Param payload body service.TLSApplyInput true "TLS apply payload"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
@@ -233,7 +233,7 @@ func UpdateAcmeCertificate(c *gin.Context) {
|
|||||||
// @Tags TLSCertificates
|
// @Tags TLSCertificates
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Certificate ID"
|
// @Param id path int true "Certificate ID"
|
||||||
// @Param payload body service.TLSApplyInput true "TLS apply payload"
|
// @Param payload body service.TLSApplyInput true "TLS apply payload"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
@@ -261,7 +261,7 @@ func ConvertTLSCertificateToAcme(c *gin.Context) {
|
|||||||
// @Summary Renew TLS certificate
|
// @Summary Renew TLS certificate
|
||||||
// @Tags TLSCertificates
|
// @Tags TLSCertificates
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Param id path int true "Certificate ID"
|
// @Param id path int true "Certificate ID"
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Failure 400 {object} map[string]interface{}
|
// @Failure 400 {object} map[string]interface{}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ type serverUpgradeRequest struct {
|
|||||||
// @Summary Get latest GitHub release
|
// @Summary Get latest GitHub release
|
||||||
// @Tags Update
|
// @Tags Update
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/update/latest-release [get]
|
// @Router /api/update/latest-release [get]
|
||||||
func GetLatestRelease(c *gin.Context) {
|
func GetLatestRelease(c *gin.Context) {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
// @Tags UptimeKuma
|
// @Tags UptimeKuma
|
||||||
// @Accept json
|
// @Accept json
|
||||||
// @Produce json
|
// @Produce json
|
||||||
// @Security BearerAuth
|
// @Security OpenFlareTokenAuth
|
||||||
// @Success 200 {object} map[string]interface{}
|
// @Success 200 {object} map[string]interface{}
|
||||||
// @Router /api/uptimekuma/sync [post]
|
// @Router /api/uptimekuma/sync [post]
|
||||||
func SyncUptimeKuma(c *gin.Context) {
|
func SyncUptimeKuma(c *gin.Context) {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package controller
|
package controller
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"openflare/common"
|
"openflare/common"
|
||||||
"openflare/model"
|
"openflare/model"
|
||||||
"openflare/utils/security"
|
"openflare/utils/security"
|
||||||
@@ -8,7 +9,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/gin-contrib/sessions"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
)
|
)
|
||||||
@@ -45,14 +45,9 @@ func Login(c *gin.Context) {
|
|||||||
setupLogin(&user, c)
|
setupLogin(&user, c)
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup session & cookies and then return user info
|
// setup token and then return user info
|
||||||
func setLoginSession(user *model.User, c *gin.Context) (*model.User, error) {
|
func setLoginToken(user *model.User) (*model.User, error) {
|
||||||
session := sessions.Default(c)
|
token, err := ensureUserOpenFlareToken(user)
|
||||||
session.Set("id", user.Id)
|
|
||||||
session.Set("username", user.Username)
|
|
||||||
session.Set("role", user.Role)
|
|
||||||
session.Set("status", user.Status)
|
|
||||||
err := session.Save()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -62,12 +57,13 @@ func setLoginSession(user *model.User, c *gin.Context) (*model.User, error) {
|
|||||||
DisplayName: user.DisplayName,
|
DisplayName: user.DisplayName,
|
||||||
Role: user.Role,
|
Role: user.Role,
|
||||||
Status: user.Status,
|
Status: user.Status,
|
||||||
|
Token: token,
|
||||||
}
|
}
|
||||||
return cleanUser, nil
|
return cleanUser, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupLogin(user *model.User, c *gin.Context) {
|
func setupLogin(user *model.User, c *gin.Context) {
|
||||||
cleanUser, err := setLoginSession(user, c)
|
cleanUser, err := setLoginToken(user)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
respondFailure(c, "无法保存会话信息,请重试")
|
respondFailure(c, "无法保存会话信息,请重试")
|
||||||
return
|
return
|
||||||
@@ -76,16 +72,45 @@ func setupLogin(user *model.User, c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Logout(c *gin.Context) {
|
func Logout(c *gin.Context) {
|
||||||
session := sessions.Default(c)
|
token := c.GetHeader("OPENFLARE_TOKEN")
|
||||||
session.Clear()
|
if token != "" {
|
||||||
err := session.Save()
|
user := model.ValidateUserToken(token)
|
||||||
if err != nil {
|
if user != nil && user.Id != 0 {
|
||||||
respondFailure(c, err.Error())
|
if err := model.DB.Model(user).Update("token", "").Error; err != nil {
|
||||||
return
|
respondFailure(c, err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
respondSuccessMessage(c, "")
|
respondSuccessMessage(c, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ensureUserOpenFlareToken(user *model.User) (string, error) {
|
||||||
|
if user.Token != "" {
|
||||||
|
return user.Token, nil
|
||||||
|
}
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
token := strings.Replace(uuid.New().String(), "-", "", -1)
|
||||||
|
if model.DB.Where("token = ?", token).First(&model.User{}).RowsAffected != 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := model.DB.Model(user).Update("token", token).Error; err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
user.Token = token
|
||||||
|
return token, nil
|
||||||
|
}
|
||||||
|
return "", errors.New("生成登录凭证失败,请重试")
|
||||||
|
}
|
||||||
|
|
||||||
|
func currentUserFromOpenFlareToken(c *gin.Context) *model.User {
|
||||||
|
token := c.GetHeader("OPENFLARE_TOKEN")
|
||||||
|
if token == "" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return model.ValidateUserToken(token)
|
||||||
|
}
|
||||||
|
|
||||||
func Register(c *gin.Context) {
|
func Register(c *gin.Context) {
|
||||||
respondFailure(c, "非法请求")
|
respondFailure(c, "非法请求")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -94,7 +94,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -122,7 +122,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -203,7 +203,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -292,7 +292,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -361,7 +361,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -419,7 +419,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -667,7 +667,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -700,7 +700,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -728,7 +728,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -753,7 +753,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -778,7 +778,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -821,7 +821,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -846,7 +846,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -871,7 +871,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -896,7 +896,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -937,7 +937,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -978,7 +978,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1010,7 +1010,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1033,7 +1033,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -1072,7 +1072,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1106,7 +1106,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -1276,7 +1276,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1299,7 +1299,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -1345,7 +1345,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1379,7 +1379,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1420,7 +1420,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -1473,7 +1473,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1496,7 +1496,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -1542,7 +1542,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1567,7 +1567,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1592,7 +1592,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1639,7 +1639,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1680,7 +1680,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1721,7 +1721,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1762,7 +1762,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1815,7 +1815,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1856,7 +1856,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1897,7 +1897,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -1970,7 +1970,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2121,7 +2121,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -2144,7 +2144,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2190,7 +2190,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -2231,7 +2231,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -2272,7 +2272,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2405,7 +2405,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -2428,7 +2428,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2474,7 +2474,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2520,7 +2520,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2584,7 +2584,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -2625,7 +2625,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -2666,7 +2666,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2719,7 +2719,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -2760,7 +2760,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -2801,7 +2801,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2854,7 +2854,7 @@ const docTemplate = `{
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2907,7 +2907,7 @@ const docTemplate = `{
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -3761,10 +3761,10 @@ const docTemplate = `{
|
|||||||
"name": "X-Agent-Token",
|
"name": "X-Agent-Token",
|
||||||
"in": "header"
|
"in": "header"
|
||||||
},
|
},
|
||||||
"BearerAuth": {
|
"OpenFlareTokenAuth": {
|
||||||
"description": "管理端可使用 Bearer Token,例如:Bearer \u003ctoken\u003e",
|
"description": "管理端 API 使用登录后返回的用户 Token",
|
||||||
"type": "apiKey",
|
"type": "apiKey",
|
||||||
"name": "Authorization",
|
"name": "OPENFLARE_TOKEN",
|
||||||
"in": "header"
|
"in": "header"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -119,7 +119,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -200,7 +200,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -289,7 +289,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -358,7 +358,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -416,7 +416,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -664,7 +664,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -697,7 +697,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -725,7 +725,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -750,7 +750,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -775,7 +775,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -818,7 +818,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -843,7 +843,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -868,7 +868,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -893,7 +893,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -934,7 +934,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -975,7 +975,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1007,7 +1007,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1030,7 +1030,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -1069,7 +1069,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1103,7 +1103,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -1273,7 +1273,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1296,7 +1296,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -1342,7 +1342,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1376,7 +1376,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1417,7 +1417,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -1470,7 +1470,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1493,7 +1493,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -1539,7 +1539,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1564,7 +1564,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1589,7 +1589,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1636,7 +1636,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1677,7 +1677,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1718,7 +1718,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1759,7 +1759,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1812,7 +1812,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1853,7 +1853,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -1894,7 +1894,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -1967,7 +1967,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2118,7 +2118,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -2141,7 +2141,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2187,7 +2187,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -2228,7 +2228,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -2269,7 +2269,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2402,7 +2402,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -2425,7 +2425,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2471,7 +2471,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2517,7 +2517,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2581,7 +2581,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -2622,7 +2622,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -2663,7 +2663,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2716,7 +2716,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -2757,7 +2757,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -2798,7 +2798,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2851,7 +2851,7 @@
|
|||||||
"post": {
|
"post": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"consumes": [
|
"consumes": [
|
||||||
@@ -2904,7 +2904,7 @@
|
|||||||
"get": {
|
"get": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
"BearerAuth": []
|
"OpenFlareTokenAuth": []
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"produces": [
|
"produces": [
|
||||||
@@ -3758,10 +3758,10 @@
|
|||||||
"name": "X-Agent-Token",
|
"name": "X-Agent-Token",
|
||||||
"in": "header"
|
"in": "header"
|
||||||
},
|
},
|
||||||
"BearerAuth": {
|
"OpenFlareTokenAuth": {
|
||||||
"description": "管理端可使用 Bearer Token,例如:Bearer \u003ctoken\u003e",
|
"description": "管理端 API 使用登录后返回的用户 Token",
|
||||||
"type": "apiKey",
|
"type": "apiKey",
|
||||||
"name": "Authorization",
|
"name": "OPENFLARE_TOKEN",
|
||||||
"in": "header"
|
"in": "header"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -541,7 +541,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: List access logs
|
summary: List access logs
|
||||||
tags:
|
tags:
|
||||||
- AccessLogs
|
- AccessLogs
|
||||||
@@ -558,7 +558,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Cleanup access logs by retention days
|
summary: Cleanup access logs by retention days
|
||||||
tags:
|
tags:
|
||||||
- AccessLogs
|
- AccessLogs
|
||||||
@@ -610,7 +610,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: List folded access logs
|
summary: List folded access logs
|
||||||
tags:
|
tags:
|
||||||
- AccessLogs
|
- AccessLogs
|
||||||
@@ -668,7 +668,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: List folded access log IP summaries
|
summary: List folded access log IP summaries
|
||||||
tags:
|
tags:
|
||||||
- AccessLogs
|
- AccessLogs
|
||||||
@@ -712,7 +712,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: List access log IP summaries
|
summary: List access log IP summaries
|
||||||
tags:
|
tags:
|
||||||
- AccessLogs
|
- AccessLogs
|
||||||
@@ -749,7 +749,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Get access log IP trend
|
summary: Get access log IP trend
|
||||||
tags:
|
tags:
|
||||||
- AccessLogs
|
- AccessLogs
|
||||||
@@ -764,7 +764,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Get default ACME account
|
summary: Get default ACME account
|
||||||
tags:
|
tags:
|
||||||
- AcmeAccounts
|
- AcmeAccounts
|
||||||
@@ -923,7 +923,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: List apply logs
|
summary: List apply logs
|
||||||
tags:
|
tags:
|
||||||
- ApplyLogs
|
- ApplyLogs
|
||||||
@@ -940,7 +940,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Cleanup apply logs
|
summary: Cleanup apply logs
|
||||||
tags:
|
tags:
|
||||||
- ApplyLogs
|
- ApplyLogs
|
||||||
@@ -955,7 +955,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: List config versions
|
summary: List config versions
|
||||||
tags:
|
tags:
|
||||||
- ConfigVersions
|
- ConfigVersions
|
||||||
@@ -981,7 +981,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Get config version detail
|
summary: Get config version detail
|
||||||
tags:
|
tags:
|
||||||
- ConfigVersions
|
- ConfigVersions
|
||||||
@@ -1007,7 +1007,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Activate an existing config version
|
summary: Activate an existing config version
|
||||||
tags:
|
tags:
|
||||||
- ConfigVersions
|
- ConfigVersions
|
||||||
@@ -1022,7 +1022,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Get active config version
|
summary: Get active config version
|
||||||
tags:
|
tags:
|
||||||
- ConfigVersions
|
- ConfigVersions
|
||||||
@@ -1049,7 +1049,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Cleanup old config versions
|
summary: Cleanup old config versions
|
||||||
tags:
|
tags:
|
||||||
- ConfigVersions
|
- ConfigVersions
|
||||||
@@ -1064,7 +1064,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Diff current draft against active version
|
summary: Diff current draft against active version
|
||||||
tags:
|
tags:
|
||||||
- ConfigVersions
|
- ConfigVersions
|
||||||
@@ -1079,7 +1079,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Preview config rendering
|
summary: Preview config rendering
|
||||||
tags:
|
tags:
|
||||||
- ConfigVersions
|
- ConfigVersions
|
||||||
@@ -1094,7 +1094,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Publish a new config version
|
summary: Publish a new config version
|
||||||
tags:
|
tags:
|
||||||
- ConfigVersions
|
- ConfigVersions
|
||||||
@@ -1114,7 +1114,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Get dashboard overview
|
summary: Get dashboard overview
|
||||||
tags:
|
tags:
|
||||||
- Dashboard
|
- Dashboard
|
||||||
@@ -1129,7 +1129,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: List DNS accounts
|
summary: List DNS accounts
|
||||||
tags:
|
tags:
|
||||||
- DnsAccounts
|
- DnsAccounts
|
||||||
@@ -1152,7 +1152,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Create DNS account
|
summary: Create DNS account
|
||||||
tags:
|
tags:
|
||||||
- DnsAccounts
|
- DnsAccounts
|
||||||
@@ -1173,7 +1173,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Delete DNS account
|
summary: Delete DNS account
|
||||||
tags:
|
tags:
|
||||||
- DnsAccounts
|
- DnsAccounts
|
||||||
@@ -1202,7 +1202,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Update DNS account
|
summary: Update DNS account
|
||||||
tags:
|
tags:
|
||||||
- DnsAccounts
|
- DnsAccounts
|
||||||
@@ -1293,7 +1293,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: List managed domains
|
summary: List managed domains
|
||||||
tags:
|
tags:
|
||||||
- ManagedDomains
|
- ManagedDomains
|
||||||
@@ -1321,7 +1321,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Create managed domain
|
summary: Create managed domain
|
||||||
tags:
|
tags:
|
||||||
- ManagedDomains
|
- ManagedDomains
|
||||||
@@ -1347,7 +1347,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Delete managed domain
|
summary: Delete managed domain
|
||||||
tags:
|
tags:
|
||||||
- ManagedDomains
|
- ManagedDomains
|
||||||
@@ -1381,7 +1381,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Update managed domain
|
summary: Update managed domain
|
||||||
tags:
|
tags:
|
||||||
- ManagedDomains
|
- ManagedDomains
|
||||||
@@ -1402,7 +1402,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Match certificate for domain
|
summary: Match certificate for domain
|
||||||
tags:
|
tags:
|
||||||
- ManagedDomains
|
- ManagedDomains
|
||||||
@@ -1417,7 +1417,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: List nodes
|
summary: List nodes
|
||||||
tags:
|
tags:
|
||||||
- Nodes
|
- Nodes
|
||||||
@@ -1445,7 +1445,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Create node
|
summary: Create node
|
||||||
tags:
|
tags:
|
||||||
- Nodes
|
- Nodes
|
||||||
@@ -1475,7 +1475,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Check latest agent release for node
|
summary: Check latest agent release for node
|
||||||
tags:
|
tags:
|
||||||
- Nodes
|
- Nodes
|
||||||
@@ -1501,7 +1501,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Request agent self-update on node
|
summary: Request agent self-update on node
|
||||||
tags:
|
tags:
|
||||||
- Nodes
|
- Nodes
|
||||||
@@ -1527,7 +1527,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Delete node
|
summary: Delete node
|
||||||
tags:
|
tags:
|
||||||
- Nodes
|
- Nodes
|
||||||
@@ -1553,7 +1553,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Request force sync config on node
|
summary: Request force sync config on node
|
||||||
tags:
|
tags:
|
||||||
- Nodes
|
- Nodes
|
||||||
@@ -1587,7 +1587,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Get node observability details
|
summary: Get node observability details
|
||||||
tags:
|
tags:
|
||||||
- Nodes
|
- Nodes
|
||||||
@@ -1613,7 +1613,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Cleanup node health events
|
summary: Cleanup node health events
|
||||||
tags:
|
tags:
|
||||||
- Nodes
|
- Nodes
|
||||||
@@ -1639,7 +1639,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Request openresty restart on node
|
summary: Request openresty restart on node
|
||||||
tags:
|
tags:
|
||||||
- Nodes
|
- Nodes
|
||||||
@@ -1673,7 +1673,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Update node
|
summary: Update node
|
||||||
tags:
|
tags:
|
||||||
- Nodes
|
- Nodes
|
||||||
@@ -1688,7 +1688,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Get global discovery token
|
summary: Get global discovery token
|
||||||
tags:
|
tags:
|
||||||
- Nodes
|
- Nodes
|
||||||
@@ -1703,7 +1703,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Rotate global discovery token
|
summary: Rotate global discovery token
|
||||||
tags:
|
tags:
|
||||||
- Nodes
|
- Nodes
|
||||||
@@ -1733,7 +1733,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Cleanup observability tables
|
summary: Cleanup observability tables
|
||||||
tags:
|
tags:
|
||||||
- Options
|
- Options
|
||||||
@@ -1829,7 +1829,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: List proxy routes
|
summary: List proxy routes
|
||||||
tags:
|
tags:
|
||||||
- ProxyRoutes
|
- ProxyRoutes
|
||||||
@@ -1857,7 +1857,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Create proxy route
|
summary: Create proxy route
|
||||||
tags:
|
tags:
|
||||||
- ProxyRoutes
|
- ProxyRoutes
|
||||||
@@ -1883,7 +1883,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Get proxy route detail
|
summary: Get proxy route detail
|
||||||
tags:
|
tags:
|
||||||
- ProxyRoutes
|
- ProxyRoutes
|
||||||
@@ -1909,7 +1909,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Delete proxy route
|
summary: Delete proxy route
|
||||||
tags:
|
tags:
|
||||||
- ProxyRoutes
|
- ProxyRoutes
|
||||||
@@ -1943,7 +1943,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Update proxy route
|
summary: Update proxy route
|
||||||
tags:
|
tags:
|
||||||
- ProxyRoutes
|
- ProxyRoutes
|
||||||
@@ -2008,7 +2008,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: List TLS certificates
|
summary: List TLS certificates
|
||||||
tags:
|
tags:
|
||||||
- TLSCertificates
|
- TLSCertificates
|
||||||
@@ -2036,7 +2036,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Create TLS certificate from PEM
|
summary: Create TLS certificate from PEM
|
||||||
tags:
|
tags:
|
||||||
- TLSCertificates
|
- TLSCertificates
|
||||||
@@ -2062,7 +2062,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Get TLS certificate detail
|
summary: Get TLS certificate detail
|
||||||
tags:
|
tags:
|
||||||
- TLSCertificates
|
- TLSCertificates
|
||||||
@@ -2088,7 +2088,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Get TLS certificate PEM content
|
summary: Get TLS certificate PEM content
|
||||||
tags:
|
tags:
|
||||||
- TLSCertificates
|
- TLSCertificates
|
||||||
@@ -2122,7 +2122,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Convert uploaded TLS certificate to ACME managed certificate
|
summary: Convert uploaded TLS certificate to ACME managed certificate
|
||||||
tags:
|
tags:
|
||||||
- TLSCertificates
|
- TLSCertificates
|
||||||
@@ -2148,7 +2148,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Delete TLS certificate
|
summary: Delete TLS certificate
|
||||||
tags:
|
tags:
|
||||||
- TLSCertificates
|
- TLSCertificates
|
||||||
@@ -2174,7 +2174,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Renew TLS certificate
|
summary: Renew TLS certificate
|
||||||
tags:
|
tags:
|
||||||
- TLSCertificates
|
- TLSCertificates
|
||||||
@@ -2208,7 +2208,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Update TLS certificate from PEM
|
summary: Update TLS certificate from PEM
|
||||||
tags:
|
tags:
|
||||||
- TLSCertificates
|
- TLSCertificates
|
||||||
@@ -2242,7 +2242,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Update ACME TLS certificate
|
summary: Update ACME TLS certificate
|
||||||
tags:
|
tags:
|
||||||
- TLSCertificates
|
- TLSCertificates
|
||||||
@@ -2271,7 +2271,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Apply TLS certificate via ACME
|
summary: Apply TLS certificate via ACME
|
||||||
tags:
|
tags:
|
||||||
- TLSCertificates
|
- TLSCertificates
|
||||||
@@ -2313,7 +2313,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Import TLS certificate from files
|
summary: Import TLS certificate from files
|
||||||
tags:
|
tags:
|
||||||
- TLSCertificates
|
- TLSCertificates
|
||||||
@@ -2328,7 +2328,7 @@ paths:
|
|||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
type: object
|
type: object
|
||||||
security:
|
security:
|
||||||
- BearerAuth: []
|
- OpenFlareTokenAuth: []
|
||||||
summary: Get latest GitHub release
|
summary: Get latest GitHub release
|
||||||
tags:
|
tags:
|
||||||
- Update
|
- Update
|
||||||
@@ -2390,9 +2390,9 @@ securityDefinitions:
|
|||||||
in: header
|
in: header
|
||||||
name: X-Agent-Token
|
name: X-Agent-Token
|
||||||
type: apiKey
|
type: apiKey
|
||||||
BearerAuth:
|
OpenFlareTokenAuth:
|
||||||
description: 管理端可使用 Bearer Token,例如:Bearer <token>
|
description: 管理端 API 使用登录后返回的用户 Token
|
||||||
in: header
|
in: header
|
||||||
name: Authorization
|
name: OPENFLARE_TOKEN
|
||||||
type: apiKey
|
type: apiKey
|
||||||
swagger: "2.0"
|
swagger: "2.0"
|
||||||
|
|||||||
@@ -33,10 +33,10 @@ var indexPage []byte
|
|||||||
// @description OpenFlare Server 管理端与 Agent API 文档。
|
// @description OpenFlare Server 管理端与 Agent API 文档。
|
||||||
// @BasePath /
|
// @BasePath /
|
||||||
// @schemes http https
|
// @schemes http https
|
||||||
// @securityDefinitions.apikey BearerAuth
|
// @securityDefinitions.apikey OpenFlareTokenAuth
|
||||||
// @in header
|
// @in header
|
||||||
// @name Authorization
|
// @name OPENFLARE_TOKEN
|
||||||
// @description 管理端可使用 Bearer Token,例如:Bearer <token>
|
// @description 管理端 API 使用登录后返回的用户 Token
|
||||||
// @securityDefinitions.apikey AccessTokenAuth
|
// @securityDefinitions.apikey AccessTokenAuth
|
||||||
// @in header
|
// @in header
|
||||||
// @name X-Agent-Token
|
// @name X-Agent-Token
|
||||||
|
|||||||
@@ -1,49 +1,35 @@
|
|||||||
package middleware
|
package middleware
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gin-contrib/sessions"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"net/http"
|
"net/http"
|
||||||
"openflare/common"
|
"openflare/common"
|
||||||
"openflare/model"
|
"openflare/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const OpenFlareTokenHeader = "OPENFLARE_TOKEN"
|
||||||
|
|
||||||
func authHelper(c *gin.Context, minRole int) {
|
func authHelper(c *gin.Context, minRole int) {
|
||||||
session := sessions.Default(c)
|
token := c.GetHeader(OpenFlareTokenHeader)
|
||||||
username := session.Get("username")
|
if token == "" {
|
||||||
role := session.Get("role")
|
c.JSON(http.StatusUnauthorized, gin.H{
|
||||||
id := session.Get("id")
|
"success": false,
|
||||||
status := session.Get("status")
|
"message": "无权进行此操作,未登录或 token 无效",
|
||||||
authByToken := false
|
})
|
||||||
if username == nil {
|
c.Abort()
|
||||||
// Check token
|
return
|
||||||
token := c.Request.Header.Get("Authorization")
|
|
||||||
if token == "" {
|
|
||||||
c.JSON(http.StatusUnauthorized, gin.H{
|
|
||||||
"success": false,
|
|
||||||
"message": "无权进行此操作,未登录或 token 无效",
|
|
||||||
})
|
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user := model.ValidateUserToken(token)
|
|
||||||
if user != nil && user.Username != "" {
|
|
||||||
// Token is valid
|
|
||||||
username = user.Username
|
|
||||||
role = user.Role
|
|
||||||
id = user.Id
|
|
||||||
status = user.Status
|
|
||||||
} else {
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
|
||||||
"success": false,
|
|
||||||
"message": "无权进行此操作,token 无效",
|
|
||||||
})
|
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
authByToken = true
|
|
||||||
}
|
}
|
||||||
if status.(int) == common.UserStatusDisabled {
|
|
||||||
|
user := model.ValidateUserToken(token)
|
||||||
|
if user == nil || user.Username == "" {
|
||||||
|
c.JSON(http.StatusUnauthorized, gin.H{
|
||||||
|
"success": false,
|
||||||
|
"message": "无权进行此操作,token 无效",
|
||||||
|
})
|
||||||
|
c.Abort()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if user.Status == common.UserStatusDisabled {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"message": "用户已被封禁",
|
"message": "用户已被封禁",
|
||||||
@@ -51,7 +37,7 @@ func authHelper(c *gin.Context, minRole int) {
|
|||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if role.(int) < minRole {
|
if user.Role < minRole {
|
||||||
c.JSON(http.StatusOK, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"success": false,
|
"success": false,
|
||||||
"message": "无权进行此操作,权限不足",
|
"message": "无权进行此操作,权限不足",
|
||||||
@@ -59,10 +45,10 @@ func authHelper(c *gin.Context, minRole int) {
|
|||||||
c.Abort()
|
c.Abort()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Set("username", username)
|
c.Set("username", user.Username)
|
||||||
c.Set("role", role)
|
c.Set("role", user.Role)
|
||||||
c.Set("id", id)
|
c.Set("id", user.Id)
|
||||||
c.Set("authByToken", authByToken)
|
c.Set("authByToken", true)
|
||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,34 +70,16 @@ func RootAuth() func(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NoTokenAuth You should always use this after normal auth middlewares.
|
// NoTokenAuth is kept as a compatibility no-op because admin APIs now always use OPENFLARE_TOKEN.
|
||||||
func NoTokenAuth() func(c *gin.Context) {
|
func NoTokenAuth() func(c *gin.Context) {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
authByToken := c.GetBool("authByToken")
|
|
||||||
if authByToken {
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
|
||||||
"success": false,
|
|
||||||
"message": "本接口不支持使用 token 进行验证",
|
|
||||||
})
|
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TokenOnlyAuth You should always use this after normal auth middlewares.
|
// TokenOnlyAuth is kept as a compatibility no-op because admin APIs now always use OPENFLARE_TOKEN.
|
||||||
func TokenOnlyAuth() func(c *gin.Context) {
|
func TokenOnlyAuth() func(c *gin.Context) {
|
||||||
return func(c *gin.Context) {
|
return func(c *gin.Context) {
|
||||||
authByToken := c.GetBool("authByToken")
|
|
||||||
if !authByToken {
|
|
||||||
c.JSON(http.StatusOK, gin.H{
|
|
||||||
"success": false,
|
|
||||||
"message": "本接口仅支持使用 token 进行验证",
|
|
||||||
})
|
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.Next()
|
c.Next()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
func CORS() gin.HandlerFunc {
|
func CORS() gin.HandlerFunc {
|
||||||
config := cors.DefaultConfig()
|
config := cors.DefaultConfig()
|
||||||
config.AllowCredentials = true
|
config.AllowCredentials = true
|
||||||
config.AllowHeaders = []string{"Origin", "Content-Length", "Content-Type", "Authorization", "X-Agent-Token", "Accept"}
|
config.AllowHeaders = []string{"Origin", "Content-Length", "Content-Type", "Authorization", "OPENFLARE_TOKEN", "X-Agent-Token", "Accept"}
|
||||||
config.AllowOriginFunc = func(origin string) bool {
|
config.AllowOriginFunc = func(origin string) bool {
|
||||||
serverAddr := strings.TrimRight(common.ServerAddress, "/")
|
serverAddr := strings.TrimRight(common.ServerAddress, "/")
|
||||||
if serverAddr == "" {
|
if serverAddr == "" {
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ func TestPhase1PublishLifecycle(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repeatPublishReq := httptest.NewRequest(http.MethodPost, "/api/config-versions/publish", nil)
|
repeatPublishReq := httptest.NewRequest(http.MethodPost, "/api/config-versions/publish", nil)
|
||||||
repeatPublishReq.Header.Set("Authorization", "Bearer "+token)
|
repeatPublishReq.Header.Set("OPENFLARE_TOKEN", token)
|
||||||
repeatPublishRecorder := httptest.NewRecorder()
|
repeatPublishRecorder := httptest.NewRecorder()
|
||||||
engine.ServeHTTP(repeatPublishRecorder, repeatPublishReq)
|
engine.ServeHTTP(repeatPublishRecorder, repeatPublishReq)
|
||||||
if repeatPublishRecorder.Code != http.StatusOK {
|
if repeatPublishRecorder.Code != http.StatusOK {
|
||||||
@@ -519,7 +519,7 @@ func performJSONRequest(t *testing.T, engine http.Handler, token string, method
|
|||||||
if body != nil {
|
if body != nil {
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
}
|
}
|
||||||
req.Header.Set("Authorization", "Bearer "+token)
|
req.Header.Set("OPENFLARE_TOKEN", token)
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
engine.ServeHTTP(recorder, req)
|
engine.ServeHTTP(recorder, req)
|
||||||
if recorder.Code != http.StatusOK {
|
if recorder.Code != http.StatusOK {
|
||||||
@@ -549,7 +549,7 @@ func performJSONRequestNoFatal(t *testing.T, engine http.Handler, token string,
|
|||||||
if body != nil {
|
if body != nil {
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
}
|
}
|
||||||
req.Header.Set("Authorization", "Bearer "+token)
|
req.Header.Set("OPENFLARE_TOKEN", token)
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
engine.ServeHTTP(recorder, req)
|
engine.ServeHTTP(recorder, req)
|
||||||
if recorder.Code != http.StatusOK && recorder.Code != http.StatusBadRequest {
|
if recorder.Code != http.StatusOK && recorder.Code != http.StatusBadRequest {
|
||||||
@@ -596,7 +596,7 @@ func performMultipartRequest(t *testing.T, engine http.Handler, token string, pa
|
|||||||
}
|
}
|
||||||
req := httptest.NewRequest(http.MethodPost, path, &body)
|
req := httptest.NewRequest(http.MethodPost, path, &body)
|
||||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||||
req.Header.Set("Authorization", "Bearer "+token)
|
req.Header.Set("OPENFLARE_TOKEN", token)
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
engine.ServeHTTP(recorder, req)
|
engine.ServeHTTP(recorder, req)
|
||||||
if recorder.Code != http.StatusOK {
|
if recorder.Code != http.StatusOK {
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ func TestPhase2BatchOptionUpdateIsAtomic(t *testing.T) {
|
|||||||
|
|
||||||
req := httptest.NewRequest(http.MethodPost, "/api/option/update-batch", bytes.NewReader(payload))
|
req := httptest.NewRequest(http.MethodPost, "/api/option/update-batch", bytes.NewReader(payload))
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
req.AddCookie(loginCookie)
|
req.Header.Set("OPENFLARE_TOKEN", loginCookie)
|
||||||
|
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
engine.ServeHTTP(recorder, req)
|
engine.ServeHTTP(recorder, req)
|
||||||
@@ -320,7 +320,7 @@ func TestExternalAccountBindingsCanBeListedAndDeleted(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func loginAsRoot(t *testing.T, engine http.Handler) *http.Cookie {
|
func loginAsRoot(t *testing.T, engine http.Handler) string {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
payload, err := json.Marshal(map[string]any{
|
payload, err := json.Marshal(map[string]any{
|
||||||
"username": "root",
|
"username": "root",
|
||||||
@@ -346,16 +346,17 @@ func loginAsRoot(t *testing.T, engine http.Handler) *http.Cookie {
|
|||||||
t.Fatalf("root login failed: %s", resp.Message)
|
t.Fatalf("root login failed: %s", resp.Message)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, cookie := range recorder.Result().Cookies() {
|
var user model.User
|
||||||
if cookie.Name == "session" {
|
if err = json.Unmarshal(resp.Data, &user); err != nil {
|
||||||
return cookie
|
t.Fatalf("failed to decode login user: %v", err)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
t.Fatal("expected session cookie after root login")
|
if user.Token == "" {
|
||||||
return nil
|
t.Fatal("expected OPENFLARE_TOKEN after root login")
|
||||||
|
}
|
||||||
|
return user.Token
|
||||||
}
|
}
|
||||||
|
|
||||||
func performSessionJSONRequest(t *testing.T, engine http.Handler, sessionCookie *http.Cookie, method string, path string, body any) apiResponse {
|
func performSessionJSONRequest(t *testing.T, engine http.Handler, token string, method string, path string, body any) apiResponse {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
var payload []byte
|
var payload []byte
|
||||||
var err error
|
var err error
|
||||||
@@ -370,7 +371,7 @@ func performSessionJSONRequest(t *testing.T, engine http.Handler, sessionCookie
|
|||||||
if body != nil {
|
if body != nil {
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
}
|
}
|
||||||
req.AddCookie(sessionCookie)
|
req.Header.Set("OPENFLARE_TOKEN", token)
|
||||||
|
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
engine.ServeHTTP(recorder, req)
|
engine.ServeHTTP(recorder, req)
|
||||||
|
|||||||
@@ -133,7 +133,7 @@ func TestUptimeKumaSyncDisabled(t *testing.T) {
|
|||||||
|
|
||||||
// Request sync, should fail
|
// Request sync, should fail
|
||||||
req := httptest.NewRequest(http.MethodPost, "/api/uptimekuma/sync", nil)
|
req := httptest.NewRequest(http.MethodPost, "/api/uptimekuma/sync", nil)
|
||||||
req.AddCookie(loginCookie)
|
req.Header.Set("OPENFLARE_TOKEN", loginCookie)
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
engine.ServeHTTP(recorder, req)
|
engine.ServeHTTP(recorder, req)
|
||||||
|
|
||||||
@@ -265,7 +265,7 @@ func TestUptimeKumaSyncSuccess(t *testing.T) {
|
|||||||
loginCookie := loginAsRoot(t, engine)
|
loginCookie := loginAsRoot(t, engine)
|
||||||
|
|
||||||
req := httptest.NewRequest(http.MethodPost, "/api/uptimekuma/sync", nil)
|
req := httptest.NewRequest(http.MethodPost, "/api/uptimekuma/sync", nil)
|
||||||
req.AddCookie(loginCookie)
|
req.Header.Set("OPENFLARE_TOKEN", loginCookie)
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
engine.ServeHTTP(recorder, req)
|
engine.ServeHTTP(recorder, req)
|
||||||
|
|
||||||
@@ -405,7 +405,7 @@ func TestUptimeKumaSyncSelectedScope(t *testing.T) {
|
|||||||
loginCookie := loginAsRoot(t, engine)
|
loginCookie := loginAsRoot(t, engine)
|
||||||
|
|
||||||
req := httptest.NewRequest(http.MethodPost, "/api/uptimekuma/sync", nil)
|
req := httptest.NewRequest(http.MethodPost, "/api/uptimekuma/sync", nil)
|
||||||
req.AddCookie(loginCookie)
|
req.Header.Set("OPENFLARE_TOKEN", loginCookie)
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
engine.ServeHTTP(recorder, req)
|
engine.ServeHTTP(recorder, req)
|
||||||
|
|
||||||
|
|||||||
@@ -77,13 +77,22 @@ func TestLatestReleaseProxy(t *testing.T) {
|
|||||||
if loginRecorder.Code != http.StatusOK {
|
if loginRecorder.Code != http.StatusOK {
|
||||||
t.Fatalf("unexpected login status code: %d", loginRecorder.Code)
|
t.Fatalf("unexpected login status code: %d", loginRecorder.Code)
|
||||||
}
|
}
|
||||||
loginResult := loginRecorder.Result()
|
var loginResp apiResponse
|
||||||
defer loginResult.Body.Close()
|
if err = json.Unmarshal(loginRecorder.Body.Bytes(), &loginResp); err != nil {
|
||||||
|
t.Fatalf("failed to decode login response: %v", err)
|
||||||
|
}
|
||||||
|
var loginUser struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
}
|
||||||
|
if err = json.Unmarshal(loginResp.Data, &loginUser); err != nil {
|
||||||
|
t.Fatalf("failed to decode login user: %v", err)
|
||||||
|
}
|
||||||
|
if loginUser.Token == "" {
|
||||||
|
t.Fatal("expected OPENFLARE_TOKEN after login")
|
||||||
|
}
|
||||||
|
|
||||||
req := httptest.NewRequest(http.MethodGet, "/api/update/latest-release", nil)
|
req := httptest.NewRequest(http.MethodGet, "/api/update/latest-release", nil)
|
||||||
for _, cookieValue := range loginResult.Cookies() {
|
req.Header.Set("OPENFLARE_TOKEN", loginUser.Token)
|
||||||
req.AddCookie(cookieValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
engine.ServeHTTP(recorder, req)
|
engine.ServeHTTP(recorder, req)
|
||||||
@@ -111,7 +120,7 @@ func TestLatestReleaseProxy(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func loginRootAndBuildEngine(t *testing.T) (*gin.Engine, []*http.Cookie) {
|
func loginRootAndBuildEngine(t *testing.T) (*gin.Engine, string) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
gin.SetMode(gin.TestMode)
|
gin.SetMode(gin.TestMode)
|
||||||
common.RedisEnabled = false
|
common.RedisEnabled = false
|
||||||
@@ -135,10 +144,21 @@ func loginRootAndBuildEngine(t *testing.T) (*gin.Engine, []*http.Cookie) {
|
|||||||
if loginRecorder.Code != http.StatusOK {
|
if loginRecorder.Code != http.StatusOK {
|
||||||
t.Fatalf("unexpected login status code: %d", loginRecorder.Code)
|
t.Fatalf("unexpected login status code: %d", loginRecorder.Code)
|
||||||
}
|
}
|
||||||
loginResult := loginRecorder.Result()
|
var loginResp apiResponse
|
||||||
defer loginResult.Body.Close()
|
if err = json.Unmarshal(loginRecorder.Body.Bytes(), &loginResp); err != nil {
|
||||||
|
t.Fatalf("failed to decode login response: %v", err)
|
||||||
|
}
|
||||||
|
var loginUser struct {
|
||||||
|
Token string `json:"token"`
|
||||||
|
}
|
||||||
|
if err = json.Unmarshal(loginResp.Data, &loginUser); err != nil {
|
||||||
|
t.Fatalf("failed to decode login user: %v", err)
|
||||||
|
}
|
||||||
|
if loginUser.Token == "" {
|
||||||
|
t.Fatal("expected OPENFLARE_TOKEN after login")
|
||||||
|
}
|
||||||
|
|
||||||
return engine, loginResult.Cookies()
|
return engine, loginUser.Token
|
||||||
}
|
}
|
||||||
|
|
||||||
func fakeManualServerBinary(version string) (string, []byte) {
|
func fakeManualServerBinary(version string) (string, []byte) {
|
||||||
@@ -157,7 +177,7 @@ func TestManualUploadRoute(t *testing.T) {
|
|||||||
service.SetServerUpgradeDispatchDelayForTest(500 * time.Millisecond)
|
service.SetServerUpgradeDispatchDelayForTest(500 * time.Millisecond)
|
||||||
})
|
})
|
||||||
|
|
||||||
engine, cookies := loginRootAndBuildEngine(t)
|
engine, token := loginRootAndBuildEngine(t)
|
||||||
fileName, content := fakeManualServerBinary("v0.5.0")
|
fileName, content := fakeManualServerBinary("v0.5.0")
|
||||||
|
|
||||||
body := &bytes.Buffer{}
|
body := &bytes.Buffer{}
|
||||||
@@ -175,9 +195,7 @@ func TestManualUploadRoute(t *testing.T) {
|
|||||||
|
|
||||||
req := httptest.NewRequest(http.MethodPost, "/api/update/manual-upload", body)
|
req := httptest.NewRequest(http.MethodPost, "/api/update/manual-upload", body)
|
||||||
req.Header.Set("Content-Type", writer.FormDataContentType())
|
req.Header.Set("Content-Type", writer.FormDataContentType())
|
||||||
for _, cookieValue := range cookies {
|
req.Header.Set("OPENFLARE_TOKEN", token)
|
||||||
req.AddCookie(cookieValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
engine.ServeHTTP(recorder, req)
|
engine.ServeHTTP(recorder, req)
|
||||||
@@ -225,7 +243,7 @@ func TestManualUpgradeConfirmRoute(t *testing.T) {
|
|||||||
service.SetServerUpgradeDispatchDelayForTest(originalDelay)
|
service.SetServerUpgradeDispatchDelayForTest(originalDelay)
|
||||||
})
|
})
|
||||||
|
|
||||||
engine, cookies := loginRootAndBuildEngine(t)
|
engine, token := loginRootAndBuildEngine(t)
|
||||||
fileName, content := fakeManualServerBinary("v0.5.0")
|
fileName, content := fakeManualServerBinary("v0.5.0")
|
||||||
|
|
||||||
body := &bytes.Buffer{}
|
body := &bytes.Buffer{}
|
||||||
@@ -243,9 +261,7 @@ func TestManualUpgradeConfirmRoute(t *testing.T) {
|
|||||||
|
|
||||||
uploadReq := httptest.NewRequest(http.MethodPost, "/api/update/manual-upload", body)
|
uploadReq := httptest.NewRequest(http.MethodPost, "/api/update/manual-upload", body)
|
||||||
uploadReq.Header.Set("Content-Type", writer.FormDataContentType())
|
uploadReq.Header.Set("Content-Type", writer.FormDataContentType())
|
||||||
for _, cookieValue := range cookies {
|
uploadReq.Header.Set("OPENFLARE_TOKEN", token)
|
||||||
uploadReq.AddCookie(cookieValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
uploadRecorder := httptest.NewRecorder()
|
uploadRecorder := httptest.NewRecorder()
|
||||||
engine.ServeHTTP(uploadRecorder, uploadReq)
|
engine.ServeHTTP(uploadRecorder, uploadReq)
|
||||||
@@ -276,9 +292,7 @@ func TestManualUpgradeConfirmRoute(t *testing.T) {
|
|||||||
}
|
}
|
||||||
confirmReq := httptest.NewRequest(http.MethodPost, "/api/update/manual-upgrade", bytes.NewReader(confirmBody))
|
confirmReq := httptest.NewRequest(http.MethodPost, "/api/update/manual-upgrade", bytes.NewReader(confirmBody))
|
||||||
confirmReq.Header.Set("Content-Type", "application/json")
|
confirmReq.Header.Set("Content-Type", "application/json")
|
||||||
for _, cookieValue := range cookies {
|
confirmReq.Header.Set("OPENFLARE_TOKEN", token)
|
||||||
confirmReq.AddCookie(cookieValue)
|
|
||||||
}
|
|
||||||
|
|
||||||
confirmRecorder := httptest.NewRecorder()
|
confirmRecorder := httptest.NewRecorder()
|
||||||
engine.ServeHTTP(confirmRecorder, confirmReq)
|
engine.ServeHTTP(confirmRecorder, confirmReq)
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
logout as logoutRequest,
|
logout as logoutRequest,
|
||||||
getCurrentUser,
|
getCurrentUser,
|
||||||
} from '@/features/auth/api/auth';
|
} from '@/features/auth/api/auth';
|
||||||
|
import { clearStoredOpenFlareToken } from '@/lib/api/auth-token';
|
||||||
import type { AuthUser } from '@/types/auth';
|
import type { AuthUser } from '@/types/auth';
|
||||||
|
|
||||||
interface AuthContextValue {
|
interface AuthContextValue {
|
||||||
@@ -41,6 +42,7 @@ export function AuthProvider({ children }: AuthProviderProps) {
|
|||||||
setUserState(nextUser);
|
setUserState(nextUser);
|
||||||
return nextUser;
|
return nextUser;
|
||||||
} catch {
|
} catch {
|
||||||
|
clearStoredOpenFlareToken();
|
||||||
setUserState(null);
|
setUserState(null);
|
||||||
return null;
|
return null;
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
import { apiRequest } from '@/lib/api/client';
|
import { apiRequest } from '@/lib/api/client';
|
||||||
|
import {
|
||||||
|
clearStoredOpenFlareToken,
|
||||||
|
setStoredOpenFlareToken,
|
||||||
|
} from '@/lib/api/auth-token';
|
||||||
import type {
|
import type {
|
||||||
AuthUser,
|
AuthUser,
|
||||||
LoginPayload,
|
LoginPayload,
|
||||||
@@ -14,11 +18,18 @@ export function login(payload: LoginPayload) {
|
|||||||
return apiRequest<AuthUser>('/user/login', {
|
return apiRequest<AuthUser>('/user/login', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(payload),
|
body: JSON.stringify(payload),
|
||||||
|
}).then((user) => {
|
||||||
|
if (user.token) {
|
||||||
|
setStoredOpenFlareToken(user.token);
|
||||||
|
}
|
||||||
|
return user;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function logout() {
|
export function logout() {
|
||||||
return apiRequest<void>('/user/logout');
|
return apiRequest<void>('/user/logout').finally(() => {
|
||||||
|
clearStoredOpenFlareToken();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function register(payload: RegisterPayload) {
|
export function register(payload: RegisterPayload) {
|
||||||
@@ -48,7 +59,14 @@ export function resetPassword(payload: PasswordResetRequestPayload) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function exchangeGitHubCode(code: string) {
|
export function exchangeGitHubCode(code: string) {
|
||||||
return apiRequest<AuthUser>(`/oauth/github?code=${encodeURIComponent(code)}`);
|
return apiRequest<AuthUser>(
|
||||||
|
`/oauth/github?code=${encodeURIComponent(code)}`,
|
||||||
|
).then((user) => {
|
||||||
|
if (user.token) {
|
||||||
|
setStoredOpenFlareToken(user.token);
|
||||||
|
}
|
||||||
|
return user;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface OAuthAuthorizeResult {
|
export interface OAuthAuthorizeResult {
|
||||||
@@ -79,12 +97,22 @@ export function exchangeOAuthCode(
|
|||||||
const searchParams = new URLSearchParams({ code, state });
|
const searchParams = new URLSearchParams({ code, state });
|
||||||
return apiRequest<OAuthCallbackResult>(
|
return apiRequest<OAuthCallbackResult>(
|
||||||
`/oauth/${encodeURIComponent(String(source))}/callback?${searchParams.toString()}`,
|
`/oauth/${encodeURIComponent(String(source))}/callback?${searchParams.toString()}`,
|
||||||
);
|
).then((result) => {
|
||||||
|
if (result.user?.token) {
|
||||||
|
setStoredOpenFlareToken(result.user.token);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function linkExistingOAuthAccount(payload: LinkExistingOAuthPayload) {
|
export function linkExistingOAuthAccount(payload: LinkExistingOAuthPayload) {
|
||||||
return apiRequest<OAuthCallbackResult>('/oauth/link-existing', {
|
return apiRequest<OAuthCallbackResult>('/oauth/link-existing', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(payload),
|
body: JSON.stringify(payload),
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.user?.token) {
|
||||||
|
setStoredOpenFlareToken(result.user.token);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { apiRequest } from '@/lib/api/client';
|
import { apiRequest } from '@/lib/api/client';
|
||||||
|
import { setStoredOpenFlareToken } from '@/lib/api/auth-token';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
BootstrapTokenPayload,
|
BootstrapTokenPayload,
|
||||||
@@ -109,7 +110,10 @@ export function updateSelf(payload: UpdateSelfPayload) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function generateAccessToken() {
|
export function generateAccessToken() {
|
||||||
return apiRequest<string>('/user/token');
|
return apiRequest<string>('/user/token').then((token) => {
|
||||||
|
setStoredOpenFlareToken(token);
|
||||||
|
return token;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function bindWeChat(code: string) {
|
export function bindWeChat(code: string) {
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
const openFlareTokenStorageKey = 'openflare_token';
|
||||||
|
|
||||||
|
export function getStoredOpenFlareToken() {
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
return window.localStorage.getItem(openFlareTokenStorageKey) || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setStoredOpenFlareToken(token: string) {
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.localStorage.setItem(openFlareTokenStorageKey, token);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearStoredOpenFlareToken() {
|
||||||
|
if (typeof window === 'undefined') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window.localStorage.removeItem(openFlareTokenStorageKey);
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { publicEnv } from '@/lib/env/public-env';
|
import { publicEnv } from '@/lib/env/public-env';
|
||||||
|
import { getStoredOpenFlareToken } from '@/lib/api/auth-token';
|
||||||
import type { ApiEnvelope } from '@/types/api';
|
import type { ApiEnvelope } from '@/types/api';
|
||||||
|
|
||||||
export class ApiError extends Error {
|
export class ApiError extends Error {
|
||||||
@@ -23,6 +24,12 @@ export async function apiRequest<T>(path: string, init?: RequestInit) {
|
|||||||
if (!(init?.body instanceof FormData) && !headers.has('Content-Type')) {
|
if (!(init?.body instanceof FormData) && !headers.has('Content-Type')) {
|
||||||
headers.set('Content-Type', 'application/json');
|
headers.set('Content-Type', 'application/json');
|
||||||
}
|
}
|
||||||
|
if (!headers.has('OPENFLARE_TOKEN')) {
|
||||||
|
const token = getStoredOpenFlareToken();
|
||||||
|
if (token) {
|
||||||
|
headers.set('OPENFLARE_TOKEN', token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const response = await fetch(getApiUrl(path), {
|
const response = await fetch(getApiUrl(path), {
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ export interface AuthUser {
|
|||||||
display_name: string;
|
display_name: string;
|
||||||
role: number;
|
role: number;
|
||||||
status: number;
|
status: number;
|
||||||
|
token?: string;
|
||||||
email?: string;
|
email?: string;
|
||||||
github_id?: string;
|
github_id?: string;
|
||||||
wechat_id?: string;
|
wechat_id?: string;
|
||||||
|
|||||||
Reference in New Issue
Block a user