diff --git a/dao/user.go b/dao/user.go index c28de65..7b23165 100644 --- a/dao/user.go +++ b/dao/user.go @@ -42,8 +42,9 @@ func DeleteUserByID(id int) int { return id } -func FindUserByID(id int) []proto.User { - var users []proto.User +func FindUserByID(id int) []User { + var users []User + //不查询密码 DB.Where("id = ?", id).First(&users) return users } @@ -67,8 +68,8 @@ func FindUserByName(name string) User { } // 根据name模糊查询,邮箱也是,不查询密码 -func FindUserByNameLike(name string) []proto.User { - var users []proto.User +func FindUserByNameLike(name string) []User { + var users []User DB.Where("name LIKE ? OR email LIKE ?", "%"+name+"%", "%"+name+"%").Find(&users).Limit(32) return users } @@ -165,3 +166,10 @@ func ClearAllUsers() error { res := DB.Exec("TRUNCATE TABLE users") return res.Error } + +// 获取前20个用户 +func FindUsersDefault() []User { + var users []User + DB.Limit(20).Find(&users) + return users +} diff --git a/handler/user.go b/handler/user.go index d1bb0cc..0ce1c40 100644 --- a/handler/user.go +++ b/handler/user.go @@ -57,7 +57,7 @@ type ResetPasswordReq struct { Email string `json:"email" form:"email"` OldPassword string `json:"old_password" form:"old_password"` NewPassword string `json:"new_password" form:"new_password"` - Type int `json:"type" form:"type"` //0获取验证码,2为邮箱重置密码,1为旧密码重置密码 + Type int `json:"type" form:"type"` //0获取验证码,2为邮箱验证码重置密码,1为旧密码重置密码 Code string `json:"code" form:"code"` //验证码 } @@ -72,11 +72,17 @@ func ResetPassword(c *gin.Context) { c.JSON(200, gin.H{"code": proto.OperationFailed, "message": "邮箱不存在", "data": "2"}) return } + if worker.IsContainKey("reset_password_" + req_data.Email) { + c.JSON(200, gin.H{"code": proto.OperationFailed, "message": "验证码已发送,请5分钟后再试", "data": "2"}) + return + } //随机字符串验证码大写 code := worker.GetRandomString(6) worker.SetRedisWithExpire("reset_password_"+req_data.Email, code, time.Minute*5) //设置5分钟过期` //发送邮件 service.SendEmail(req_data.Email, "大学生学业作品AI生成工具开发重置密码", "验证码:"+code+" ,请在5分钟内使用!") + c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": "2"}) + return } else if req_data.Type == 1 { //旧密码重置密码 if len(req_data.OldPassword) != 32 { @@ -103,6 +109,17 @@ func ResetPassword(c *gin.Context) { return } dao.UpdateUserByID(int(user.ID), user.Name, req_data.NewPassword, user.Email) + var resp proto.ResponseOAuth + token, err2 := service.CreateTokenAndSave(user) + if err2 != nil { + c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "new token error", "data": resp}) + return + } + resp.Token = token + resp.ID = user.ID + resp.Name = user.Name + resp.Email = user.Email + c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": resp}) } else if req_data.Type == 2 { //邮箱重置密码 if len(req_data.NewPassword) != 32 { @@ -121,6 +138,17 @@ func ResetPassword(c *gin.Context) { return } dao.UpdateUserByID(int(user.ID), user.Name, req_data.NewPassword, user.Email) + token, err2 := service.CreateTokenAndSave(user) + if err2 != nil { + c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "new token error", "data": "2"}) + return + } + var resp proto.ResponseOAuth + resp.Token = token + resp.ID = user.ID + resp.Name = user.Name + resp.Email = user.Email + c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": resp}) } else { c.JSON(200, gin.H{"code": proto.OperationFailed, "message": "type error", "data": "2"}) return @@ -130,7 +158,6 @@ func ResetPassword(c *gin.Context) { c.JSON(200, gin.H{"code": proto.ParameterError, "message": err, "data": "2"}) return } - c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": "2"}) } func GetUserInfo(c *gin.Context) { @@ -340,7 +367,8 @@ func SearchHandler(c *gin.Context) { c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": users}) return } else { - c.JSON(200, gin.H{"code": proto.ParameterError, "message": "error", "data": "无ID 与 关键字"}) + users := service.GetUsersDefault() + c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "error", "data": users}) } } else { c.JSON(200, gin.H{"error": err.Error(), "code": proto.ParameterError, "message": "error"}) diff --git a/proto/conf.go b/proto/conf.go index e6ed1c3..273ab3d 100644 --- a/proto/conf.go +++ b/proto/conf.go @@ -9,7 +9,7 @@ import ( var Config ConfigStruct var SigningKey = []byte{} -var Url_map = map[string]bool{"/login": true, "/register": true, "/uuid": true, "/gqr": true, "/cid/callback": true, "/tool/monitor": true, "/user/sync": true, "/tool/file/": true} // 不需要token验证的url +var Url_map = map[string]bool{"/login": true, "/register": true, "/uuid": true, "/gqr": true, "/cid/callback": true, "/tool/monitor": true, "/user/sync": true, "/tool/file/": true, "/user/reset": true} // 不需要token验证的url var Per_menu_map = map[string]int{"/video/": 1, "/device/": 2, "/cid/": 3} var File_Type = map[string]int{"im": 1, "avatar": 2, "file": 3, "config": 4} // 文件类型 const ( @@ -60,6 +60,7 @@ type User struct { Age int `gorm:"column:age"` Email string `gorm:"column:email"` Gender string `gorm:"column:gender"` + Role string `gorm:"column:role"` } type ConfigStruct struct { diff --git a/proto/user_req.go b/proto/user_req.go index 61875d6..84af5b1 100644 --- a/proto/user_req.go +++ b/proto/user_req.go @@ -110,3 +110,10 @@ type UpdateShellRespV2 struct { ID uint `json:"id" form:"id"` Status int `json:"status" form:"status"` } + +type ResponseOAuth struct { + ID uint `json:"id" form:"id"` + Name string `json:"name" form:"name"` + Email string `json:"email" form:"email"` + Token string `json:"token" form:"token"` +} diff --git a/service/userService.go b/service/userService.go index 82b737b..63deb57 100644 --- a/service/userService.go +++ b/service/userService.go @@ -7,6 +7,7 @@ import ( "encoding/json" "errors" "fmt" + "github.com/golang-jwt/jwt" "regexp" "strconv" "time" @@ -48,8 +49,12 @@ func ContainsUser(name, email string) bool { return false } -func GetUserByID(id int) []proto.User { - return dao.FindUserByID(id) +func GetUserByID(id int) []dao.User { + users := dao.FindUserByID(id) + for i, _ := range users { + users[i].Password = "" //不返回密码 + } + return users } // 获取用户信息,有redis缓存 @@ -84,8 +89,21 @@ func GetUserByIDWithCache(id int) dao.User { return user } -func GetUserByNameLike(name string) []proto.User { - return dao.FindUserByNameLike(name) +func GetUserByNameLike(name string) []dao.User { + users := dao.FindUserByNameLike(name) + for i, _ := range users { + users[i].Password = "" + } + return users +} + +// 获取默认前20个用户 +func GetUsersDefault() []dao.User { + users := dao.FindUsersDefault() + for i, _ := range users { + users[i].Password = "" + } + return users } func UpdateUser(user_id int, req proto.UpdateUserInfoReq) (int, error) { @@ -367,3 +385,35 @@ func ConfirmSyncUserData(device string, data proto.UserSyncConfirm) error { } return err } + +// 生成新的token,存入redis,返回信息 +func CreateTokenAndSave(user dao.User) (string, error) { + var tokenString string + var err error + key := "user_" + user.Name + redis_token := worker.GetRedis(string(key)) + if redis_token == "" { + // 生成 JWT 令牌 + token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ + "username": user.Name, + "id": user.ID, + "exp": time.Now().Add(time.Hour * 10).Unix(), // 令牌过期时间, 10小时后过期 + }) + tokenString, err = token.SignedString(proto.SigningKey) + if err != nil { + return "", err + } + + worker.SetRedisWithExpire("user_"+user.Name, tokenString, time.Hour*10) // 将用户信息存入 + worker.SetRedisWithExpire(tokenString, tokenString, time.Hour*10) // 设置过期时间为10分钟 + data := make(map[string]interface{}) + data["id"] = user.ID + data["username"] = user.Name + data["email"] = user.Email + worker.SetHash(tokenString, data) // 将用户信息存入 + } else { + tokenString = redis_token + } + // 返回令牌 + return tokenString, err +}