diff --git a/pkg/api/api.go b/pkg/api/api.go index e6aa793..4d0de43 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -58,6 +58,10 @@ func Init(cfg *config.APIConfig) { config.PUT("/chains/:chain", updateChain) config.DELETE("/chains/:chain", deleteChain) + config.POST("/authers", createAuther) + config.PUT("/authers/:auther", updateAuther) + config.DELETE("/authers/:auther", deleteAuther) + config.POST("/bypasses", createBypass) config.PUT("/bypasses/:bypass", updateBypass) config.DELETE("/bypasses/:bypass", deleteBypass) diff --git a/pkg/api/config_auther.go b/pkg/api/config_auther.go new file mode 100644 index 0000000..eea668b --- /dev/null +++ b/pkg/api/config_auther.go @@ -0,0 +1,156 @@ +package api + +import ( + "net/http" + + "github.com/gin-gonic/gin" + "github.com/go-gost/gost/pkg/config" + "github.com/go-gost/gost/pkg/config/parsing" + "github.com/go-gost/gost/pkg/registry" +) + +// swagger:parameters createAutherRequest +type createAutherRequest struct { + // in: body + Data config.AutherConfig `json:"data"` +} + +// successful operation. +// swagger:response createAutherResponse +type createAutherResponse struct { + Data Response +} + +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. + // + // Responses: + // 200: createAutherResponse + + var req createAutherRequest + ctx.ShouldBindJSON(&req.Data) + + if req.Data.Name == "" { + writeError(ctx, ErrInvalid) + return + } + + v := parsing.ParseAuther(&req.Data) + if err := registry.Auther().Register(req.Data.Name, v); err != nil { + writeError(ctx, ErrDup) + return + } + + cfg := config.Global() + cfg.Authers = append(cfg.Authers, &req.Data) + config.SetGlobal(cfg) + + ctx.JSON(http.StatusOK, Response{ + Msg: "OK", + }) +} + +// swagger:parameters updateAutherRequest +type updateAutherRequest struct { + // in: path + // required: true + Auther string `uri:"auther" json:"auther"` + // in: body + Data config.AutherConfig `json:"data"` +} + +// successful operation. +// swagger:response updateAutherResponse +type updateAutherResponse struct { + Data Response +} + +func updateAuther(ctx *gin.Context) { + // swagger:route PUT /config/authers/{auther} ConfigManagement updateAutherRequest + // + // update auther by name, the auther must already exist. + // + // Responses: + // 200: updateAutherResponse + + var req updateAutherRequest + ctx.ShouldBindUri(&req) + ctx.ShouldBindJSON(&req.Data) + + if !registry.Auther().IsRegistered(req.Auther) { + writeError(ctx, ErrNotFound) + return + } + + req.Data.Name = req.Auther + + v := parsing.ParseAuther(&req.Data) + registry.Auther().Unregister(req.Auther) + + if err := registry.Auther().Register(req.Auther, v); err != nil { + writeError(ctx, ErrDup) + return + } + + cfg := config.Global() + for i := range cfg.Authers { + if cfg.Authers[i].Name == req.Auther { + cfg.Authers[i] = &req.Data + break + } + } + config.SetGlobal(cfg) + + ctx.JSON(http.StatusOK, Response{ + Msg: "OK", + }) +} + +// swagger:parameters deleteAutherRequest +type deleteAutherRequest struct { + // in: path + // required: true + Auther string `uri:"auther" json:"auther"` +} + +// successful operation. +// swagger:response deleteAutherResponse +type deleteAutherResponse struct { + Data Response +} + +func deleteAuther(ctx *gin.Context) { + // swagger:route DELETE /config/authers/{auther} ConfigManagement deleteAutherRequest + // + // delete auther by name. + // + // Responses: + // 200: deleteAutherResponse + + var req deleteAutherRequest + ctx.ShouldBindUri(&req) + + svc := registry.Auther().Get(req.Auther) + if svc == nil { + writeError(ctx, ErrNotFound) + return + } + registry.Auther().Unregister(req.Auther) + + cfg := config.Global() + authers := cfg.Authers + cfg.Authers = nil + for _, s := range authers { + if s.Name == req.Auther { + continue + } + cfg.Authers = append(cfg.Authers, s) + } + config.SetGlobal(cfg) + + ctx.JSON(http.StatusOK, Response{ + Msg: "OK", + }) +} diff --git a/pkg/api/doc.go b/pkg/api/doc.go index fe45a6d..9265f32 100644 --- a/pkg/api/doc.go +++ b/pkg/api/doc.go @@ -1,6 +1,6 @@ // Documentation of Web API. // -// Schemes: http +// Schemes: https, http // BasePath: / // Version: 1.0.0 // diff --git a/pkg/api/swagger.yaml b/pkg/api/swagger.yaml index 1a235fb..19c8cc5 100644 --- a/pkg/api/swagger.yaml +++ b/pkg/api/swagger.yaml @@ -25,6 +25,22 @@ definitions: x-go-name: Username type: object x-go-package: github.com/go-gost/gost/pkg/config + AutherConfig: + properties: + auths: + items: + $ref: '#/definitions/AuthConfig' + type: array + x-go-name: Auths + name: + type: string + x-go-name: Name + type: + description: inline, file, redis, etc. + type: string + x-go-name: Type + type: object + x-go-package: github.com/go-gost/gost/pkg/config BypassConfig: properties: matchers: @@ -38,6 +54,10 @@ definitions: reverse: type: boolean x-go-name: Reverse + type: + description: inline, file, etc. + type: string + x-go-name: Type type: object x-go-package: github.com/go-gost/gost/pkg/config ChainConfig: @@ -58,6 +78,11 @@ definitions: properties: api: $ref: '#/definitions/APIConfig' + authers: + items: + $ref: '#/definitions/AutherConfig' + type: array + x-go-name: Authers bypasses: items: $ref: '#/definitions/BypassConfig' @@ -144,11 +169,11 @@ definitions: x-go-package: github.com/go-gost/gost/pkg/config HandlerConfig: properties: - auths: - items: - $ref: '#/definitions/AuthConfig' - type: array - x-go-name: Auths + auth: + $ref: '#/definitions/AuthConfig' + auther: + type: string + x-go-name: Auther chain: type: string x-go-name: Chain @@ -216,15 +241,19 @@ definitions: name: type: string x-go-name: Name + type: + description: inline, file, etc. + type: string + x-go-name: Type type: object x-go-package: github.com/go-gost/gost/pkg/config ListenerConfig: properties: - auths: - items: - $ref: '#/definitions/AuthConfig' - type: array - x-go-name: Auths + auth: + $ref: '#/definitions/AuthConfig' + auther: + type: string + x-go-name: Auther chain: type: string x-go-name: Chain @@ -319,6 +348,10 @@ definitions: $ref: '#/definitions/NameserverConfig' type: array x-go-name: Nameservers + type: + description: inline, file, etc. + type: string + x-go-name: Type type: object x-go-package: github.com/go-gost/gost/pkg/config Response: @@ -408,6 +441,56 @@ paths: summary: Get current config. tags: - ConfigManagement + /config/authers: + post: + operationId: createAutherRequest + parameters: + - in: body + name: data + schema: + $ref: '#/definitions/AutherConfig' + x-go-name: Data + responses: + "200": + $ref: '#/responses/createAutherResponse' + summary: create a new auther, the name of the auther must be unique in auther + list. + tags: + - ConfigManagement + /config/authers/{auther}: + delete: + operationId: deleteAutherRequest + parameters: + - in: path + name: auther + required: true + type: string + x-go-name: Auther + responses: + "200": + $ref: '#/responses/deleteAutherResponse' + summary: delete auther by name. + tags: + - ConfigManagement + put: + operationId: updateAutherRequest + parameters: + - in: path + name: auther + required: true + type: string + x-go-name: Auther + - in: body + name: data + schema: + $ref: '#/definitions/AutherConfig' + x-go-name: Data + responses: + "200": + $ref: '#/responses/updateAutherResponse' + summary: update auther by name, the auther must already exist. + tags: + - ConfigManagement /config/bypasses: post: operationId: createBypassRequest @@ -658,6 +741,12 @@ paths: produces: - application/json responses: + createAutherResponse: + description: successful operation. + headers: + Data: {} + schema: + $ref: '#/definitions/Response' createBypassResponse: description: successful operation. headers: @@ -688,6 +777,12 @@ responses: Data: {} schema: $ref: '#/definitions/Response' + deleteAutherResponse: + description: successful operation. + headers: + Data: {} + schema: + $ref: '#/definitions/Response' deleteBypassResponse: description: successful operation. headers: @@ -724,6 +819,12 @@ responses: Config: {} schema: $ref: '#/definitions/Config' + updateAutherResponse: + description: successful operation. + headers: + Data: {} + schema: + $ref: '#/definitions/Response' updateBypassResponse: description: successful operation. headers: @@ -755,6 +856,7 @@ responses: schema: $ref: '#/definitions/Response' schemes: +- https - http securityDefinitions: api_key: null diff --git a/pkg/registry/auther.go b/pkg/registry/auther.go index 2281d72..d5d02e9 100644 --- a/pkg/registry/auther.go +++ b/pkg/registry/auther.go @@ -18,8 +18,11 @@ type autherRegistry struct { m sync.Map } -func (r *autherRegistry) Register(name string, auth auth.Authenticator) error { - if _, loaded := r.m.LoadOrStore(name, auth); loaded { +func (r *autherRegistry) Register(name string, auther auth.Authenticator) error { + if name == "" || auther == nil { + return nil + } + if _, loaded := r.m.LoadOrStore(name, auther); loaded { return ErrDup } diff --git a/pkg/registry/bypass.go b/pkg/registry/bypass.go index a77da73..8f37797 100644 --- a/pkg/registry/bypass.go +++ b/pkg/registry/bypass.go @@ -19,6 +19,9 @@ type bypassRegistry struct { } func (r *bypassRegistry) Register(name string, bypass bypass.Bypass) error { + if name == "" || bypass == nil { + return nil + } if _, loaded := r.m.LoadOrStore(name, bypass); loaded { return ErrDup } diff --git a/pkg/registry/chain.go b/pkg/registry/chain.go index 99b74ce..75d5683 100644 --- a/pkg/registry/chain.go +++ b/pkg/registry/chain.go @@ -19,6 +19,9 @@ type chainRegistry struct { } func (r *chainRegistry) Register(name string, chain chain.Chainer) error { + if name == "" || chain == nil { + return nil + } if _, loaded := r.m.LoadOrStore(name, chain); loaded { return ErrDup } diff --git a/pkg/registry/hosts.go b/pkg/registry/hosts.go index 6692609..f1817e7 100644 --- a/pkg/registry/hosts.go +++ b/pkg/registry/hosts.go @@ -20,6 +20,9 @@ type hostsRegistry struct { } func (r *hostsRegistry) Register(name string, hosts hosts.HostMapper) error { + if name == "" || hosts == nil { + return nil + } if _, loaded := r.m.LoadOrStore(name, hosts); loaded { return ErrDup } diff --git a/pkg/registry/resolver.go b/pkg/registry/resolver.go index 6035590..26c16f0 100644 --- a/pkg/registry/resolver.go +++ b/pkg/registry/resolver.go @@ -21,6 +21,9 @@ type resolverRegistry struct { } func (r *resolverRegistry) Register(name string, resolver resolver.Resolver) error { + if name == "" || resolver == nil { + return nil + } if _, loaded := r.m.LoadOrStore(name, resolver); loaded { return ErrDup } diff --git a/pkg/registry/service.go b/pkg/registry/service.go index 5b4da05..c4ee266 100644 --- a/pkg/registry/service.go +++ b/pkg/registry/service.go @@ -19,6 +19,9 @@ type serviceRegistry struct { } func (r *serviceRegistry) Register(name string, svc *service.Service) error { + if name == "" || svc == nil { + return nil + } if _, loaded := r.m.LoadOrStore(name, svc); loaded { return ErrDup }