(r *http.Request, tx *storage.Connection, u *models.User, flowType models.FlowType)
| 395 | } |
| 396 | |
| 397 | func (a *API) sendPasswordRecovery(r *http.Request, tx *storage.Connection, u *models.User, flowType models.FlowType) error { |
| 398 | config := a.config |
| 399 | otpLength := config.Mailer.OtpLength |
| 400 | |
| 401 | if err := validateSentWithinFrequencyLimit(u.RecoverySentAt, config.SMTP.MaxFrequency); err != nil { |
| 402 | return err |
| 403 | } |
| 404 | |
| 405 | oldToken := u.RecoveryToken |
| 406 | otp := crypto.GenerateOtp(otpLength) |
| 407 | |
| 408 | token := crypto.GenerateTokenHash(u.GetEmail(), otp) |
| 409 | u.RecoveryToken = addFlowPrefixToToken(token, flowType) |
| 410 | now := time.Now() |
| 411 | err := a.sendEmail(r, tx, u, sendEmailParams{ |
| 412 | emailActionType: mail.RecoveryVerification, |
| 413 | otp: otp, |
| 414 | tokenHashWithPrefix: u.RecoveryToken, |
| 415 | }) |
| 416 | if err != nil { |
| 417 | u.RecoveryToken = oldToken |
| 418 | if errors.Is(err, EmailRateLimitExceeded) { |
| 419 | return apierrors.NewTooManyRequestsError(apierrors.ErrorCodeOverEmailSendRateLimit, "%s", EmailRateLimitExceeded.Error()) |
| 420 | } else if herr, ok := err.(*HTTPError); ok { |
| 421 | return herr |
| 422 | } |
| 423 | return apierrors.NewInternalServerError("Error sending recovery email").WithInternalError(err) |
| 424 | } |
| 425 | u.RecoverySentAt = &now |
| 426 | |
| 427 | if err := tx.UpdateOnly(u, "recovery_token", "recovery_sent_at"); err != nil { |
| 428 | return apierrors.NewInternalServerError("Error sending recovery email").WithInternalError(errors.Wrap(err, "Database error updating user for recovery")) |
| 429 | } |
| 430 | |
| 431 | if err := models.CreateOneTimeToken(tx, u.ID, u.GetEmail(), u.RecoveryToken, models.RecoveryToken); err != nil { |
| 432 | return apierrors.NewInternalServerError("Error sending recovery email").WithInternalError(errors.Wrap(err, "Database error creating recovery token")) |
| 433 | } |
| 434 | |
| 435 | return nil |
| 436 | } |
| 437 | |
| 438 | func (a *API) sendReauthenticationOtp(r *http.Request, tx *storage.Connection, u *models.User) error { |
| 439 | config := a.config |
no test coverage detected