diff --git a/README.md b/README.md index b493358..921e412 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ 16. 插件应用:支持一键生成插件模板,每个插件之间开发隔离,拥有独立多应用入口、独立配置。完美支持多人协同开发、插件插拔不会对原系统产生影响等。 17. 服务监控:监视当前系统CPU、内存、磁盘、网络、堆栈等相关信息。 18. 附件管理:文件图片上传,支持本地、阿里云oss、腾讯云cos、ucloud对象存储、七牛云对象存储等多种上传驱动,后台一键切换配置。 -19. TCP服务:基于gtcp的应用化实例,支持长连接、断线重连、自动维护心跳、服务登录、服务授权等。主要用于网络服务进程之间的消息通讯。 +19. TCP服务:基于gtcp的应用实例,支持长连接、断线重连、自动维护心跳、签名、服务登录、服务授权等。主要用于C/S服务器和服务进程之间的数据通讯。 20. 消息队列:同时兼容 kafka、redis、rocketmq、磁盘队列,一键配置切换到场景适用的MQ。 21. 通知公告:采用websocket实时推送在线用户最新通知、公告、私信消息。 22. 地区编码:整合国内通用省市区编码,运用于项目于一身,支持动态省市区选项。 diff --git a/docs/guide-zh-CN/README.md b/docs/guide-zh-CN/README.md index 3998cdf..b9291e9 100644 --- a/docs/guide-zh-CN/README.md +++ b/docs/guide-zh-CN/README.md @@ -16,7 +16,8 @@ - [目录结构](sys-catalog.md) - [开发规范](sys-exploit.md) - [控制台](sys-console.md) -- 请求中间件和WebHook +- [中间件/拦截器](sys-middleware.md) +- [WebHook](sys-webhook.md) - [权限控制](sys-auth.md) - [支付网关](sys-payment.md) - [数据库](sys-db.md) diff --git a/docs/guide-zh-CN/images/sys-middleware-error-log.png b/docs/guide-zh-CN/images/sys-middleware-error-log.png new file mode 100644 index 0000000..224dfb5 Binary files /dev/null and b/docs/guide-zh-CN/images/sys-middleware-error-log.png differ diff --git a/docs/guide-zh-CN/sys-console.md b/docs/guide-zh-CN/sys-console.md index 9c9f641..83e7806 100644 --- a/docs/guide-zh-CN/sys-console.md +++ b/docs/guide-zh-CN/sys-console.md @@ -13,6 +13,7 @@ - 仅推荐在开发期间快速调试使用,线上实际部署时建议将各个服务分开部署,这样重新部署某个服务时无需全部重启。 ```shell + # 默认 go run main.go @@ -22,6 +23,7 @@ gf run main.go ### HTTP服务 - 启动HTTP服务,包含websocket。 + ```shell # 默认 go run main.go http @@ -41,7 +43,7 @@ go run main.go queue gf run main.go --args "queue" ``` -### 定时任务(暂未拆分,目前随HTTP服务启动) +### 定时任务 - 启动系统中统一注册的定时任务。 ```shell @@ -55,6 +57,8 @@ gf run main.go --args "cron" ### 常用工具 - 释放casbin权限,用于清理无效的权限设置。 + + ```shell go run main.go tools -m=casbin -a1=refresh ``` @@ -62,6 +66,7 @@ go run main.go tools -m=casbin -a1=refresh ### Makefile - 通过make提供一些快捷命令 + ```shell # 一键编译,打包前后端代码到可执行文件 make build diff --git a/docs/guide-zh-CN/sys-middleware.md b/docs/guide-zh-CN/sys-middleware.md new file mode 100644 index 0000000..95498d3 --- /dev/null +++ b/docs/guide-zh-CN/sys-middleware.md @@ -0,0 +1,204 @@ +## 中间件/拦截器 + +目录 + +- 介绍 +- 全局中间件 +- 鉴权中间件 +- 响应中间件 +- 更多 + +### 介绍 +- 在hotgo中,中间件/拦截器主要作用于web请求的上下文预设、跨域请求处理、鉴权处理、请求拦截和请求结束后统一响应处理等。 + + +### 全局中间件 +```go +package main + +import ( + "hotgo/internal/service" +) + +func main() { + + // 初始化请求上下文,一般需要第一个进行加载,后续中间件存在依赖关系 + service.Middleware().Ctx() + + // 跨域中间件,自动处理跨域问题 + service.Middleware().CORS() + + // IP黑名单中间件,如果请求IP被后台拉黑,所有请求将被拒绝 + service.Middleware().Blacklist() + + // 演示系統操作限制,当开启演示模式时,所有POST请求将被拒绝 + service.Middleware().DemoLimit() + + // HTTP响应预处理,在业务处理完成后,对响应结果进行格式化和错误过滤,将处理后的数据发送给请求方 + service.Middleware().ResponseHandler() + +} + +``` +### 鉴权中间件 +```go +package main + +import ( + "github.com/gogf/gf/v2/frame/g" +) + +func main() { + + // 在鉴权中间件下的路由如果没有通过权限验证,后续请求将被拒绝 + // 在hotgo中,鉴权中间件一般是配合一个业务模块下的路由组进行使用 + // 目前admin、api、home、websocket模块都已接入 + // 如果你需要创建一个新的模块也需要用到鉴权中间件,可以参考:server/internal/logic/middleware/admin_auth.go + + + // 一个简单例子 + s := g.Server() + s.Group("/api", func(group *ghttp.RouterGroup) { + group.Middleware(service.Middleware().ApiAuth) + group.Bind( + member.Member, // 管理员 + ) + }) + +} + +``` + +### 响应中间件 +- 文件路径:server/internal/logic/middleware/response.go + + +#### 自定义响应 +- 由于响应中间件是全局的,并且是统一使用json格式进行响应的,但是在实际的开发中可能存在一些需要使用非json格式的响应,所以你需要进行单独的处理。 +- 推荐以下几种处理方式,可做参考: +1. 使用`ghttp.ExitAll()`,需要注意的是此方法会终止后续所有的http处理 + +```go +package main + +import ( + "github.com/gogf/gf/v2/net/ghttp" +) + +func main() { + r := new(ghttp.Request) // 当前请求对象 + + // 清空响应 + r.Response.ClearBuffer() + + // 写入响应 + r.Response.Write("自定义响应内容") + + // 终止后续http处理 + r.ExitAll() +} +``` + +2. 在`server/internal/logic/middleware/response.go`中根据请求的独有特征进行单独的处理,兼容后续http处理。 + + +#### 重写响应错误提示 + +- 在实际开发中,我们可能想要隐藏一些敏感错误,返回给客户端友好的错误提示,但开发者同时又想需要看到真实的敏感错误。对此hotgo已经进行了过滤处理,下面是一个简单的例子: + +```go +package main + +import ( + "github.com/gogf/gf/v2/errors/gerror" +) + +func test() error { + err = gerror.New("这是一个sql执行错误") + err = gerror.Wrap(err, "用户创建失败,请稍后重试!~") + return err +} +``` + +- 开启debug时的客户端响应: +```json +{ + "code": -1, + "message": "用户创建失败,请稍后重试!~", + "error": [ + "1. 用户创建失败,请稍后重试!~", + " 1). hotgo/internal/logic/admin.(*sAdminMember).List", + " E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/admin/member.go:526", + "2. 这是一个sql执行错误", " 1). hotgo/internal/logic/admin.(*sAdminMember).List", + " E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/admin/member.go:525", + " 2). hotgo/internal/controller/admin/admin.(*cMember).List", + " E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/controller/admin/admin/member.go:157", " 3). github.com/gogf/gf/v2/net/ghttp.(*middleware).callHandlerFunc.func1", " E:/gopath/pkg/mod/github.com/gogf/gf/v2@v2.4.1/net/ghttp/ghttp_request_middleware.go:152", " 4). github.com/gogf/gf/v2/net/ghttp.niceCallFunc", " E:/gopath/pkg/mod/github.com/gogf/gf/v2@v2.4.1/net/ghttp/ghttp_func.go:55", " 5). github.com/gogf/gf/v2/net/ghttp.(*middleware).callHandlerFunc", " E:/gopath/pkg/mod/github.com/gogf/gf/v2@v2.4.1/net/ghttp/ghttp_request_middleware.go:129", " 6). github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1", " E:/gopath/pkg/mod/github.com/gogf/gf/v2@v2.4.1/net/ghttp/ghttp_request_middleware.go:75", " 7). github.com/gogf/gf/v2/util/gutil.TryCatch", " E:/gopath/pkg/mod/github.com/gogf/gf/v2@v2.4.1/util/gutil/gutil.go:56", " 8). github.com/gogf/gf/v2/net/ghttp.(*middleware).Next", " E:/gopath/pkg/mod/github.com/gogf/gf/v2@v2.4.1/net/ghttp/ghttp_request_middleware.go:49", " 9). hotgo/internal/logic/middleware.(*sMiddleware).AdminAuth", " E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/middleware/admin_auth.go:53", " 10). github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1.1", " E:/gopath/pkg/mod/github.com/gogf/gf/v2@v2.4.1/net/ghttp/ghttp_request_middleware.go:55", " 11). github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1", " E:/gopath/pkg/mod/github.com/gogf/gf/v2@v2.4.1/net/ghttp/ghttp_request_middleware.go:54", " 12). hotgo/internal/logic/middleware.(*sMiddleware).ResponseHandler", " E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/middleware/response.go:24", " 13). hotgo/internal/logic/middleware.(*sMiddleware).DemoLimit", " E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/middleware/init.go:90", " 14). hotgo/internal/logic/middleware.(*sMiddleware).Blacklist", " E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/middleware/limit_blacklist.go:22", " 15). hotgo/internal/logic/middleware.(*sMiddleware).CORS", " E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/middleware/init.go:83", " 16). hotgo/internal/logic/middleware.(*sMiddleware).Ctx", " E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/middleware/init.go:62", " 17). github.com/gogf/gf/v2/net/ghttp.internalMiddlewareServerTracing", " E:/gopath/pkg/mod/github.com/gogf/gf/v2@v2.4.1/net/ghttp/ghttp_middleware_tracing.go:79", " 18). github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1.5", " E:/gopath/pkg/mod/github.com/gogf/gf/v2@v2.4.1/net/ghttp/ghttp_request_middleware.go:96", " 19). github.com/gogf/gf/v2/net/ghttp.(*middleware).Next.func1", " E:/gopath/pkg/mod/github.com/gogf/gf/v2@v2.4.1/net/ghttp/ghttp_request_middleware.go:95", " 20). github.com/gogf/gf/v2/net/ghttp.(*Server).ServeHTTP", " E:/gopath/pkg/mod/github.com/gogf/gf/v2@v2.4.1/net/ghttp/ghttp_server_handler.go:132", "" + ], + "timestamp": 1684145107, + "traceID": "084022730d495f17f19e550140f3e1a8" +} +``` + +- 关闭debug时的客户端响应: +```json +{ + "code": -1, + "message": "用户创建失败,请稍后重试!~", + "timestamp": 1684145107, + "traceID": "084022730d495f17f19e550140f3e1a8" +} +``` + +- 控制台的输出日志: +```shell +2023-05-15 18:05:07.776 {084022730d495f17f19e550140f3e1a8} 200 "GET http localhost:8000 /admin/member/list?page=1&pageSize=10&roleId=-1 HTTP/1.1" 0.002, 127.0.0.1, "http://192.168.0.207:8001/login", "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.71 Safari/537.36 Co +re/1.94.197.400 QQBrowser/11.7.5287.400", -1, "", "" +Stack: +1. 用户创建失败,请稍后重试!~ + 1). hotgo/internal/logic/admin.(*sAdminMember).List + E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/admin/member.go:526 +2. 这是一个sql执行错误 + 1). hotgo/internal/logic/admin.(*sAdminMember).List + E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/middleware/response.go:24 + 13). hotgo/internal/logic/middleware.(*sMiddleware).DemoLimit + E:/Users/Administrator/Desktop/gosrc/hotgo_dev/server/internal/logic/middleware/init.go:90 + +``` + +- 如果你开启了访问日志,那么日志记录中会详细记录本次请求的相关信息,内容如下: +![./images/sys-middleware-error-log.png](./images/sys-middleware-error-log.png) + + +#### 重写错误码 +- hotgo默认使用了gf内置的错误码进行业务处理,通常情况下成功状态码为`0`,失败状态码为`-1` +- 查看gf内置错误码:https://goframe.org/pages/viewpage.action?pageId=30739587 +- 以下是自定义错误码的简单例子: + +```go +package main + +import ( + "github.com/gogf/gf/v2/errors/gerror" +) + +func test() error { + // 使用自定义状态码30001响应客户端 + err = gerror.NewCode(gcode.New(30001, "用户创建失败,请稍后重试!~", nil)) + return err +} +``` + + +- 客户端响应如下: +```json +{ + "code": 30001, + "message": "用户创建失败,请稍后重试!~", + "timestamp": 1684146313, + "traceID": "b4f90e16264a5f17cd3fc27141aba448" +} +``` + +### 更多 +- 更多关于中间件/拦截器的介绍请参考:https://goframe.org/pages/viewpage.action?pageId=55289881 + diff --git a/docs/guide-zh-CN/sys-webhook.md b/docs/guide-zh-CN/sys-webhook.md new file mode 100644 index 0000000..c8adf35 --- /dev/null +++ b/docs/guide-zh-CN/sys-webhook.md @@ -0,0 +1,3 @@ +## WebHook + +待写 diff --git a/server/internal/cmd/auth.go b/server/internal/cmd/auth.go index fe13cb0..e71b385 100644 --- a/server/internal/cmd/auth.go +++ b/server/internal/cmd/auth.go @@ -7,9 +7,9 @@ package cmd import ( "context" + "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gcmd" "hotgo/internal/service" - "os" ) var ( @@ -20,17 +20,17 @@ var ( Func: func(ctx context.Context, parser *gcmd.Parser) (err error) { service.AuthClient().Start(ctx) - // 退出信号监听 - signalListen(ctx, func(sig os.Signal) { - service.AuthClient().Stop(ctx) - }) + serverWg.Add(1) // 信号监听 signalListen(ctx, signalHandlerForOverall) select { case <-serverCloseSignal: - // ... + service.AuthClient().Stop(ctx) + serverWg.Done() } + + g.Log().Debug(ctx, "auth successfully closed ..") return }, } diff --git a/server/internal/cmd/cmd.go b/server/internal/cmd/cmd.go index 5555c4a..d2cf16e 100644 --- a/server/internal/cmd/cmd.go +++ b/server/internal/cmd/cmd.go @@ -13,8 +13,7 @@ import ( ) var ( - serverCloseSignal chan struct{} - Main = &gcmd.Command{ + Main = &gcmd.Command{ Description: `默认启动所有服务`, Func: func(ctx context.Context, parser *gcmd.Parser) (err error) { return All.Func(ctx, parser) @@ -76,10 +75,10 @@ var ( select { case <-serverCloseSignal: - // ... + serverWg.Wait() } - g.Log().Debug(ctx, "service successfully closed ..") + g.Log().Debug(ctx, "all service successfully closed ..") return }, } @@ -89,5 +88,4 @@ func init() { if err := Main.AddCommand(All, Http, Queue, Cron, Auth, Tools, Help); err != nil { panic(err) } - serverCloseSignal = make(chan struct{}, 1) } diff --git a/server/internal/cmd/cron.go b/server/internal/cmd/cron.go index c8bfc0c..891e496 100644 --- a/server/internal/cmd/cron.go +++ b/server/internal/cmd/cron.go @@ -7,10 +7,10 @@ package cmd import ( "context" + "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gcmd" "hotgo/internal/crons" "hotgo/internal/service" - "os" ) var ( @@ -25,17 +25,18 @@ var ( // tcp客户端 service.CronClient().Start(ctx) - // 退出信号监听 - signalListen(ctx, func(sig os.Signal) { - service.CronClient().Stop(ctx) - crons.StopALL() - serverCloseSignal <- struct{}{} - }) + serverWg.Add(1) + // 信号监听 + signalListen(ctx, signalHandlerForOverall) select { case <-serverCloseSignal: - // ... + service.CronClient().Stop(ctx) + crons.StopALL() + serverWg.Done() } + + g.Log().Debug(ctx, "cron successfully closed ..") return }, } diff --git a/server/internal/cmd/handler_shutdown.go b/server/internal/cmd/handler_shutdown.go index bcdd9e2..3de2130 100644 --- a/server/internal/cmd/handler_shutdown.go +++ b/server/internal/cmd/handler_shutdown.go @@ -3,7 +3,6 @@ // @Copyright Copyright (c) 2023 HotGo CLI // @Author Ms <133814250@qq.com> // @License https://github.com/bufanyun/hotgo/blob/master/LICENSE -// package cmd import ( @@ -11,6 +10,12 @@ import ( "github.com/gogf/gf/v2/os/gproc" "hotgo/utility/simple" "os" + "sync" +) + +var ( + serverCloseSignal = make(chan struct{}, 1) + serverWg = sync.WaitGroup{} ) func signalHandlerForOverall(sig os.Signal) { diff --git a/server/internal/cmd/http.go b/server/internal/cmd/http.go index dbad3e5..b85025e 100644 --- a/server/internal/cmd/http.go +++ b/server/internal/cmd/http.go @@ -10,13 +10,11 @@ import ( "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gcmd" - "hotgo/internal/crons" "hotgo/internal/library/addons" "hotgo/internal/library/casbin" "hotgo/internal/router" "hotgo/internal/service" "hotgo/internal/websocket" - "os" ) var ( @@ -77,13 +75,20 @@ var ( // https setSSL(ctx, s) - // 退出信号监听 - signalListen(ctx, func(sig os.Signal) { - s.Shutdown() - crons.StopALL() - websocket.Stop() - service.TCPServer().Stop(ctx) - }) + serverWg.Add(1) + + // 信号监听 + signalListen(ctx, signalHandlerForOverall) + go func() { + select { + case <-serverCloseSignal: + websocket.Stop() + service.TCPServer().Stop(ctx) + s.Shutdown() // 主服务建议放在最后一个关闭 + g.Log().Debug(ctx, "http successfully closed ..") + serverWg.Done() + } + }() // Just run the server. s.Run() diff --git a/server/internal/cmd/queue.go b/server/internal/cmd/queue.go index 8972d1a..b8c9c12 100644 --- a/server/internal/cmd/queue.go +++ b/server/internal/cmd/queue.go @@ -25,12 +25,14 @@ var ( g.Log().Debug(ctx, "start queue consumer success..") }) + serverWg.Add(1) + // 信号监听 signalListen(ctx, signalHandlerForOverall) select { case <-serverCloseSignal: - // ... + serverWg.Done() } g.Log().Debug(ctx, "queue successfully closed ..") diff --git a/server/internal/consts/config.go b/server/internal/consts/config.go index 4039745..7c9c80d 100644 --- a/server/internal/consts/config.go +++ b/server/internal/consts/config.go @@ -7,7 +7,9 @@ package consts import "github.com/gogf/gf/v2/util/gconv" -// RequestEncryptKey 请求加密密钥用于敏感数据加密,16位字符,前后端需保持一致。安全起见请修改此值 +// RequestEncryptKey +// 请求加密密钥用于敏感数据加密,16位字符,前后端需保持一致 +// 安全起见,生产环境运行时请注意修改 var RequestEncryptKey = []byte("f080a463654b2279") // 配置数据类型 diff --git a/server/internal/library/addons/build.go b/server/internal/library/addons/build.go index 974a1ba..2abc077 100644 --- a/server/internal/library/addons/build.go +++ b/server/internal/library/addons/build.go @@ -27,6 +27,7 @@ func Build(ctx context.Context, sk Skeleton, conf *model.BuildAddonConfig) (err "@{.description}": sk.Description, "@{.author}": sk.Author, "@{.version}": sk.Version, + "@{.hgVersion}": consts.VersionApp, // HG 版本 } ) diff --git a/server/internal/library/network/tcp/client.go b/server/internal/library/network/tcp/client.go index c55dd37..aa5fe7d 100644 --- a/server/internal/library/network/tcp/client.go +++ b/server/internal/library/network/tcp/client.go @@ -195,7 +195,9 @@ func (client *Client) connect() { reconnect: conn := client.dial() if conn == nil { - client.Logger.Debugf(client.Ctx, "client dial failed") + if !client.stopFlag { + client.Logger.Debugf(client.Ctx, "client dial failed") + } return } @@ -311,6 +313,11 @@ func (client *Client) Stop() { client.Close() } +// IsStop 是否已停止 +func (client *Client) IsStop() bool { + return client.stopFlag +} + // Destroy 销毁当前连接 func (client *Client) Destroy() { client.stopCron() diff --git a/server/internal/library/network/tcp/server.go b/server/internal/library/network/tcp/server.go index 47fa078..a0df114 100644 --- a/server/internal/library/network/tcp/server.go +++ b/server/internal/library/network/tcp/server.go @@ -294,6 +294,11 @@ func (server *Server) Close() { server.wgLn.Wait() } +// IsClose 服务是否关闭 +func (server *Server) IsClose() bool { + return server.closeFlag +} + // Write 向指定客户端发送消息 func (server *Server) Write(conn *gtcp.Conn, data interface{}) (err error) { if server.closeFlag { diff --git a/server/internal/library/token/token.go b/server/internal/library/token/token.go index e8e513f..1869629 100644 --- a/server/internal/library/token/token.go +++ b/server/internal/library/token/token.go @@ -99,6 +99,8 @@ func Logout(r *ghttp.Request) (err error) { claims, err := parseToken(ctx, header) if err != nil { + g.Log().Debugf(ctx, "logout parseToken err:%+v", err) + err = errorLogin return } @@ -138,10 +140,13 @@ func ParseLoginUser(r *ghttp.Request) (user *model.Identity, err error) { claims, err := parseToken(ctx, header) if err != nil { + g.Log().Debugf(ctx, "parseToken err:%+v", err) + err = errorLogin return } var ( + // 认证key authKey = GetAuthKey(header) // 登录token tokenKey = GetTokenKey(claims.App, authKey) @@ -285,7 +290,7 @@ func GetAuthorization(r *ghttp.Request) string { // GetAuthKey 认证key func GetAuthKey(token string) string { - return gmd5.MustEncryptString(token) + return gmd5.MustEncryptString("hotgo" + token) } // GetTokenKey 令牌缓存key diff --git a/server/internal/logic/admin/member.go b/server/internal/logic/admin/member.go index e1efa79..d73d408 100644 --- a/server/internal/logic/admin/member.go +++ b/server/internal/logic/admin/member.go @@ -227,18 +227,18 @@ func (s *sAdminMember) UpdateMobile(ctx context.Context, in adminin.MemberUpdate return err } - var memberInfo *entity.AdminMember - if err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Scan(&memberInfo); err != nil { + var mb *entity.AdminMember + if err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Scan(&mb); err != nil { err = gerror.Wrap(err, consts.ErrorORM) return err } - if memberInfo == nil { + if mb == nil { err = gerror.New("用户信息不存在") return err } - if memberInfo.Mobile == in.Mobile { + if mb.Mobile == in.Mobile { err = gerror.New("新旧手机号不能一样") return } @@ -249,10 +249,10 @@ func (s *sAdminMember) UpdateMobile(ctx context.Context, in adminin.MemberUpdate } // 存在原绑定号码,需要进行验证 - if memberInfo.Mobile != "" { + if mb.Mobile != "" { err = service.SysSmsLog().VerifyCode(ctx, sysin.VerifyCodeInp{ Event: consts.SmsTemplateBind, - Mobile: memberInfo.Mobile, + Mobile: mb.Mobile, Code: in.Code, }) if err != nil { @@ -264,8 +264,7 @@ func (s *sAdminMember) UpdateMobile(ctx context.Context, in adminin.MemberUpdate dao.AdminMember.Columns().Mobile: in.Mobile, } - _, err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Data(update).Update() - if err != nil { + if _, err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Data(update).Update(); err != nil { err = gerror.Wrap(err, consts.ErrorORM) return err } @@ -281,13 +280,13 @@ func (s *sAdminMember) UpdateProfile(ctx context.Context, in adminin.MemberUpdat return err } - var memberInfo *entity.AdminMember - if err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Scan(&memberInfo); err != nil { + var mb *entity.AdminMember + if err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Scan(&mb); err != nil { err = gerror.Wrap(err, consts.ErrorORM) return err } - if memberInfo == nil { + if mb == nil { err = gerror.New("用户信息不存在") return err } @@ -302,8 +301,7 @@ func (s *sAdminMember) UpdateProfile(ctx context.Context, in adminin.MemberUpdat dao.AdminMember.Columns().Address: in.Address, } - _, err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Data(update).Update() - if err != nil { + if _, err = dao.AdminMember.Ctx(ctx).Where("id", memberId).Data(update).Update(); err != nil { err = gerror.Wrap(err, consts.ErrorORM) return err } @@ -718,7 +716,9 @@ func (s *sAdminMember) MemberLoginStat(ctx context.Context, in adminin.MemberLog // GetIdByCode 通过邀请码获取用户ID func (s *sAdminMember) GetIdByCode(ctx context.Context, in adminin.GetIdByCodeInp) (res *adminin.GetIdByCodeModel, err error) { - err = dao.AdminMember.Ctx(ctx).Fields(adminin.GetIdByCodeModel{}).Where("invite_code", in.Code).Scan(&res) + if err = dao.AdminMember.Ctx(ctx).Fields(adminin.GetIdByCodeModel{}).Where("invite_code", in.Code).Scan(&res); err != nil { + err = gerror.Wrap(err, consts.ErrorORM) + } return } @@ -728,6 +728,9 @@ func (s *sAdminMember) Select(ctx context.Context, in adminin.MemberSelectInp) ( Fields("id as value,real_name as label,username,avatar"). Handler(handler.FilterAuthWithField("id")). Scan(&res) + if err != nil { + err = gerror.Wrap(err, consts.ErrorORM) + } return } diff --git a/server/internal/logic/admin/site.go b/server/internal/logic/admin/site.go index 082c734..3172c2e 100644 --- a/server/internal/logic/admin/site.go +++ b/server/internal/logic/admin/site.go @@ -12,7 +12,6 @@ import ( "hotgo/internal/dao" "hotgo/internal/library/token" "hotgo/internal/model" - "hotgo/internal/model/do" "hotgo/internal/model/entity" "hotgo/internal/model/input/adminin" "hotgo/internal/model/input/sysin" @@ -255,16 +254,6 @@ func (s *sAdminSite) handleLogin(ctx context.Context, mb *entity.AdminMember) (r return nil, err } - update := do.AdminMember{ - LastActiveAt: user.LoginAt, - } - - // 更新登录信息 - if _, err = dao.AdminMember.Ctx(ctx).Data(update).Where(do.AdminMember{Id: mb.Id}).Update(); err != nil { - err = gerror.Wrap(err, consts.ErrorORM) - return - } - res = &adminin.LoginModel{ Username: user.Username, Id: user.Id, diff --git a/server/internal/logic/hook/access_log.go b/server/internal/logic/hook/access_log.go index 314d86b..0ea56db 100644 --- a/server/internal/logic/hook/access_log.go +++ b/server/internal/logic/hook/access_log.go @@ -20,9 +20,9 @@ func (s *sHook) accessLog(r *ghttp.Request) { if r.IsFileRequest() { return } + var ctx = contexts.Detach(r.Context()) - modelCtx := contexts.Get(ctx) - if modelCtx == nil { + if contexts.Get(ctx) == nil { return } diff --git a/server/internal/logic/hook/last_active.go b/server/internal/logic/hook/last_active.go index e05b275..84ea7d0 100644 --- a/server/internal/logic/hook/last_active.go +++ b/server/internal/logic/hook/last_active.go @@ -79,7 +79,6 @@ func (s *sHook) lastAdminActive(r *ghttp.Request) { _, err := g.Model("admin_member"). Ctx(ctx). Where("id", member.Id). - WhereLT("last_active_at", gtime.Now()). Data(g.Map{"last_active_at": gtime.Now()}). Update() if err != nil { diff --git a/server/internal/logic/middleware/response.go b/server/internal/logic/middleware/response.go index ede181f..149030a 100644 --- a/server/internal/logic/middleware/response.go +++ b/server/internal/logic/middleware/response.go @@ -101,16 +101,16 @@ func responseJson(r *ghttp.Request) { if err = r.GetError(); err != nil { // 记录到自定义错误日志文件 - g.Log().Warningf(ctx, "exception:%v", err) + g.Log().Stdout(false).Printf(ctx, "exception:%v", err) code = gerror.Code(err).Code() // 是否输出错误到页面 if g.Cfg().MustGet(ctx, "hotgo.debug", true).Bool() { - message = err.Error() + message = gerror.Current(err).Error() data = charset.ParseErrStack(err) } else { - message = consts.ErrorMessage(err) + message = consts.ErrorMessage(gerror.Current(err)) } } else { data = r.GetHandlerResponse() diff --git a/server/internal/logic/sys/log.go b/server/internal/logic/sys/log.go index 08e346d..0dec417 100644 --- a/server/internal/logic/sys/log.go +++ b/server/internal/logic/sys/log.go @@ -105,7 +105,7 @@ func (s *sSysLog) AutoLog(ctx context.Context) error { var err error defer func() { if err != nil { - panic(err) + g.Log().Error(ctx, "autoLog err:%+v", err) } }() diff --git a/server/internal/logic/tcpclient/auth.go b/server/internal/logic/tcpclient/auth.go index 768dea4..84317c8 100644 --- a/server/internal/logic/tcpclient/auth.go +++ b/server/internal/logic/tcpclient/auth.go @@ -75,7 +75,7 @@ func (s *sAuthClient) Start(ctx context.Context) { // Stop 停止服务 func (s *sAuthClient) Stop(ctx context.Context) { - if s.client != nil { + if s.client != nil && !s.client.IsStop() { s.client.Stop() g.Log().Debug(ctx, "AuthClient stop..") } diff --git a/server/internal/logic/tcpclient/cron.go b/server/internal/logic/tcpclient/cron.go index 55dcb73..eff8ae5 100644 --- a/server/internal/logic/tcpclient/cron.go +++ b/server/internal/logic/tcpclient/cron.go @@ -76,7 +76,7 @@ func (s *sCronClient) Start(ctx context.Context) { // Stop 停止服务 func (s *sCronClient) Stop(ctx context.Context) { - if s.client != nil { + if s.client != nil && !s.client.IsStop() { s.client.Stop() g.Log().Debug(ctx, "CronClient stop..") } diff --git a/server/internal/logic/tcpserver/server.go b/server/internal/logic/tcpserver/server.go index 3b2462c..a3cff17 100644 --- a/server/internal/logic/tcpserver/server.go +++ b/server/internal/logic/tcpserver/server.go @@ -53,15 +53,17 @@ func (s *sTCPServer) Start(ctx context.Context) { }) // 服务监听 - if err := s.serv.Listen(); err != nil { - g.Log().Warningf(ctx, "TCPServer Listen err:%v", err) + if err = s.serv.Listen(); err != nil { + if !s.serv.IsClose() { + g.Log().Warningf(ctx, "TCPServer Listen err:%v", err) + } } }) } // Stop 关闭服务 func (s *sTCPServer) Stop(ctx context.Context) { - if s.serv != nil { + if s.serv != nil && !s.serv.IsClose() { s.serv.Close() g.Log().Debug(ctx, "TCPServer stop..") } diff --git a/server/internal/model/input/adminin/site.go b/server/internal/model/input/adminin/site.go index c061442..c21e87a 100644 --- a/server/internal/model/input/adminin/site.go +++ b/server/internal/model/input/adminin/site.go @@ -2,11 +2,9 @@ package adminin import ( "context" - "github.com/gogf/gf/v2/encoding/gbase64" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gtime" - "hotgo/internal/consts" - "hotgo/utility/encrypt" + "hotgo/utility/simple" ) // RegisterInp 账号注册 @@ -20,18 +18,11 @@ type RegisterInp struct { func (in *RegisterInp) Filter(ctx context.Context) (err error) { // 解密密码 - str, err := gbase64.Decode([]byte(in.Password)) + password, err := simple.DecryptText(in.Password) if err != nil { return err } - str, err = encrypt.AesECBDecrypt(str, consts.RequestEncryptKey) - if err != nil { - return err - } - - password := string(str) - if err = g.Validator().Data(password).Rules("password").Messages("密码长度在6~18之间").Run(ctx); err != nil { return } diff --git a/server/resource/generate/default/addon/README.MD.template b/server/resource/generate/default/addon/README.MD.template index b054efe..6d9080b 100644 --- a/server/resource/generate/default/addon/README.MD.template +++ b/server/resource/generate/default/addon/README.MD.template @@ -12,7 +12,7 @@ ### 迁移或安装 -1、安装 HotGo (2.1.4及以上) +1、安装 HotGo (@{.hgVersion}及以上) 项目介绍:https://github.com/bufanyun/hotgo diff --git a/server/utility/simple/simple.go b/server/utility/simple/simple.go index 4bc2f5d..7551ad5 100644 --- a/server/utility/simple/simple.go +++ b/server/utility/simple/simple.go @@ -18,20 +18,30 @@ import ( "hotgo/utility/encrypt" ) +// DecryptText 解密文本 +func DecryptText(text string) (string, error) { + str, err := gbase64.Decode([]byte(text)) + if err != nil { + return "", err + } + + str, err = encrypt.AesECBDecrypt(str, consts.RequestEncryptKey) + if err != nil { + return "", err + } + + return string(str), nil +} + // CheckPassword 检查密码 func CheckPassword(input, salt, hash string) (err error) { // 解密密码 - password, err := gbase64.Decode([]byte(input)) + password, err := DecryptText(input) if err != nil { return err } - password, err = encrypt.AesECBDecrypt(password, consts.RequestEncryptKey) - if err != nil { - return err - } - - if hash != gmd5.MustEncryptString(string(password)+salt) { + if hash != gmd5.MustEncryptString(password+salt) { err = gerror.New("用户密码不正确") return } diff --git a/web/src/components/Editor/editor.vue b/web/src/components/Editor/editor.vue index c68ba75..062db48 100644 --- a/web/src/components/Editor/editor.vue +++ b/web/src/components/Editor/editor.vue @@ -1,6 +1,6 @@