package handler import ( "crypto/md5" "encoding/hex" "encoding/json" "fmt" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt" "github.com/google/uuid" "time" "videoplayer/dao" "videoplayer/proto" "videoplayer/service" "videoplayer/worker" ) var signingKey = []byte(proto.TOKEN_SECRET) func SetUpUserGroup(router *gin.Engine) { userGroup := router.Group("/user") userGroup.POST("/register", registerHandler) userGroup.POST("/login", loginHandler) userGroup.POST("/uuid", GetScanUUID) userGroup.POST("/gqr", GetQRStatus) userGroup.POST("/sqr", SetQRStatus) userGroup.POST("/confirm", ConfirmQRLogin) userGroup.POST("/search", SearchHandler) userGroup.POST("/info", GetUserInfo) } type RLReq struct { User string `json:"username" form:"username"` Email string `json:"email" form:"email"` Password string `json:"password" form:"password"` Age int `json:"age" form:"age"` Gender string `json:"gender" form:"gender"` } type QRReq struct { UUID string `json:"uuid" form:"uuid"` Address string `json:"address" form:"address"` IP string `json:"ip" form:"ip"` } type SearchReq struct { Keyword string `json:"keyword" form:"keyword"` ID int `json:"id" form:"id"` } func GetUserInfo(c *gin.Context) { id, _ := c.Get("id") user_id := int(id.(float64)) user := dao.FindUserByID2(user_id) user.Password = "" //不返回密码 c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": user}) } func GetScanUUID(c *gin.Context) { var ReqData QRReq if err := c.ShouldBind(&ReqData); err != nil { c.JSON(200, gin.H{"code": proto.DeviceRestartFailed, "message": err, "data": "2"}) return } data := map[string]interface{}{"status": "0", "address": ReqData.Address, "ip": c.ClientIP()} jsonData, err := json.Marshal(data) if err != nil { c.JSON(200, gin.H{"code": proto.DeviceRestartFailed, "message": err, "data": "2"}) return } id := uuid.New() res := worker.SetRedisWithExpire(id.String(), string(jsonData), time.Minute*30) if res { var retrievedData map[string]interface{} if err2 := json.Unmarshal([]byte(worker.GetRedis(id.String())), &retrievedData); err2 != nil { c.JSON(200, gin.H{"code": proto.DeviceRestartFailed, "message": err2, "data": "2"}) return } c.JSON(200, gin.H{"code": proto.SuccessCode, "message": retrievedData, "data": id.String()}) } else { c.JSON(200, gin.H{"code": proto.RedisSetError, "message": "qr code invalid", "data": "1"}) } } func SetQRStatus(c *gin.Context) { var qrsetReq QRReq if err := c.ShouldBind(&qrsetReq); err == nil && qrsetReq.UUID != "" { if worker.IsContainKey(qrsetReq.UUID) == false { c.JSON(200, gin.H{"code": proto.UUIDNotFound, "message": "uuid not found in server", "data": "0"}) return } var retrievedData map[string]interface{} if err2 := json.Unmarshal([]byte(worker.GetRedis(qrsetReq.UUID)), &retrievedData); err2 != nil { c.JSON(200, gin.H{"code": proto.DeviceRestartFailed, "message": err2, "data": "2"}) return } retrievedData["status"] = "1" jsonData, err2 := json.Marshal(retrievedData) if err2 != nil { c.JSON(200, gin.H{"code": proto.DeviceRestartFailed, "message": err2, "data": "2"}) return } res := worker.SetRedisWithExpire(qrsetReq.UUID, string(jsonData), time.Minute*30) if res { c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": retrievedData}) } else { c.JSON(200, gin.H{"code": proto.RedisSetError, "message": "qr code invalid", "data": "1"}) } } else { c.JSON(200, gin.H{"code": proto.DeviceRestartFailed, "message": err, "data": "2"}) } } // 确认返回token数据 func ConfirmQRLogin(c *gin.Context) { var qrsetReq QRReq if err := c.ShouldBind(&qrsetReq); err == nil && qrsetReq.UUID != "" { //user_id, _ := c.Get("id") user_name, _ := c.Get("username") if user_name != "" { key := "user_" + user_name.(string) token := worker.GetRedis(key) if token == "" { c.JSON(200, gin.H{"code": proto.RedisGetError, "message": "Token不存在", "data": "20"}) } if worker.IsContainKey(qrsetReq.UUID) == false { c.JSON(200, gin.H{"code": proto.UUIDNotFound, "message": "uuid not found in server", "data": "0"}) return } var retrievedData map[string]interface{} if err2 := json.Unmarshal([]byte(worker.GetRedis(qrsetReq.UUID)), &retrievedData); err2 != nil { c.JSON(200, gin.H{"code": proto.DeviceRestartFailed, "message": err2, "data": "2"}) return } retrievedData["status"] = token jsonData, err2 := json.Marshal(retrievedData) if err2 != nil { c.JSON(200, gin.H{"code": proto.DeviceRestartFailed, "message": err2, "data": "2"}) return } if worker.SetRedisWithExpire(qrsetReq.UUID, string(jsonData), time.Minute*10) { c.JSON(200, gin.H{"code": 0, "message": "success", "data": "0"}) } else { c.JSON(200, gin.H{"code": proto.RedisSetError, "message": "设置Token失败", "data": "8"}) } } else { c.JSON(200, gin.H{"code": proto.RedisGetError, "message": "failed", "data": "20"}) } } else { c.JSON(200, gin.H{"code": proto.DeviceRestartFailed, "message": err, "data": "3"}) } } func GetQRStatus(c *gin.Context) { var qrReq QRReq if err := c.ShouldBind(&qrReq); err == nil { var retrievedData map[string]interface{} if err2 := json.Unmarshal([]byte(worker.GetRedis(qrReq.UUID)), &retrievedData); err2 != nil { c.JSON(200, gin.H{"code": proto.DeviceRestartFailed, "message": err2, "data": "2"}) return } str := retrievedData["status"].(string) switch str { case "": c.JSON(200, gin.H{"code": proto.UUIDNotFound, "message": "uuid not found", "data": "0"}) //空值 case "0": c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": "0"}) //空值 case "1": c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": "1"}) //已扫描待确认 default: // 解析 JWT 令牌 token, err := jwt.Parse(str, func(token *jwt.Token) (interface{}, error) { return signingKey, nil }) if err != nil { c.JSON(200, gin.H{"error": err.Error(), "code": proto.TokenParseError, "message": "error"}) return } // 返回令牌 data := make(map[string]interface{}) data["id"] = token.Claims.(jwt.MapClaims)["id"] data["username"] = token.Claims.(jwt.MapClaims)["username"] data["email"] = token.Claims.(jwt.MapClaims)["email"] data["token"] = str c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": data}) //确认返回token数据 } } else { c.JSON(200, gin.H{"error": err.Error(), "code": proto.DeviceRestartFailed, "message": "error"}) } } func SearchHandler(c *gin.Context) { var req_data SearchReq if err := c.ShouldBind(&req_data); err == nil { if req_data.ID != -1 { user := service.GetUserByID(req_data.ID) group := service.GetGroupByID(req_data.ID) c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": user, "group": group}) return } else if req_data.Keyword != "" { users := service.GetUserByNameLike(req_data.Keyword) groups := service.GetGroupByNameLike(req_data.Keyword) c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": users, "group": groups}) return } else { c.JSON(200, gin.H{"code": proto.ParameterError, "message": "error", "data": "无ID 与 关键字"}) } } else { c.JSON(200, gin.H{"error": err.Error(), "code": proto.ParameterError, "message": "error"}) } } func loginHandler(c *gin.Context) { var req_data RLReq tokenString := "" if err := c.ShouldBind(&req_data); err == nil { if len(req_data.Password) != 32 { hasher := md5.New() hasher.Write([]byte(req_data.Password)) // 生成密码的 MD5 散列值 req_data.Password = hex.EncodeToString(hasher.Sum(nil)) // 生成密码的 MD5 散列值 } user := service.GetUser(req_data.User, req_data.Password, req_data.Password) if user.ID != 0 { 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(signingKey) if err != nil { c.JSON(200, gin.H{"error": err.Error(), "code": proto.TokenGenerationError, "message": "error"}) return } 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 } // 返回令牌 data := make(map[string]interface{}) data["id"] = user.ID data["username"] = user.Name data["email"] = user.Email data["token"] = tokenString c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": data}) } else { //用户名或密码错误 c.JSON(200, gin.H{"error": "用户名或密码错误", "code": proto.UsernameOrPasswordError, "message": "error"}) } } else { c.JSON(200, gin.H{"error": err.Error(), "code": proto.DeviceRestartFailed, "message": "error"}) } } func registerHandler(c *gin.Context) { var req_data RLReq tokenString := "" var id uint if err := c.ShouldBind(&req_data); err == nil { if len(req_data.Password) != 32 { hasher := md5.New() hasher.Write([]byte(req_data.Password)) // 生成密码的 MD5 散列值 req_data.Password = hex.EncodeToString(hasher.Sum(nil)) // 生成密码的 MD5 散列值 } if service.ContainsUser(req_data.User, req_data.Email) == true { c.JSON(200, gin.H{"error": "user already exists", "code": proto.UsernameExists, "message": "error"}) return } id = service.CreateUser(req_data.User, req_data.Password, req_data.Email, req_data.Gender, req_data.Age) if id == 0 { c.JSON(200, gin.H{"error": "create user error", "code": proto.OperationFailed, "message": "error"}) return } // 生成 JWT 令牌 token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.MapClaims{ "username": req_data.User, "id": id, "exp": time.Now().Add(time.Hour * 10).Unix(), // 令牌过期时间, 1分钟后过期 }) tokenString, err = token.SignedString(signingKey) if err != nil { c.JSON(200, gin.H{"error": err.Error(), "code": proto.TokenGenerationError, "message": "error"}) return } } else { c.JSON(200, gin.H{"error": err.Error(), "code": proto.ParameterError, "message": "error"}) return } fmt.Println(req_data) res := worker.SetRedisWithExpire(tokenString, tokenString, time.Hour*10) // 设置过期时间为10分钟 if !res { c.JSON(200, gin.H{"error": "set token error", "code": proto.RedisSetError, "message": "error"}) return } // 返回令牌 data := make(map[string]interface{}) data["id"] = id data["username"] = req_data.User data["email"] = req_data.Email data["token"] = tokenString c.JSON(200, gin.H{"code": proto.SuccessCode, "message": "success", "data": data}) return }