package user import ( "Yimaru-Backend/internal/domain" "Yimaru-Backend/internal/pkgs/helpers" "context" "fmt" "time" "golang.org/x/crypto/bcrypt" ) func (s *Service) renderOtpMessage(ctx context.Context, otpCode, firstName string) (domain.RenderedEmail, error) { return s.emailTemplateSvc.Render(ctx, domain.EmailTemplateSlugOTP, map[string]any{ "OTP": otpCode, "FirstName": firstName, "ExpiresMinutes": int(OtpExpiry.Minutes()), }) } func (s *Service) ResendOtp( ctx context.Context, email, phone string, ) error { user, err := s.userStore.GetUserByEmailPhone(ctx, email, phone) if err != nil { return err } otpCode := helpers.GenerateOTP() otp, err := s.otpStore.GetOtp(ctx, user.ID) if err != nil { return err } rendered, err := s.renderOtpMessage(ctx, otpCode, user.FirstName) if err != nil { return err } switch otp.Medium { case domain.OtpMediumSms: if err := s.messengerSvc.SendAfroMessageSMSLatest(ctx, otp.SentTo, rendered.Text, nil); err != nil { return err } case domain.OtpMediumEmail: if err := s.messengerSvc.SendEmail( ctx, otp.SentTo, rendered.Text, rendered.HTML, rendered.Subject, ); err != nil { return err } default: return fmt.Errorf("invalid otp medium: %s", otp.Medium) } if err := s.otpStore.UpdateOtp(ctx, otpCode, user.ID); err != nil { return err } return nil } func (s *Service) SendOtp(ctx context.Context, userID int64, sentTo string, otpFor domain.OtpFor, medium domain.OtpMedium, provider domain.SMSProvider) error { otpCode := helpers.GenerateOTP() firstName := "" if userID > 0 { user, err := s.userStore.GetUserByID(ctx, userID) if err == nil { firstName = user.FirstName } } rendered, err := s.renderOtpMessage(ctx, otpCode, firstName) if err != nil { return err } switch medium { case domain.OtpMediumSms: if err := s.messengerSvc.SendAfroMessageSMSLatest(ctx, sentTo, rendered.Text, nil); err != nil { return err } case domain.OtpMediumEmail: if err := s.messengerSvc.SendEmail(ctx, sentTo, rendered.Text, rendered.HTML, rendered.Subject); err != nil { return err } } otp := domain.Otp{ UserID: userID, SentTo: sentTo, Medium: medium, For: otpFor, Otp: otpCode, Used: false, CreatedAt: time.Now(), ExpiresAt: time.Now().Add(OtpExpiry), } return s.otpStore.CreateOtp(ctx, otp) } func hashPassword(plaintextPassword string) ([]byte, error) { hash, err := bcrypt.GenerateFromPassword([]byte(plaintextPassword), 12) if err != nil { return []byte{}, err } return hash, nil }