From 2d65afdf3385f59020a9fa33aa1b1a5d0bc7824b Mon Sep 17 00:00:00 2001 From: des <18638715007@163.com> Date: Mon, 19 Jan 2026 00:07:20 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=9D=E8=AF=95=E7=99=BB=E5=BD=95=E9=80=BB?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- model/users.gen.go | 26 ++ srv/cmd/gatekeeper/main.go | 24 +- srv/go.mod | 18 +- srv/go.sum | 31 +++ srv/internal/common/context_variable.go | 26 ++ srv/internal/ero/error.go | 27 ++ srv/internal/middle/error_handle.go | 7 - srv/internal/middle/package.go | 25 ++ srv/internal/model/users.gen.go | 26 ++ srv/internal/query/gen.go | 103 +++++++ srv/internal/query/users.gen.go | 347 ++++++++++++++++++++++++ srv/internal/user/controller.go | 42 +-- srv/internal/user/controller_test.go | 11 +- srv/internal/user/entity.go | 14 - srv/internal/user/service.go | 25 ++ srv/tools/gorm_generate/main.go | 27 ++ 16 files changed, 713 insertions(+), 66 deletions(-) create mode 100644 model/users.gen.go create mode 100644 srv/internal/common/context_variable.go create mode 100644 srv/internal/ero/error.go delete mode 100644 srv/internal/middle/error_handle.go create mode 100644 srv/internal/middle/package.go create mode 100644 srv/internal/model/users.gen.go create mode 100644 srv/internal/query/gen.go create mode 100644 srv/internal/query/users.gen.go delete mode 100644 srv/internal/user/entity.go create mode 100644 srv/internal/user/service.go create mode 100644 srv/tools/gorm_generate/main.go diff --git a/model/users.gen.go b/model/users.gen.go new file mode 100644 index 0000000..d5cfee0 --- /dev/null +++ b/model/users.gen.go @@ -0,0 +1,26 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameUser = "users" + +// User mapped from table +type User struct { + ID int64 `gorm:"column:id;primaryKey;comment:用户ID" json:"id"` // 用户ID + CreateTime time.Time `gorm:"column:create_time;not null" json:"create_time"` + LastUpdateTime time.Time `gorm:"column:last_update_time;not null" json:"last_update_time"` + Name string `gorm:"column:name;not null;comment:用户在系统内的名称" json:"name"` // 用户在系统内的名称 + Account string `gorm:"column:account;not null;comment:用户登录凭证" json:"account"` // 用户登录凭证 + Passwd string `gorm:"column:passwd;not null;comment:用户登录密钥" json:"passwd"` // 用户登录密钥 +} + +// TableName User's table name +func (*User) TableName() string { + return TableNameUser +} diff --git a/srv/cmd/gatekeeper/main.go b/srv/cmd/gatekeeper/main.go index 16a446c..69f7628 100644 --- a/srv/cmd/gatekeeper/main.go +++ b/srv/cmd/gatekeeper/main.go @@ -1,34 +1,30 @@ package main import ( - "fmt" - "net/http" - "Crimson-Gatekeeper/internal/common" + "Crimson-Gatekeeper/internal/middle" + "Crimson-Gatekeeper/internal/query" "Crimson-Gatekeeper/internal/user" + "fmt" "github.com/gin-gonic/gin" ) func main() { - app, close := launchApplication() + app, clean := launchApplication() + defer clean() err := app.Run(":3333") if err != nil { fmt.Println("应用启动失败") panic(err) } - defer close() } func launchApplication() (*gin.Engine, func() error) { - client, close := common.GetDataBaseClient() + db, clean := common.GetDataBaseClient() + q := query.Use(db) app := gin.Default() - app.GET("/test", func(ctx *gin.Context) { - fmt.Println(ctx.Request.URL.Path) - ctx.JSON(http.StatusOK, gin.H{ - "message": "success", - }) - }) - user.New(client).RegisterRoute(app) - return app, close + app.Use(middle.ResponsePackageMiddle) + user.New(q).RegisterRoute(app) + return app, clean } diff --git a/srv/go.mod b/srv/go.mod index 403b4eb..9d47262 100644 --- a/srv/go.mod +++ b/srv/go.mod @@ -9,6 +9,7 @@ require ( ) require ( + filippo.io/edwards25519 v1.1.0 // indirect github.com/bytedance/sonic v1.14.0 // indirect github.com/bytedance/sonic/loader v0.3.0 // indirect github.com/cloudwego/base64x v0.1.6 // indirect @@ -17,8 +18,10 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.27.0 // indirect + github.com/go-sql-driver/mysql v1.9.3 // indirect github.com/goccy/go-json v0.10.2 // indirect github.com/goccy/go-yaml v1.18.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgx/v5 v5.8.0 // indirect @@ -38,12 +41,17 @@ require ( github.com/ugorji/go/codec v1.3.0 // indirect go.uber.org/mock v0.5.0 // indirect golang.org/x/arch v0.20.0 // indirect - golang.org/x/crypto v0.46.0 // indirect - golang.org/x/mod v0.31.0 // indirect - golang.org/x/net v0.48.0 // indirect + golang.org/x/crypto v0.47.0 // indirect + golang.org/x/mod v0.32.0 // indirect + golang.org/x/net v0.49.0 // indirect golang.org/x/sync v0.19.0 // indirect - golang.org/x/sys v0.39.0 // indirect + golang.org/x/sys v0.40.0 // indirect golang.org/x/text v0.33.0 // indirect - golang.org/x/tools v0.40.0 // indirect + golang.org/x/tools v0.41.0 // indirect google.golang.org/protobuf v1.36.9 // indirect + gorm.io/datatypes v1.2.7 // indirect + gorm.io/driver/mysql v1.6.0 // indirect + gorm.io/gen v0.3.27 // indirect + gorm.io/hints v1.1.2 // indirect + gorm.io/plugin/dbresolver v1.6.2 // indirect ) diff --git a/srv/go.sum b/srv/go.sum index dcad19b..564667a 100644 --- a/srv/go.sum +++ b/srv/go.sum @@ -1,3 +1,5 @@ +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA= github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= @@ -21,6 +23,8 @@ github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJn github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4= github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= +github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= +github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= @@ -28,6 +32,8 @@ github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7Lk github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= @@ -48,6 +54,8 @@ github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= 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= +github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= @@ -80,26 +88,49 @@ golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c= golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU= golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0= +golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= +golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI= golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg= +golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= +golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= +golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA= golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc= +golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= +golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/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= +gorm.io/datatypes v1.2.7 h1:ww9GAhF1aGXZY3EB3cJPJ7//JiuQo7DlQA7NNlVaTdk= +gorm.io/datatypes v1.2.7/go.mod h1:M2iO+6S3hhi4nAyYe444Pcb0dcIiOMJ7QHaUXxyiNZY= +gorm.io/driver/mysql v1.6.0 h1:eNbLmNTpPpTOVZi8MMxCi2aaIm0ZpInbORNXDwyLGvg= +gorm.io/driver/mysql v1.6.0/go.mod h1:D/oCC2GWK3M/dqoLxnOlaNKmXz8WNTfcS9y5ovaSqKo= gorm.io/driver/postgres v1.6.0 h1:2dxzU8xJ+ivvqTRph34QX+WrRaJlmfyPqXmoGVjMBa4= gorm.io/driver/postgres v1.6.0/go.mod h1:vUw0mrGgrTK+uPHEhAdV4sfFELrByKVGnaVRkXDhtWo= +gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I= +gorm.io/gen v0.3.27 h1:ziocAFLpE7e0g4Rum69pGfB9S6DweTxK8gAun7cU8as= +gorm.io/gen v0.3.27/go.mod h1:9zquz2xD1f3Eb/eHq4oLn2z6vDVvQlCY5S3uMBLv4EA= +gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= +gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= gorm.io/gorm v1.31.1 h1:7CA8FTFz/gRfgqgpeKIBcervUn3xSyPUmr6B2WXJ7kg= gorm.io/gorm v1.31.1/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= +gorm.io/hints v1.1.2 h1:b5j0kwk5p4+3BtDtYqqfY+ATSxjj+6ptPgVveuynn9o= +gorm.io/hints v1.1.2/go.mod h1:/ARdpUHAtyEMCh5NNi3tI7FsGh+Cj/MIUlvNxCNCFWg= +gorm.io/plugin/dbresolver v1.6.2 h1:F4b85TenghUeITqe3+epPSUtHH7RIk3fXr5l83DF8Pc= +gorm.io/plugin/dbresolver v1.6.2/go.mod h1:tctw63jdrOezFR9HmrKnPkmig3m5Edem9fdxk9bQSzM= diff --git a/srv/internal/common/context_variable.go b/srv/internal/common/context_variable.go new file mode 100644 index 0000000..5822c46 --- /dev/null +++ b/srv/internal/common/context_variable.go @@ -0,0 +1,26 @@ +package common + +import ( + "github.com/gin-gonic/gin" +) + +type ctxKey struct { + desc string +} + +var ( + dataKey = ctxKey{"响应体内容"} +) + +// SetData 设置响应数据,可以设置为 nil,或者干脆不设置。此时会返回空的响应包装。 +func SetData(c *gin.Context, data any) { + c.Set(dataKey, data) +} + +// GetData 获取响应数据 +// 除了响应包装器,你不应该在任何地方调用该方法。因为响应数据的类型不一。 +// 如果你真的对响应数据处理。请在中间件向上下文中塞入数据,在 handler 中处理好。 +func GetData(c *gin.Context) any { + data, _ := c.Get(dataKey) + return data +} diff --git a/srv/internal/ero/error.go b/srv/internal/ero/error.go new file mode 100644 index 0000000..c5edb59 --- /dev/null +++ b/srv/internal/ero/error.go @@ -0,0 +1,27 @@ +package ero + +import "net/http" + +type Type int + +const ( + // ServerError 通用的,不需要特殊处理暴露给前端的错误 + ServerError Type = iota + // FormError 表单校验异常,没有执行成功。Data 内会有明确的字段级错误返回给前端处理 + FormError +) + +// GeneralError 通用的错误数据包装 +type GeneralError struct { + Status int + // Type 错误类型,参考自定义类型 Type + Type Type + // Message 当前错误的简短解释 + Message string + // Data 如果是复杂错误,此处会返回前端协助前端展示错误的数据 + Data any +} + +func SimpleError(msg string) *GeneralError { + return &GeneralError{http.StatusInternalServerError, ServerError, msg, nil} +} diff --git a/srv/internal/middle/error_handle.go b/srv/internal/middle/error_handle.go deleted file mode 100644 index 9ca689c..0000000 --- a/srv/internal/middle/error_handle.go +++ /dev/null @@ -1,7 +0,0 @@ -package middle - -import "github.com/gin-gonic/gin" - -func SetContextError(ctx *gin.Context) { - -} diff --git a/srv/internal/middle/package.go b/srv/internal/middle/package.go new file mode 100644 index 0000000..ccda584 --- /dev/null +++ b/srv/internal/middle/package.go @@ -0,0 +1,25 @@ +package middle + +import ( + "Crimson-Gatekeeper/internal/common" + "Crimson-Gatekeeper/internal/ero" + + "github.com/gin-gonic/gin" +) + +// GeneralResponse 通用的返回包装结构体。不管错误与否 +type GeneralResponse struct { + success string + data any +} + +// ResponsePackageMiddle 返回包装中间件 +func ResponsePackageMiddle(c *gin.Context) { + c.Next() + data := common.GetData(c) + if data, ok := data.(ero.GeneralError); ok { + c.JSON(200, &GeneralResponse{"false", data}) + } else { + c.JSON(200, &GeneralResponse{"fail", data}) + } +} diff --git a/srv/internal/model/users.gen.go b/srv/internal/model/users.gen.go new file mode 100644 index 0000000..d5cfee0 --- /dev/null +++ b/srv/internal/model/users.gen.go @@ -0,0 +1,26 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package model + +import ( + "time" +) + +const TableNameUser = "users" + +// User mapped from table +type User struct { + ID int64 `gorm:"column:id;primaryKey;comment:用户ID" json:"id"` // 用户ID + CreateTime time.Time `gorm:"column:create_time;not null" json:"create_time"` + LastUpdateTime time.Time `gorm:"column:last_update_time;not null" json:"last_update_time"` + Name string `gorm:"column:name;not null;comment:用户在系统内的名称" json:"name"` // 用户在系统内的名称 + Account string `gorm:"column:account;not null;comment:用户登录凭证" json:"account"` // 用户登录凭证 + Passwd string `gorm:"column:passwd;not null;comment:用户登录密钥" json:"passwd"` // 用户登录密钥 +} + +// TableName User's table name +func (*User) TableName() string { + return TableNameUser +} diff --git a/srv/internal/query/gen.go b/srv/internal/query/gen.go new file mode 100644 index 0000000..59f0e0d --- /dev/null +++ b/srv/internal/query/gen.go @@ -0,0 +1,103 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package query + +import ( + "context" + "database/sql" + + "gorm.io/gorm" + + "gorm.io/gen" + + "gorm.io/plugin/dbresolver" +) + +var ( + Q = new(Query) + User *user +) + +func SetDefault(db *gorm.DB, opts ...gen.DOOption) { + *Q = *Use(db, opts...) + User = &Q.User +} + +func Use(db *gorm.DB, opts ...gen.DOOption) *Query { + return &Query{ + db: db, + User: newUser(db, opts...), + } +} + +type Query struct { + db *gorm.DB + + User user +} + +func (q *Query) Available() bool { return q.db != nil } + +func (q *Query) clone(db *gorm.DB) *Query { + return &Query{ + db: db, + User: q.User.clone(db), + } +} + +func (q *Query) ReadDB() *Query { + return q.ReplaceDB(q.db.Clauses(dbresolver.Read)) +} + +func (q *Query) WriteDB() *Query { + return q.ReplaceDB(q.db.Clauses(dbresolver.Write)) +} + +func (q *Query) ReplaceDB(db *gorm.DB) *Query { + return &Query{ + db: db, + User: q.User.replaceDB(db), + } +} + +type queryCtx struct { + User *userDo +} + +func (q *Query) WithContext(ctx context.Context) *queryCtx { + return &queryCtx{ + User: q.User.WithContext(ctx), + } +} + +func (q *Query) Transaction(fc func(tx *Query) error, opts ...*sql.TxOptions) error { + return q.db.Transaction(func(tx *gorm.DB) error { return fc(q.clone(tx)) }, opts...) +} + +func (q *Query) Begin(opts ...*sql.TxOptions) *QueryTx { + tx := q.db.Begin(opts...) + return &QueryTx{Query: q.clone(tx), Error: tx.Error} +} + +type QueryTx struct { + *Query + Error error +} + +func (q *QueryTx) Commit() error { + return q.db.Commit().Error +} + +func (q *QueryTx) Rollback() error { + return q.db.Rollback().Error +} + +func (q *QueryTx) SavePoint(name string) error { + return q.db.SavePoint(name).Error +} + +func (q *QueryTx) RollbackTo(name string) error { + return q.db.RollbackTo(name).Error +} diff --git a/srv/internal/query/users.gen.go b/srv/internal/query/users.gen.go new file mode 100644 index 0000000..847bcc3 --- /dev/null +++ b/srv/internal/query/users.gen.go @@ -0,0 +1,347 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package query + +import ( + "context" + + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" + + "Crimson-Gatekeeper/internal/model" +) + +func newUser(db *gorm.DB, opts ...gen.DOOption) user { + _user := user{} + + _user.userDo.UseDB(db, opts...) + _user.userDo.UseModel(&model.User{}) + + tableName := _user.userDo.TableName() + _user.ALL = field.NewAsterisk(tableName) + _user.ID = field.NewInt64(tableName, "id") + _user.CreateTime = field.NewTime(tableName, "create_time") + _user.LastUpdateTime = field.NewTime(tableName, "last_update_time") + _user.Name = field.NewString(tableName, "name") + _user.Account = field.NewString(tableName, "account") + _user.Passwd = field.NewString(tableName, "passwd") + + _user.fillFieldMap() + + return _user +} + +type user struct { + userDo userDo + + ALL field.Asterisk + ID field.Int64 // 用户ID + CreateTime field.Time + LastUpdateTime field.Time + Name field.String // 用户在系统内的名称 + Account field.String // 用户登录凭证 + Passwd field.String // 用户登录密钥 + + fieldMap map[string]field.Expr +} + +func (u user) Table(newTableName string) *user { + u.userDo.UseTable(newTableName) + return u.updateTableName(newTableName) +} + +func (u user) As(alias string) *user { + u.userDo.DO = *(u.userDo.As(alias).(*gen.DO)) + return u.updateTableName(alias) +} + +func (u *user) updateTableName(table string) *user { + u.ALL = field.NewAsterisk(table) + u.ID = field.NewInt64(table, "id") + u.CreateTime = field.NewTime(table, "create_time") + u.LastUpdateTime = field.NewTime(table, "last_update_time") + u.Name = field.NewString(table, "name") + u.Account = field.NewString(table, "account") + u.Passwd = field.NewString(table, "passwd") + + u.fillFieldMap() + + return u +} + +func (u *user) WithContext(ctx context.Context) *userDo { return u.userDo.WithContext(ctx) } + +func (u user) TableName() string { return u.userDo.TableName() } + +func (u user) Alias() string { return u.userDo.Alias() } + +func (u user) Columns(cols ...field.Expr) gen.Columns { return u.userDo.Columns(cols...) } + +func (u *user) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := u.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (u *user) fillFieldMap() { + u.fieldMap = make(map[string]field.Expr, 6) + u.fieldMap["id"] = u.ID + u.fieldMap["create_time"] = u.CreateTime + u.fieldMap["last_update_time"] = u.LastUpdateTime + u.fieldMap["name"] = u.Name + u.fieldMap["account"] = u.Account + u.fieldMap["passwd"] = u.Passwd +} + +func (u user) clone(db *gorm.DB) user { + u.userDo.ReplaceConnPool(db.Statement.ConnPool) + return u +} + +func (u user) replaceDB(db *gorm.DB) user { + u.userDo.ReplaceDB(db) + return u +} + +type userDo struct{ gen.DO } + +func (u userDo) Debug() *userDo { + return u.withDO(u.DO.Debug()) +} + +func (u userDo) WithContext(ctx context.Context) *userDo { + return u.withDO(u.DO.WithContext(ctx)) +} + +func (u userDo) ReadDB() *userDo { + return u.Clauses(dbresolver.Read) +} + +func (u userDo) WriteDB() *userDo { + return u.Clauses(dbresolver.Write) +} + +func (u userDo) Session(config *gorm.Session) *userDo { + return u.withDO(u.DO.Session(config)) +} + +func (u userDo) Clauses(conds ...clause.Expression) *userDo { + return u.withDO(u.DO.Clauses(conds...)) +} + +func (u userDo) Returning(value interface{}, columns ...string) *userDo { + return u.withDO(u.DO.Returning(value, columns...)) +} + +func (u userDo) Not(conds ...gen.Condition) *userDo { + return u.withDO(u.DO.Not(conds...)) +} + +func (u userDo) Or(conds ...gen.Condition) *userDo { + return u.withDO(u.DO.Or(conds...)) +} + +func (u userDo) Select(conds ...field.Expr) *userDo { + return u.withDO(u.DO.Select(conds...)) +} + +func (u userDo) Where(conds ...gen.Condition) *userDo { + return u.withDO(u.DO.Where(conds...)) +} + +func (u userDo) Order(conds ...field.Expr) *userDo { + return u.withDO(u.DO.Order(conds...)) +} + +func (u userDo) Distinct(cols ...field.Expr) *userDo { + return u.withDO(u.DO.Distinct(cols...)) +} + +func (u userDo) Omit(cols ...field.Expr) *userDo { + return u.withDO(u.DO.Omit(cols...)) +} + +func (u userDo) Join(table schema.Tabler, on ...field.Expr) *userDo { + return u.withDO(u.DO.Join(table, on...)) +} + +func (u userDo) LeftJoin(table schema.Tabler, on ...field.Expr) *userDo { + return u.withDO(u.DO.LeftJoin(table, on...)) +} + +func (u userDo) RightJoin(table schema.Tabler, on ...field.Expr) *userDo { + return u.withDO(u.DO.RightJoin(table, on...)) +} + +func (u userDo) Group(cols ...field.Expr) *userDo { + return u.withDO(u.DO.Group(cols...)) +} + +func (u userDo) Having(conds ...gen.Condition) *userDo { + return u.withDO(u.DO.Having(conds...)) +} + +func (u userDo) Limit(limit int) *userDo { + return u.withDO(u.DO.Limit(limit)) +} + +func (u userDo) Offset(offset int) *userDo { + return u.withDO(u.DO.Offset(offset)) +} + +func (u userDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *userDo { + return u.withDO(u.DO.Scopes(funcs...)) +} + +func (u userDo) Unscoped() *userDo { + return u.withDO(u.DO.Unscoped()) +} + +func (u userDo) Create(values ...*model.User) error { + if len(values) == 0 { + return nil + } + return u.DO.Create(values) +} + +func (u userDo) CreateInBatches(values []*model.User, batchSize int) error { + return u.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (u userDo) Save(values ...*model.User) error { + if len(values) == 0 { + return nil + } + return u.DO.Save(values) +} + +func (u userDo) First() (*model.User, error) { + if result, err := u.DO.First(); err != nil { + return nil, err + } else { + return result.(*model.User), nil + } +} + +func (u userDo) Take() (*model.User, error) { + if result, err := u.DO.Take(); err != nil { + return nil, err + } else { + return result.(*model.User), nil + } +} + +func (u userDo) Last() (*model.User, error) { + if result, err := u.DO.Last(); err != nil { + return nil, err + } else { + return result.(*model.User), nil + } +} + +func (u userDo) Find() ([]*model.User, error) { + result, err := u.DO.Find() + return result.([]*model.User), err +} + +func (u userDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*model.User, err error) { + buf := make([]*model.User, 0, batchSize) + err = u.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (u userDo) FindInBatches(result *[]*model.User, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return u.DO.FindInBatches(result, batchSize, fc) +} + +func (u userDo) Attrs(attrs ...field.AssignExpr) *userDo { + return u.withDO(u.DO.Attrs(attrs...)) +} + +func (u userDo) Assign(attrs ...field.AssignExpr) *userDo { + return u.withDO(u.DO.Assign(attrs...)) +} + +func (u userDo) Joins(fields ...field.RelationField) *userDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Joins(_f)) + } + return &u +} + +func (u userDo) Preload(fields ...field.RelationField) *userDo { + for _, _f := range fields { + u = *u.withDO(u.DO.Preload(_f)) + } + return &u +} + +func (u userDo) FirstOrInit() (*model.User, error) { + if result, err := u.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*model.User), nil + } +} + +func (u userDo) FirstOrCreate() (*model.User, error) { + if result, err := u.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*model.User), nil + } +} + +func (u userDo) FindByPage(offset int, limit int) (result []*model.User, count int64, err error) { + result, err = u.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = u.Offset(-1).Limit(-1).Count() + return +} + +func (u userDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = u.Count() + if err != nil { + return + } + + err = u.Offset(offset).Limit(limit).Scan(result) + return +} + +func (u userDo) Scan(result interface{}) (err error) { + return u.DO.Scan(result) +} + +func (u userDo) Delete(models ...*model.User) (result gen.ResultInfo, err error) { + return u.DO.Delete(models) +} + +func (u *userDo) withDO(do gen.Dao) *userDo { + u.DO = *do.(*gen.DO) + return u +} diff --git a/srv/internal/user/controller.go b/srv/internal/user/controller.go index 236a1b2..07e55b6 100644 --- a/srv/internal/user/controller.go +++ b/srv/internal/user/controller.go @@ -1,50 +1,52 @@ package user import ( + "Crimson-Gatekeeper/internal/common" + "Crimson-Gatekeeper/internal/ero" + "Crimson-Gatekeeper/internal/query" "context" - "errors" "fmt" - "net/http" "github.com/gin-gonic/gin" - "gorm.io/gorm" ) const version = "/api/v1" const group = "/user" type Controller struct { - client *gorm.DB + query *query.Query } -type PostLoginParam struct { +type postLoginParam struct { Account string `json:"account" binding:"required"` Password string `json:"password" binding:"required"` } -func (c *Controller) PostLogin(ctx *gin.Context) { - param := &PostLoginParam{} +func (c *Controller) postLogin(ctx *gin.Context) { + param := &postLoginParam{} if err := ctx.ShouldBindJSON(¶m); err != nil { fmt.Println("参数解析失败,请确认参数是否为 JSON") fmt.Println(err) } - user, err := gorm.G[User](c.client).Where("account = ?", param.Account).First(context.Background()) - if errors.Is(err, gorm.ErrRecordNotFound) { - fmt.Println("没有找到用户") - } else { + u := c.query.User + user, err := u.WithContext(context.Background()).Where(u.Account.Eq(param.Account)).Take() + if err != nil { fmt.Println("查询错误") - panic(err) + common.SetData(ctx, ero.SimpleError("服务器繁忙,请稍后重试")) + } + if user == nil { + fmt.Println("没有找到用户") + return + } + if user.Passwd != param.Password { + fmt.Println("用户密码错误") + return } - fmt.Println("接受参数") - fmt.Println(user) - ctx.JSON(http.StatusOK, gin.H{ - "message": "success", - }) } func (c *Controller) RegisterRoute(gin *gin.Engine) { group := gin.Group(version).Group(group) - group.POST("/login", c.PostLogin) + group.POST("/login", c.postLogin) } // New 获取用户模块的控制器 @@ -54,6 +56,6 @@ func (c *Controller) RegisterRoute(gin *gin.Engine) { // // 返回值 // - Controller 控制器的实例指针 -func New(client *gorm.DB) *Controller { - return &Controller{client} +func New(param *query.Query) *Controller { + return &Controller{param} } diff --git a/srv/internal/user/controller_test.go b/srv/internal/user/controller_test.go index d2cd33b..0545904 100644 --- a/srv/internal/user/controller_test.go +++ b/srv/internal/user/controller_test.go @@ -2,6 +2,7 @@ package user_test import ( "Crimson-Gatekeeper/internal/common" + "Crimson-Gatekeeper/internal/query" "Crimson-Gatekeeper/internal/user" "bytes" "encoding/json" @@ -14,16 +15,14 @@ import ( ) func TestLogin(t *testing.T) { - client, close := common.GetDataBaseClient() - defer close() - + client, clean := common.GetDataBaseClient() + defer clean() gin.SetMode(gin.TestMode) app := gin.Default() - user.New(client).RegisterRoute(app) - + user.New(query.Use(client)).RegisterRoute(app) w := httptest.NewRecorder() param := gin.H{ - "account": "admin", + "account": "admin1", "password": "123445", } data, ero := json.Marshal(param) diff --git a/srv/internal/user/entity.go b/srv/internal/user/entity.go deleted file mode 100644 index d1949c6..0000000 --- a/srv/internal/user/entity.go +++ /dev/null @@ -1,14 +0,0 @@ -package user - -import ( - "time" -) - -type User struct { - Id int64 - CreateTime time.Time - LastUpdateTime time.Time - Name string - Account string - Passwd string -} diff --git a/srv/internal/user/service.go b/srv/internal/user/service.go new file mode 100644 index 0000000..9c01ce1 --- /dev/null +++ b/srv/internal/user/service.go @@ -0,0 +1,25 @@ +package user + +import ( + "Crimson-Gatekeeper/internal/model" + "Crimson-Gatekeeper/internal/query" + "sync" + "time" +) + +// loginInfo 储存用户的登录状态 +type loginInfo struct { + // user 信息指针 + user *model.User + // invalidation 失效时间,此事件之后,该数据应该失效且被删除 + invalidation time.Time +} + +var loginIn = sync.Map{} + +type Service struct { + c *query.Query +} + +func (s *Service) login(user *model.User) error { +} diff --git a/srv/tools/gorm_generate/main.go b/srv/tools/gorm_generate/main.go new file mode 100644 index 0000000..762861b --- /dev/null +++ b/srv/tools/gorm_generate/main.go @@ -0,0 +1,27 @@ +package main + +import ( + "Crimson-Gatekeeper/internal/common" + "fmt" + + "gorm.io/gen" +) + +func main() { + client, clean := common.GetDataBaseClient() + defer func() { + err := clean() + if err != nil { + fmt.Println("关闭数据库链接失败") + } + }() + g := gen.NewGenerator(gen.Config{ + OutPath: "./internal/query", + ModelPkgPath: "./internal/model", + Mode: gen.WithDefaultQuery, + FieldNullable: true, + }) + g.UseDB(client) + g.ApplyBasic(g.GenerateAllTable()...) + g.Execute() +}