From 10fd43ce29b79693e75f31bc8a457eb90e298190 Mon Sep 17 00:00:00 2001 From: lwnmengjing Date: Tue, 7 Nov 2023 20:56:36 +0800 Subject: [PATCH 1/4] :construction: save --- go.mod | 8 ++++ go.sum | 21 +++++++++++ pkg/config/rate_limit.go | 46 +++++++++++++++++++++++ pkg/middlewares/limit.go | 52 ++++++++++++++++++++++++++ pkg/response/actions/virtual/create.go | 48 ++++++++++++++++++++++++ pkg/response/actions/virtual/delete.go | 4 ++ virtual/model/field.go | 36 ++++++++++++++++++ virtual/model/model.go | 16 ++++++++ 8 files changed, 231 insertions(+) create mode 100644 pkg/config/rate_limit.go create mode 100644 pkg/middlewares/limit.go diff --git a/go.mod b/go.mod index bc2a979..94ff4f7 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/casbin/mongodb-adapter/v3 v3.5.0 github.com/coreos/go-oidc/v3 v3.7.0 github.com/gin-contrib/pprof v1.4.0 + github.com/go-openapi/spec v0.20.9 github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 github.com/google/uuid v1.4.0 github.com/grpc-ecosystem/go-grpc-middleware/providers/prometheus v1.0.0 @@ -24,6 +25,7 @@ require ( github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e github.com/smartystreets/goconvey v1.8.1 github.com/spf13/cast v1.5.1 + golang.org/x/time v0.3.0 google.golang.org/grpc v1.59.0 gorm.io/driver/mysql v1.5.2 gorm.io/driver/postgres v1.5.4 @@ -40,11 +42,16 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/go-jose/go-jose/v3 v3.0.0 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-openapi/swag v0.19.15 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/google/go-cmp v0.6.0 // 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.5 // indirect github.com/lib/pq v1.10.9 // indirect + github.com/mailru/easyjson v0.7.6 // indirect github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect github.com/montanaflynn/stats v0.7.1 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect @@ -58,6 +65,7 @@ require ( golang.org/x/arch v0.5.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20231016165738-49dd2c1f3d0b // indirect google.golang.org/protobuf v1.31.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect ) require ( diff --git a/go.sum b/go.sum index 2942897..bec64e0 100644 --- a/go.sum +++ b/go.sum @@ -109,6 +109,16 @@ github.com/glebarez/sqlite v1.10.0 h1:u4gt8y7OND/cCei/NMHmfbLxF6xP2wgKcT/BJf2pYk github.com/glebarez/sqlite v1.10.0/go.mod h1:IJ+lfSOmiekhQsFTJRx/lHtGYmCdtAiTaf5wI9u5uHA= github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= +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.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8= +github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= +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= @@ -191,6 +201,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= +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.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= @@ -220,6 +232,10 @@ 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/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +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.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= @@ -239,6 +255,7 @@ github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJ github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE= github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo= github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4= github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= @@ -404,6 +421,8 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190531172133-b3315ee88b7d/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= @@ -425,6 +444,7 @@ google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 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= @@ -434,6 +454,7 @@ 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/pkg/config/rate_limit.go b/pkg/config/rate_limit.go new file mode 100644 index 0000000..2d4a866 --- /dev/null +++ b/pkg/config/rate_limit.go @@ -0,0 +1,46 @@ +package config + +import ( + "context" + "golang.org/x/time/rate" +) + +/* + * @Author: lwnmengjing + * @Date: 2023/11/4 10:41:05 + * @Last Modified by: lwnmengjing + * @Last Modified time: 2023/11/4 10:41:05 + */ + +type Limiter interface { + Allow() bool + Wait(context.Context) error +} + +type LimiterName string + +const ( + SingleLimiter LimiterName = "single" +) + +type RateLimit struct { + // 限流器类型 + Name LimiterName `json:"name" yaml:"name"` + // 限流器配置 + Rate float64 `json:"rate" yaml:"rate"` + // 限流器最大存储令牌数 + Bursts int `json:"bursts" yaml:"bursts"` +} + +func (e *RateLimit) String() string { + return string(e.Name) +} + +func (e *RateLimit) Init() Limiter { + switch e.Name { + case SingleLimiter: + return rate.NewLimiter(rate.Limit(e.Rate), e.Bursts) + default: + return nil + } +} diff --git a/pkg/middlewares/limit.go b/pkg/middlewares/limit.go new file mode 100644 index 0000000..eb15835 --- /dev/null +++ b/pkg/middlewares/limit.go @@ -0,0 +1,52 @@ +package middlewares + +import ( + "context" + "net/http" + + "github.com/gin-gonic/gin" + "github.com/mss-boot-io/mss-boot/pkg/response" +) + +/* + * @Author: lwnmengjing + * @Date: 2023/11/4 10:26:49 + * @Last Modified by: lwnmengjing + * @Last Modified time: 2023/11/4 10:26:49 + */ + +var DefaultLimiter Limiter + +type Limiter interface { + Allow() bool + Wait(context.Context) error +} + +// LimitMiddleware 限流中间件 +func LimitMiddleware() gin.HandlerFunc { + if DefaultLimiter == nil { + return func(c *gin.Context) { + c.Next() + } + } + return func(c *gin.Context) { + var count int8 + GATE: + count++ + if !DefaultLimiter.Allow() { + if err := DefaultLimiter.Wait(c.Request.Context()); err != nil { + api := response.Make(c) + api.AddError(err).Log.Error("rate limit wait error", "err", err) + api.Err(http.StatusInternalServerError) + return + } + if count > 5 { + api := response.Make(c) + api.Err(http.StatusTooManyRequests) + return + } + goto GATE + } + c.Next() + } +} diff --git a/pkg/response/actions/virtual/create.go b/pkg/response/actions/virtual/create.go index 3c3a69e..e2161d8 100644 --- a/pkg/response/actions/virtual/create.go +++ b/pkg/response/actions/virtual/create.go @@ -4,9 +4,11 @@ import ( "net/http" "github.com/gin-gonic/gin" + "github.com/go-openapi/spec" "github.com/mss-boot-io/mss-boot/pkg/config/gormdb" "github.com/mss-boot-io/mss-boot/pkg/response" + "github.com/mss-boot-io/mss-boot/virtual/model" ) /* @@ -64,3 +66,49 @@ func (e *Create) Handler() gin.HandlerFunc { } } } + +// GenOpenAPI gen open api method: post, Parameters: nil +func (e *Create) GenOpenAPI(m *model.Model) *spec.PathItemProps { + return &spec.PathItemProps{ + Post: &spec.Operation{ + OperationProps: spec.OperationProps{ + Tags: []string{m.Name}, + Summary: "create " + m.Name, + Description: "create " + m.Name, + Consumes: []string{"application/json"}, + Produces: []string{"application/json"}, + Parameters: []spec.Parameter{ + { + ParamProps: spec.ParamProps{ + Name: "data", + Description: m.Name + " create input body", + Required: true, + In: "body", + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Ref: spec.MustCreateRef("#/definitions/" + m.Name), + }, + }, + }, + }, + }, + Security: []map[string][]string{ + { + "Authorization": {}, + }, + }, + Responses: &spec.Responses{ + ResponsesProps: spec.ResponsesProps{ + StatusCodeResponses: map[int]spec.Response{ + http.StatusCreated: { + ResponseProps: spec.ResponseProps{ + Description: "OK", + }, + }, + }, + }, + }, + }, + }, + } +} diff --git a/pkg/response/actions/virtual/delete.go b/pkg/response/actions/virtual/delete.go index 760eac8..d450b12 100644 --- a/pkg/response/actions/virtual/delete.go +++ b/pkg/response/actions/virtual/delete.go @@ -69,3 +69,7 @@ func (e *Delete) Handler() gin.HandlerFunc { } } } + +//func (e *Delete) GenOpenAPI(m *model.Model) *spec.PathItemProps { +// +//} diff --git a/virtual/model/field.go b/virtual/model/field.go index 7b9938e..4d24d4d 100644 --- a/virtual/model/field.go +++ b/virtual/model/field.go @@ -2,6 +2,8 @@ package model import ( "fmt" + "github.com/aws/smithy-go/ptr" + "github.com/go-openapi/spec" "reflect" "strings" "time" @@ -115,3 +117,37 @@ func (f *Field) MakeField() reflect.StructField { } return field } + +func (f *Field) GenOpenAPIFie() *spec.Schema { + s := &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{string(f.DataType)}, + }, + } + if f.DataType == schema.String { + s.MaxLength = ptr.Int64(int64(f.Size)) + } + //todo float64 + //if f.DataType == schema.Float { + // s.Maximum = ptr.Float64(f.Precision) + // s.Minimum = &f.Scale + //} + if f.DataType == schema.Time { + s.Format = "date-time" + } + if f.DefaultValue != "" { + s.Default = f.DefaultValue + } + if f.NotNull { + s.Nullable = false + } + //if f.PrimaryKey != "" { + // s.Extensions = spec.Extensions(map[string]interface{}{ + // "x-order": f.PrimaryKey, + // }) + //} + if f.Comment != "" { + s.Description = f.Comment + } + return s +} diff --git a/virtual/model/model.go b/virtual/model/model.go index e34e0e0..f6c24c1 100644 --- a/virtual/model/model.go +++ b/virtual/model/model.go @@ -2,6 +2,7 @@ package model import ( "fmt" + "github.com/go-openapi/spec" "reflect" "strings" "time" @@ -19,6 +20,8 @@ import ( type Model struct { Table string `json:"tableName" yaml:"tableName" binding:"required"` + Name string `json:"name" yaml:"name" binding:"required"` + Description string `json:"description" yaml:"description"` HardDeleted bool `json:"hardDeleted" yaml:"hardDeleted"` Fields []*Field `json:"fields" yaml:"fields" binding:"required"` } @@ -178,3 +181,16 @@ func (m *Model) Search(ctx *gin.Context) (f func(*gorm.DB) *gorm.DB) { return db } } + +func (m *Model) GenOpenAPIModel() *spec.Schema { + s := spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: make(map[string]spec.Schema), + }, + } + for i := range m.Fields { + s.Properties[m.Fields[i].JsonTag] = *m.Fields[i].GenOpenAPIFie() + } + return &s +} From bab7266a158f017dff41a194b9d7a1dcaed29cfe Mon Sep 17 00:00:00 2001 From: lwnmengjing Date: Tue, 7 Nov 2023 22:54:16 +0800 Subject: [PATCH 2/4] :construction: save --- pkg/config/logger.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/config/logger.go b/pkg/config/logger.go index 918b3ad..9a1dd9d 100644 --- a/pkg/config/logger.go +++ b/pkg/config/logger.go @@ -14,6 +14,7 @@ import ( "os" "time" + "github.com/gin-gonic/gin" "gorm.io/gorm/logger" "github.com/mss-boot-io/mss-boot/core/logger/writer" @@ -73,6 +74,7 @@ func (e *Logger) Init() { Colorful: true, }) + gin.DefaultWriter = output } func (e *Logger) GormLevel() logger.LogLevel { From f9e05f3888cf17aaad21e4104855e81ecd73ba4b Mon Sep 17 00:00:00 2001 From: lwnmengjing Date: Wed, 8 Nov 2023 21:58:04 +0800 Subject: [PATCH 3/4] save --- pkg/response/action.go | 10 -- pkg/response/actions/{authentic => }/base.go | 2 +- .../actions/{authentic => }/control_gorm.go | 2 +- .../actions/{authentic => }/control_mgm.go | 7 +- .../actions/{authentic => }/delete_gorm.go | 2 +- .../actions/{authentic => }/delete_mgm.go | 7 +- .../actions/{authentic => }/get_gorm.go | 2 +- .../actions/{authentic => }/get_mgm.go | 7 +- .../actions/{authentic => }/search_gorm.go | 14 ++- .../actions/{authentic => }/search_mgm.go | 6 +- .../actions/{authentic => }/search_test.go | 2 +- pkg/response/actions/{authentic => }/type.go | 2 +- pkg/response/antd/model.go | 74 +++++++++++- pkg/response/antd/return.go | 70 +++++------ pkg/response/api.go | 6 +- pkg/response/controller/options.go | 10 +- pkg/response/controller/simple.go | 23 ++-- pkg/response/model.go | 58 ++++++++++ pkg/response/return.go | 109 +++++++++--------- pkg/response/type.go | 5 + .../virtual => virtual/action}/base.go | 2 +- .../virtual => virtual/action}/create.go | 2 +- .../virtual => virtual/action}/delete.go | 2 +- .../actions/virtual => virtual/action}/get.go | 2 +- .../virtual => virtual/action}/search.go | 2 +- .../virtual => virtual/action}/type.go | 15 ++- .../virtual => virtual/action}/update.go | 2 +- virtual/api/base.go | 43 +++++++ virtual/api/options.go | 80 +++++++++++++ virtual/api/type.go | 1 + .../controller => virtual/api}/virtual.go | 21 ++-- virtual/model/model.go | 2 +- virtual/model/type.go | 22 ++++ 33 files changed, 442 insertions(+), 172 deletions(-) rename pkg/response/actions/{authentic => }/base.go (96%) rename pkg/response/actions/{authentic => }/control_gorm.go (99%) rename pkg/response/actions/{authentic => }/control_mgm.go (95%) rename pkg/response/actions/{authentic => }/delete_gorm.go (97%) rename pkg/response/actions/{authentic => }/delete_mgm.go (93%) rename pkg/response/actions/{authentic => }/get_gorm.go (98%) rename pkg/response/actions/{authentic => }/get_mgm.go (93%) rename pkg/response/actions/{authentic => }/search_gorm.go (81%) rename pkg/response/actions/{authentic => }/search_mgm.go (98%) rename pkg/response/actions/{authentic => }/search_test.go (98%) rename pkg/response/actions/{authentic => }/type.go (98%) rename {pkg/response/actions/virtual => virtual/action}/base.go (98%) rename {pkg/response/actions/virtual => virtual/action}/create.go (99%) rename {pkg/response/actions/virtual => virtual/action}/delete.go (98%) rename {pkg/response/actions/virtual => virtual/action}/get.go (98%) rename {pkg/response/actions/virtual => virtual/action}/search.go (98%) rename {pkg/response/actions/virtual => virtual/action}/type.go (66%) rename {pkg/response/actions/virtual => virtual/action}/update.go (98%) create mode 100644 virtual/api/base.go create mode 100644 virtual/api/options.go create mode 100644 virtual/api/type.go rename {pkg/response/controller => virtual/api}/virtual.go (72%) create mode 100644 virtual/model/type.go diff --git a/pkg/response/action.go b/pkg/response/action.go index 171fe27..212d46a 100644 --- a/pkg/response/action.go +++ b/pkg/response/action.go @@ -11,8 +11,6 @@ import ( "fmt" "github.com/gin-gonic/gin" - - "github.com/mss-boot-io/mss-boot/virtual/model" ) const ( @@ -43,11 +41,3 @@ type Searcher interface { GetPage() int64 GetPageSize() int64 } - -// VirtualAction virtual action -type VirtualAction interface { - String() string - Handler() gin.HandlerFunc - SetModel(key string, m *model.Model) - GetModel(ctx *gin.Context) *model.Model -} diff --git a/pkg/response/actions/authentic/base.go b/pkg/response/actions/base.go similarity index 96% rename from pkg/response/actions/authentic/base.go rename to pkg/response/actions/base.go index 6f5868e..56c1517 100644 --- a/pkg/response/actions/authentic/base.go +++ b/pkg/response/actions/base.go @@ -1,4 +1,4 @@ -package authentic +package actions /* * @Author: lwnmengjing diff --git a/pkg/response/actions/authentic/control_gorm.go b/pkg/response/actions/control_gorm.go similarity index 99% rename from pkg/response/actions/authentic/control_gorm.go rename to pkg/response/actions/control_gorm.go index 18aa91a..0cd845f 100644 --- a/pkg/response/actions/authentic/control_gorm.go +++ b/pkg/response/actions/control_gorm.go @@ -1,4 +1,4 @@ -package authentic +package actions /* * @Author: lwnmengjing diff --git a/pkg/response/actions/authentic/control_mgm.go b/pkg/response/actions/control_mgm.go similarity index 95% rename from pkg/response/actions/authentic/control_mgm.go rename to pkg/response/actions/control_mgm.go index ddd6599..c3b4983 100644 --- a/pkg/response/actions/authentic/control_mgm.go +++ b/pkg/response/actions/control_mgm.go @@ -1,4 +1,4 @@ -package authentic +package actions /* * @Author: lwnmengjing @@ -9,7 +9,6 @@ package authentic import ( "errors" - "fmt" "net/http" "github.com/gin-gonic/gin" @@ -64,9 +63,7 @@ func (e *Control) Handler() gin.HandlerFunc { break } default: - response.Error(c, - http.StatusNotImplemented, - fmt.Errorf("not implemented")) + response.Make(c).Err(http.StatusNotImplemented, "not implemented") } } } diff --git a/pkg/response/actions/authentic/delete_gorm.go b/pkg/response/actions/delete_gorm.go similarity index 97% rename from pkg/response/actions/authentic/delete_gorm.go rename to pkg/response/actions/delete_gorm.go index 9455598..0b3b0fe 100644 --- a/pkg/response/actions/authentic/delete_gorm.go +++ b/pkg/response/actions/delete_gorm.go @@ -1,4 +1,4 @@ -package authentic +package actions /* * @Author: lwnmengjing diff --git a/pkg/response/actions/authentic/delete_mgm.go b/pkg/response/actions/delete_mgm.go similarity index 93% rename from pkg/response/actions/authentic/delete_mgm.go rename to pkg/response/actions/delete_mgm.go index 3f1f222..5fa7192 100644 --- a/pkg/response/actions/authentic/delete_mgm.go +++ b/pkg/response/actions/delete_mgm.go @@ -1,4 +1,4 @@ -package authentic +package actions /* * @Author: lwnmengjing @@ -9,7 +9,6 @@ package authentic import ( "errors" - "fmt" "net/http" "github.com/gin-gonic/gin" @@ -59,9 +58,7 @@ func (e *Delete) Handler() gin.HandlerFunc { e.deleteGorm(c, v) return } - response.Error(c, - http.StatusNotImplemented, - fmt.Errorf("not implemented")) + response.Make(c).Err(http.StatusNotImplemented, "not implemented") } } diff --git a/pkg/response/actions/authentic/get_gorm.go b/pkg/response/actions/get_gorm.go similarity index 98% rename from pkg/response/actions/authentic/get_gorm.go rename to pkg/response/actions/get_gorm.go index 58ff9f3..26aea03 100644 --- a/pkg/response/actions/authentic/get_gorm.go +++ b/pkg/response/actions/get_gorm.go @@ -1,4 +1,4 @@ -package authentic +package actions /* * @Author: lwnmengjing diff --git a/pkg/response/actions/authentic/get_mgm.go b/pkg/response/actions/get_mgm.go similarity index 93% rename from pkg/response/actions/authentic/get_mgm.go rename to pkg/response/actions/get_mgm.go index d9b0c02..d3d7ca7 100644 --- a/pkg/response/actions/authentic/get_mgm.go +++ b/pkg/response/actions/get_mgm.go @@ -1,4 +1,4 @@ -package authentic +package actions /* * @Author: lwnmengjing @@ -9,7 +9,6 @@ package authentic import ( "errors" - "fmt" "net/http" "github.com/gin-gonic/gin" @@ -52,9 +51,7 @@ func (e *Get) Handler() gin.HandlerFunc { e.getMgm(c, e.Key) return } - response.Error(c, - http.StatusNotImplemented, - fmt.Errorf("not implemented")) + response.Make(c).Err(http.StatusNotImplemented, "not implemented") } } diff --git a/pkg/response/actions/authentic/search_gorm.go b/pkg/response/actions/search_gorm.go similarity index 81% rename from pkg/response/actions/authentic/search_gorm.go rename to pkg/response/actions/search_gorm.go index 493583d..6050567 100644 --- a/pkg/response/actions/authentic/search_gorm.go +++ b/pkg/response/actions/search_gorm.go @@ -1,4 +1,4 @@ -package authentic +package actions /* * @Author: lwnmengjing @@ -44,6 +44,12 @@ func (e *Search) searchGorm(c *gin.Context) { gorms.MakeCondition(req), gorms.Paginate(int(req.GetPageSize()), int(req.GetPage())), ) + if err := query.Limit(-1).Offset(-1).Count(&count).Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { + api.AddError(err).Log.ErrorContext(c, "Search error", "error", err) + api.Err(http.StatusInternalServerError) + return + } + rows, err := query.Rows() if err != nil { api.AddError(err).Log.ErrorContext(c, "Search error", "error", err) @@ -56,7 +62,7 @@ func (e *Search) searchGorm(c *gin.Context) { m = pkg.TablerDeepCopy(e.ModelGorm) err = db.ScanRows(rows, m) if err != nil { - api.AddError(err).Log.ErrorContext(c, "Search error", "error", err) + api.AddError(err).Log.ErrorContext(c, "search error", "error", err) api.Err(http.StatusInternalServerError) return } @@ -64,10 +70,10 @@ func (e *Search) searchGorm(c *gin.Context) { } err = query.Limit(-1).Offset(-1).Count(&count).Error if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { - api.AddError(err).Log.ErrorContext(c, "Search error", "error", err) + api.AddError(err).Log.ErrorContext(c, "search error", "error", err) api.Err(http.StatusInternalServerError) return } - response.PageOK(c, items, count, req.GetPage(), req.GetPageSize(), "search success") + api.PageOK(items, count, req.GetPage(), req.GetPageSize(), "search success") c.Next() } diff --git a/pkg/response/actions/authentic/search_mgm.go b/pkg/response/actions/search_mgm.go similarity index 98% rename from pkg/response/actions/authentic/search_mgm.go rename to pkg/response/actions/search_mgm.go index 3627e3d..b5c41f3 100644 --- a/pkg/response/actions/authentic/search_mgm.go +++ b/pkg/response/actions/search_mgm.go @@ -1,4 +1,4 @@ -package authentic +package actions /* * @Author: lwnmengjing @@ -79,9 +79,7 @@ func (e *Search) Handler() gin.HandlerFunc { e.searchGorm(c) return } - response.Error(c, - http.StatusNotImplemented, - fmt.Errorf("not implemented")) + response.Make(c).Err(http.StatusNotImplemented, "not implemented") } } diff --git a/pkg/response/actions/authentic/search_test.go b/pkg/response/actions/search_test.go similarity index 98% rename from pkg/response/actions/authentic/search_test.go rename to pkg/response/actions/search_test.go index 153589a..f2debcd 100644 --- a/pkg/response/actions/authentic/search_test.go +++ b/pkg/response/actions/search_test.go @@ -1,4 +1,4 @@ -package authentic +package actions /* * @Author: lwnmengjing diff --git a/pkg/response/actions/authentic/type.go b/pkg/response/actions/type.go similarity index 98% rename from pkg/response/actions/authentic/type.go rename to pkg/response/actions/type.go index 0f2814c..e28cedb 100644 --- a/pkg/response/actions/authentic/type.go +++ b/pkg/response/actions/type.go @@ -1,4 +1,4 @@ -package authentic +package actions /* * @Author: lwnmengjing diff --git a/pkg/response/antd/model.go b/pkg/response/antd/model.go index 93339f7..951d6e1 100644 --- a/pkg/response/antd/model.go +++ b/pkg/response/antd/model.go @@ -2,8 +2,13 @@ package antd import ( "fmt" + "log/slog" + "net/http" + "os" "strings" + "github.com/gin-gonic/gin" + "github.com/mss-boot-io/mss-boot/pkg" resp "github.com/mss-boot-io/mss-boot/pkg/response" ) @@ -36,14 +41,14 @@ type response struct { // Pages 分页数据 type Pages struct { - Total int `json:"total,omitempty"` - Current int `json:"current,omitempty"` - PageSize int `json:"pageSize,omitempty"` + Total int64 `json:"total,omitempty"` + Current int64 `json:"current,omitempty"` + PageSize int64 `json:"pageSize,omitempty"` } type pages struct { Pages - Data interface{} `json:"data,omitempty"` + response } // SetCode 设置错误码 @@ -83,3 +88,64 @@ func (e *response) Clone() resp.Responses { clone := *e return &clone } + +func checkContext(c *gin.Context) { + if c == nil { + slog.Error("context is nil, please check, e.g. e.Make(c) add your controller function") + os.Exit(-1) + } +} + +// Error error +func (e *response) Error(c *gin.Context, code int, err error, msg ...string) { + checkContext(c) + res := e.Clone() + if msg == nil { + msg = make([]string, 0) + } + if err != nil { + msg = append(msg, err.Error()) + } + res.SetMsg(msg...) + res.SetTraceID(pkg.GenerateMsgIDFromContext(c)) + res.SetCode(code) + res.SetStatus("error") + c.Set("result", res) + c.Set("status", code) + c.AbortWithStatusJSON(code, res) +} + +// OK ok +func (e *response) OK(c *gin.Context, data interface{}) { + checkContext(c) + res := e.Clone() + res.SetList(data) + res.SetTraceID(pkg.GenerateMsgIDFromContext(c)) + switch c.Request.Method { + case http.MethodDelete: + res.SetCode(http.StatusNoContent) + c.AbortWithStatusJSON(http.StatusNoContent, data) + return + case http.MethodPost: + res.SetCode(http.StatusCreated) + c.AbortWithStatusJSON(http.StatusCreated, data) + return + default: + res.SetCode(http.StatusOK) + c.AbortWithStatusJSON(http.StatusOK, data) + } +} + +// PageOK page ok +func (e *response) PageOK(c *gin.Context, result interface{}, count, pageIndex, pageSize int64) { + checkContext(c) + var res pages + res.Total = count + res.Current = pageIndex + res.PageSize = pageSize + res.response.SetList(result) + res.response.SetTraceID(pkg.GenerateMsgIDFromContext(c)) + c.Set("result", res) + c.Set("status", http.StatusOK) + c.AbortWithStatusJSON(http.StatusOK, res) +} \ No newline at end of file diff --git a/pkg/response/antd/return.go b/pkg/response/antd/return.go index 68009fc..71b3994 100644 --- a/pkg/response/antd/return.go +++ b/pkg/response/antd/return.go @@ -7,43 +7,43 @@ import ( "github.com/mss-boot-io/mss-boot/pkg" ) -// Error 失败数据处理 -func Error(c *gin.Context, errCode string, errMsg string, showType string) { - var res response - res.Success = false - if errMsg != "" { - res.ErrorMessage = errMsg - } - if showType != "" { - res.ShowType = showType - } - res.TraceID = pkg.GenerateMsgIDFromContext(c) - res.ErrorCode = errCode - c.Set("result", res) - c.Set("status", errCode) - c.AbortWithStatusJSON(http.StatusOK, res) -} +// // Error 失败数据处理 +// func Error(c *gin.Context, errCode string, errMsg string, showType string) { +// var res response +// res.Success = false +// if errMsg != "" { +// res.ErrorMessage = errMsg +// } +// if showType != "" { +// res.ShowType = showType +// } +// res.TraceID = pkg.GenerateMsgIDFromContext(c) +// res.ErrorCode = errCode +// c.Set("result", res) +// c.Set("status", errCode) +// c.AbortWithStatusJSON(http.StatusOK, res) +// } -// OK 通常成功数据处理 -func OK(c *gin.Context, data interface{}) { - var res response - res.Data = data - res.Success = true - res.TraceID = pkg.GenerateMsgIDFromContext(c) - c.Set("result", res) - c.Set("status", http.StatusOK) - c.AbortWithStatusJSON(http.StatusOK, res) -} +// // OK 通常成功数据处理 +// func OK(c *gin.Context, data interface{}) { +// var res response +// res.Data = data +// res.Success = true +// res.TraceID = pkg.GenerateMsgIDFromContext(c) +// c.Set("result", res) +// c.Set("status", http.StatusOK) +// c.AbortWithStatusJSON(http.StatusOK, res) +// } -// PageOK 分页数据处理 -func PageOK(c *gin.Context, result interface{}, total int, current int, pageSize int) { - var res pages - res.Data = result - res.Total = total - res.Current = current - res.PageSize = pageSize - OK(c, res) -} +// // PageOK 分页数据处理 +// func PageOK(c *gin.Context, result interface{}, total int, current int, pageSize int) { +// var res pages +// res.Data = result +// res.Total = total +// res.Current = current +// res.PageSize = pageSize +// OK(c, res) +// } // Custum 兼容函数 func Custum(c *gin.Context, data gin.H) { diff --git a/pkg/response/api.go b/pkg/response/api.go index c1e2adb..20bb2ba 100644 --- a/pkg/response/api.go +++ b/pkg/response/api.go @@ -186,17 +186,17 @@ func (e *API) Bind(d interface{}, bindings ...binding.Binding) *API { // Err 通常错误数据处理 func (e *API) Err(code int, msg ...string) { - Error(e.Context, code, e.Error, msg...) + Default.Error(e.Context, code, e.Error, msg...) } // OK 通常成功数据处理 func (e *API) OK(data interface{}, msg ...string) { - OK(e.Context, data, msg...) + Default.OK(e.Context, data) } // PageOK 分页数据处理 func (e *API) PageOK(result interface{}, count int64, pageIndex int64, pageSize int64, msg ...string) { - PageOK(e.Context, result, count, pageIndex, pageSize, msg...) + Default.PageOK(e.Context, result, count, pageIndex, pageSize) } // getAcceptLanguage 获取当前语言 diff --git a/pkg/response/controller/options.go b/pkg/response/controller/options.go index 51cb09d..7272df4 100644 --- a/pkg/response/controller/options.go +++ b/pkg/response/controller/options.go @@ -9,7 +9,7 @@ package controller import ( "github.com/mss-boot-io/mss-boot/pkg/response" - "github.com/mss-boot-io/mss-boot/pkg/response/actions/authentic" + "github.com/mss-boot-io/mss-boot/pkg/response/actions" ) // Option set options @@ -19,9 +19,9 @@ type Option func(*Options) type Options struct { actions []response.Action search response.Searcher - model authentic.Model + model actions.Model auth bool - modelProvider authentic.ModelProvider + modelProvider actions.ModelProvider } // getAction get action @@ -59,7 +59,7 @@ func WithSearch(search response.Searcher) Option { } // WithModel set model -func WithModel(m authentic.Model) Option { +func WithModel(m actions.Model) Option { return func(o *Options) { o.model = m } @@ -73,7 +73,7 @@ func WithAuth(auth bool) Option { } // WithModelProvider set model provider -func WithModelProvider(provider authentic.ModelProvider) Option { +func WithModelProvider(provider actions.ModelProvider) Option { return func(o *Options) { o.modelProvider = provider } diff --git a/pkg/response/controller/simple.go b/pkg/response/controller/simple.go index 57e81a0..649c8e4 100644 --- a/pkg/response/controller/simple.go +++ b/pkg/response/controller/simple.go @@ -8,10 +8,9 @@ package controller */ import ( + "github.com/mss-boot-io/mss-boot/pkg/response/actions" "strings" - "github.com/mss-boot-io/mss-boot/pkg/response/actions/authentic" - "github.com/gin-gonic/gin" mgm "github.com/kamva/mgm/v3" @@ -54,9 +53,9 @@ func (e *Simple) GetAction(key string) response.Action { return action } switch e.options.modelProvider { - case authentic.ModelProviderMgm: + case actions.ModelProviderMgm: return e.getActionMgm(key) - case authentic.ModelProviderGorm: + case actions.ModelProviderGorm: return e.getActionGorm(key) default: return nil @@ -66,13 +65,13 @@ func (e *Simple) GetAction(key string) response.Action { func (e *Simple) getActionMgm(key string) response.Action { switch key { case response.Get: - return authentic.NewGetMgm(e.options.model, e.GetKey()) + return actions.NewGetMgm(e.options.model, e.GetKey()) case response.Control: - return authentic.NewControlMgm(e.options.model, e.GetKey()) + return actions.NewControlMgm(e.options.model, e.GetKey()) case response.Delete: - return authentic.NewDeleteMgm(e.options.model, e.GetKey()) + return actions.NewDeleteMgm(e.options.model, e.GetKey()) case response.Search: - return authentic.NewSearchMgm(e.options.model, e.options.search) + return actions.NewSearchMgm(e.options.model, e.options.search) default: return nil } @@ -81,13 +80,13 @@ func (e *Simple) getActionMgm(key string) response.Action { func (e *Simple) getActionGorm(key string) response.Action { switch key { case response.Get: - return authentic.NewGetGorm(e.options.model, e.GetKey()) + return actions.NewGetGorm(e.options.model, e.GetKey()) case response.Control: - return authentic.NewControlGorm(e.options.model, e.GetKey()) + return actions.NewControlGorm(e.options.model, e.GetKey()) case response.Delete: - return authentic.NewDeleteGorm(e.options.model, e.GetKey()) + return actions.NewDeleteGorm(e.options.model, e.GetKey()) case response.Search: - return authentic.NewSearchGorm(e.options.model, e.options.search) + return actions.NewSearchGorm(e.options.model, e.options.search) default: return nil } diff --git a/pkg/response/model.go b/pkg/response/model.go index 8407464..7ab0f3f 100644 --- a/pkg/response/model.go +++ b/pkg/response/model.go @@ -1,7 +1,11 @@ package response import ( + "net/http" "strings" + + "github.com/gin-gonic/gin" + "github.com/mss-boot-io/mss-boot/pkg" ) // Response response @@ -62,3 +66,57 @@ func (e *response) SetCode(code int) { func (e *response) SetStatus(status string) { e.Status = status } + +// Error error +func (e *response) Error(c *gin.Context, code int, err error, msg ...string) { + checkContext(c) + res := Default.Clone() + if msg == nil { + msg = make([]string, 0) + } + if err != nil { + msg = append(msg, err.Error()) + } + res.SetMsg(msg...) + res.SetTraceID(pkg.GenerateMsgIDFromContext(c)) + res.SetCode(code) + res.SetStatus("error") + c.Set("result", res) + c.Set("status", code) + c.AbortWithStatusJSON(code, res) +} + +// OK ok +func (e *response) OK(c *gin.Context, data interface{}) { + checkContext(c) + res := Default.Clone() + res.SetList(data) + res.SetTraceID(pkg.GenerateMsgIDFromContext(c)) + switch c.Request.Method { + case http.MethodDelete: + res.SetCode(http.StatusNoContent) + c.AbortWithStatusJSON(http.StatusNoContent, data) + return + case http.MethodPost: + res.SetCode(http.StatusCreated) + c.AbortWithStatusJSON(http.StatusCreated, data) + return + default: + res.SetCode(http.StatusOK) + c.AbortWithStatusJSON(http.StatusOK, data) + } +} + +// PageOK page ok +func (e *response) PageOK(c *gin.Context, result interface{}, count, pageIndex, pageSize int64) { + checkContext(c) + var res page + res.Count = count + res.Current = pageIndex + res.PageSize = pageSize + res.response.SetList(result) + res.response.SetTraceID(pkg.GenerateMsgIDFromContext(c)) + c.Set("result", res) + c.Set("status", http.StatusOK) + c.AbortWithStatusJSON(http.StatusOK, res) +} diff --git a/pkg/response/return.go b/pkg/response/return.go index b44fd05..53a8460 100644 --- a/pkg/response/return.go +++ b/pkg/response/return.go @@ -2,72 +2,69 @@ package response import ( "log/slog" - "net/http" "os" "github.com/gin-gonic/gin" - - "github.com/mss-boot-io/mss-boot/pkg" ) // Default 默认返回 var Default Responses = &response{} -// Error 失败数据处理 -func Error(c *gin.Context, code int, err error, msg ...string) { - checkContext(c) - res := Default.Clone() - if msg == nil { - msg = make([]string, 0) - } - if err != nil { - msg = append(msg, err.Error()) - } - res.SetMsg(msg...) - res.SetTraceID(pkg.GenerateMsgIDFromContext(c)) - res.SetCode(code) - res.SetStatus("error") - c.Set("result", res) - c.Set("status", code) - c.AbortWithStatusJSON(code, res) -} +// // Error 失败数据处理 +// func Error(c *gin.Context, code int, err error, msg ...string) { +// checkContext(c) +// res := Default.Clone() +// if msg == nil { +// msg = make([]string, 0) +// } +// if err != nil { +// msg = append(msg, err.Error()) +// } +// res.SetMsg(msg...) +// res.SetTraceID(pkg.GenerateMsgIDFromContext(c)) +// res.SetCode(code) +// res.SetStatus("error") +// c.Set("result", res) +// c.Set("status", code) +// c.AbortWithStatusJSON(code, res) +// } -// OK 通常成功数据处理 -func OK(c *gin.Context, data interface{}, msg ...string) { - checkContext(c) - res := Default.Clone() - res.SetList(data) - res.SetTraceID(pkg.GenerateMsgIDFromContext(c)) - switch c.Request.Method { - case http.MethodDelete: - res.SetCode(http.StatusNoContent) - c.AbortWithStatusJSON(http.StatusNoContent, data) - return - case http.MethodPost: - res.SetCode(http.StatusCreated) - c.AbortWithStatusJSON(http.StatusCreated, data) - return - default: - res.SetCode(http.StatusOK) - c.AbortWithStatusJSON(http.StatusOK, data) - } -} +// // OK 通常成功数据处理 +// func OK(c *gin.Context, data interface{}, msg ...string) { +// checkContext(c) +// res := Default.Clone() +// res.SetList(data) +// res.SetTraceID(pkg.GenerateMsgIDFromContext(c)) +// switch c.Request.Method { +// case http.MethodDelete: +// res.SetCode(http.StatusNoContent) +// c.AbortWithStatusJSON(http.StatusNoContent, data) +// return +// case http.MethodPost: +// res.SetCode(http.StatusCreated) +// c.AbortWithStatusJSON(http.StatusCreated, data) +// return +// default: +// res.SetCode(http.StatusOK) +// c.AbortWithStatusJSON(http.StatusOK, data) +// } +// } -// PageOK 分页数据处理 -func PageOK(c *gin.Context, result interface{}, count int64, pageIndex int64, pageSize int64, msg ...string) { - checkContext(c) - var res page - res.Count = count - res.Current = pageIndex - res.PageSize = pageSize - res.response.SetList(result) - //res.response.SetMsg(msg...) - res.response.SetTraceID(pkg.GenerateMsgIDFromContext(c)) - //res.response.SetCode(http.StatusOK) - c.Set("result", res) - c.Set("status", http.StatusOK) - c.AbortWithStatusJSON(http.StatusOK, res) -} +// // PageOK 分页数据处理 +// func PageOK(c *gin.Context, result interface{}, count int64, pageIndex int64, pageSize int64, msg ...string) { +// checkContext(c) +// var res page +// res.Count = count +// res.Current = pageIndex +// res.PageSize = pageSize +// res.response.SetList(result) +// //res.response.SetMsg(msg...) +// res.response.SetTraceID(pkg.GenerateMsgIDFromContext(c)) +// //res.response.SetCode(http.StatusOK) +// c.Set("result", res) +// c.Set("status", http.StatusOK) +// c.AbortWithStatusJSON(http.StatusOK, res) +// } func checkContext(c *gin.Context) { if c == nil { diff --git a/pkg/response/type.go b/pkg/response/type.go index bea67a5..39d229d 100644 --- a/pkg/response/type.go +++ b/pkg/response/type.go @@ -1,5 +1,7 @@ package response +import "github.com/gin-gonic/gin" + /* * @Author: lwnmengjing * @Date: 2021/6/8 5:51 下午 @@ -15,4 +17,7 @@ type Responses interface { SetList(interface{}) SetStatus(string) Clone() Responses + Error(ctx *gin.Context, code int, err error, msg ...string) + OK(ctx *gin.Context, data any) + PageOK(ctx *gin.Context, result any, count, pageIndex, pageSize int64) } diff --git a/pkg/response/actions/virtual/base.go b/virtual/action/base.go similarity index 98% rename from pkg/response/actions/virtual/base.go rename to virtual/action/base.go index cf5f8c6..122a970 100644 --- a/pkg/response/actions/virtual/base.go +++ b/virtual/action/base.go @@ -1,4 +1,4 @@ -package virtual +package action import ( "net/http" diff --git a/pkg/response/actions/virtual/create.go b/virtual/action/create.go similarity index 99% rename from pkg/response/actions/virtual/create.go rename to virtual/action/create.go index e2161d8..37e0995 100644 --- a/pkg/response/actions/virtual/create.go +++ b/virtual/action/create.go @@ -1,4 +1,4 @@ -package virtual +package action import ( "net/http" diff --git a/pkg/response/actions/virtual/delete.go b/virtual/action/delete.go similarity index 98% rename from pkg/response/actions/virtual/delete.go rename to virtual/action/delete.go index d450b12..dbe8767 100644 --- a/pkg/response/actions/virtual/delete.go +++ b/virtual/action/delete.go @@ -1,4 +1,4 @@ -package virtual +package action import ( "errors" diff --git a/pkg/response/actions/virtual/get.go b/virtual/action/get.go similarity index 98% rename from pkg/response/actions/virtual/get.go rename to virtual/action/get.go index a45c14e..be5b0bf 100644 --- a/pkg/response/actions/virtual/get.go +++ b/virtual/action/get.go @@ -1,4 +1,4 @@ -package virtual +package action import ( "errors" diff --git a/pkg/response/actions/virtual/search.go b/virtual/action/search.go similarity index 98% rename from pkg/response/actions/virtual/search.go rename to virtual/action/search.go index 18ff940..c7a7206 100644 --- a/pkg/response/actions/virtual/search.go +++ b/virtual/action/search.go @@ -1,4 +1,4 @@ -package virtual +package action import ( "net/http" diff --git a/pkg/response/actions/virtual/type.go b/virtual/action/type.go similarity index 66% rename from pkg/response/actions/virtual/type.go rename to virtual/action/type.go index 29faba7..ac54969 100644 --- a/pkg/response/actions/virtual/type.go +++ b/virtual/action/type.go @@ -1,4 +1,9 @@ -package virtual +package action + +import ( + "github.com/gin-gonic/gin" + "github.com/mss-boot-io/mss-boot/virtual/model" +) /* * @Author: lwnmengjing @@ -7,6 +12,14 @@ package virtual * @Last Modified time: 2023/9/17 08:12:38 */ +// VirtualAction virtual action +type VirtualAction interface { + String() string + Handler() gin.HandlerFunc + SetModel(key string, m *model.Model) + GetModel(ctx *gin.Context) *model.Model +} + // Pagination pagination params type Pagination struct { Page int64 `form:"page" query:"page"` diff --git a/pkg/response/actions/virtual/update.go b/virtual/action/update.go similarity index 98% rename from pkg/response/actions/virtual/update.go rename to virtual/action/update.go index a68c9db..abab97c 100644 --- a/pkg/response/actions/virtual/update.go +++ b/virtual/action/update.go @@ -1,4 +1,4 @@ -package virtual +package action import ( "net/http" diff --git a/virtual/api/base.go b/virtual/api/base.go new file mode 100644 index 0000000..c746112 --- /dev/null +++ b/virtual/api/base.go @@ -0,0 +1,43 @@ +package api + +/* + * @Author: lwnmengjing + * @Date: 2023/1/26 01:15:07 + * @Last Modified by: lwnmengjing + * @Last Modified time: 2023/1/26 01:15:07 + */ + +import ( + "github.com/gin-gonic/gin" + + "github.com/mss-boot-io/mss-boot/pkg/response" +) + +// DefaultKey default key +var DefaultKey = "id" + +// Base controller +type Base struct{} + +// Path http path +func (e *Base) Path() string { + return "" +} + +// Handlers middlewares +func (e *Base) Handlers() gin.HandlersChain { + return nil +} + +// GetAction get action +func (e *Base) GetAction(_ string) response.Action { + return nil +} + +// Other handler +func (e *Base) Other(_ *gin.RouterGroup) {} + +// GetKey get key +func (e *Base) GetKey() string { + return DefaultKey +} diff --git a/virtual/api/options.go b/virtual/api/options.go new file mode 100644 index 0000000..d4e2497 --- /dev/null +++ b/virtual/api/options.go @@ -0,0 +1,80 @@ +package api + +/* + * @Author: lwnmengjing + * @Date: 2023/1/26 11:24:55 + * @Last Modified by: lwnmengjing + * @Last Modified time: 2023/1/26 11:24:55 + */ + +import ( + "github.com/mss-boot-io/mss-boot/pkg/response" + "github.com/mss-boot-io/mss-boot/virtual/model" +) + +// Option set options +type Option func(*Options) + +// Options options +type Options struct { + actions []response.Action + search response.Searcher + model model.ModelImpl + auth bool + modelProvider model.ModelProvider +} + +// getAction get action +func (o *Options) getAction(key string) response.Action { + for i := range o.actions { + if o.actions[i].String() == key { + return o.actions[i] + } + } + return nil +} + +// DefaultOptions make default options +func DefaultOptions() Options { + return Options{ + actions: make([]response.Action, 0), + } +} + +// WithAction set action +func WithAction(action response.Action) Option { + return func(o *Options) { + if o.actions == nil { + o.actions = make([]response.Action, 0) + } + o.actions = append(o.actions, action) + } +} + +// WithSearch set search +func WithSearch(search response.Searcher) Option { + return func(o *Options) { + o.search = search + } +} + +// WithModel set model +func WithModel(m model.ModelImpl) Option { + return func(o *Options) { + o.model = m + } +} + +// WithAuth set auth +func WithAuth(auth bool) Option { + return func(o *Options) { + o.auth = auth + } +} + +// WithModelProvider set model provider +func WithModelProvider(provider model.ModelProvider) Option { + return func(o *Options) { + o.modelProvider = provider + } +} diff --git a/virtual/api/type.go b/virtual/api/type.go new file mode 100644 index 0000000..a57cc3f --- /dev/null +++ b/virtual/api/type.go @@ -0,0 +1 @@ +package api \ No newline at end of file diff --git a/pkg/response/controller/virtual.go b/virtual/api/virtual.go similarity index 72% rename from pkg/response/controller/virtual.go rename to virtual/api/virtual.go index e62daf7..3022260 100644 --- a/pkg/response/controller/virtual.go +++ b/virtual/api/virtual.go @@ -1,9 +1,10 @@ -package controller +package api import ( "github.com/gin-gonic/gin" + "github.com/mss-boot-io/mss-boot/pkg/response" - "github.com/mss-boot-io/mss-boot/pkg/response/actions/virtual" + "github.com/mss-boot-io/mss-boot/virtual/action" ) /* @@ -17,11 +18,11 @@ import ( type Virtual struct { Base options Options - Provider *virtual.Base + Provider *action.Base } // NewVirtual new virtual controller -func NewVirtual(provider *virtual.Base, options ...Option) *Virtual { +func NewVirtual(provider *action.Base, options ...Option) *Virtual { v := &Virtual{ Provider: provider, options: DefaultOptions(), @@ -34,7 +35,7 @@ func NewVirtual(provider *virtual.Base, options ...Option) *Virtual { // Path http path func (v *Virtual) Path() string { - return ":" + virtual.PathKey + return ":" + action.PathKey } // Handlers middlewares @@ -53,15 +54,15 @@ func (v *Virtual) GetAction(key string) response.Action { func (v *Virtual) getAction(key string) response.Action { switch key { case response.Get: - return virtual.NewGet(v.Provider) + return action.NewGet(v.Provider) case response.Create: - return virtual.NewCreate(v.Provider) + return action.NewCreate(v.Provider) case response.Update: - return virtual.NewUpdate(v.Provider) + return action.NewUpdate(v.Provider) case response.Delete: - return virtual.NewDelete(v.Provider) + return action.NewDelete(v.Provider) case response.Search: - return virtual.NewSearch(v.Provider) + return action.NewSearch(v.Provider) default: return nil } diff --git a/virtual/model/model.go b/virtual/model/model.go index f6c24c1..dcfdb0a 100644 --- a/virtual/model/model.go +++ b/virtual/model/model.go @@ -2,11 +2,11 @@ package model import ( "fmt" - "github.com/go-openapi/spec" "reflect" "strings" "time" + "github.com/go-openapi/spec" "github.com/gin-gonic/gin" "gorm.io/gorm" ) diff --git a/virtual/model/type.go b/virtual/model/type.go new file mode 100644 index 0000000..ce202cf --- /dev/null +++ b/virtual/model/type.go @@ -0,0 +1,22 @@ +package model + +import ( + mgm "github.com/kamva/mgm/v3" + "gorm.io/gorm/schema" +) + +// ModelProvider model provider +type ModelProvider string + +const ( + // ModelProviderMgm mgm model provider + ModelProviderMgm ModelProvider = "mgm" + // ModelProviderGorm gorm model provider + ModelProviderGorm ModelProvider = "gorm" +) + +// ModelImpl gorm and mgm model +type ModelImpl interface { + mgm.Model + schema.Tabler +} From f655f71339c42320d6b8f654fdce0c0f9b644142 Mon Sep 17 00:00:00 2001 From: lwnmengjing Date: Thu, 30 Nov 2023 16:47:38 +0800 Subject: [PATCH 4/4] :sparkles: feat: migrate generate code server --- pkg/response/api.go | 2 +- pkg/response/return.go | 56 ------------------------------------------ 2 files changed, 1 insertion(+), 57 deletions(-) diff --git a/pkg/response/api.go b/pkg/response/api.go index 20bb2ba..f96870f 100644 --- a/pkg/response/api.go +++ b/pkg/response/api.go @@ -42,7 +42,7 @@ func (*API) Path() string { } // Handlers 路由 -func (*API) Handlers() []gin.HandlerFunc { +func (*API) Handlers() gin.HandlersChain { return []gin.HandlerFunc{} } diff --git a/pkg/response/return.go b/pkg/response/return.go index 53a8460..f45d59d 100644 --- a/pkg/response/return.go +++ b/pkg/response/return.go @@ -10,62 +10,6 @@ import ( // Default 默认返回 var Default Responses = &response{} -// // Error 失败数据处理 -// func Error(c *gin.Context, code int, err error, msg ...string) { -// checkContext(c) -// res := Default.Clone() -// if msg == nil { -// msg = make([]string, 0) -// } -// if err != nil { -// msg = append(msg, err.Error()) -// } -// res.SetMsg(msg...) -// res.SetTraceID(pkg.GenerateMsgIDFromContext(c)) -// res.SetCode(code) -// res.SetStatus("error") -// c.Set("result", res) -// c.Set("status", code) -// c.AbortWithStatusJSON(code, res) -// } - -// // OK 通常成功数据处理 -// func OK(c *gin.Context, data interface{}, msg ...string) { -// checkContext(c) -// res := Default.Clone() -// res.SetList(data) -// res.SetTraceID(pkg.GenerateMsgIDFromContext(c)) -// switch c.Request.Method { -// case http.MethodDelete: -// res.SetCode(http.StatusNoContent) -// c.AbortWithStatusJSON(http.StatusNoContent, data) -// return -// case http.MethodPost: -// res.SetCode(http.StatusCreated) -// c.AbortWithStatusJSON(http.StatusCreated, data) -// return -// default: -// res.SetCode(http.StatusOK) -// c.AbortWithStatusJSON(http.StatusOK, data) -// } -// } - -// // PageOK 分页数据处理 -// func PageOK(c *gin.Context, result interface{}, count int64, pageIndex int64, pageSize int64, msg ...string) { -// checkContext(c) -// var res page -// res.Count = count -// res.Current = pageIndex -// res.PageSize = pageSize -// res.response.SetList(result) -// //res.response.SetMsg(msg...) -// res.response.SetTraceID(pkg.GenerateMsgIDFromContext(c)) -// //res.response.SetCode(http.StatusOK) -// c.Set("result", res) -// c.Set("status", http.StatusOK) -// c.AbortWithStatusJSON(http.StatusOK, res) -// } - func checkContext(c *gin.Context) { if c == nil { slog.Error("context is nil, please check, e.g. e.Make(c) add your controller function")