diff --git a/atsf_server/controller/agent.go b/atsf_server/controller/agent.go index fe2dd094..fa235d73 100644 --- a/atsf_server/controller/agent.go +++ b/atsf_server/controller/agent.go @@ -9,6 +9,16 @@ import ( "github.com/gin-gonic/gin" ) +// AgentRegister godoc +// @Summary Register or discover agent node +// @Tags Agent +// @Accept json +// @Produce json +// @Security AgentTokenAuth +// @Param payload body service.AgentNodePayload true "Agent node payload" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/agent/nodes/register [post] func AgentRegister(c *gin.Context) { var payload service.AgentNodePayload if err := json.NewDecoder(c.Request.Body).Decode(&payload); err != nil { @@ -41,6 +51,16 @@ func AgentRegister(c *gin.Context) { }) } +// AgentHeartbeat godoc +// @Summary Report agent heartbeat +// @Tags Agent +// @Accept json +// @Produce json +// @Security AgentTokenAuth +// @Param payload body service.AgentNodePayload true "Agent heartbeat payload" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/agent/nodes/heartbeat [post] func AgentHeartbeat(c *gin.Context) { var payload service.AgentNodePayload if err := json.NewDecoder(c.Request.Body).Decode(&payload); err != nil { @@ -74,6 +94,13 @@ func AgentHeartbeat(c *gin.Context) { }) } +// AgentGetActiveConfig godoc +// @Summary Get active config for agent +// @Tags Agent +// @Produce json +// @Security AgentTokenAuth +// @Success 200 {object} map[string]interface{} +// @Router /api/agent/config-versions/active [get] func AgentGetActiveConfig(c *gin.Context) { config, err := service.GetActiveConfigForAgent() if err != nil { @@ -90,6 +117,16 @@ func AgentGetActiveConfig(c *gin.Context) { }) } +// AgentReportApplyLog godoc +// @Summary Report agent apply result +// @Tags Agent +// @Accept json +// @Produce json +// @Security AgentTokenAuth +// @Param payload body service.ApplyLogPayload true "Apply log payload" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/agent/apply-logs [post] func AgentReportApplyLog(c *gin.Context) { var payload service.ApplyLogPayload if err := json.NewDecoder(c.Request.Body).Decode(&payload); err != nil { @@ -118,6 +155,13 @@ func AgentReportApplyLog(c *gin.Context) { }) } +// GetNodes godoc +// @Summary List nodes +// @Tags Nodes +// @Produce json +// @Security BearerAuth +// @Success 200 {object} map[string]interface{} +// @Router /api/nodes/ [get] func GetNodes(c *gin.Context) { nodes, err := service.ListNodeViews() if err != nil { @@ -134,6 +178,14 @@ func GetNodes(c *gin.Context) { }) } +// GetApplyLogs godoc +// @Summary List apply logs +// @Tags ApplyLogs +// @Produce json +// @Security BearerAuth +// @Param node_id query string false "Node ID" +// @Success 200 {object} map[string]interface{} +// @Router /api/apply-logs/ [get] func GetApplyLogs(c *gin.Context) { logs, err := service.ListApplyLogs(c.Query("node_id")) if err != nil { diff --git a/atsf_server/controller/config_version.go b/atsf_server/controller/config_version.go index d4debcba..7c423a76 100644 --- a/atsf_server/controller/config_version.go +++ b/atsf_server/controller/config_version.go @@ -7,6 +7,13 @@ import ( "strconv" ) +// GetConfigVersions godoc +// @Summary List config versions +// @Tags ConfigVersions +// @Produce json +// @Security BearerAuth +// @Success 200 {object} map[string]interface{} +// @Router /api/config-versions/ [get] func GetConfigVersions(c *gin.Context) { versions, err := service.ListConfigVersions() if err != nil { @@ -23,6 +30,13 @@ func GetConfigVersions(c *gin.Context) { }) } +// GetActiveConfigVersion godoc +// @Summary Get active config version +// @Tags ConfigVersions +// @Produce json +// @Security BearerAuth +// @Success 200 {object} map[string]interface{} +// @Router /api/config-versions/active [get] func GetActiveConfigVersion(c *gin.Context) { version, err := service.GetActiveConfigVersion() if err != nil { @@ -39,6 +53,13 @@ func GetActiveConfigVersion(c *gin.Context) { }) } +// PreviewConfigVersion godoc +// @Summary Preview config rendering +// @Tags ConfigVersions +// @Produce json +// @Security BearerAuth +// @Success 200 {object} map[string]interface{} +// @Router /api/config-versions/preview [get] func PreviewConfigVersion(c *gin.Context) { preview, err := service.PreviewConfigVersion() if err != nil { @@ -55,6 +76,13 @@ func PreviewConfigVersion(c *gin.Context) { }) } +// DiffConfigVersion godoc +// @Summary Diff current draft against active version +// @Tags ConfigVersions +// @Produce json +// @Security BearerAuth +// @Success 200 {object} map[string]interface{} +// @Router /api/config-versions/diff [get] func DiffConfigVersion(c *gin.Context) { diff, err := service.DiffConfigVersion() if err != nil { @@ -71,6 +99,13 @@ func DiffConfigVersion(c *gin.Context) { }) } +// PublishConfigVersion godoc +// @Summary Publish a new config version +// @Tags ConfigVersions +// @Produce json +// @Security BearerAuth +// @Success 200 {object} map[string]interface{} +// @Router /api/config-versions/publish [post] func PublishConfigVersion(c *gin.Context) { username := c.GetString("username") result, err := service.PublishConfigVersion(username) @@ -88,6 +123,15 @@ func PublishConfigVersion(c *gin.Context) { }) } +// ActivateConfigVersion godoc +// @Summary Activate an existing config version +// @Tags ConfigVersions +// @Produce json +// @Security BearerAuth +// @Param id path int true "Version ID" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/config-versions/{id}/activate [put] func ActivateConfigVersion(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil || id == 0 { diff --git a/atsf_server/controller/managed_domain.go b/atsf_server/controller/managed_domain.go index d9d37371..c71def59 100644 --- a/atsf_server/controller/managed_domain.go +++ b/atsf_server/controller/managed_domain.go @@ -9,6 +9,13 @@ import ( "strings" ) +// GetManagedDomains godoc +// @Summary List managed domains +// @Tags ManagedDomains +// @Produce json +// @Security BearerAuth +// @Success 200 {object} map[string]interface{} +// @Router /api/managed-domains/ [get] func GetManagedDomains(c *gin.Context) { domains, err := service.ListManagedDomains() if err != nil { @@ -25,6 +32,16 @@ func GetManagedDomains(c *gin.Context) { }) } +// CreateManagedDomain godoc +// @Summary Create managed domain +// @Tags ManagedDomains +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param payload body service.ManagedDomainInput true "Managed domain payload" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/managed-domains/ [post] func CreateManagedDomain(c *gin.Context) { var input service.ManagedDomainInput if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil { @@ -49,6 +66,17 @@ func CreateManagedDomain(c *gin.Context) { }) } +// UpdateManagedDomain godoc +// @Summary Update managed domain +// @Tags ManagedDomains +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param id path int true "Managed domain ID" +// @Param payload body service.ManagedDomainInput true "Managed domain payload" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/managed-domains/{id} [put] func UpdateManagedDomain(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil || id == 0 { @@ -81,6 +109,15 @@ func UpdateManagedDomain(c *gin.Context) { }) } +// DeleteManagedDomain godoc +// @Summary Delete managed domain +// @Tags ManagedDomains +// @Produce json +// @Security BearerAuth +// @Param id path int true "Managed domain ID" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/managed-domains/{id} [delete] func DeleteManagedDomain(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil || id == 0 { @@ -103,6 +140,14 @@ func DeleteManagedDomain(c *gin.Context) { }) } +// MatchManagedDomainCertificate godoc +// @Summary Match certificate for domain +// @Tags ManagedDomains +// @Produce json +// @Security BearerAuth +// @Param domain query string true "Domain" +// @Success 200 {object} map[string]interface{} +// @Router /api/managed-domains/match [get] func MatchManagedDomainCertificate(c *gin.Context) { domain := strings.TrimSpace(c.Query("domain")) result, err := service.MatchManagedDomainCertificate(domain) diff --git a/atsf_server/controller/misc.go b/atsf_server/controller/misc.go index d7368489..7c692ef8 100644 --- a/atsf_server/controller/misc.go +++ b/atsf_server/controller/misc.go @@ -9,6 +9,12 @@ import ( "net/http" ) +// GetStatus godoc +// @Summary Get server status +// @Tags Public +// @Produce json +// @Success 200 {object} map[string]interface{} +// @Router /api/status [get] func GetStatus(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "success": true, diff --git a/atsf_server/controller/node.go b/atsf_server/controller/node.go index 61540f8a..b4291a68 100644 --- a/atsf_server/controller/node.go +++ b/atsf_server/controller/node.go @@ -9,6 +9,16 @@ import ( "github.com/gin-gonic/gin" ) +// CreateNode godoc +// @Summary Create node +// @Tags Nodes +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param payload body service.NodeInput true "Node payload" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/nodes/ [post] func CreateNode(c *gin.Context) { var input service.NodeInput if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil { @@ -33,6 +43,13 @@ func CreateNode(c *gin.Context) { }) } +// GetNodeBootstrapToken godoc +// @Summary Get global discovery token +// @Tags Nodes +// @Produce json +// @Security BearerAuth +// @Success 200 {object} map[string]interface{} +// @Router /api/nodes/bootstrap-token [get] func GetNodeBootstrapToken(c *gin.Context) { bootstrap, err := service.GetNodeBootstrapView() if err != nil { @@ -49,6 +66,13 @@ func GetNodeBootstrapToken(c *gin.Context) { }) } +// RotateNodeBootstrapToken godoc +// @Summary Rotate global discovery token +// @Tags Nodes +// @Produce json +// @Security BearerAuth +// @Success 200 {object} map[string]interface{} +// @Router /api/nodes/bootstrap-token/rotate [post] func RotateNodeBootstrapToken(c *gin.Context) { bootstrap, err := service.RotateGlobalDiscoveryToken() if err != nil { @@ -65,6 +89,17 @@ func RotateNodeBootstrapToken(c *gin.Context) { }) } +// UpdateNode godoc +// @Summary Update node +// @Tags Nodes +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param id path int true "Node ID" +// @Param payload body service.NodeInput true "Node payload" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/nodes/{id} [put] func UpdateNode(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil || id == 0 { @@ -97,6 +132,15 @@ func UpdateNode(c *gin.Context) { }) } +// DeleteNode godoc +// @Summary Delete node +// @Tags Nodes +// @Produce json +// @Security BearerAuth +// @Param id path int true "Node ID" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/nodes/{id} [delete] func DeleteNode(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil || id == 0 { @@ -119,6 +163,15 @@ func DeleteNode(c *gin.Context) { }) } +// RequestNodeAgentUpdate godoc +// @Summary Request agent self-update on node +// @Tags Nodes +// @Produce json +// @Security BearerAuth +// @Param id path int true "Node ID" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/nodes/{id}/agent-update [post] func RequestNodeAgentUpdate(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil || id == 0 { diff --git a/atsf_server/controller/option.go b/atsf_server/controller/option.go index e627ec60..23e03ca8 100644 --- a/atsf_server/controller/option.go +++ b/atsf_server/controller/option.go @@ -9,6 +9,12 @@ import ( "strings" ) +// GetOptions godoc +// @Summary List editable options +// @Tags Options +// @Produce json +// @Success 200 {object} map[string]interface{} +// @Router /api/option/ [get] func GetOptions(c *gin.Context) { var options []*model.Option common.OptionMapRWMutex.Lock() @@ -30,6 +36,15 @@ func GetOptions(c *gin.Context) { return } +// UpdateOption godoc +// @Summary Update option +// @Tags Options +// @Accept json +// @Produce json +// @Param payload body model.Option true "Option payload" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/option/ [put] func UpdateOption(c *gin.Context) { var option model.Option err := json.NewDecoder(c.Request.Body).Decode(&option) diff --git a/atsf_server/controller/proxy_route.go b/atsf_server/controller/proxy_route.go index 7ddd2e28..58fec1f8 100644 --- a/atsf_server/controller/proxy_route.go +++ b/atsf_server/controller/proxy_route.go @@ -8,6 +8,13 @@ import ( "strconv" ) +// GetProxyRoutes godoc +// @Summary List proxy routes +// @Tags ProxyRoutes +// @Produce json +// @Security BearerAuth +// @Success 200 {object} map[string]interface{} +// @Router /api/proxy-routes/ [get] func GetProxyRoutes(c *gin.Context) { routes, err := service.ListProxyRoutes() if err != nil { @@ -24,6 +31,16 @@ func GetProxyRoutes(c *gin.Context) { }) } +// CreateProxyRoute godoc +// @Summary Create proxy route +// @Tags ProxyRoutes +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param payload body service.ProxyRouteInput true "Proxy route payload" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/proxy-routes/ [post] func CreateProxyRoute(c *gin.Context) { var input service.ProxyRouteInput if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil { @@ -48,6 +65,17 @@ func CreateProxyRoute(c *gin.Context) { }) } +// UpdateProxyRoute godoc +// @Summary Update proxy route +// @Tags ProxyRoutes +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param id path int true "Route ID" +// @Param payload body service.ProxyRouteInput true "Proxy route payload" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/proxy-routes/{id} [put] func UpdateProxyRoute(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil || id == 0 { @@ -80,6 +108,15 @@ func UpdateProxyRoute(c *gin.Context) { }) } +// DeleteProxyRoute godoc +// @Summary Delete proxy route +// @Tags ProxyRoutes +// @Produce json +// @Security BearerAuth +// @Param id path int true "Route ID" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/proxy-routes/{id} [delete] func DeleteProxyRoute(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil || id == 0 { diff --git a/atsf_server/controller/tls_certificate.go b/atsf_server/controller/tls_certificate.go index 5b38c0ec..c5861058 100644 --- a/atsf_server/controller/tls_certificate.go +++ b/atsf_server/controller/tls_certificate.go @@ -8,6 +8,13 @@ import ( "strconv" ) +// GetTLSCertificates godoc +// @Summary List TLS certificates +// @Tags TLSCertificates +// @Produce json +// @Security BearerAuth +// @Success 200 {object} map[string]interface{} +// @Router /api/tls-certificates/ [get] func GetTLSCertificates(c *gin.Context) { certificates, err := service.ListTLSCertificates() if err != nil { @@ -24,6 +31,16 @@ func GetTLSCertificates(c *gin.Context) { }) } +// CreateTLSCertificate godoc +// @Summary Create TLS certificate from PEM +// @Tags TLSCertificates +// @Accept json +// @Produce json +// @Security BearerAuth +// @Param payload body service.TLSCertificateInput true "TLS certificate payload" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/tls-certificates/ [post] func CreateTLSCertificate(c *gin.Context) { var input service.TLSCertificateInput if err := json.NewDecoder(c.Request.Body).Decode(&input); err != nil { @@ -48,6 +65,19 @@ func CreateTLSCertificate(c *gin.Context) { }) } +// ImportTLSCertificateFile godoc +// @Summary Import TLS certificate from files +// @Tags TLSCertificates +// @Accept multipart/form-data +// @Produce json +// @Security BearerAuth +// @Param name formData string true "Certificate name" +// @Param remark formData string false "Remark" +// @Param cert_file formData file true "Certificate file" +// @Param key_file formData file true "Private key file" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/tls-certificates/import-file [post] func ImportTLSCertificateFile(c *gin.Context) { name := c.PostForm("name") remark := c.PostForm("remark") @@ -82,6 +112,15 @@ func ImportTLSCertificateFile(c *gin.Context) { }) } +// DeleteTLSCertificate godoc +// @Summary Delete TLS certificate +// @Tags TLSCertificates +// @Produce json +// @Security BearerAuth +// @Param id path int true "Certificate ID" +// @Success 200 {object} map[string]interface{} +// @Failure 400 {object} map[string]interface{} +// @Router /api/tls-certificates/{id} [delete] func DeleteTLSCertificate(c *gin.Context) { id, err := strconv.ParseUint(c.Param("id"), 10, 64) if err != nil || id == 0 { diff --git a/atsf_server/controller/update.go b/atsf_server/controller/update.go index 8999ce1e..22621052 100644 --- a/atsf_server/controller/update.go +++ b/atsf_server/controller/update.go @@ -22,6 +22,12 @@ type latestReleaseResponse struct { PublishedAt string `json:"published_at"` } +// GetLatestRelease godoc +// @Summary Get latest GitHub release +// @Tags Update +// @Produce json +// @Success 200 {object} map[string]interface{} +// @Router /api/update/latest-release [get] func GetLatestRelease(c *gin.Context) { req, err := http.NewRequestWithContext(c.Request.Context(), http.MethodGet, latestReleaseURL, nil) if err != nil { diff --git a/atsf_server/docs/docs.go b/atsf_server/docs/docs.go new file mode 100644 index 00000000..b89c9179 --- /dev/null +++ b/atsf_server/docs/docs.go @@ -0,0 +1,1438 @@ +// Package docs Code generated by swaggo/swag. DO NOT EDIT +package docs + +import "github.com/swaggo/swag" + +const docTemplate = `{ + "schemes": {{ marshal .Schemes }}, + "swagger": "2.0", + "info": { + "description": "{{escape .Description}}", + "title": "{{.Title}}", + "contact": {}, + "version": "{{.Version}}" + }, + "host": "{{.Host}}", + "basePath": "{{.BasePath}}", + "paths": { + "/api/agent/apply-logs": { + "post": { + "security": [ + { + "AgentTokenAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Agent" + ], + "summary": "Report agent apply result", + "parameters": [ + { + "description": "Apply log payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.ApplyLogPayload" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/agent/config-versions/active": { + "get": { + "security": [ + { + "AgentTokenAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Agent" + ], + "summary": "Get active config for agent", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/agent/nodes/heartbeat": { + "post": { + "security": [ + { + "AgentTokenAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Agent" + ], + "summary": "Report agent heartbeat", + "parameters": [ + { + "description": "Agent heartbeat payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.AgentNodePayload" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/agent/nodes/register": { + "post": { + "security": [ + { + "AgentTokenAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Agent" + ], + "summary": "Register or discover agent node", + "parameters": [ + { + "description": "Agent node payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.AgentNodePayload" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/apply-logs/": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ApplyLogs" + ], + "summary": "List apply logs", + "parameters": [ + { + "type": "string", + "description": "Node ID", + "name": "node_id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/config-versions/": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ConfigVersions" + ], + "summary": "List config versions", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/config-versions/active": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ConfigVersions" + ], + "summary": "Get active config version", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/config-versions/diff": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ConfigVersions" + ], + "summary": "Diff current draft against active version", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/config-versions/preview": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ConfigVersions" + ], + "summary": "Preview config rendering", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/config-versions/publish": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ConfigVersions" + ], + "summary": "Publish a new config version", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/config-versions/{id}/activate": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ConfigVersions" + ], + "summary": "Activate an existing config version", + "parameters": [ + { + "type": "integer", + "description": "Version ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/managed-domains/": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ManagedDomains" + ], + "summary": "List managed domains", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ManagedDomains" + ], + "summary": "Create managed domain", + "parameters": [ + { + "description": "Managed domain payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.ManagedDomainInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/managed-domains/match": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ManagedDomains" + ], + "summary": "Match certificate for domain", + "parameters": [ + { + "type": "string", + "description": "Domain", + "name": "domain", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/managed-domains/{id}": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ManagedDomains" + ], + "summary": "Update managed domain", + "parameters": [ + { + "type": "integer", + "description": "Managed domain ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Managed domain payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.ManagedDomainInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ManagedDomains" + ], + "summary": "Delete managed domain", + "parameters": [ + { + "type": "integer", + "description": "Managed domain ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/nodes/": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Nodes" + ], + "summary": "List nodes", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Nodes" + ], + "summary": "Create node", + "parameters": [ + { + "description": "Node payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.NodeInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/nodes/bootstrap-token": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Nodes" + ], + "summary": "Get global discovery token", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/nodes/bootstrap-token/rotate": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Nodes" + ], + "summary": "Rotate global discovery token", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/nodes/{id}": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Nodes" + ], + "summary": "Update node", + "parameters": [ + { + "type": "integer", + "description": "Node ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Node payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.NodeInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Nodes" + ], + "summary": "Delete node", + "parameters": [ + { + "type": "integer", + "description": "Node ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/nodes/{id}/agent-update": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Nodes" + ], + "summary": "Request agent self-update on node", + "parameters": [ + { + "type": "integer", + "description": "Node ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/option/": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Options" + ], + "summary": "List editable options", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "put": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Options" + ], + "summary": "Update option", + "parameters": [ + { + "description": "Option payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.Option" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/proxy-routes/": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ProxyRoutes" + ], + "summary": "List proxy routes", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ProxyRoutes" + ], + "summary": "Create proxy route", + "parameters": [ + { + "description": "Proxy route payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.ProxyRouteInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/proxy-routes/{id}": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ProxyRoutes" + ], + "summary": "Update proxy route", + "parameters": [ + { + "type": "integer", + "description": "Route ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Proxy route payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.ProxyRouteInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ProxyRoutes" + ], + "summary": "Delete proxy route", + "parameters": [ + { + "type": "integer", + "description": "Route ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/status": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Public" + ], + "summary": "Get server status", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/tls-certificates/": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "TLSCertificates" + ], + "summary": "List TLS certificates", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "TLSCertificates" + ], + "summary": "Create TLS certificate from PEM", + "parameters": [ + { + "description": "TLS certificate payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.TLSCertificateInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/tls-certificates/import-file": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "TLSCertificates" + ], + "summary": "Import TLS certificate from files", + "parameters": [ + { + "type": "string", + "description": "Certificate name", + "name": "name", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "Remark", + "name": "remark", + "in": "formData" + }, + { + "type": "file", + "description": "Certificate file", + "name": "cert_file", + "in": "formData", + "required": true + }, + { + "type": "file", + "description": "Private key file", + "name": "key_file", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/tls-certificates/{id}": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "TLSCertificates" + ], + "summary": "Delete TLS certificate", + "parameters": [ + { + "type": "integer", + "description": "Certificate ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/update/latest-release": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Update" + ], + "summary": "Get latest GitHub release", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + } + }, + "definitions": { + "model.Option": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, + "service.AgentNodePayload": { + "type": "object", + "properties": { + "agent_version": { + "type": "string" + }, + "current_version": { + "type": "string" + }, + "ip": { + "type": "string" + }, + "last_error": { + "type": "string" + }, + "name": { + "type": "string" + }, + "nginx_version": { + "type": "string" + }, + "node_id": { + "type": "string" + } + } + }, + "service.ApplyLogPayload": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "node_id": { + "type": "string" + }, + "result": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "service.ManagedDomainInput": { + "type": "object", + "properties": { + "cert_id": { + "type": "integer" + }, + "domain": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "remark": { + "type": "string" + } + } + }, + "service.NodeInput": { + "type": "object", + "properties": { + "auto_update_enabled": { + "type": "boolean" + }, + "name": { + "type": "string" + } + } + }, + "service.ProxyRouteCustomHeaderInput": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, + "service.ProxyRouteInput": { + "type": "object", + "properties": { + "cert_id": { + "type": "integer" + }, + "custom_headers": { + "type": "array", + "items": { + "$ref": "#/definitions/service.ProxyRouteCustomHeaderInput" + } + }, + "domain": { + "type": "string" + }, + "enable_https": { + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "origin_url": { + "type": "string" + }, + "redirect_http": { + "type": "boolean" + }, + "remark": { + "type": "string" + } + } + }, + "service.TLSCertificateInput": { + "type": "object", + "properties": { + "cert_pem": { + "type": "string" + }, + "key_pem": { + "type": "string" + }, + "name": { + "type": "string" + }, + "remark": { + "type": "string" + } + } + } + }, + "securityDefinitions": { + "AgentTokenAuth": { + "description": "Agent API 使用节点专属 Agent Token 或全局 Discovery Token", + "type": "apiKey", + "name": "X-Agent-Token", + "in": "header" + }, + "BearerAuth": { + "description": "管理端可使用 Bearer Token,例如:Bearer \u003ctoken\u003e", + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + } +}` + +// SwaggerInfo holds exported Swagger Info so clients can modify it +var SwaggerInfo = &swag.Spec{ + Version: "3.0", + Host: "", + BasePath: "/", + Schemes: []string{"http", "https"}, + Title: "ATSFlare Server API", + Description: "ATSFlare Server 管理端与 Agent API 文档。", + InfoInstanceName: "swagger", + SwaggerTemplate: docTemplate, + LeftDelim: "{{", + RightDelim: "}}", +} + +func init() { + swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo) +} diff --git a/atsf_server/docs/swagger.json b/atsf_server/docs/swagger.json new file mode 100644 index 00000000..4efa7a7a --- /dev/null +++ b/atsf_server/docs/swagger.json @@ -0,0 +1,1417 @@ +{ + "schemes": [ + "http", + "https" + ], + "swagger": "2.0", + "info": { + "description": "ATSFlare Server 管理端与 Agent API 文档。", + "title": "ATSFlare Server API", + "contact": {}, + "version": "3.0" + }, + "basePath": "/", + "paths": { + "/api/agent/apply-logs": { + "post": { + "security": [ + { + "AgentTokenAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Agent" + ], + "summary": "Report agent apply result", + "parameters": [ + { + "description": "Apply log payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.ApplyLogPayload" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/agent/config-versions/active": { + "get": { + "security": [ + { + "AgentTokenAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Agent" + ], + "summary": "Get active config for agent", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/agent/nodes/heartbeat": { + "post": { + "security": [ + { + "AgentTokenAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Agent" + ], + "summary": "Report agent heartbeat", + "parameters": [ + { + "description": "Agent heartbeat payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.AgentNodePayload" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/agent/nodes/register": { + "post": { + "security": [ + { + "AgentTokenAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Agent" + ], + "summary": "Register or discover agent node", + "parameters": [ + { + "description": "Agent node payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.AgentNodePayload" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/apply-logs/": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ApplyLogs" + ], + "summary": "List apply logs", + "parameters": [ + { + "type": "string", + "description": "Node ID", + "name": "node_id", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/config-versions/": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ConfigVersions" + ], + "summary": "List config versions", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/config-versions/active": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ConfigVersions" + ], + "summary": "Get active config version", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/config-versions/diff": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ConfigVersions" + ], + "summary": "Diff current draft against active version", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/config-versions/preview": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ConfigVersions" + ], + "summary": "Preview config rendering", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/config-versions/publish": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ConfigVersions" + ], + "summary": "Publish a new config version", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/config-versions/{id}/activate": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ConfigVersions" + ], + "summary": "Activate an existing config version", + "parameters": [ + { + "type": "integer", + "description": "Version ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/managed-domains/": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ManagedDomains" + ], + "summary": "List managed domains", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ManagedDomains" + ], + "summary": "Create managed domain", + "parameters": [ + { + "description": "Managed domain payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.ManagedDomainInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/managed-domains/match": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ManagedDomains" + ], + "summary": "Match certificate for domain", + "parameters": [ + { + "type": "string", + "description": "Domain", + "name": "domain", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/managed-domains/{id}": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ManagedDomains" + ], + "summary": "Update managed domain", + "parameters": [ + { + "type": "integer", + "description": "Managed domain ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Managed domain payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.ManagedDomainInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ManagedDomains" + ], + "summary": "Delete managed domain", + "parameters": [ + { + "type": "integer", + "description": "Managed domain ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/nodes/": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Nodes" + ], + "summary": "List nodes", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Nodes" + ], + "summary": "Create node", + "parameters": [ + { + "description": "Node payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.NodeInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/nodes/bootstrap-token": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Nodes" + ], + "summary": "Get global discovery token", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/nodes/bootstrap-token/rotate": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Nodes" + ], + "summary": "Rotate global discovery token", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/nodes/{id}": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Nodes" + ], + "summary": "Update node", + "parameters": [ + { + "type": "integer", + "description": "Node ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Node payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.NodeInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Nodes" + ], + "summary": "Delete node", + "parameters": [ + { + "type": "integer", + "description": "Node ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/nodes/{id}/agent-update": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Nodes" + ], + "summary": "Request agent self-update on node", + "parameters": [ + { + "type": "integer", + "description": "Node ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/option/": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Options" + ], + "summary": "List editable options", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "put": { + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Options" + ], + "summary": "Update option", + "parameters": [ + { + "description": "Option payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/model.Option" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/proxy-routes/": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ProxyRoutes" + ], + "summary": "List proxy routes", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ProxyRoutes" + ], + "summary": "Create proxy route", + "parameters": [ + { + "description": "Proxy route payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.ProxyRouteInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/proxy-routes/{id}": { + "put": { + "security": [ + { + "BearerAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "ProxyRoutes" + ], + "summary": "Update proxy route", + "parameters": [ + { + "type": "integer", + "description": "Route ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Proxy route payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.ProxyRouteInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "ProxyRoutes" + ], + "summary": "Delete proxy route", + "parameters": [ + { + "type": "integer", + "description": "Route ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/status": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Public" + ], + "summary": "Get server status", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/tls-certificates/": { + "get": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "TLSCertificates" + ], + "summary": "List TLS certificates", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + }, + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "TLSCertificates" + ], + "summary": "Create TLS certificate from PEM", + "parameters": [ + { + "description": "TLS certificate payload", + "name": "payload", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/service.TLSCertificateInput" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/tls-certificates/import-file": { + "post": { + "security": [ + { + "BearerAuth": [] + } + ], + "consumes": [ + "multipart/form-data" + ], + "produces": [ + "application/json" + ], + "tags": [ + "TLSCertificates" + ], + "summary": "Import TLS certificate from files", + "parameters": [ + { + "type": "string", + "description": "Certificate name", + "name": "name", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "Remark", + "name": "remark", + "in": "formData" + }, + { + "type": "file", + "description": "Certificate file", + "name": "cert_file", + "in": "formData", + "required": true + }, + { + "type": "file", + "description": "Private key file", + "name": "key_file", + "in": "formData", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/tls-certificates/{id}": { + "delete": { + "security": [ + { + "BearerAuth": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "TLSCertificates" + ], + "summary": "Delete TLS certificate", + "parameters": [ + { + "type": "integer", + "description": "Certificate ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + }, + "400": { + "description": "Bad Request", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + }, + "/api/update/latest-release": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "Update" + ], + "summary": "Get latest GitHub release", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "object", + "additionalProperties": true + } + } + } + } + } + }, + "definitions": { + "model.Option": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, + "service.AgentNodePayload": { + "type": "object", + "properties": { + "agent_version": { + "type": "string" + }, + "current_version": { + "type": "string" + }, + "ip": { + "type": "string" + }, + "last_error": { + "type": "string" + }, + "name": { + "type": "string" + }, + "nginx_version": { + "type": "string" + }, + "node_id": { + "type": "string" + } + } + }, + "service.ApplyLogPayload": { + "type": "object", + "properties": { + "message": { + "type": "string" + }, + "node_id": { + "type": "string" + }, + "result": { + "type": "string" + }, + "version": { + "type": "string" + } + } + }, + "service.ManagedDomainInput": { + "type": "object", + "properties": { + "cert_id": { + "type": "integer" + }, + "domain": { + "type": "string" + }, + "enabled": { + "type": "boolean" + }, + "remark": { + "type": "string" + } + } + }, + "service.NodeInput": { + "type": "object", + "properties": { + "auto_update_enabled": { + "type": "boolean" + }, + "name": { + "type": "string" + } + } + }, + "service.ProxyRouteCustomHeaderInput": { + "type": "object", + "properties": { + "key": { + "type": "string" + }, + "value": { + "type": "string" + } + } + }, + "service.ProxyRouteInput": { + "type": "object", + "properties": { + "cert_id": { + "type": "integer" + }, + "custom_headers": { + "type": "array", + "items": { + "$ref": "#/definitions/service.ProxyRouteCustomHeaderInput" + } + }, + "domain": { + "type": "string" + }, + "enable_https": { + "type": "boolean" + }, + "enabled": { + "type": "boolean" + }, + "origin_url": { + "type": "string" + }, + "redirect_http": { + "type": "boolean" + }, + "remark": { + "type": "string" + } + } + }, + "service.TLSCertificateInput": { + "type": "object", + "properties": { + "cert_pem": { + "type": "string" + }, + "key_pem": { + "type": "string" + }, + "name": { + "type": "string" + }, + "remark": { + "type": "string" + } + } + } + }, + "securityDefinitions": { + "AgentTokenAuth": { + "description": "Agent API 使用节点专属 Agent Token 或全局 Discovery Token", + "type": "apiKey", + "name": "X-Agent-Token", + "in": "header" + }, + "BearerAuth": { + "description": "管理端可使用 Bearer Token,例如:Bearer \u003ctoken\u003e", + "type": "apiKey", + "name": "Authorization", + "in": "header" + } + } +} \ No newline at end of file diff --git a/atsf_server/docs/swagger.yaml b/atsf_server/docs/swagger.yaml new file mode 100644 index 00000000..8c2ffae4 --- /dev/null +++ b/atsf_server/docs/swagger.yaml @@ -0,0 +1,897 @@ +basePath: / +definitions: + model.Option: + properties: + key: + type: string + value: + type: string + type: object + service.AgentNodePayload: + properties: + agent_version: + type: string + current_version: + type: string + ip: + type: string + last_error: + type: string + name: + type: string + nginx_version: + type: string + node_id: + type: string + type: object + service.ApplyLogPayload: + properties: + message: + type: string + node_id: + type: string + result: + type: string + version: + type: string + type: object + service.ManagedDomainInput: + properties: + cert_id: + type: integer + domain: + type: string + enabled: + type: boolean + remark: + type: string + type: object + service.NodeInput: + properties: + auto_update_enabled: + type: boolean + name: + type: string + type: object + service.ProxyRouteCustomHeaderInput: + properties: + key: + type: string + value: + type: string + type: object + service.ProxyRouteInput: + properties: + cert_id: + type: integer + custom_headers: + items: + $ref: '#/definitions/service.ProxyRouteCustomHeaderInput' + type: array + domain: + type: string + enable_https: + type: boolean + enabled: + type: boolean + origin_url: + type: string + redirect_http: + type: boolean + remark: + type: string + type: object + service.TLSCertificateInput: + properties: + cert_pem: + type: string + key_pem: + type: string + name: + type: string + remark: + type: string + type: object +info: + contact: {} + description: ATSFlare Server 管理端与 Agent API 文档。 + title: ATSFlare Server API + version: "3.0" +paths: + /api/agent/apply-logs: + post: + consumes: + - application/json + parameters: + - description: Apply log payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/service.ApplyLogPayload' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - AgentTokenAuth: [] + summary: Report agent apply result + tags: + - Agent + /api/agent/config-versions/active: + get: + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + security: + - AgentTokenAuth: [] + summary: Get active config for agent + tags: + - Agent + /api/agent/nodes/heartbeat: + post: + consumes: + - application/json + parameters: + - description: Agent heartbeat payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/service.AgentNodePayload' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - AgentTokenAuth: [] + summary: Report agent heartbeat + tags: + - Agent + /api/agent/nodes/register: + post: + consumes: + - application/json + parameters: + - description: Agent node payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/service.AgentNodePayload' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - AgentTokenAuth: [] + summary: Register or discover agent node + tags: + - Agent + /api/apply-logs/: + get: + parameters: + - description: Node ID + in: query + name: node_id + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: List apply logs + tags: + - ApplyLogs + /api/config-versions/: + get: + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: List config versions + tags: + - ConfigVersions + /api/config-versions/{id}/activate: + put: + parameters: + - description: Version ID + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Activate an existing config version + tags: + - ConfigVersions + /api/config-versions/active: + get: + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Get active config version + tags: + - ConfigVersions + /api/config-versions/diff: + get: + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Diff current draft against active version + tags: + - ConfigVersions + /api/config-versions/preview: + get: + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Preview config rendering + tags: + - ConfigVersions + /api/config-versions/publish: + post: + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Publish a new config version + tags: + - ConfigVersions + /api/managed-domains/: + get: + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: List managed domains + tags: + - ManagedDomains + post: + consumes: + - application/json + parameters: + - description: Managed domain payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/service.ManagedDomainInput' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Create managed domain + tags: + - ManagedDomains + /api/managed-domains/{id}: + delete: + parameters: + - description: Managed domain ID + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Delete managed domain + tags: + - ManagedDomains + put: + consumes: + - application/json + parameters: + - description: Managed domain ID + in: path + name: id + required: true + type: integer + - description: Managed domain payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/service.ManagedDomainInput' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Update managed domain + tags: + - ManagedDomains + /api/managed-domains/match: + get: + parameters: + - description: Domain + in: query + name: domain + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Match certificate for domain + tags: + - ManagedDomains + /api/nodes/: + get: + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: List nodes + tags: + - Nodes + post: + consumes: + - application/json + parameters: + - description: Node payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/service.NodeInput' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Create node + tags: + - Nodes + /api/nodes/{id}: + delete: + parameters: + - description: Node ID + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Delete node + tags: + - Nodes + put: + consumes: + - application/json + parameters: + - description: Node ID + in: path + name: id + required: true + type: integer + - description: Node payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/service.NodeInput' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Update node + tags: + - Nodes + /api/nodes/{id}/agent-update: + post: + parameters: + - description: Node ID + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Request agent self-update on node + tags: + - Nodes + /api/nodes/bootstrap-token: + get: + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Get global discovery token + tags: + - Nodes + /api/nodes/bootstrap-token/rotate: + post: + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Rotate global discovery token + tags: + - Nodes + /api/option/: + get: + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + summary: List editable options + tags: + - Options + put: + consumes: + - application/json + parameters: + - description: Option payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/model.Option' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + summary: Update option + tags: + - Options + /api/proxy-routes/: + get: + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: List proxy routes + tags: + - ProxyRoutes + post: + consumes: + - application/json + parameters: + - description: Proxy route payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/service.ProxyRouteInput' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Create proxy route + tags: + - ProxyRoutes + /api/proxy-routes/{id}: + delete: + parameters: + - description: Route ID + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Delete proxy route + tags: + - ProxyRoutes + put: + consumes: + - application/json + parameters: + - description: Route ID + in: path + name: id + required: true + type: integer + - description: Proxy route payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/service.ProxyRouteInput' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Update proxy route + tags: + - ProxyRoutes + /api/status: + get: + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + summary: Get server status + tags: + - Public + /api/tls-certificates/: + get: + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: List TLS certificates + tags: + - TLSCertificates + post: + consumes: + - application/json + parameters: + - description: TLS certificate payload + in: body + name: payload + required: true + schema: + $ref: '#/definitions/service.TLSCertificateInput' + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Create TLS certificate from PEM + tags: + - TLSCertificates + /api/tls-certificates/{id}: + delete: + parameters: + - description: Certificate ID + in: path + name: id + required: true + type: integer + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Delete TLS certificate + tags: + - TLSCertificates + /api/tls-certificates/import-file: + post: + consumes: + - multipart/form-data + parameters: + - description: Certificate name + in: formData + name: name + required: true + type: string + - description: Remark + in: formData + name: remark + type: string + - description: Certificate file + in: formData + name: cert_file + required: true + type: file + - description: Private key file + in: formData + name: key_file + required: true + type: file + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + "400": + description: Bad Request + schema: + additionalProperties: true + type: object + security: + - BearerAuth: [] + summary: Import TLS certificate from files + tags: + - TLSCertificates + /api/update/latest-release: + get: + produces: + - application/json + responses: + "200": + description: OK + schema: + additionalProperties: true + type: object + summary: Get latest GitHub release + tags: + - Update +schemes: +- http +- https +securityDefinitions: + AgentTokenAuth: + description: Agent API 使用节点专属 Agent Token 或全局 Discovery Token + in: header + name: X-Agent-Token + type: apiKey + BearerAuth: + description: 管理端可使用 Bearer Token,例如:Bearer + in: header + name: Authorization + type: apiKey +swagger: "2.0" diff --git a/atsf_server/go.mod b/atsf_server/go.mod index a3a40087..aa6a5abf 100644 --- a/atsf_server/go.mod +++ b/atsf_server/go.mod @@ -12,12 +12,18 @@ require ( github.com/go-playground/validator/v10 v10.14.0 github.com/go-redis/redis/v8 v8.11.5 github.com/google/uuid v1.3.0 - golang.org/x/crypto v0.9.0 + github.com/swaggo/files v1.0.1 + github.com/swaggo/gin-swagger v1.6.1 + github.com/swaggo/swag v1.8.12 + golang.org/x/crypto v0.36.0 gorm.io/driver/mysql v1.4.3 gorm.io/gorm v1.25.7 ) require ( + github.com/KyleBanks/depth v1.2.1 // indirect + github.com/PuerkitoBio/purell v1.1.1 // indirect + github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff // indirect github.com/bytedance/sonic v1.9.1 // indirect github.com/cespare/xxhash/v2 v2.1.2 // indirect @@ -27,6 +33,10 @@ require ( github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/glebarez/go-sqlite v1.21.2 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.19.6 // indirect + github.com/go-openapi/spec v0.20.4 // indirect + github.com/go-openapi/swag v0.19.15 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-sql-driver/mysql v1.6.0 // indirect @@ -37,9 +47,11 @@ require ( github.com/gorilla/sessions v1.2.1 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect + github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect github.com/leodido/go-urn v1.2.4 // indirect + github.com/mailru/easyjson v0.7.6 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -48,10 +60,12 @@ require ( github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/net v0.10.0 // indirect - golang.org/x/sys v0.8.0 // indirect - golang.org/x/text v0.9.0 // indirect - google.golang.org/protobuf v1.30.0 // indirect + golang.org/x/net v0.38.0 // indirect + golang.org/x/sys v0.31.0 // indirect + golang.org/x/text v0.23.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect + google.golang.org/protobuf v1.33.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect modernc.org/libc v1.22.5 // indirect modernc.org/mathutil v1.5.0 // indirect diff --git a/atsf_server/go.sum b/atsf_server/go.sum index c9c17f3c..ad295b64 100644 --- a/atsf_server/go.sum +++ b/atsf_server/go.sum @@ -1,3 +1,9 @@ +github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc= +github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE= +github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= +github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= +github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff h1:RmdPFa+slIr4SCBg4st/l/vZWVe9QJKMXGO60Bxbe04= github.com/boj/redistore v0.0.0-20180917114910-cd5dcc76aeff/go.mod h1:+RTT1BOk5P97fT2CiHkbFQwkK3mjsFAP6zCYV2aXtjw= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= @@ -17,10 +23,13 @@ github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cu github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gin-contrib/cors v1.4.0 h1:oJ6gwtUl3lqV0WEIwM/LxPF1QZ5qe2lGWdY2+bz7y0g= github.com/gin-contrib/cors v1.4.0/go.mod h1:bs9pNM0x/UsmHPBWT2xZz9ROh8xYjYkiURUfmBoMlcs= +github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4= +github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk= github.com/gin-contrib/sessions v0.0.5 h1:CATtfHmLMQrMNpJRgzjWXD7worTh7g7ritsQfmF+0jE= github.com/gin-contrib/sessions v0.0.5/go.mod h1:vYAuaUPqie3WUSsft6HUlCjlwwoJQs97miaG2+7neKY= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= @@ -35,8 +44,19 @@ github.com/glebarez/go-sqlite v1.21.2 h1:3a6LFC4sKahUunAmynQKLZceZCOzUthkRkEAl9g github.com/glebarez/go-sqlite v1.21.2/go.mod h1:sfxdZyhQjTM2Wry3gVYWaW072Ri1WMdWJi0k6+3382k= github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw= github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs= +github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns= +github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M= +github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= @@ -60,10 +80,12 @@ github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaW github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= +github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8= @@ -78,6 +100,8 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= @@ -96,6 +120,10 @@ github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgx github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= @@ -106,9 +134,13 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= +github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= +github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= +github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= @@ -134,6 +166,12 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE= +github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg= +github.com/swaggo/gin-swagger v1.6.1 h1:Ri06G4gc9N4t4k8hekMigJ9zKTFSlqj/9paAQCQs7cY= +github.com/swaggo/gin-swagger v1.6.1/go.mod h1:LQ+hJStHakCWRiK/YNYtJOu4mR2FP+pxLnILT/qNiTw= +github.com/swaggo/swag v1.8.12 h1:pctzkNPu0AlQP2royqX3apjKCQonAnf7KGoxeO4y64w= +github.com/swaggo/swag v1.8.12/go.mod h1:lNfm6Gg+oAq3zRJQNEMBE66LIJKM44mxFqhEEgy2its= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= @@ -142,48 +180,79 @@ github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLY github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= +golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= +golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= +golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= +golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= +golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/atsf_server/main.go b/atsf_server/main.go index 01bb1353..b1621eb4 100644 --- a/atsf_server/main.go +++ b/atsf_server/main.go @@ -2,6 +2,7 @@ package main import ( "atsflare/common" + _ "atsflare/docs" "atsflare/middleware" "atsflare/model" "atsflare/router" @@ -22,6 +23,19 @@ var buildFS embed.FS //go:embed web/build/index.html var indexPage []byte +// @title ATSFlare Server API +// @version 3.0 +// @description ATSFlare Server 管理端与 Agent API 文档。 +// @BasePath / +// @schemes http https +// @securityDefinitions.apikey BearerAuth +// @in header +// @name Authorization +// @description 管理端可使用 Bearer Token,例如:Bearer +// @securityDefinitions.apikey AgentTokenAuth +// @in header +// @name X-Agent-Token +// @description Agent API 使用节点专属 Agent Token 或全局 Discovery Token func main() { common.SetupGinLog() common.SysLog("ATSFlare " + common.Version + " started") diff --git a/atsf_server/router/main.go b/atsf_server/router/main.go index 30b25c82..c34df932 100644 --- a/atsf_server/router/main.go +++ b/atsf_server/router/main.go @@ -1,11 +1,24 @@ package router import ( + "atsflare/middleware" "embed" + "github.com/gin-gonic/gin" + swaggerFiles "github.com/swaggo/files" + ginSwagger "github.com/swaggo/gin-swagger" ) func SetRouter(router *gin.Engine, buildFS embed.FS, indexPage []byte) { SetApiRouter(router) + swaggerRoute := router.Group("/swagger") + swaggerRoute.Use(middleware.AdminAuth()) + swaggerRoute.GET("/*any", ginSwagger.WrapHandler( + swaggerFiles.Handler, + ginSwagger.URL("/swagger/doc.json"), + ginSwagger.DocExpansion("list"), + ginSwagger.PersistAuthorization(true), + ginSwagger.DefaultModelsExpandDepth(1), + )) setWebRouter(router, buildFS, indexPage) } diff --git a/atsf_server/web/src/components/OperationSetting.js b/atsf_server/web/src/components/OperationSetting.js index f6c0ef43..1fa061c4 100644 --- a/atsf_server/web/src/components/OperationSetting.js +++ b/atsf_server/web/src/components/OperationSetting.js @@ -132,11 +132,23 @@ const OperationSetting = () => { const curlCommand = inputs.AgentDiscoveryToken ? `curl -fsSL https://raw.githubusercontent.com/Rain-kl/ATSFlare/main/scripts/install-agent.sh | bash -s -- --server-url ${serverAddr} --discovery-token ${inputs.AgentDiscoveryToken}` : ''; + const openSwaggerDoc = () => { + window.open('/swagger/index.html', '_blank', 'noopener,noreferrer'); + }; return (
+
接口文档
+ +

通过 Swagger UI 查看当前 Server API,并直接在浏览器中调试接口。

+
+ + +
Agent 运行参数

这些参数通过心跳响应下发到所有 Agent,修改后下次心跳即生效。

diff --git a/docs/development-guidelines.md b/docs/development-guidelines.md index f7e379a2..9c00e960 100644 --- a/docs/development-guidelines.md +++ b/docs/development-guidelines.md @@ -296,7 +296,13 @@ V3 新增行为: 更新顺序: -1. `docs/design.md` -2. `docs/development-guidelines.md` -3. `docs/development-plan.md` -4. `docs/deployment.md` +1. `docs/design.md` +2. `docs/development-guidelines.md` +3. `docs/development-plan.md` +4. `docs/deployment.md` + +## 12. Swagger 鏂囨。绾︽潫 + +* Server 鎻愪緵 Swagger UI 鍏ュ彛锛?`/swagger/index.html` +* Swagger UI 浠呭宸茬櫥褰曠殑绠$悊绔敤鎴峰紑鏀撅紝涓嶅悜鍖垮悕鐢ㄦ埛鍏紑 +* 鏂板鎴栦慨鏀?API 鏃讹紝闇€鍚屾鏇存柊 Swag 娉ㄨВ骞堕噸鏂扮敓鎴?`atsf_server/docs`