package service import ( "ai-gateway/common/constant" "ai-gateway/common/dto" "ai-gateway/common/email" "ai-gateway/common/logs" "ai-gateway/common/utils" "ai-gateway/infrastructure/redis" "ai-gateway/infrastructure/repository" "context" "crypto/sha256" "encoding/hex" "encoding/json" "errors" "github.com/google/uuid" "github.com/labstack/echo/v4" "golang.org/x/time/rate" "strings" "time" ) type login struct { } var Login login // 令牌桶大小为 100, 以每秒 10 个 Token 的速率向桶中放置 Token var limiter = rate.NewLimiter(10, 10) // Register 注册 func (l login) Register(ctx context.Context, req dto.ThirdRegisterReq) error { acUser := repository.GUser.FindByAccount(ctx, req.Account) if acUser != nil && acUser.Deleted == 0 { return errors.New("user exist") } var user repository.AccountDO user.Name = req.Name user.Avatar = req.Icon user.Email = req.Account //密码加密 h := sha256.Sum256([]byte(req.Password)) passHash := hex.EncodeToString(h[:]) user.Pwd = passHash repository.GUser.Create(ctx, &user) return nil } func (l login) Login(ctx context.Context, req dto.ThirdLoginReq) (string, error) { start := time.Now().UnixMilli() //1. 验证账号密码 h := sha256.Sum256([]byte(req.Password)) passHash := hex.EncodeToString(h[:]) acUser := repository.GUser.FindByAccount(ctx, req.Account) if acUser == nil || acUser.Deleted == 1 { return "", errors.New("user not exist") } if passHash != acUser.Pwd { return "", errors.New("password is error") } //生成token token := uuid.New().String() token = strings.ReplaceAll(token, "-", "") var thirdUserToken = repository.GLoginToken{ Uid: acUser.Id, AccessToken: token, ExpireTime: time.Now().Add(time.Duration(24*365*100) * time.Hour).UnixMilli(), } gUserToken := repository.GUserToken.FindByUid(ctx, acUser.Id) if gUserToken == nil { repository.GUserToken.SaveUserLoginToken(ctx, &thirdUserToken) return l.GenAccessToken(&thirdUserToken), nil } gUserToken.AccessToken = thirdUserToken.AccessToken gUserToken.ExpireTime = thirdUserToken.ExpireTime repository.GUserToken.UpdateUserLoginToken(ctx, gUserToken) diff := time.Now().UnixMilli() - start logs.NewLog("").Infof("Login cost: %d", diff) return l.GenAccessToken(gUserToken), nil } func (l login) SendResetPwdCode(ctx context.Context, account string) error { //1. 验证账号 acUser := repository.GUser.FindByAccount(ctx, account) if acUser == nil || acUser.Deleted == 1 { return errors.New("user not exist") } //2. 生成code & 发送 code := utils.GetPseudoRandomCode(6) //3. save into redis if err := redis.Set(constant.G_RESET_PWD_CODE+account, code, time.Duration(30)*time.Minute); err != nil { return errors.New("cache illegal") } //频控 if !limiter.Allow() { return errors.New("rate limit, please try again later") } //4. send code if err := email.SendEmailVerifyCodeByEmail(code, account); err != nil { return errors.New("send email code illegal") } return nil } // ResetPwd 重置密码 func (l login) ResetPwd(ctx context.Context, req dto.ThirdResetPwdReq) error { //1. 验证code redisStr, err := redis.Get(constant.G_RESET_PWD_CODE + req.Account) if err != nil && redisStr != req.Code { return errors.New("code is error") } //2. 查询用户 acUser := repository.GUser.FindByAccount(ctx, req.Account) if acUser == nil || acUser.Deleted == 1 { return errors.New("user not exist") } //3. 重置密码 h := sha256.Sum256([]byte(req.Password)) passHash := hex.EncodeToString(h[:]) acUser.Pwd = passHash repository.GUser.UpdateById(ctx, acUser) //生成token token := uuid.New().String() token = strings.ReplaceAll(token, "-", "") var thirdUserToken = repository.GLoginToken{ Uid: acUser.Id, Platform: "web", AccessToken: token, ExpireTime: time.Now().Add(time.Duration(24*365*100) * time.Hour).UnixMilli(), } loginUserToken := repository.GUserToken.FindByUid(ctx, acUser.Id) if loginUserToken == nil { repository.GUserToken.SaveUserLoginToken(ctx, &thirdUserToken) return nil } loginUserToken.AccessToken = thirdUserToken.AccessToken loginUserToken.ExpireTime = thirdUserToken.ExpireTime repository.GUserToken.UpdateUserLoginToken(ctx, loginUserToken) return nil } func (l login) GetLoginResult(ctx context.Context, c *echo.Context) *dto.ThirdUserLoginToken { accessToken := utils.GetAccessToken(c) if accessToken == "" { return nil } //redis redisStr, err := redis.Get(constant.THIRD_LOGIN_TOKEN + accessToken) if err != nil && redisStr != "" { var loginInfo dto.ThirdUserLoginToken if redisErr := json.Unmarshal([]byte(redisStr), &loginInfo); redisErr == nil { return &loginInfo } } //repository dbData := repository.GUserToken.FindByToken(ctx, accessToken) if dbData == nil { return nil } var finalData = dto.ThirdUserLoginToken{ Uid: dbData.Uid, AccessToken: l.GenAccessToken(dbData), } //save into redis if bytes, saveErr := json.Marshal(finalData); saveErr == nil { redis.Set(constant.THIRD_LOGIN_TOKEN+accessToken, string(bytes), time.Duration(6)*time.Hour) } return &finalData } func (login) GenAccessToken(data *repository.GLoginToken) string { return data.AccessToken }