add basic auth for config webapi
This commit is contained in:
parent
edca3e0a55
commit
5daefb8e3c
@ -2,7 +2,9 @@ package api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-gost/gost/pkg/config"
|
||||
@ -26,6 +28,9 @@ func getConfig(ctx *gin.Context) {
|
||||
//
|
||||
// Get current config.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: getConfigResponse
|
||||
|
||||
@ -51,3 +56,63 @@ func getConfig(ctx *gin.Context) {
|
||||
|
||||
ctx.Data(http.StatusOK, contentType, buf.Bytes())
|
||||
}
|
||||
|
||||
// swagger:parameters saveConfigRequest
|
||||
type saveConfigRequest struct {
|
||||
// output format, one of yaml|json, default is yaml.
|
||||
// in: query
|
||||
Format string `form:"format" json:"format"`
|
||||
}
|
||||
|
||||
// successful operation.
|
||||
// swagger:response saveConfigResponse
|
||||
type saveConfigResponse struct {
|
||||
Data Response
|
||||
}
|
||||
|
||||
func saveConfig(ctx *gin.Context) {
|
||||
// swagger:route POST /config ConfigManagement saveConfigRequest
|
||||
//
|
||||
// Save current config to file (gost.yaml or gost.json).
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: saveConfigResponse
|
||||
|
||||
var req saveConfigRequest
|
||||
ctx.ShouldBindQuery(&req)
|
||||
|
||||
file := "gost.yaml"
|
||||
switch req.Format {
|
||||
case "json":
|
||||
file = "gost.json"
|
||||
default:
|
||||
req.Format = "yaml"
|
||||
}
|
||||
|
||||
f, err := os.Create(file)
|
||||
if err != nil {
|
||||
writeError(ctx, &Error{
|
||||
statusCode: http.StatusInternalServerError,
|
||||
Code: 40005,
|
||||
Msg: fmt.Sprintf("create file: %s", err.Error()),
|
||||
})
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if err := config.Global().Write(f, req.Format); err != nil {
|
||||
writeError(ctx, &Error{
|
||||
statusCode: http.StatusInternalServerError,
|
||||
Code: 40006,
|
||||
Msg: fmt.Sprintf("write: %s", err.Error()),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
ctx.JSON(http.StatusOK, Response{
|
||||
Msg: "OK",
|
||||
})
|
||||
}
|
||||
|
@ -24,7 +24,10 @@ type createAutherResponse struct {
|
||||
func createAuther(ctx *gin.Context) {
|
||||
// swagger:route POST /config/authers ConfigManagement createAutherRequest
|
||||
//
|
||||
// create a new auther, the name of the auther must be unique in auther list.
|
||||
// Create a new auther, the name of the auther must be unique in auther list.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: createAutherResponse
|
||||
@ -70,7 +73,10 @@ type updateAutherResponse struct {
|
||||
func updateAuther(ctx *gin.Context) {
|
||||
// swagger:route PUT /config/authers/{auther} ConfigManagement updateAutherRequest
|
||||
//
|
||||
// update auther by name, the auther must already exist.
|
||||
// Update auther by name, the auther must already exist.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: updateAutherResponse
|
||||
@ -124,7 +130,10 @@ type deleteAutherResponse struct {
|
||||
func deleteAuther(ctx *gin.Context) {
|
||||
// swagger:route DELETE /config/authers/{auther} ConfigManagement deleteAutherRequest
|
||||
//
|
||||
// delete auther by name.
|
||||
// Delete auther by name.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: deleteAutherResponse
|
||||
|
@ -24,7 +24,10 @@ type createBypassResponse struct {
|
||||
func createBypass(ctx *gin.Context) {
|
||||
// swagger:route POST /config/bypasses ConfigManagement createBypassRequest
|
||||
//
|
||||
// create a new bypass, the name of bypass must be unique in bypass list.
|
||||
// Create a new bypass, the name of bypass must be unique in bypass list.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: createBypassResponse
|
||||
@ -71,7 +74,10 @@ type updateBypassResponse struct {
|
||||
func updateBypass(ctx *gin.Context) {
|
||||
// swagger:route PUT /config/bypasses/{bypass} ConfigManagement updateBypassRequest
|
||||
//
|
||||
// update bypass by name, the bypass must already exist.
|
||||
// Update bypass by name, the bypass must already exist.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: updateBypassResponse
|
||||
@ -126,7 +132,10 @@ type deleteBypassResponse struct {
|
||||
func deleteBypass(ctx *gin.Context) {
|
||||
// swagger:route DELETE /config/bypasses/{bypass} ConfigManagement deleteBypassRequest
|
||||
//
|
||||
// delete bypass by name.
|
||||
// Delete bypass by name.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: deleteBypassResponse
|
||||
|
@ -24,7 +24,10 @@ type createChainResponse struct {
|
||||
func createChain(ctx *gin.Context) {
|
||||
// swagger:route POST /config/chains ConfigManagement createChainRequest
|
||||
//
|
||||
// create a new chain, the name of chain must be unique in chain list.
|
||||
// Create a new chain, the name of chain must be unique in chain list.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: createChainResponse
|
||||
@ -76,7 +79,10 @@ type updateChainResponse struct {
|
||||
func updateChain(ctx *gin.Context) {
|
||||
// swagger:route PUT /config/chains/{chain} ConfigManagement updateChainRequest
|
||||
//
|
||||
// update chain by name, the chain must already exist.
|
||||
// Update chain by name, the chain must already exist.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: updateChainResponse
|
||||
@ -135,7 +141,10 @@ type deleteChainResponse struct {
|
||||
func deleteChain(ctx *gin.Context) {
|
||||
// swagger:route DELETE /config/chains/{chain} ConfigManagement deleteChainRequest
|
||||
//
|
||||
// delete chain by name.
|
||||
// Delete chain by name.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: deleteChainResponse
|
||||
|
@ -24,7 +24,10 @@ type createHostsesponse struct {
|
||||
func createHosts(ctx *gin.Context) {
|
||||
// swagger:route POST /config/hosts ConfigManagement createHostsRequest
|
||||
//
|
||||
// create a new hosts, the name of the hosts must be unique in hosts list.
|
||||
// Create a new hosts, the name of the hosts must be unique in hosts list.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: createHostsResponse
|
||||
@ -71,7 +74,10 @@ type updateHostsResponse struct {
|
||||
func updateHosts(ctx *gin.Context) {
|
||||
// swagger:route PUT /config/hosts/{hosts} ConfigManagement updateHostsRequest
|
||||
//
|
||||
// update hosts by name, the hosts must already exist.
|
||||
// Update hosts by name, the hosts must already exist.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: updateHostsResponse
|
||||
@ -126,7 +132,10 @@ type deleteHostsResponse struct {
|
||||
func deleteHosts(ctx *gin.Context) {
|
||||
// swagger:route DELETE /config/hosts/{hosts} ConfigManagement deleteHostsRequest
|
||||
//
|
||||
// delete hosts by name.
|
||||
// Delete hosts by name.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: deleteHostsResponse
|
||||
|
@ -24,7 +24,10 @@ type createResolverResponse struct {
|
||||
func createResolver(ctx *gin.Context) {
|
||||
// swagger:route POST /config/resolvers ConfigManagement createResolverRequest
|
||||
//
|
||||
// create a new resolver, the name of the resolver must be unique in resolver list.
|
||||
// Create a new resolver, the name of the resolver must be unique in resolver list.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: createResolverResponse
|
||||
@ -75,7 +78,10 @@ type updateResolverResponse struct {
|
||||
func updateResolver(ctx *gin.Context) {
|
||||
// swagger:route PUT /config/resolvers/{resolver} ConfigManagement updateResolverRequest
|
||||
//
|
||||
// update resolver by name, the resolver must already exist.
|
||||
// Update resolver by name, the resolver must already exist.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: updateResolverResponse
|
||||
@ -134,7 +140,10 @@ type deleteResolverResponse struct {
|
||||
func deleteResolver(ctx *gin.Context) {
|
||||
// swagger:route DELETE /config/resolvers/{resolver} ConfigManagement deleteResolverRequest
|
||||
//
|
||||
// delete resolver by name.
|
||||
// Delete resolver by name.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: deleteResolverResponse
|
||||
|
@ -24,7 +24,10 @@ type createServiceResponse struct {
|
||||
func createService(ctx *gin.Context) {
|
||||
// swagger:route POST /config/services ConfigManagement createServiceRequest
|
||||
//
|
||||
// create a new service, the name of the service must be unique in service list.
|
||||
// Create a new service, the name of the service must be unique in service list.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: createServiceResponse
|
||||
@ -83,7 +86,10 @@ type updateServiceResponse struct {
|
||||
func updateService(ctx *gin.Context) {
|
||||
// swagger:route PUT /config/services/{service} ConfigManagement updateServiceRequest
|
||||
//
|
||||
// update service by name, the service must already exist.
|
||||
// Update service by name, the service must already exist.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: updateServiceResponse
|
||||
@ -147,7 +153,10 @@ type deleteServiceResponse struct {
|
||||
func deleteService(ctx *gin.Context) {
|
||||
// swagger:route DELETE /config/services/{service} ConfigManagement deleteServiceRequest
|
||||
//
|
||||
// delete service by name.
|
||||
// Delete service by name.
|
||||
//
|
||||
// Security:
|
||||
// basicAuth: []
|
||||
//
|
||||
// Responses:
|
||||
// 200: deleteServiceResponse
|
||||
|
@ -11,7 +11,8 @@
|
||||
// - application/json
|
||||
//
|
||||
// SecurityDefinitions:
|
||||
// api_key:
|
||||
// basicAuth:
|
||||
// type: basic
|
||||
//
|
||||
// swagger:meta
|
||||
package api
|
||||
|
@ -12,6 +12,7 @@ var (
|
||||
ErrDup = &Error{statusCode: http.StatusBadRequest, Code: 40002, Msg: "instance duplicated"}
|
||||
ErrCreate = &Error{statusCode: http.StatusConflict, Code: 40003, Msg: "instance creation failed"}
|
||||
ErrNotFound = &Error{statusCode: http.StatusBadRequest, Code: 40004, Msg: "instance not found"}
|
||||
ErrSave = &Error{statusCode: http.StatusInternalServerError, Code: 40005, Msg: "save config failed"}
|
||||
)
|
||||
|
||||
// Error is an api error.
|
||||
|
@ -99,6 +99,7 @@ func (s *Server) Close() error {
|
||||
|
||||
func registerConfig(config *gin.RouterGroup) {
|
||||
config.GET("", getConfig)
|
||||
config.POST("", saveConfig)
|
||||
|
||||
config.POST("/services", createService)
|
||||
config.PUT("/services/:service", updateService)
|
||||
|
@ -10,6 +10,11 @@ definitions:
|
||||
addr:
|
||||
type: string
|
||||
x-go-name: Addr
|
||||
auth:
|
||||
$ref: '#/definitions/AuthConfig'
|
||||
auther:
|
||||
type: string
|
||||
x-go-name: Auther
|
||||
pathPrefix:
|
||||
type: string
|
||||
x-go-name: PathPrefix
|
||||
@ -100,6 +105,8 @@ definitions:
|
||||
x-go-name: Hosts
|
||||
log:
|
||||
$ref: '#/definitions/LogConfig'
|
||||
metrics:
|
||||
$ref: '#/definitions/MetricsConfig'
|
||||
profiling:
|
||||
$ref: '#/definitions/ProfilingConfig'
|
||||
resolvers:
|
||||
@ -282,6 +289,19 @@ definitions:
|
||||
x-go-name: Output
|
||||
type: object
|
||||
x-go-package: github.com/go-gost/gost/pkg/config
|
||||
MetricsConfig:
|
||||
properties:
|
||||
addr:
|
||||
type: string
|
||||
x-go-name: Addr
|
||||
enable:
|
||||
type: boolean
|
||||
x-go-name: Enable
|
||||
path:
|
||||
type: string
|
||||
x-go-name: Path
|
||||
type: object
|
||||
x-go-package: github.com/go-gost/gost/pkg/config
|
||||
NameserverConfig:
|
||||
properties:
|
||||
addr:
|
||||
@ -333,9 +353,9 @@ definitions:
|
||||
addr:
|
||||
type: string
|
||||
x-go-name: Addr
|
||||
enabled:
|
||||
enable:
|
||||
type: boolean
|
||||
x-go-name: Enabled
|
||||
x-go-name: Enable
|
||||
type: object
|
||||
x-go-package: github.com/go-gost/gost/pkg/config
|
||||
ResolverConfig:
|
||||
@ -438,9 +458,29 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/getConfigResponse'
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Get current config.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
post:
|
||||
operationId: saveConfigRequest
|
||||
parameters:
|
||||
- description: output format, one of yaml|json, default is yaml.
|
||||
in: query
|
||||
name: format
|
||||
type: string
|
||||
x-go-name: Format
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/saveConfigResponse'
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Save current config to file (gost.yaml or gost.json).
|
||||
tags:
|
||||
- ConfigManagement
|
||||
/config/authers:
|
||||
post:
|
||||
operationId: createAutherRequest
|
||||
@ -453,7 +493,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/createAutherResponse'
|
||||
summary: create a new auther, the name of the auther must be unique in auther
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Create a new auther, the name of the auther must be unique in auther
|
||||
list.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
@ -469,7 +512,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/deleteAutherResponse'
|
||||
summary: delete auther by name.
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Delete auther by name.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
put:
|
||||
@ -488,7 +534,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/updateAutherResponse'
|
||||
summary: update auther by name, the auther must already exist.
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Update auther by name, the auther must already exist.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
/config/bypasses:
|
||||
@ -503,7 +552,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/createBypassResponse'
|
||||
summary: create a new bypass, the name of bypass must be unique in bypass list.
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Create a new bypass, the name of bypass must be unique in bypass list.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
/config/bypasses/{bypass}:
|
||||
@ -518,7 +570,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/deleteBypassResponse'
|
||||
summary: delete bypass by name.
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Delete bypass by name.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
put:
|
||||
@ -537,7 +592,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/updateBypassResponse'
|
||||
summary: update bypass by name, the bypass must already exist.
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Update bypass by name, the bypass must already exist.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
/config/chains:
|
||||
@ -552,7 +610,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/createChainResponse'
|
||||
summary: create a new chain, the name of chain must be unique in chain list.
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Create a new chain, the name of chain must be unique in chain list.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
/config/chains/{chain}:
|
||||
@ -567,7 +628,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/deleteChainResponse'
|
||||
summary: delete chain by name.
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Delete chain by name.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
put:
|
||||
@ -586,7 +650,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/updateChainResponse'
|
||||
summary: update chain by name, the chain must already exist.
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Update chain by name, the chain must already exist.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
/config/hosts:
|
||||
@ -601,7 +668,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/createHostsResponse'
|
||||
summary: create a new hosts, the name of the hosts must be unique in hosts list.
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Create a new hosts, the name of the hosts must be unique in hosts list.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
/config/hosts/{hosts}:
|
||||
@ -616,7 +686,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/deleteHostsResponse'
|
||||
summary: delete hosts by name.
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Delete hosts by name.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
put:
|
||||
@ -635,7 +708,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/updateHostsResponse'
|
||||
summary: update hosts by name, the hosts must already exist.
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Update hosts by name, the hosts must already exist.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
/config/resolvers:
|
||||
@ -650,7 +726,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/createResolverResponse'
|
||||
summary: create a new resolver, the name of the resolver must be unique in resolver
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Create a new resolver, the name of the resolver must be unique in resolver
|
||||
list.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
@ -666,7 +745,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/deleteResolverResponse'
|
||||
summary: delete resolver by name.
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Delete resolver by name.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
put:
|
||||
@ -685,7 +767,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/updateResolverResponse'
|
||||
summary: update resolver by name, the resolver must already exist.
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Update resolver by name, the resolver must already exist.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
/config/services:
|
||||
@ -700,7 +785,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/createServiceResponse'
|
||||
summary: create a new service, the name of the service must be unique in service
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Create a new service, the name of the service must be unique in service
|
||||
list.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
@ -716,7 +804,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/deleteServiceResponse'
|
||||
summary: delete service by name.
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Delete service by name.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
put:
|
||||
@ -735,7 +826,10 @@ paths:
|
||||
responses:
|
||||
"200":
|
||||
$ref: '#/responses/updateServiceResponse'
|
||||
summary: update service by name, the service must already exist.
|
||||
security:
|
||||
- basicAuth:
|
||||
- '[]'
|
||||
summary: Update service by name, the service must already exist.
|
||||
tags:
|
||||
- ConfigManagement
|
||||
produces:
|
||||
@ -819,6 +913,12 @@ responses:
|
||||
Config: {}
|
||||
schema:
|
||||
$ref: '#/definitions/Config'
|
||||
saveConfigResponse:
|
||||
description: successful operation.
|
||||
headers:
|
||||
Data: {}
|
||||
schema:
|
||||
$ref: '#/definitions/Response'
|
||||
updateAutherResponse:
|
||||
description: successful operation.
|
||||
headers:
|
||||
@ -859,5 +959,6 @@ schemes:
|
||||
- https
|
||||
- http
|
||||
securityDefinitions:
|
||||
api_key: null
|
||||
basicAuth:
|
||||
type: basic
|
||||
swagger: "2.0"
|
||||
|
Loading…
Reference in New Issue
Block a user