Skip to content

Commit

Permalink
fix: redirects on email change
Browse files Browse the repository at this point in the history
  • Loading branch information
kangmingtay committed Sep 7, 2021
1 parent 6f75827 commit d9cba5b
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 8 deletions.
10 changes: 9 additions & 1 deletion api/mail.go
Original file line number Diff line number Diff line change
Expand Up @@ -232,13 +232,21 @@ func (a *API) sendMagicLink(tx *storage.Connection, u *models.User, mailer maile
func (a *API) sendEmailChange(tx *storage.Connection, u *models.User, mailer mailer.Mailer, email string, referrerURL string) error {
u.EmailChangeTokenCurrent, u.EmailChangeTokenNew = crypto.SecureToken(), crypto.SecureToken()
u.EmailChange = email
u.EmailChangeConfirmStatus = noneConfirmed
now := time.Now()
if err := mailer.EmailChangeMail(u, referrerURL); err != nil {
return err
}

u.EmailChangeSentAt = &now
return errors.Wrap(tx.UpdateOnly(u, "email_change_token_current", "email_change_token_new", "email_change", "email_change_sent_at"), "Database error updating user for email change")
return errors.Wrap(tx.UpdateOnly(
u,
"email_change_token_current",
"email_change_token_new",
"email_change",
"email_change_sent_at",
"email_change_confirm_status",
), "Database error updating user for email change")
}

func (a *API) validateEmail(ctx context.Context, email string) error {
Expand Down
16 changes: 11 additions & 5 deletions api/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ const (
smsVerification = "sms"
)

const (
noneConfirmed int = iota
oneConfirmed
)

// VerifyParams are the parameters the Verify endpoint accepts
type VerifyParams struct {
Type string `json:"type"`
Expand Down Expand Up @@ -306,7 +311,7 @@ func (a *API) emailChangeVerify(ctx context.Context, conn *storage.Connection, p
nextDay := user.EmailChangeSentAt.Add(24 * time.Hour)
if user.EmailChangeSentAt != nil && time.Now().After(nextDay) {
err = a.db.Transaction(func(tx *storage.Connection) error {
user.EmailChangeConfirmStatus = 0
user.EmailChangeConfirmStatus = noneConfirmed
return tx.UpdateOnly(user, "email_change_confirm_status")
})
if err != nil {
Expand All @@ -315,9 +320,9 @@ func (a *API) emailChangeVerify(ctx context.Context, conn *storage.Connection, p
return nil, expiredTokenError("Email change token expired").WithInternalError(redirectWithQueryError)
}

if user.EmailChangeConfirmStatus < 1 {
if user.EmailChangeConfirmStatus == noneConfirmed {
err = a.db.Transaction(func(tx *storage.Connection) error {
user.EmailChangeConfirmStatus++
user.EmailChangeConfirmStatus = oneConfirmed
if params.Token == user.EmailChangeTokenCurrent {
user.EmailChangeTokenCurrent = ""
} else if params.Token == user.EmailChangeTokenNew {
Expand All @@ -331,9 +336,10 @@ func (a *API) emailChangeVerify(ctx context.Context, conn *storage.Connection, p
if err != nil {
return nil, err
}
return nil, acceptedTokenError("Email change request accepted")
return nil, acceptedTokenError("Email change request accepted").WithInternalError(redirectWithQueryError)
}

// one email is confirmed at this point
err = a.db.Transaction(func(tx *storage.Connection) error {
var terr error

Expand All @@ -345,7 +351,7 @@ func (a *API) emailChangeVerify(ctx context.Context, conn *storage.Connection, p
return terr
}

if terr = user.ConfirmEmailChange(tx); terr != nil {
if terr = user.ConfirmEmailChange(tx, noneConfirmed); terr != nil {
return internalServerError("Error confirm email").WithInternalError(terr)
}

Expand Down
4 changes: 2 additions & 2 deletions models/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,12 +279,12 @@ func (u *User) UpdateLastSignInAt(tx *storage.Connection) error {
}

// ConfirmEmailChange confirm the change of email for a user
func (u *User) ConfirmEmailChange(tx *storage.Connection) error {
func (u *User) ConfirmEmailChange(tx *storage.Connection, status int) error {
u.Email = storage.NullString(u.EmailChange)
u.EmailChange = ""
u.EmailChangeTokenCurrent = ""
u.EmailChangeTokenNew = ""
u.EmailChangeConfirmStatus = 0
u.EmailChangeConfirmStatus = status
return tx.UpdateOnly(
u,
"email",
Expand Down

0 comments on commit d9cba5b

Please sign in to comment.