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