diff --git a/pkg/server/app/email.go b/pkg/server/app/email.go index 0897e415..2f721a6f 100644 --- a/pkg/server/app/email.go +++ b/pkg/server/app/email.go @@ -65,28 +65,6 @@ func getNoreplySender(webURL string) (string, error) { return addr, nil } -// SendVerificationEmail sends verification email -func (a *App) SendVerificationEmail(email, tokenValue string) error { - body, err := a.EmailTemplates.Execute(mailer.EmailTypeEmailVerification, mailer.EmailKindText, mailer.EmailVerificationTmplData{ - Token: tokenValue, - WebURL: a.WebURL, - }) - if err != nil { - return errors.Wrapf(err, "executing reset verification template for %s", email) - } - - from, err := GetSenderEmail(a.WebURL, defaultSender) - if err != nil { - return errors.Wrap(err, "getting the sender email") - } - - if err := a.EmailBackend.Queue("Verify your Dnote email address", from, []string{email}, mailer.EmailKindText, body); err != nil { - return errors.Wrapf(err, "queueing email for %s", email) - } - - return nil -} - // SendWelcomeEmail sends welcome email func (a *App) SendWelcomeEmail(email string) error { body, err := a.EmailTemplates.Execute(mailer.EmailTypeWelcome, mailer.EmailKindText, mailer.WelcomeTmplData{ diff --git a/pkg/server/app/email_test.go b/pkg/server/app/email_test.go index 1c68a96f..56270604 100644 --- a/pkg/server/app/email_test.go +++ b/pkg/server/app/email_test.go @@ -26,22 +26,6 @@ import ( "github.com/dnote/dnote/pkg/server/testutils" ) -func TestSendVerificationEmail(t *testing.T) { - emailBackend := testutils.MockEmailbackendImplementation{} - a := NewTest() - a.EmailBackend = &emailBackend - a.WebURL = "http://example.com" - - if err := a.SendVerificationEmail("alice@example.com", "mockTokenValue"); err != nil { - t.Fatal(err, "failed to perform") - } - - assert.Equalf(t, len(emailBackend.Emails), 1, "email queue count mismatch") - assert.Equal(t, emailBackend.Emails[0].From, "noreply@example.com", "email sender mismatch") - assert.DeepEqual(t, emailBackend.Emails[0].To, []string{"alice@example.com"}, "email sender mismatch") - -} - func TestSendWelcomeEmail(t *testing.T) { emailBackend := testutils.MockEmailbackendImplementation{} a := NewTest() diff --git a/pkg/server/app/errors.go b/pkg/server/app/errors.go index 250de5d1..895fc40f 100644 --- a/pkg/server/app/errors.go +++ b/pkg/server/app/errors.go @@ -79,7 +79,4 @@ var ( ErrInvalidPassword appError = "Invalid currnet password." // ErrEmailTooLong is an error for email length exceeding the limit ErrEmailTooLong appError = "Email is too long." - - // ErrEmailAlreadyVerified is an error for trying to verify email that is already verified - ErrEmailAlreadyVerified appError = "Email is already verified." ) diff --git a/pkg/server/controllers/helpers.go b/pkg/server/controllers/helpers.go index 0e88034b..72100c8b 100644 --- a/pkg/server/controllers/helpers.go +++ b/pkg/server/controllers/helpers.go @@ -232,8 +232,6 @@ func getStatusCode(err error) int { return http.StatusUnauthorized case app.ErrEmailTooLong: return http.StatusBadRequest - case app.ErrEmailAlreadyVerified: - return http.StatusConflict case app.ErrMissingToken: return http.StatusBadRequest case app.ErrExpiredToken: diff --git a/pkg/server/controllers/routes.go b/pkg/server/controllers/routes.go index 0c873fa3..db8b706d 100644 --- a/pkg/server/controllers/routes.go +++ b/pkg/server/controllers/routes.go @@ -58,8 +58,6 @@ func NewWebRoutes(a *app.App, c *Controllers) []Route { {"PATCH", "/password-reset", c.Users.PasswordReset, true}, {"GET", "/password-reset/{token}", c.Users.PasswordResetConfirm, true}, {"POST", "/reset-token", c.Users.CreateResetToken, true}, - {"POST", "/verification-token", mw.Auth(a.DB, c.Users.CreateEmailVerificationToken, redirectGuest), true}, - {"GET", "/verify-email/{token}", mw.Auth(a.DB, c.Users.VerifyEmail, redirectGuest), true}, {"PATCH", "/account/profile", mw.Auth(a.DB, c.Users.ProfileUpdate, nil), true}, {"PATCH", "/account/password", mw.Auth(a.DB, c.Users.PasswordUpdate, nil), true}, diff --git a/pkg/server/controllers/users.go b/pkg/server/controllers/users.go index 4643f599..67baca6a 100644 --- a/pkg/server/controllers/users.go +++ b/pkg/server/controllers/users.go @@ -30,7 +30,6 @@ import ( "github.com/dnote/dnote/pkg/server/database" "github.com/dnote/dnote/pkg/server/helpers" "github.com/dnote/dnote/pkg/server/log" - "github.com/dnote/dnote/pkg/server/mailer" "github.com/dnote/dnote/pkg/server/token" "github.com/dnote/dnote/pkg/server/views" "github.com/gorilla/mux" @@ -80,10 +79,6 @@ func NewUsers(app *app.App, viewEngine *views.Engine) *Users { views.Config{Title: "About", Layout: "base", HelperFuncs: commonHelpers, HeaderTemplate: "navbar"}, "users/settings_about", ), - EmailVerificationView: viewEngine.NewView(app, - views.Config{Layout: "base", HelperFuncs: commonHelpers, HeaderTemplate: "navbar"}, - "users/email_verification", - ), app: app, } } @@ -96,7 +91,6 @@ type Users struct { AboutView *views.View PasswordResetView *views.View PasswordResetConfirmView *views.View - EmailVerificationView *views.View app *app.App } @@ -599,10 +593,6 @@ func (u *Users) ProfileUpdate(w http.ResponseWriter, r *http.Request) { return } - // check if email was changed - if form.Email != account.Email.String { - account.EmailVerified = false - } account.Email.String = form.Email if err := tx.Save(&account).Error; err != nil { @@ -620,119 +610,3 @@ func (u *Users) ProfileUpdate(w http.ResponseWriter, r *http.Request) { views.RedirectAlert(w, r, "/", http.StatusFound, alert) } -func (u *Users) VerifyEmail(w http.ResponseWriter, r *http.Request) { - vd := views.Data{} - - vars := mux.Vars(r) - tokenValue := vars["token"] - - if tokenValue == "" { - handleHTMLError(w, r, app.ErrMissingToken, "Missing email verification token", u.EmailVerificationView, vd) - return - } - - var token database.Token - if err := u.app.DB. - Where("value = ? AND type = ?", tokenValue, database.TokenTypeEmailVerification). - First(&token).Error; err != nil { - handleHTMLError(w, r, app.ErrInvalidToken, "Finding token", u.EmailVerificationView, vd) - return - } - - if token.UsedAt != nil { - handleHTMLError(w, r, app.ErrInvalidToken, "Token has already been used.", u.EmailVerificationView, vd) - return - } - - // Expire after ttl - if time.Since(token.CreatedAt).Minutes() > 30 { - handleHTMLError(w, r, app.ErrExpiredToken, "Token has expired.", u.EmailVerificationView, vd) - return - } - - var account database.Account - if err := u.app.DB.Where("user_id = ?", token.UserID).First(&account).Error; err != nil { - handleHTMLError(w, r, err, "finding account", u.EmailVerificationView, vd) - return - } - if account.EmailVerified { - handleHTMLError(w, r, app.ErrEmailAlreadyVerified, "Already verified", u.EmailVerificationView, vd) - return - } - - tx := u.app.DB.Begin() - account.EmailVerified = true - if err := tx.Save(&account).Error; err != nil { - tx.Rollback() - handleHTMLError(w, r, err, "updating email_verified", u.EmailVerificationView, vd) - return - } - if err := tx.Model(&token).Update("used_at", time.Now()).Error; err != nil { - tx.Rollback() - handleHTMLError(w, r, err, "updating reset token", u.EmailVerificationView, vd) - return - } - tx.Commit() - - var user database.User - if err := u.app.DB.Where("id = ?", token.UserID).First(&user).Error; err != nil { - handleHTMLError(w, r, err, "finding user", u.EmailVerificationView, vd) - return - } - - session, err := u.app.SignIn(&user) - if err != nil { - handleHTMLError(w, r, err, "Creating session", u.EmailVerificationView, vd) - } - - setSessionCookie(w, session.Key, session.ExpiresAt) - http.Redirect(w, r, "/", http.StatusFound) -} - -func (u *Users) CreateEmailVerificationToken(w http.ResponseWriter, r *http.Request) { - vd := views.Data{} - - user := context.User(r.Context()) - if user == nil { - handleHTMLError(w, r, app.ErrLoginRequired, "No authenticated user found", u.SettingView, vd) - return - } - - var account database.Account - err := u.app.DB.Where("user_id = ?", user.ID).First(&account).Error - if err != nil { - handleHTMLError(w, r, err, "finding account", u.SettingView, vd) - return - } - - if account.EmailVerified { - handleHTMLError(w, r, app.ErrEmailAlreadyVerified, "email is already verified.", u.SettingView, vd) - return - } - if account.Email.String == "" { - handleHTMLError(w, r, app.ErrEmailRequired, "email is empty.", u.SettingView, vd) - return - } - - tok, err := token.Create(u.app.DB, account.UserID, database.TokenTypeEmailVerification) - if err != nil { - handleHTMLError(w, r, err, "saving token", u.SettingView, vd) - return - } - - if err := u.app.SendVerificationEmail(account.Email.String, tok.Value); err != nil { - if pkgErrors.Cause(err) == mailer.ErrSMTPNotConfigured { - handleHTMLError(w, r, app.ErrInvalidSMTPConfig, "SMTP config is not configured correctly.", u.SettingView, vd) - } else { - handleHTMLError(w, r, err, "sending verification email", u.SettingView, vd) - } - - return - } - - alert := views.Alert{ - Level: views.AlertLvlSuccess, - Message: "Please check your email for the verification", - } - views.RedirectAlert(w, r, "/", http.StatusFound, alert) -} diff --git a/pkg/server/controllers/users_test.go b/pkg/server/controllers/users_test.go index e4c9ff2d..643cb016 100644 --- a/pkg/server/controllers/users_test.go +++ b/pkg/server/controllers/users_test.go @@ -578,12 +578,6 @@ func TestResetPassword(t *testing.T) { Type: database.TokenTypeResetPassword, } testutils.MustExec(t, db.Save(&tok), "preparing token") - otherTok := database.Token{ - UserID: u.ID, - Value: "somerandomvalue", - Type: database.TokenTypeEmailVerification, - } - testutils.MustExec(t, db.Save(&otherTok), "preparing another token") s1 := database.Session{ Key: "some-session-key-1", @@ -618,16 +612,14 @@ func TestResetPassword(t *testing.T) { // Test assert.StatusCodeEquals(t, res, http.StatusFound, "Status code mismatch") - var resetToken, verificationToken database.Token + var resetToken database.Token var account database.Account testutils.MustExec(t, db.Where("value = ?", "MivFxYiSMMA4An9dP24DNQ==").First(&resetToken), "finding reset token") - testutils.MustExec(t, db.Where("value = ?", "somerandomvalue").First(&verificationToken), "finding reset token") testutils.MustExec(t, db.Where("id = ?", acc.ID).First(&account), "finding account") assert.NotEqual(t, resetToken.UsedAt, nil, "reset_token UsedAt mismatch") passwordErr := bcrypt.CompareHashAndPassword([]byte(account.Password.String), []byte("newpassword")) assert.Equal(t, passwordErr, nil, "Password mismatch") - assert.Equal(t, verificationToken.UsedAt, (*time.Time)(nil), "verificationToken UsedAt mismatch") var s1Count, s2Count int64 testutils.MustExec(t, db.Model(&database.Session{}).Where("id = ?", s1.ID).Count(&s1Count), "counting s1") @@ -777,46 +769,6 @@ func TestResetPassword(t *testing.T) { } }) - t.Run("using wrong type token: email_verification", func(t *testing.T) { - db := testutils.InitMemoryDB(t) - - // Setup - a := app.NewTest() - a.Clock = clock.NewMock() - a.DB = db - server := MustNewServer(t, &a) - defer server.Close() - - u := testutils.SetupUserData(db) - acc := testutils.SetupAccountData(db, u, "alice@example.com", "somepassword") - tok := database.Token{ - UserID: u.ID, - Value: "MivFxYiSMMA4An9dP24DNQ==", - Type: database.TokenTypeEmailVerification, - } - testutils.MustExec(t, db.Save(&tok), "Failed to prepare reset_token") - testutils.MustExec(t, db.Model(&tok).Update("created_at", time.Now().Add(time.Minute*-11)), "Failed to prepare reset_token created_at") - - dat := url.Values{} - dat.Set("token", "MivFxYiSMMA4An9dP24DNQ==") - dat.Set("password", "oldpassword") - dat.Set("password_confirmation", "oldpassword") - req := testutils.MakeFormReq(server.URL, "PATCH", "/password-reset", dat) - - // Execute - res := testutils.HTTPDo(t, req) - - // Test - assert.StatusCodeEquals(t, res, http.StatusBadRequest, "Status code mismatch") - - var resetToken database.Token - var account database.Account - testutils.MustExec(t, db.Where("value = ?", "MivFxYiSMMA4An9dP24DNQ==").First(&resetToken), "failed to find reset_token") - testutils.MustExec(t, db.Where("id = ?", acc.ID).First(&account), "failed to find account") - - assert.Equal(t, acc.Password, account.Password, "password should not have been updated") - assert.Equal(t, resetToken.UsedAt, (*time.Time)(nil), "used_at should be nil") - }) } func TestCreateResetToken(t *testing.T) { @@ -1018,9 +970,7 @@ func TestUpdateEmail(t *testing.T) { defer server.Close() u := testutils.SetupUserData(db) - acc := testutils.SetupAccountData(db, u, "alice@example.com", "pass1234") - acc.EmailVerified = true - testutils.MustExec(t, db.Save(&acc), "updating email_verified") + testutils.SetupAccountData(db, u, "alice@example.com", "pass1234") // Execute dat := url.Values{} @@ -1039,7 +989,6 @@ func TestUpdateEmail(t *testing.T) { testutils.MustExec(t, db.Where("user_id = ?", u.ID).First(&account), "finding account") assert.Equal(t, account.Email.String, "alice-new@example.com", "email mismatch") - assert.Equal(t, account.EmailVerified, false, "EmailVerified mismatch") }) t.Run("password mismatch", func(t *testing.T) { @@ -1053,9 +1002,7 @@ func TestUpdateEmail(t *testing.T) { defer server.Close() u := testutils.SetupUserData(db) - acc := testutils.SetupAccountData(db, u, "alice@example.com", "pass1234") - acc.EmailVerified = true - testutils.MustExec(t, db.Save(&acc), "updating email_verified") + testutils.SetupAccountData(db, u, "alice@example.com", "pass1234") // Execute dat := url.Values{} @@ -1074,238 +1021,6 @@ func TestUpdateEmail(t *testing.T) { testutils.MustExec(t, db.Where("user_id = ?", u.ID).First(&account), "finding account") assert.Equal(t, account.Email.String, "alice@example.com", "email mismatch") - assert.Equal(t, account.EmailVerified, true, "EmailVerified mismatch") }) } -func TestVerifyEmail(t *testing.T) { - t.Run("success", func(t *testing.T) { - db := testutils.InitMemoryDB(t) - - // Setup - a := app.NewTest() - a.Clock = clock.NewMock() - a.DB = db - server := MustNewServer(t, &a) - defer server.Close() - - user := testutils.SetupUserData(db) - testutils.SetupAccountData(db, user, "alice@example.com", "pass1234") - tok := database.Token{ - UserID: user.ID, - Type: database.TokenTypeEmailVerification, - Value: "someTokenValue", - } - testutils.MustExec(t, db.Save(&tok), "preparing token") - - // Execute - req := testutils.MakeReq(server.URL, "GET", fmt.Sprintf("/verify-email/%s", "someTokenValue"), "") - res := testutils.HTTPAuthDo(t, db, req, user) - - // Test - assert.StatusCodeEquals(t, res, http.StatusFound, "Status code mismatch") - - var account database.Account - var token database.Token - var tokenCount int64 - testutils.MustExec(t, db.Where("user_id = ?", user.ID).First(&account), "finding account") - testutils.MustExec(t, db.Where("user_id = ? AND type = ?", user.ID, database.TokenTypeEmailVerification).First(&token), "finding token") - testutils.MustExec(t, db.Model(&database.Token{}).Count(&tokenCount), "counting token") - - assert.Equal(t, account.EmailVerified, true, "email_verified mismatch") - assert.NotEqual(t, token.Value, "", "token value should not have been updated") - assert.Equal(t, tokenCount, int64(1), "token count mismatch") - assert.NotEqual(t, token.UsedAt, (*time.Time)(nil), "token should have been used") - }) - - t.Run("used token", func(t *testing.T) { - db := testutils.InitMemoryDB(t) - - // Setup - a := app.NewTest() - a.Clock = clock.NewMock() - a.DB = db - server := MustNewServer(t, &a) - defer server.Close() - - user := testutils.SetupUserData(db) - testutils.SetupAccountData(db, user, "alice@example.com", "pass1234") - - usedAt := time.Now().Add(time.Hour * -11).UTC() - tok := database.Token{ - UserID: user.ID, - Type: database.TokenTypeEmailVerification, - Value: "someTokenValue", - UsedAt: &usedAt, - } - testutils.MustExec(t, db.Save(&tok), "preparing token") - - // Execute - req := testutils.MakeReq(server.URL, "GET", fmt.Sprintf("/verify-email/%s", "someTokenValue"), "") - res := testutils.HTTPAuthDo(t, db, req, user) - - // Test - assert.StatusCodeEquals(t, res, http.StatusBadRequest, "") - - var account database.Account - var token database.Token - var tokenCount int64 - testutils.MustExec(t, db.Where("user_id = ?", user.ID).First(&account), "finding account") - testutils.MustExec(t, db.Where("user_id = ? AND type = ?", user.ID, database.TokenTypeEmailVerification).First(&token), "finding token") - testutils.MustExec(t, db.Model(&database.Token{}).Count(&tokenCount), "counting token") - - assert.Equal(t, account.EmailVerified, false, "email_verified mismatch") - assert.NotEqual(t, token.UsedAt, nil, "token used_at mismatch") - assert.Equal(t, tokenCount, int64(1), "token count mismatch") - assert.NotEqual(t, token.UsedAt, (*time.Time)(nil), "token should have been used") - }) - - t.Run("expired token", func(t *testing.T) { - db := testutils.InitMemoryDB(t) - - // Setup - a := app.NewTest() - a.Clock = clock.NewMock() - a.DB = db - server := MustNewServer(t, &a) - defer server.Close() - - user := testutils.SetupUserData(db) - testutils.SetupAccountData(db, user, "alice@example.com", "pass1234") - - tok := database.Token{ - UserID: user.ID, - Type: database.TokenTypeEmailVerification, - Value: "someTokenValue", - } - testutils.MustExec(t, db.Save(&tok), "preparing token") - testutils.MustExec(t, db.Model(&tok).Update("created_at", time.Now().Add(time.Minute*-31)), "Failed to prepare token created_at") - - // Execute - req := testutils.MakeReq(server.URL, "GET", fmt.Sprintf("/verify-email/%s", "someTokenValue"), "") - res := testutils.HTTPAuthDo(t, db, req, user) - - // Test - assert.StatusCodeEquals(t, res, http.StatusGone, "") - - var account database.Account - var token database.Token - var tokenCount int64 - testutils.MustExec(t, db.Where("user_id = ?", user.ID).First(&account), "finding account") - testutils.MustExec(t, db.Where("user_id = ? AND type = ?", user.ID, database.TokenTypeEmailVerification).First(&token), "finding token") - testutils.MustExec(t, db.Model(&database.Token{}).Count(&tokenCount), "counting token") - - assert.Equal(t, account.EmailVerified, false, "email_verified mismatch") - assert.Equal(t, tokenCount, int64(1), "token count mismatch") - assert.Equal(t, token.UsedAt, (*time.Time)(nil), "token should have not been used") - }) - - t.Run("already verified", func(t *testing.T) { - db := testutils.InitMemoryDB(t) - - // Setup - a := app.NewTest() - a.Clock = clock.NewMock() - a.DB = db - server := MustNewServer(t, &a) - defer server.Close() - - user := testutils.SetupUserData(db) - acc := testutils.SetupAccountData(db, user, "alice@example.com", "oldpass1234") - acc.EmailVerified = true - testutils.MustExec(t, db.Save(&acc), "preparing account") - - tok := database.Token{ - UserID: user.ID, - Type: database.TokenTypeEmailVerification, - Value: "someTokenValue", - } - testutils.MustExec(t, db.Save(&tok), "preparing token") - - // Execute - req := testutils.MakeReq(server.URL, "GET", fmt.Sprintf("/verify-email/%s", "someTokenValue"), "") - res := testutils.HTTPAuthDo(t, db, req, user) - - // Test - assert.StatusCodeEquals(t, res, http.StatusConflict, "") - - var account database.Account - var token database.Token - var tokenCount int64 - testutils.MustExec(t, db.Where("user_id = ?", user.ID).First(&account), "finding account") - testutils.MustExec(t, db.Where("user_id = ? AND type = ?", user.ID, database.TokenTypeEmailVerification).First(&token), "finding token") - testutils.MustExec(t, db.Model(&database.Token{}).Count(&tokenCount), "counting token") - - assert.Equal(t, account.EmailVerified, true, "email_verified mismatch") - assert.Equal(t, tokenCount, int64(1), "token count mismatch") - assert.Equal(t, token.UsedAt, (*time.Time)(nil), "token should have not been used") - }) -} - -func TestCreateVerificationToken(t *testing.T) { - t.Run("success", func(t *testing.T) { - db := testutils.InitMemoryDB(t) - - // Setup - emailBackend := testutils.MockEmailbackendImplementation{} - a := app.NewTest() - a.Clock = clock.NewMock() - a.DB = db - a.EmailBackend = &emailBackend - server := MustNewServer(t, &a) - defer server.Close() - - user := testutils.SetupUserData(db) - testutils.SetupAccountData(db, user, "alice@example.com", "pass1234") - - // Execute - req := testutils.MakeReq(server.URL, "POST", "/verification-token", "") - res := testutils.HTTPAuthDo(t, db, req, user) - - // Test - assert.StatusCodeEquals(t, res, http.StatusFound, "status code mismatch") - - var account database.Account - var token database.Token - var tokenCount int64 - testutils.MustExec(t, db.Where("user_id = ?", user.ID).First(&account), "finding account") - testutils.MustExec(t, db.Where("user_id = ? AND type = ?", user.ID, database.TokenTypeEmailVerification).First(&token), "finding token") - testutils.MustExec(t, db.Model(&database.Token{}).Count(&tokenCount), "counting token") - - assert.Equal(t, account.EmailVerified, false, "email_verified should not have been updated") - assert.NotEqual(t, token.Value, "", "token Value mismatch") - assert.Equal(t, tokenCount, int64(1), "token count mismatch") - assert.Equal(t, token.UsedAt, (*time.Time)(nil), "token UsedAt mismatch") - assert.Equal(t, len(emailBackend.Emails), 1, "email queue count mismatch") - }) - - t.Run("already verified", func(t *testing.T) { - db := testutils.InitMemoryDB(t) - // Setup - a := app.NewTest() - a.Clock = clock.NewMock() - a.DB = db - server := MustNewServer(t, &a) - defer server.Close() - - user := testutils.SetupUserData(db) - acc := testutils.SetupAccountData(db, user, "alice@example.com", "pass1234") - acc.EmailVerified = true - testutils.MustExec(t, db.Save(&acc), "preparing account") - - // Execute - req := testutils.MakeReq(server.URL, "POST", "/verification-token", "") - res := testutils.HTTPAuthDo(t, db, req, user) - - // Test - assert.StatusCodeEquals(t, res, http.StatusConflict, "Status code mismatch") - - var account database.Account - var tokenCount int64 - testutils.MustExec(t, db.Where("user_id = ?", user.ID).First(&account), "finding account") - testutils.MustExec(t, db.Model(&database.Token{}).Count(&tokenCount), "counting token") - - assert.Equal(t, account.EmailVerified, true, "email_verified should not have been updated") - assert.Equal(t, tokenCount, int64(0), "token count mismatch") - }) -} diff --git a/pkg/server/database/consts.go b/pkg/server/database/consts.go index b4a1db03..6a9abc0c 100644 --- a/pkg/server/database/consts.go +++ b/pkg/server/database/consts.go @@ -21,8 +21,6 @@ package database const ( // TokenTypeResetPassword is a type of a token for reseting password TokenTypeResetPassword = "reset_password" - // TokenTypeEmailVerification is a type of a token for verifying email - TokenTypeEmailVerification = "email_verification" ) const ( diff --git a/pkg/server/database/models.go b/pkg/server/database/models.go index ac3e4e56..98571e10 100644 --- a/pkg/server/database/models.go +++ b/pkg/server/database/models.go @@ -73,10 +73,9 @@ type User struct { // Account is a model for an account type Account struct { Model - UserID int `gorm:"index"` - Email NullString - EmailVerified bool `gorm:"default:false"` - Password NullString + UserID int `gorm:"index"` + Email NullString + Password NullString } // Token is a model for a token diff --git a/pkg/server/mailer/mailer.go b/pkg/server/mailer/mailer.go index d02d8911..1cf786a7 100644 --- a/pkg/server/mailer/mailer.go +++ b/pkg/server/mailer/mailer.go @@ -34,8 +34,6 @@ var ( EmailTypeResetPassword = "reset_password" // EmailTypeResetPasswordAlert represents a password change notification email EmailTypeResetPasswordAlert = "reset_password_alert" - // EmailTypeEmailVerification represents an email verification email - EmailTypeEmailVerification = "verify_email" // EmailTypeWelcome represents an welcome email EmailTypeWelcome = "welcome" ) @@ -79,10 +77,6 @@ func NewTemplates() Templates { if err != nil { panic(errors.Wrap(err, "initializing welcome template")) } - verifyEmailText, err := initTextTmpl(EmailTypeEmailVerification) - if err != nil { - panic(errors.Wrap(err, "initializing email verification template")) - } passwordResetText, err := initTextTmpl(EmailTypeResetPassword) if err != nil { panic(errors.Wrap(err, "initializing password reset template")) @@ -95,7 +89,6 @@ func NewTemplates() Templates { T := Templates{} T.set(EmailTypeResetPassword, EmailKindText, passwordResetText) T.set(EmailTypeResetPasswordAlert, EmailKindText, passwordResetAlertText) - T.set(EmailTypeEmailVerification, EmailKindText, verifyEmailText) T.set(EmailTypeWelcome, EmailKindText, welcomeText) return T diff --git a/pkg/server/mailer/mailer_test.go b/pkg/server/mailer/mailer_test.go index df95b1f9..5837192a 100644 --- a/pkg/server/mailer/mailer_test.go +++ b/pkg/server/mailer/mailer_test.go @@ -32,7 +32,6 @@ func TestAllTemplatesInitialized(t *testing.T) { emailTypes := []string{ EmailTypeResetPassword, EmailTypeResetPasswordAlert, - EmailTypeEmailVerification, EmailTypeWelcome, } @@ -46,44 +45,6 @@ func TestAllTemplatesInitialized(t *testing.T) { } } -func TestEmailVerificationEmail(t *testing.T) { - testCases := []struct { - token string - webURL string - }{ - { - token: "someRandomToken1", - webURL: "http://localhost:3000", - }, - { - token: "someRandomToken2", - webURL: "http://localhost:3001", - }, - } - - tmpl := NewTemplates() - - for _, tc := range testCases { - t.Run(fmt.Sprintf("with WebURL %s", tc.webURL), func(t *testing.T) { - dat := EmailVerificationTmplData{ - Token: tc.token, - WebURL: tc.webURL, - } - body, err := tmpl.Execute(EmailTypeEmailVerification, EmailKindText, dat) - if err != nil { - t.Fatal(errors.Wrap(err, "executing")) - } - - if ok := strings.Contains(body, tc.webURL); !ok { - t.Errorf("email body did not contain %s", tc.webURL) - } - if ok := strings.Contains(body, tc.token); !ok { - t.Errorf("email body did not contain %s", tc.token) - } - }) - } -} - func TestResetPasswordEmail(t *testing.T) { testCases := []struct { token string diff --git a/pkg/server/mailer/templates/verify_email.txt b/pkg/server/mailer/templates/verify_email.txt deleted file mode 100644 index c21af88d..00000000 --- a/pkg/server/mailer/templates/verify_email.txt +++ /dev/null @@ -1,5 +0,0 @@ -Hi, - -Welcome to Dnote! To verify your email, visit the following link: - - {{ .WebURL }}/verify-email/{{ .Token }} diff --git a/pkg/server/mailer/types.go b/pkg/server/mailer/types.go index 3a371911..6ad862de 100644 --- a/pkg/server/mailer/types.go +++ b/pkg/server/mailer/types.go @@ -18,12 +18,6 @@ package mailer -// EmailVerificationTmplData is a template data for email verification emails -type EmailVerificationTmplData struct { - Token string - WebURL string -} - // EmailResetPasswordTmplData is a template data for reset password emails type EmailResetPasswordTmplData struct { AccountEmail string diff --git a/pkg/server/middleware/auth_test.go b/pkg/server/middleware/auth_test.go index 8451ae5d..1485befa 100644 --- a/pkg/server/middleware/auth_test.go +++ b/pkg/server/middleware/auth_test.go @@ -178,7 +178,7 @@ func TestTokenAuth(t *testing.T) { user := testutils.SetupUserData(db) tok := database.Token{ UserID: user.ID, - Type: database.TokenTypeEmailVerification, + Type: database.TokenTypeResetPassword, Value: "xpwFnc0MdllFUePDq9DLeQ==", } testutils.MustExec(t, db.Save(&tok), "preparing token") @@ -193,7 +193,7 @@ func TestTokenAuth(t *testing.T) { w.WriteHeader(http.StatusOK) } - server := httptest.NewServer(TokenAuth(db, handler, database.TokenTypeEmailVerification, nil)) + server := httptest.NewServer(TokenAuth(db, handler, database.TokenTypeResetPassword, nil)) defer server.Close() t.Run("with token", func(t *testing.T) { diff --git a/pkg/server/session/session.go b/pkg/server/session/session.go index 8c55549c..a9494c58 100644 --- a/pkg/server/session/session.go +++ b/pkg/server/session/session.go @@ -24,16 +24,14 @@ import ( // Session represents user session type Session struct { - UUID string `json:"uuid"` - Email string `json:"email"` - EmailVerified bool `json:"email_verified"` + UUID string `json:"uuid"` + Email string `json:"email"` } // New returns a new session for the given user func New(user database.User, account database.Account) Session { return Session{ - UUID: user.UUID, - Email: account.Email.String, - EmailVerified: account.EmailVerified, + UUID: user.UUID, + Email: account.Email.String, } } diff --git a/pkg/server/session/session_test.go b/pkg/server/session/session_test.go index 107dacfe..dec674b7 100644 --- a/pkg/server/session/session_test.go +++ b/pkg/server/session/session_test.go @@ -28,10 +28,10 @@ import ( func TestNew(t *testing.T) { u1 := database.User{UUID: "0f5f0054-d23f-4be1-b5fb-57673109e9cb"} - a1 := database.Account{Email: database.ToNullString("alice@example.com"), EmailVerified: false} + a1 := database.Account{Email: database.ToNullString("alice@example.com")} u2 := database.User{UUID: "718a1041-bbe6-496e-bbe4-ea7e572c295e"} - a2 := database.Account{Email: database.ToNullString("bob@example.com"), EmailVerified: false} + a2 := database.Account{Email: database.ToNullString("bob@example.com")} testCases := []struct { user database.User @@ -52,9 +52,8 @@ func TestNew(t *testing.T) { // Execute got := New(tc.user, tc.account) expected := Session{ - UUID: tc.user.UUID, - Email: tc.account.Email.String, - EmailVerified: tc.account.EmailVerified, + UUID: tc.user.UUID, + Email: tc.account.Email.String, } assert.DeepEqual(t, got, expected, "result mismatch") diff --git a/pkg/server/token/token_test.go b/pkg/server/token/token_test.go index 922cc93d..426ff3d1 100644 --- a/pkg/server/token/token_test.go +++ b/pkg/server/token/token_test.go @@ -33,7 +33,7 @@ func TestCreate(t *testing.T) { kind string }{ { - kind: database.TokenTypeEmailVerification, + kind: database.TokenTypeResetPassword, }, } diff --git a/pkg/server/views/templates/users/email_verification.gohtml b/pkg/server/views/templates/users/email_verification.gohtml deleted file mode 100644 index 969688a4..00000000 --- a/pkg/server/views/templates/users/email_verification.gohtml +++ /dev/null @@ -1,2 +0,0 @@ -{{define "yield"}} -{{end}} diff --git a/pkg/server/views/templates/users/settings.gohtml b/pkg/server/views/templates/users/settings.gohtml index a9639468..9f747b3e 100644 --- a/pkg/server/views/templates/users/settings.gohtml +++ b/pkg/server/views/templates/users/settings.gohtml @@ -144,34 +144,6 @@ -