From f80fe6d0415a74f84ce5bf6b979cc80ef70c5321 Mon Sep 17 00:00:00 2001 From: chenzifan Date: Tue, 12 Mar 2024 18:06:49 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E7=AE=A1=E7=90=86=E5=91=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/core/config.go | 1 - api/core/types/config.go | 9 ---- api/handler/admin/admin_handler.go | 76 +++++++++++++++++++++--------- api/main.go | 18 +++---- api/store/vo/admin_user.go | 1 - 5 files changed, 62 insertions(+), 43 deletions(-) diff --git a/api/core/config.go b/api/core/config.go index bf8a1e63..5447542e 100644 --- a/api/core/config.go +++ b/api/core/config.go @@ -16,7 +16,6 @@ func NewDefaultConfig() *types.AppConfig { return &types.AppConfig{ Listen: "0.0.0.0:5678", ProxyURL: "", - Manager: types.Manager{Username: "admin", Password: "admin123"}, StaticDir: "./static", StaticUrl: "http://localhost/5678/static", Redis: types.RedisConfig{Host: "localhost", Port: 6379, Password: ""}, diff --git a/api/core/types/config.go b/api/core/types/config.go index 2acf2856..1352a1a5 100644 --- a/api/core/types/config.go +++ b/api/core/types/config.go @@ -10,7 +10,6 @@ type AppConfig struct { Session Session ProxyURL string MysqlDns string // mysql 连接地址 - Manager Manager // 后台管理员账户信息 StaticDir string // 静态资源目录 StaticUrl string // 静态资源 URL Redis RedisConfig // redis 连接信息 @@ -122,14 +121,6 @@ func (c RedisConfig) Url() string { return fmt.Sprintf("%s:%d", c.Host, c.Port) } -// Manager 管理员 -type Manager struct { - Username string `json:"username"` - Password string `json:"password"` - Captcha string `json:"captcha"` // 验证码 - CaptchaId string `json:"captcha_id"` // 验证码id -} - // ChatConfig 系统默认的聊天配置 type ChatConfig struct { OpenAI ModelAPIConfig `json:"open_ai"` diff --git a/api/handler/admin/admin_handler.go b/api/handler/admin/admin_handler.go index c11dba65..8adaadf8 100644 --- a/api/handler/admin/admin_handler.go +++ b/api/handler/admin/admin_handler.go @@ -5,6 +5,8 @@ import ( "chatplus/core/types" "chatplus/handler" logger2 "chatplus/logger" + "chatplus/store/model" + "chatplus/utils" "chatplus/utils/resp" "context" "github.com/go-redis/redis/v8" @@ -18,6 +20,14 @@ import ( var logger = logger2.GetLogger() +// Manager 管理员 +type Manager struct { + Username string `json:"username"` + Password string `json:"password"` + Captcha string `json:"captcha"` // 验证码 + CaptchaId string `json:"captcha_id"` // 验证码id +} + type ManagerHandler struct { handler.BaseHandler db *gorm.DB @@ -32,7 +42,8 @@ func NewAdminHandler(app *core.AppServer, db *gorm.DB, client *redis.Client) *Ma // Login 登录 func (h *ManagerHandler) Login(c *gin.Context) { - var data types.Manager + + var data Manager if err := c.ShouldBindJSON(&data); err != nil { resp.ERROR(c, types.InvalidArgs) return @@ -40,32 +51,51 @@ func (h *ManagerHandler) Login(c *gin.Context) { // add captcha if !base64Captcha.DefaultMemStore.Verify(data.CaptchaId, data.Captcha, true) { - resp.ERROR(c, "验证码错误,请重新输入!") + resp.ERROR(c, "验证码错误!") return } - manager := h.App.Config.Manager - if data.Username == manager.Username && data.Password == manager.Password { - // 创建 token - token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ - "user_id": manager.Username, - "expired": time.Now().Add(time.Second * time.Duration(h.App.Config.Session.MaxAge)).Unix(), - }) - tokenString, err := token.SignedString([]byte(h.App.Config.Session.SecretKey)) - if err != nil { - resp.ERROR(c, "Failed to generate token, "+err.Error()) - return - } - // 保存到 redis - key := "users/" + manager.Username - if _, err := h.redis.Set(context.Background(), key, tokenString, 0).Result(); err != nil { - resp.ERROR(c, "error with save token: "+err.Error()) - return - } - resp.SUCCESS(c, tokenString) - } else { - resp.ERROR(c, "用户名或者密码错误") + var manager model.AdminUser + res := h.db.Model(&model.AdminUser{}).Where("username = ?", data.Username).First(&manager) + if res.Error != nil { + resp.ERROR(c, "请检查用户名或者密码是否填写正确") + return } + password := utils.GenPassword(data.Password, manager.Salt) + if password != manager.Password { + resp.ERROR(c, "用户名或密码错误") + return + } + + // 超级管理员默认是ID:1 + if manager.Id != 1 && manager.Status == false { + resp.ERROR(c, "该用户已被禁止登录,请联系超级管理员") + return + } + + // 创建 token + token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ + "user_id": manager.Username, + "expired": time.Now().Add(time.Second * time.Duration(h.App.Config.Session.MaxAge)).Unix(), + }) + tokenString, err := token.SignedString([]byte(h.App.Config.Session.SecretKey)) + if err != nil { + resp.ERROR(c, "Failed to generate token, "+err.Error()) + return + } + // 保存到 redis + key := "users/" + manager.Username + if _, err := h.redis.Set(context.Background(), key, tokenString, 0).Result(); err != nil { + resp.ERROR(c, "error with save token: "+err.Error()) + return + } + + // 更新最后登录时间和IP + manager.LastLoginIp = c.ClientIP() + manager.LastLoginAt = time.Now().Unix() + h.db.Model(&manager).Updates(manager) + + resp.SUCCESS(c, tokenString) } // Logout 注销 diff --git a/api/main.go b/api/main.go index 3fac07ad..0bf3f6e0 100644 --- a/api/main.go +++ b/api/main.go @@ -383,15 +383,15 @@ func main() { s.Engine.GET("/api/admin/upload/remove", h.Remove) }), - //// 系统管理员 - //fx.Provide(admin.NewSysUserHandler), - //fx.Invoke(func(s *core.AppServer, h *admin.SysUserHandler) { - // group := s.Engine.Group("/api/admin/sysUser/") - // group.POST("save", h.Save) - // group.GET("list", h.List) - // group.POST("remove", h.Remove) - // group.POST("resetPass", h.ResetPass) - //}), + // 系统管理员 + fx.Provide(admin.NewSysUserHandler), + fx.Invoke(func(s *core.AppServer, h *admin.SysUserHandler) { + group := s.Engine.Group("/api/admin/sysUser/") + group.POST("save", h.Save) + group.GET("list", h.List) + group.POST("remove", h.Remove) + group.POST("resetPass", h.ResetPass) + }), fx.Provide(handler.NewFunctionHandler), fx.Invoke(func(s *core.AppServer, h *handler.FunctionHandler) { diff --git a/api/store/vo/admin_user.go b/api/store/vo/admin_user.go index 92512461..70c4a9ea 100644 --- a/api/store/vo/admin_user.go +++ b/api/store/vo/admin_user.go @@ -3,7 +3,6 @@ package vo type AdminUser struct { BaseVo Username string `json:"username"` - Salt string `json:"salt"` // 密码盐 Status bool `json:"status"` // 当前状态 LastLoginAt int64 `json:"last_login_at"` // 最后登录时间 LastLoginIp string `json:"last_login_ip"` // 最后登录 IP