docs(openflare): complete Swagger for protocol and dashboard APIs

Add Swagger annotations for all Agent, Relay, and Tunnel protocol
endpoints under /api/v1. Register AgentTokenAuth and TunnelTokenAuth
security definitions. Align dashboard API docs to return 404 for
insufficient admin permission.
This commit is contained in:
ryan
2026-06-19 11:26:56 +08:00
parent 68ddad98fb
commit e3353cd09d
14 changed files with 4121 additions and 3866 deletions
+1461 -1411
View File
File diff suppressed because it is too large Load Diff
+1461 -1411
View File
File diff suppressed because it is too large Load Diff
+1004 -985
View File
File diff suppressed because it is too large Load Diff
@@ -15,6 +15,17 @@ import (
)
// RegisterHandler registers or discovers an agent node.
// @Summary 注册或发现 Agent 节点
// @Description 使用节点 access token 重新注册,或使用全局 discovery token 发现新节点;请求头需携带 X-Agent-Token
// @Tags openflare-agent
// @Accept json
// @Produce json
// @Security AgentTokenAuth
// @Param body body agent.NodePayload true "节点上报数据"
// @Success 200 {object} response.Any{data=agent.RegistrationResponse} "注册成功"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "Token 无效"
// @Router /api/v1/agent/nodes/register [post]
func RegisterHandler(c *gin.Context) {
var payload NodePayload
if !apiutil.BindJSON(c, &payload) {
@@ -38,6 +49,17 @@ func RegisterHandler(c *gin.Context) {
}
// HeartbeatHandler records agent heartbeat state.
// @Summary Agent 心跳上报
// @Description 上报节点状态、指标与健康事件,返回远程控制配置与活跃配置元信息
// @Tags openflare-agent
// @Accept json
// @Produce json
// @Security AgentTokenAuth
// @Param body body agent.NodePayload true "心跳数据"
// @Success 200 {object} response.Any{data=agent.HeartbeatResponse} "心跳成功"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "Token 无效"
// @Router /api/v1/agent/nodes/heartbeat [post]
func HeartbeatHandler(c *gin.Context) {
var payload NodePayload
if !apiutil.BindJSON(c, &payload) {
@@ -59,6 +81,15 @@ func HeartbeatHandler(c *gin.Context) {
}
// GetActiveConfigHandler returns the active configuration version.
// @Summary 获取活跃配置版本
// @Description 返回当前生效的完整配置包,供 Agent 拉取并应用
// @Tags openflare-agent
// @Produce json
// @Security AgentTokenAuth
// @Success 200 {object} response.Any{data=agent.ConfigResponse} "活跃配置"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "Token 无效"
// @Router /api/v1/agent/config-versions/active [get]
func GetActiveConfigHandler(c *gin.Context) {
if _, ok := AgentNodeFromContext(c); !ok {
response.AbortUnauthorized(c, errNodeMissingFromContext)
@@ -72,6 +103,17 @@ func GetActiveConfigHandler(c *gin.Context) {
}
// SyncWAFIPGroupsHandler syncs WAF IP groups for an agent.
// @Summary 同步 WAF IP 组
// @Description 按 ID 与校验和增量同步 WAF IP 组定义
// @Tags openflare-agent
// @Accept json
// @Produce json
// @Security AgentTokenAuth
// @Param body body agent.WAFIPGroupSyncInput true "同步请求"
// @Success 200 {object} response.Any{data=agent.WAFIPGroupSyncResult} "同步结果"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "Token 无效"
// @Router /api/v1/agent/waf/ip-groups/sync [post]
func SyncWAFIPGroupsHandler(c *gin.Context) {
var input WAFIPGroupSyncInput
if !apiutil.BindJSON(c, &input) {
@@ -85,6 +127,17 @@ func SyncWAFIPGroupsHandler(c *gin.Context) {
}
// ReportApplyLogHandler records an agent apply log entry.
// @Summary 上报配置应用日志
// @Description 记录 Agent 配置下发与应用结果
// @Tags openflare-agent
// @Accept json
// @Produce json
// @Security AgentTokenAuth
// @Param body body agent.ApplyLogPayload true "应用日志"
// @Success 200 {object} response.Any{data=model.OpenFlareApplyLog} "日志记录"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "Token 无效"
// @Router /api/v1/agent/apply-logs [post]
func ReportApplyLogHandler(c *gin.Context) {
var payload ApplyLogPayload
if !apiutil.BindJSON(c, &payload) {
@@ -101,6 +154,16 @@ func ReportApplyLogHandler(c *gin.Context) {
}
// DownloadPagesPackageHandler streams the Pages deployment artifact to an authenticated agent.
// @Summary 下载 Pages 部署包
// @Description 流式下载指定部署的静态资源压缩包,供 Agent 边缘分发
// @Tags openflare-agent
// @Produce application/octet-stream
// @Security AgentTokenAuth
// @Param deployment_id path int true "部署 ID"
// @Success 200 {file} binary "部署包文件"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "Token 无效"
// @Router /api/v1/agent/pages/deployments/{deployment_id}/package [get]
func DownloadPagesPackageHandler(c *gin.Context) {
deploymentID, ok := pagesDeploymentIDParam(c)
if !ok {
@@ -133,6 +196,12 @@ func pagesDeploymentIDParam(c *gin.Context) (uint, bool) {
}
// AgentWebSocketHandler upgrades an authenticated agent websocket connection.
// @Summary Agent WebSocket 连接
// @Description 升级为 WebSocket 长连接,用于实时推送配置同步、WAF IP 组等指令;需携带 X-Agent-Token
// @Tags openflare-agent
// @Security AgentTokenAuth
// @Failure 401 {object} response.Any "Token 无效"
// @Router /api/v1/agent/ws [get]
func AgentWebSocketHandler(c *gin.Context) {
authNode, ok := AgentNodeFromContext(c)
if !ok {
@@ -20,7 +20,7 @@ import (
// @Success 200 {object} response.Any{data=dashboard.OverviewPayload} "仪表盘概览"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/dashboard/overview [get]
func GetOverviewHandler(c *gin.Context) {
@@ -14,6 +14,18 @@ import (
)
// PostHeartbeat handles POST /tunnel/heartbeat.
// @Summary 上报 Tunnel 心跳
// @Description Tunnel 客户端定期上报运行状态与中继连接信息,返回活跃配置元数据与隧道设置
// @Tags openflare-tunnel
// @Accept json
// @Produce json
// @Security TunnelTokenAuth
// @Param body body flared.HeartbeatPayload true "心跳载荷"
// @Success 200 {object} response.Any{data=flared.HeartbeatResponse} "心跳响应"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "Tunnel Token 无效"
// @Failure 403 {object} response.Any "节点类型不匹配"
// @Router /api/v1/tunnel/heartbeat [post]
func PostHeartbeat(c *gin.Context) {
var payload HeartbeatPayload
if !apiutil.BindJSON(c, &payload) {
@@ -35,6 +47,16 @@ func PostHeartbeat(c *gin.Context) {
}
// GetActiveConfig handles GET /tunnel/config/active.
// @Summary 获取活跃隧道配置
// @Description 返回 Tunnel 客户端当前应应用的完整路由配置(含中继列表与代理定义)
// @Tags openflare-tunnel
// @Produce json
// @Security TunnelTokenAuth
// @Success 200 {object} response.Any{data=flared.TunnelConfigResponse} "隧道配置"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "Tunnel Token 无效"
// @Failure 403 {object} response.Any "节点类型不匹配"
// @Router /api/v1/tunnel/config/active [get]
func GetActiveConfig(c *gin.Context) {
authNode, ok := c.Get(ctxFlaredNodeKey)
if !ok {
@@ -51,6 +73,18 @@ func GetActiveConfig(c *gin.Context) {
}
// PostApplyLog handles POST /tunnel/apply-log.
// @Summary 上报 Tunnel 配置下发结果
// @Description Tunnel 客户端上报配置应用结果,服务端记录下发日志
// @Tags openflare-tunnel
// @Accept json
// @Produce json
// @Security TunnelTokenAuth
// @Param body body flared.ApplyLogPayload true "下发结果载荷"
// @Success 200 {object} response.Any{data=model.OpenFlareApplyLog} "下发日志记录"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "Tunnel Token 无效"
// @Failure 403 {object} response.Any "节点类型不匹配"
// @Router /api/v1/tunnel/apply-log [post]
func PostApplyLog(c *gin.Context) {
var payload ApplyLogPayload
if !apiutil.BindJSON(c, &payload) {
@@ -68,6 +102,13 @@ func PostApplyLog(c *gin.Context) {
}
// GetWebSocket handles GET /tunnel/ws.
// @Summary 升级 Tunnel WebSocket 连接
// @Description 将已认证的 Tunnel 客户端连接升级为 WebSocket 长连接,用于配置推送
// @Tags openflare-tunnel
// @Security TunnelTokenAuth
// @Failure 401 {object} response.Any "Tunnel Token 无效"
// @Failure 403 {object} response.Any "节点类型不匹配"
// @Router /api/v1/tunnel/ws [get]
func GetWebSocket(c *gin.Context) {
authNode, ok := c.Get(ctxFlaredNodeKey)
if !ok {
@@ -29,7 +29,7 @@ import (
// @Success 200 {object} response.Any{data=observability.AccessLogList} "访问日志列表"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/access-logs [get]
func GetAccessLogsHandler(c *gin.Context) {
@@ -58,7 +58,7 @@ func GetAccessLogsHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=observability.FoldedAccessLogList} "折叠访问日志列表"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/access-logs/folds [get]
func GetFoldedAccessLogsHandler(c *gin.Context) {
@@ -90,7 +90,7 @@ func GetFoldedAccessLogsHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=observability.FoldedAccessLogIPList} "折叠 IP 汇总列表"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/access-logs/folds/ip-summary [get]
func GetFoldedAccessLogIPsHandler(c *gin.Context) {
@@ -128,7 +128,7 @@ func GetFoldedAccessLogIPsHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=observability.AccessLogIPSummaryList} "IP 汇总列表"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/access-logs/ip-summary [get]
func GetAccessLogIPSummariesHandler(c *gin.Context) {
@@ -161,7 +161,7 @@ func GetAccessLogIPSummariesHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=observability.AccessLogIPTrendView} "IP 访问趋势"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/access-logs/ip-summary/trend [get]
func GetAccessLogIPTrendHandler(c *gin.Context) {
@@ -189,7 +189,7 @@ func GetAccessLogIPTrendHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=observability.AccessLogCleanupResult} "清理结果"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/access-logs/cleanup [post]
func CleanupAccessLogsHandler(c *gin.Context) {
@@ -59,7 +59,7 @@ func GetNoticeHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=[]model.OpenFlareOption} "配置项列表"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/option [get]
// ListOptionsHandler lists OpenFlare options.
@@ -82,7 +82,7 @@ func ListOptionsHandler(c *gin.Context) {
// @Success 200 {object} response.Any "更新成功"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/option/update [post]
// UpdateOptionHandler updates a single option.
@@ -108,7 +108,7 @@ func UpdateOptionHandler(c *gin.Context) {
// @Success 200 {object} response.Any "更新成功"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/option/update-batch [post]
// UpdateOptionsBatchHandler updates options in batch.
@@ -134,7 +134,7 @@ func UpdateOptionsBatchHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=option.geoIPLookupView} "GeoIP 查询结果"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/option/geoip/lookup [post]
// LookupGeoIPHandler performs a GeoIP lookup.
@@ -161,7 +161,7 @@ func LookupGeoIPHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=option.databaseCleanupResult} "清理结果"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/option/database/cleanup [post]
// CleanupDatabaseHandler cleans up observability data.
@@ -188,7 +188,7 @@ func CleanupDatabaseHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=string} "同步成功"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/uptimekuma/sync [post]
// SyncUptimeKumaHandler triggers UptimeKuma sync.
@@ -43,7 +43,7 @@ func deploymentIDParam(c *gin.Context) (uint, bool) {
// @Success 200 {object} response.Any{data=[]pages.View} "Pages 项目列表"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/pages [get]
func ListProjectsHandler(c *gin.Context) {
@@ -64,7 +64,7 @@ func ListProjectsHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=pages.View} "Pages 项目详情"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "项目不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/pages/{id} [get]
@@ -91,7 +91,7 @@ func GetProjectHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=pages.View} "创建成功的项目"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/pages [post]
func CreateProjectHandler(c *gin.Context) {
@@ -118,7 +118,7 @@ func CreateProjectHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=pages.View} "更新后的项目"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "项目不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/pages/{id}/update [post]
@@ -148,7 +148,7 @@ func UpdateProjectHandler(c *gin.Context) {
// @Success 200 {object} response.Any "删除成功"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "项目不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/pages/{id}/delete [post]
@@ -173,7 +173,7 @@ func DeleteProjectHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=[]pages.DeploymentView} "部署列表"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "项目不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/pages/{id}/deployments [get]
@@ -201,7 +201,7 @@ func ListDeploymentsHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=pages.DeploymentView} "部署记录"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "项目不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/pages/{id}/deployments/upload [post]
@@ -233,7 +233,7 @@ func UploadDeploymentHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=pages.View} "激活后的项目"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "项目或部署不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/pages/{id}/deployments/{deployment_id}/activate [post]
@@ -264,7 +264,7 @@ func ActivateDeploymentHandler(c *gin.Context) {
// @Success 200 {object} response.Any "删除成功"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "项目或部署不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/pages/{id}/deployments/{deployment_id}/delete [post]
@@ -293,7 +293,7 @@ func DeleteDeploymentHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=[]pages.DeploymentFileView} "部署文件列表"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "部署不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/pages/deployments/{deployment_id}/files [get]
@@ -14,6 +14,18 @@ import (
)
// PostHeartbeat handles POST /relay/heartbeat.
// @Summary 上报 Relay 心跳
// @Description Relay 节点定期上报运行状态与 frps 观测数据,返回运行时配置
// @Tags openflare-relay
// @Accept json
// @Produce json
// @Security AgentTokenAuth
// @Param body body relay.HeartbeatPayload true "心跳载荷"
// @Success 200 {object} response.Any{data=relay.HeartbeatResponse} "心跳响应"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "Agent Token 无效"
// @Failure 403 {object} response.Any "节点类型不匹配"
// @Router /api/v1/relay/heartbeat [post]
func PostHeartbeat(c *gin.Context) {
var payload HeartbeatPayload
if !apiutil.BindJSON(c, &payload) {
@@ -36,6 +48,13 @@ func PostHeartbeat(c *gin.Context) {
}
// GetWebSocket handles GET /relay/ws.
// @Summary 升级 Relay WebSocket 连接
// @Description 将已认证的 Relay 连接升级为 WebSocket 长连接,用于配置推送
// @Tags openflare-relay
// @Security AgentTokenAuth
// @Failure 401 {object} response.Any "Agent Token 无效"
// @Failure 403 {object} response.Any "节点类型不匹配"
// @Router /api/v1/relay/ws [get]
func GetWebSocket(c *gin.Context) {
authNode, ok := c.Get(ctxRelayNodeKey)
if !ok {
+21 -21
View File
@@ -29,7 +29,7 @@ func handleLogicError(c *gin.Context, err error) bool {
// @Success 200 {object} response.Any{data=[]model.TLSCertificate} "证书列表"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/tls-certificates [get]
func GetCertificates(c *gin.Context) {
@@ -50,7 +50,7 @@ func GetCertificates(c *gin.Context) {
// @Success 200 {object} response.Any{data=model.TLSCertificate} "证书详情"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/tls-certificates/{id} [get]
@@ -76,7 +76,7 @@ func GetCertificateDetail(c *gin.Context) {
// @Success 200 {object} response.Any{data=tls.CertificateContent} "证书 PEM 内容"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/tls-certificates/{id}/content [get]
@@ -103,7 +103,7 @@ func GetCertificateContentHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=model.TLSCertificate} "创建成功的证书"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/tls-certificates [post]
func CreateCertificateHandler(c *gin.Context) {
@@ -130,7 +130,7 @@ func CreateCertificateHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=model.TLSCertificate} "更新后的证书"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/tls-certificates/{id}/update [post]
@@ -164,7 +164,7 @@ func UpdateCertificateHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=model.TLSCertificate} "导入成功的证书"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/tls-certificates/import-file [post]
func ImportCertificateFile(c *gin.Context) {
@@ -197,7 +197,7 @@ func ImportCertificateFile(c *gin.Context) {
// @Success 200 {object} response.Any "删除成功"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/tls-certificates/{id}/delete [post]
@@ -223,7 +223,7 @@ func DeleteCertificateHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=model.TLSCertificate} "申请中的证书"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/tls-certificates/apply [post]
func ApplyCertificateHandler(c *gin.Context) {
@@ -250,7 +250,7 @@ func ApplyCertificateHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=model.TLSCertificate} "更新后的证书"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/tls-certificates/{id}/update-acme [post]
@@ -282,7 +282,7 @@ func UpdateACMECertificateHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=model.TLSCertificate} "转换后的证书"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/tls-certificates/{id}/convert-acme [post]
@@ -312,7 +312,7 @@ func ConvertCertificateToACMEHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=model.TLSCertificate} "续期后的证书"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/tls-certificates/{id}/renew [post]
@@ -337,7 +337,7 @@ func RenewCertificateHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=[]model.ManagedDomain} "托管域名列表"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/managed-domains [get]
func GetManagedDomains(c *gin.Context) {
@@ -359,7 +359,7 @@ func GetManagedDomains(c *gin.Context) {
// @Success 200 {object} response.Any{data=model.ManagedDomain} "创建成功的托管域名"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/managed-domains [post]
func CreateManagedDomainHandler(c *gin.Context) {
@@ -386,7 +386,7 @@ func CreateManagedDomainHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=model.ManagedDomain} "更新后的托管域名"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/managed-domains/{id}/update [post]
@@ -416,7 +416,7 @@ func UpdateManagedDomainHandler(c *gin.Context) {
// @Success 200 {object} response.Any "删除成功"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/managed-domains/{id}/delete [post]
@@ -441,7 +441,7 @@ func DeleteManagedDomainHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=tls.ManagedDomainMatchResult} "证书匹配结果"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/managed-domains/match [get]
func MatchManagedDomainCertificateHandler(c *gin.Context) {
@@ -462,7 +462,7 @@ func MatchManagedDomainCertificateHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=[]model.DNSAccount} "DNS 账号列表"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/dns-accounts [get]
func GetDNSAccounts(c *gin.Context) {
@@ -484,7 +484,7 @@ func GetDNSAccounts(c *gin.Context) {
// @Success 200 {object} response.Any{data=model.DNSAccount} "创建成功的 DNS 账号"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/dns-accounts [post]
func CreateDNSAccountHandler(c *gin.Context) {
@@ -511,7 +511,7 @@ func CreateDNSAccountHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=model.DNSAccount} "更新后的 DNS 账号"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/dns-accounts/{id}/update [post]
@@ -541,7 +541,7 @@ func UpdateDNSAccountHandler(c *gin.Context) {
// @Success 200 {object} response.Any "删除成功"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/dns-accounts/{id}/delete [post]
@@ -565,7 +565,7 @@ func DeleteDNSAccountHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=model.AcmeAccount} "默认 ACME 账号"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/acme-accounts/default [get]
+15 -15
View File
@@ -43,7 +43,7 @@ func routeIDParam(c *gin.Context) (uint, bool) {
// @Success 200 {object} response.Any{data=[]waf.RuleGroupView} "规则组列表"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/waf/rule-groups [get]
func ListRuleGroupsHandler(c *gin.Context) {
@@ -64,7 +64,7 @@ func ListRuleGroupsHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=waf.RuleGroupView} "规则组详情"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/waf/rule-groups/{id} [get]
@@ -91,7 +91,7 @@ func GetRuleGroupHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=waf.RuleGroupView} "创建成功的规则组"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/waf/rule-groups [post]
func CreateRuleGroupHandler(c *gin.Context) {
@@ -118,7 +118,7 @@ func CreateRuleGroupHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=waf.RuleGroupView} "更新后的规则组"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/waf/rule-groups/{id}/update [post]
@@ -148,7 +148,7 @@ func UpdateRuleGroupHandler(c *gin.Context) {
// @Success 200 {object} response.Any "删除成功"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/waf/rule-groups/{id}/delete [post]
@@ -175,7 +175,7 @@ func DeleteRuleGroupHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=waf.RuleGroupView} "更新后的规则组"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/waf/rule-groups/{id}/sites [post]
@@ -205,7 +205,7 @@ func ReplaceRuleGroupSitesHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=waf.SiteRuleGroupsView} "站点规则组绑定"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/waf/sites/{route_id}/rule-groups [get]
@@ -233,7 +233,7 @@ func GetSiteRuleGroupsHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=waf.SiteRuleGroupsView} "更新后的站点规则组绑定"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/waf/sites/{route_id}/rule-groups [post]
@@ -262,7 +262,7 @@ func ReplaceSiteRuleGroupsHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=[]waf.IPGroupView} "IP 组列表"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/waf/ip-groups [get]
func ListIPGroupsHandler(c *gin.Context) {
@@ -283,7 +283,7 @@ func ListIPGroupsHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=waf.IPGroupView} "IP 组详情"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/waf/ip-groups/{id} [get]
@@ -310,7 +310,7 @@ func GetIPGroupHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=waf.IPGroupView} "创建成功的 IP 组"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/waf/ip-groups [post]
func CreateIPGroupHandler(c *gin.Context) {
@@ -337,7 +337,7 @@ func CreateIPGroupHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=waf.IPGroupView} "更新后的 IP 组"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/waf/ip-groups/{id}/update [post]
@@ -367,7 +367,7 @@ func UpdateIPGroupHandler(c *gin.Context) {
// @Success 200 {object} response.Any "删除成功"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/waf/ip-groups/{id}/delete [post]
@@ -392,7 +392,7 @@ func DeleteIPGroupHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=waf.IPGroupSyncResult} "同步结果"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 404 {object} response.Any "记录不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/waf/ip-groups/{id}/sync [post]
@@ -419,7 +419,7 @@ func SyncIPGroupHandler(c *gin.Context) {
// @Success 200 {object} response.Any{data=waf.IPGroupAutoTestResult} "测试结果"
// @Failure 400 {object} response.Any "参数错误"
// @Failure 401 {object} response.Any "未登录"
// @Failure 403 {object} response.Any "无管理员权限"
// @Failure 404 {object} response.Any "无权限或不存在"
// @Failure 500 {object} response.Any "内部错误"
// @Router /api/v1/d/waf/ip-groups/test [post]
func TestIPGroupAutoConfigHandler(c *gin.Context) {
+6
View File
@@ -17,6 +17,12 @@ import "github.com/Rain-kl/Wavelet/internal/cmd"
// @securityDefinitions.apikey SessionCookie
// @in cookie
// @name session
// @securityDefinitions.apikey AgentTokenAuth
// @in header
// @name X-Agent-Token
// @securityDefinitions.apikey TunnelTokenAuth
// @in header
// @name X-Tunnel-Token
func main() {
cmd.Execute()
}
+1
View File
@@ -72,6 +72,7 @@ sidebar: false
### 变更
- 补齐 OpenFlare Swagger 文档:新增 Agent/Relay/Tunnel 协议端点(13 个 `/api/v1/agent|relay|tunnel/*`)注解与安全定义(`AgentTokenAuth`、`TunnelTokenAuth`);管理端注解将权限不足响应由 403 统一为 404。
- Wavelet API 路径统一:管理端由 `/api/v1/openflare/*` 调整为 `/api/v1/d/*`;Agent/Relay/Tunnel 协议路由分别迁移至 `/api/v1/agent/*`、`/api/v1/relay/*`、`/api/v1/tunnel/*`(原 `/api/flared/*`)。同步更新 Wavelet 前端服务层与 `openflare-agent`、`openflare-relay`、`openflared` 客户端连接端点。
- Agent/Relay/Tunnel 协议 API 响应格式对齐 Wavelet `{error_msg, data}`:服务端移除 `compat` 包,业务错误改为 HTTP 4xx + `error_msg`;同步更新 `openflare-agent`、`openflare-relay`、`openflared` HTTP 客户端解析逻辑。
- OpenFlare 管理端权限模型对齐 Wavelet:取消旧系统 Admin/Root 三级角色区分,统一以 `user.IsAdmin` 为管理门槛;Access Token 访问敏感接口(Option、Update 等)须 `token_admin=true`;权限不足返回 HTTP 404 + `error_msg`,参数错误返回 HTTP 400 + `error_msg`(`apiutil.AdminMiddlewares` = `oauth.LoginRequired` + `admin.LoginAdminRequired`)。