web/console: Save timestamp when creating users to mark their first email verification notification.

This value will be updated whenever we send a reminder for a user to verify their email.

Change-Id: I7f08b16eccc6633b8eb3662eb7efed1f1f780f44
This commit is contained in:
Malcolm Bouzi 2021-12-22 10:43:37 -05:00
parent e6961e1fd7
commit 3451162583
5 changed files with 47 additions and 10 deletions

View File

@ -317,6 +317,10 @@ func (a *Auth) Register(w http.ResponseWriter, r *http.Request) {
UserName: userName,
},
)
if err = a.service.UpdateEmailVerificationReminder(ctx, time.Now().UTC()); err != nil {
a.serveJSONError(w, err)
}
}
// loadSession looks for a cookie for the session id.
@ -586,6 +590,10 @@ func (a *Auth) ResendEmail(w http.ResponseWriter, r *http.Request) {
UserName: userName,
},
)
if err = a.service.UpdateEmailVerificationReminder(ctx, time.Now().UTC()); err != nil {
a.serveJSONError(w, err)
}
}
// EnableUserMFA enables multi-factor authentication for the user.

View File

@ -964,6 +964,21 @@ func (s *Service) UpdateAccount(ctx context.Context, fullName string, shortName
return nil
}
// UpdateEmailVerificationReminder updates the last time a user was sent a verification email.
func (s *Service) UpdateEmailVerificationReminder(ctx context.Context, t time.Time) (err error) {
defer mon.Task()(&ctx)(&err)
err = s.store.Users().Update(ctx, &User{
LastVerificationReminder: t,
})
if err != nil {
return Error.Wrap(err)
}
return nil
}
// ChangeEmail updates email for a given user.
func (s *Service) ChangeEmail(ctx context.Context, newEmail string) (err error) {
defer mon.Task()(&ctx)(&err)

View File

@ -157,4 +157,6 @@ type User struct {
MFARecoveryCodes []string `json:"mfaRecoveryCodes"`
SignupPromoCode string `json:"signupPromoCode"`
LastVerificationReminder time.Time `json:"lastVerificationReminder"`
}

View File

@ -190,6 +190,7 @@ func testUsers(ctx context.Context, t *testing.T, repository console.Users, user
assert.False(t, user.MFAEnabled)
assert.Empty(t, user.MFASecretKey)
assert.Empty(t, user.MFARecoveryCodes)
assert.Empty(t, user.LastVerificationReminder)
if user.IsProfessional {
assert.Equal(t, workingOn, userByEmail.WorkingOn)
@ -212,6 +213,7 @@ func testUsers(ctx context.Context, t *testing.T, repository console.Users, user
assert.False(t, user.MFAEnabled)
assert.Empty(t, user.MFASecretKey)
assert.Empty(t, user.MFARecoveryCodes)
assert.Empty(t, user.LastVerificationReminder)
if user.IsProfessional {
assert.Equal(t, workingOn, userByID.WorkingOn)
@ -244,17 +246,21 @@ func testUsers(ctx context.Context, t *testing.T, repository console.Users, user
oldUser, err := repository.GetByEmail(ctx, email)
assert.NoError(t, err)
d := (60 * time.Second)
date := time.Now().Add(-24 * 365 * time.Hour).Truncate(d)
newUserInfo := &console.User{
ID: oldUser.ID,
FullName: newName,
ShortName: newLastName,
Email: newEmail,
Status: console.Active,
PaidTier: true,
MFAEnabled: true,
MFASecretKey: mfaSecretKey,
MFARecoveryCodes: []string{"1", "2"},
PasswordHash: []byte(newPass),
ID: oldUser.ID,
FullName: newName,
ShortName: newLastName,
Email: newEmail,
Status: console.Active,
PaidTier: true,
MFAEnabled: true,
MFASecretKey: mfaSecretKey,
MFARecoveryCodes: []string{"1", "2"},
PasswordHash: []byte(newPass),
LastVerificationReminder: date,
}
err = repository.Update(ctx, newUserInfo)
@ -271,6 +277,7 @@ func testUsers(ctx context.Context, t *testing.T, repository console.Users, user
assert.True(t, newUser.MFAEnabled)
assert.Equal(t, mfaSecretKey, newUser.MFASecretKey)
assert.Equal(t, newUserInfo.MFARecoveryCodes, newUser.MFARecoveryCodes)
assert.Equal(t, newUserInfo.LastVerificationReminder, newUser.LastVerificationReminder)
// PartnerID should not change
assert.Equal(t, user.PartnerID, newUser.PartnerID)
assert.Equal(t, oldUser.CreatedAt, newUser.CreatedAt)

View File

@ -219,6 +219,7 @@ func toUpdateUser(user *console.User) (*dbx.User_Update_Fields, error) {
}
update.MfaRecoveryCodes = dbx.User_MfaRecoveryCodes(string(recoveryBytes))
update.MfaSecretKey = dbx.User_MfaSecretKey(user.MFASecretKey)
update.LastVerificationReminder = dbx.User_LastVerificationReminder(user.LastVerificationReminder)
// extra password check to update only calculated hash from service
if len(user.PasswordHash) != 0 {
@ -308,6 +309,10 @@ func userFromDBX(ctx context.Context, user *dbx.User) (_ *console.User, err erro
result.SignupPromoCode = *user.SignupPromoCode
}
if user.LastVerificationReminder != nil {
result.LastVerificationReminder = *user.LastVerificationReminder
}
return &result, nil
}