MCPcopy Index your code
hub / github.com/supabase/auth / sendEmailChange

Method sendEmailChange

internal/api/mail.go:523–588  ·  view source on GitHub ↗

sendEmailChange sends out an email change token to the new email.

(r *http.Request, tx *storage.Connection, u *models.User, email string, flowType models.FlowType)

Source from the content-addressed store, hash-verified

521
522// sendEmailChange sends out an email change token to the new email.
523func (a *API) sendEmailChange(r *http.Request, tx *storage.Connection, u *models.User, email string, flowType models.FlowType) error {
524 config := a.config
525 otpLength := config.Mailer.OtpLength
526
527 if err := validateSentWithinFrequencyLimit(u.EmailChangeSentAt, config.SMTP.MaxFrequency); err != nil {
528 return err
529 }
530
531 otpNew := crypto.GenerateOtp(otpLength)
532
533 u.EmailChange = email
534 token := crypto.GenerateTokenHash(u.EmailChange, otpNew)
535 u.EmailChangeTokenNew = addFlowPrefixToToken(token, flowType)
536
537 otpCurrent := ""
538 if config.Mailer.SecureEmailChangeEnabled && u.GetEmail() != "" {
539 otpCurrent = crypto.GenerateOtp(otpLength)
540
541 currentToken := crypto.GenerateTokenHash(u.GetEmail(), otpCurrent)
542 u.EmailChangeTokenCurrent = addFlowPrefixToToken(currentToken, flowType)
543 }
544
545 u.EmailChangeConfirmStatus = zeroConfirmation
546 now := time.Now()
547
548 err := a.sendEmail(r, tx, u, sendEmailParams{
549 emailActionType: mail.EmailChangeVerification,
550 otp: otpCurrent,
551 otpNew: otpNew,
552 tokenHashWithPrefix: u.EmailChangeTokenNew,
553 })
554 if err != nil {
555 if errors.Is(err, EmailRateLimitExceeded) {
556 return apierrors.NewTooManyRequestsError(apierrors.ErrorCodeOverEmailSendRateLimit, "%s", EmailRateLimitExceeded.Error())
557 } else if herr, ok := err.(*HTTPError); ok {
558 return herr
559 }
560 return apierrors.NewInternalServerError("Error sending email change email").WithInternalError(err)
561 }
562
563 u.EmailChangeSentAt = &now
564 if err := tx.UpdateOnly(
565 u,
566 "email_change_token_current",
567 "email_change_token_new",
568 "email_change",
569 "email_change_sent_at",
570 "email_change_confirm_status",
571 ); err != nil {
572 return apierrors.NewInternalServerError("Error sending email change email").WithInternalError(errors.Wrap(err, "Database error updating user for email change"))
573 }
574
575 if u.EmailChangeTokenCurrent != "" {
576 if err := models.CreateOneTimeToken(tx, u.ID, u.GetEmail(), u.EmailChangeTokenCurrent, models.EmailChangeTokenCurrent); err != nil {
577 return apierrors.NewInternalServerError("Error sending email change email").WithInternalError(errors.Wrap(err, "Database error creating email change token current"))
578 }
579 }
580

Callers 2

ResendMethod · 0.95
UserUpdateMethod · 0.95

Calls 14

sendEmailMethod · 0.95
GenerateOtpFunction · 0.92
GenerateTokenHashFunction · 0.92
NewTooManyRequestsErrorFunction · 0.92
NewInternalServerErrorFunction · 0.92
CreateOneTimeTokenFunction · 0.92
addFlowPrefixToTokenFunction · 0.85
NowMethod · 0.80
UpdateOnlyMethod · 0.80
GetEmailMethod · 0.45
IsMethod · 0.45

Tested by

no test coverage detected