package service import ( "context" "errors" "fmt" "math/rand" "gitea.com/bitwsd/core/common/log" "gitea.com/bitwsd/document_ai/internal/storage/cache" "gitea.com/bitwsd/document_ai/internal/storage/dao" "gitea.com/bitwsd/document_ai/pkg/sms" ) type UserService struct { userDao *dao.UserDao } func NewUserService() *UserService { return &UserService{ userDao: dao.NewUserDao(), } } func (svc *UserService) GetSmsCode(ctx context.Context, phone string) (string, error) { limit, err := cache.GetUserSendSmsLimit(ctx, phone) if err != nil { log.Error(ctx, "func", "GetSmsCode", "msg", "get user send sms limit error", "error", err) return "", err } if limit >= cache.UserSendSmsLimitCount { return "", errors.New("sms code send limit reached") } user, err := svc.userDao.GetByPhone(dao.DB.WithContext(ctx), phone) if err != nil { log.Error(ctx, "func", "GetSmsCode", "msg", "get user error", "error", err) return "", err } if user == nil { user = &dao.User{Phone: phone} err = svc.userDao.Create(dao.DB.WithContext(ctx), user) if err != nil { log.Error(ctx, "func", "GetSmsCode", "msg", "create user error", "error", err) return "", err } } code := fmt.Sprintf("%06d", rand.Intn(1000000)) err = sms.SendMessage(&sms.SendSmsRequest{PhoneNumbers: phone, SignName: sms.Signature, TemplateCode: sms.TemplateCode, TemplateParam: fmt.Sprintf(sms.TemplateParam, code)}) if err != nil { log.Error(ctx, "func", "GetSmsCode", "msg", "send message error", "error", err) return "", err } cacheErr := cache.SetUserSmsCode(ctx, phone, code) if cacheErr != nil { log.Error(ctx, "func", "GetSmsCode", "msg", "set user sms code error", "error", cacheErr) } cacheErr = cache.SetUserSendSmsLimit(ctx, phone) if cacheErr != nil { log.Error(ctx, "func", "GetSmsCode", "msg", "set user send sms limit error", "error", cacheErr) } return code, nil } func (svc *UserService) VerifySmsCode(ctx context.Context, phone, code string) (uid int64, err error) { user, err := svc.userDao.GetByPhone(dao.DB.WithContext(ctx), phone) if err != nil { log.Error(ctx, "func", "VerifySmsCode", "msg", "get user error", "error", err, "phone", phone) return 0, err } if user == nil { log.Error(ctx, "func", "VerifySmsCode", "msg", "user not found", "phone", phone) return 0, errors.New("user not found") } storedCode, err := cache.GetUserSmsCode(ctx, phone) if err != nil { log.Error(ctx, "func", "VerifySmsCode", "msg", "get user sms code error", "error", err) return 0, err } if storedCode != code { log.Error(ctx, "func", "VerifySmsCode", "msg", "invalid sms code", "phone", phone, "code", code, "storedCode", storedCode) return 0, errors.New("invalid sms code") } cacheErr := cache.DeleteUserSmsCode(ctx, phone) if cacheErr != nil { log.Error(ctx, "func", "VerifySmsCode", "msg", "delete user sms code error", "error", cacheErr) } return user.ID, nil } func (svc *UserService) GetUserInfo(ctx context.Context, uid int64) (*dao.User, error) { user, err := svc.userDao.GetByID(dao.DB.WithContext(ctx), uid) if err != nil { log.Error(ctx, "func", "GetUserInfo", "msg", "get user error", "error", err) return nil, err } if user == nil { log.Warn(ctx, "func", "GetUserInfo", "msg", "user not found", "uid", uid) return &dao.User{}, nil } return user, nil }