+ Your email has been verified +
++ You have completed the verification process. Thank you! +
+ + Go Home + + } else { ++ Error during verification +
++ Please try again by sign up process +
+ + Sign Up + + } +diff --git a/handler/auth.go b/handler/auth.go
index 74ade85..d92aa21 100644
--- a/handler/auth.go
+++ b/handler/auth.go
@@ -171,11 +171,17 @@ func (handler AuthImpl) handleSignUpVerifyResponsePage() http.HandlerFunc {
err := handler.service.VerifyUserEmail(token)
- if err != nil {
- utils.DoRedirect(w, r, "/auth/signin")
+ isVerified := err == nil
+ comp := auth.VerifyResponseComp(isVerified)
+
+ var status int
+ if isVerified {
+ status = http.StatusOK
} else {
- utils.DoRedirect(w, r, "/")
+ status = http.StatusBadRequest
}
+
+ handler.render.RenderLayoutWithStatus(r, w, comp, nil, status)
}
}
diff --git a/handler/render.go b/handler/render.go
index c3f007c..28cb3b9 100644
--- a/handler/render.go
+++ b/handler/render.go
@@ -21,8 +21,9 @@ func NewRender(settings *types.Settings) *Render {
}
}
-func (render *Render) Render(r *http.Request, w http.ResponseWriter, comp templ.Component) {
+func (render *Render) RenderWithStatus(r *http.Request, w http.ResponseWriter, comp templ.Component, status int) {
w.Header().Set("Content-Type", "text/html")
+ w.WriteHeader(status)
err := comp.Render(r.Context(), w)
if err != nil {
log.Error("Failed to render layout: %v", err)
@@ -30,11 +31,19 @@ func (render *Render) Render(r *http.Request, w http.ResponseWriter, comp templ.
}
}
+func (render *Render) Render(r *http.Request, w http.ResponseWriter, comp templ.Component) {
+ render.RenderWithStatus(r, w, comp, http.StatusOK)
+}
+
func (render *Render) RenderLayout(r *http.Request, w http.ResponseWriter, slot templ.Component, user *types.User) {
+ render.RenderLayoutWithStatus(r, w, slot, user, http.StatusOK)
+}
+
+func (render *Render) RenderLayoutWithStatus(r *http.Request, w http.ResponseWriter, slot templ.Component, user *types.User, status int) {
userComp := render.getUserComp(user)
layout := template.Layout(slot, userComp, render.settings.Environment)
- render.Render(r, w, layout)
+ render.RenderWithStatus(r, w, layout, status)
}
func (render *Render) getUserComp(user *types.User) templ.Component {
diff --git a/main_test.go b/main_test.go
index b7ceb89..e0234c6 100644
--- a/main_test.go
+++ b/main_test.go
@@ -618,6 +618,92 @@ func TestIntegrationAuth(t *testing.T) {
err = db.QueryRow("SELECT COUNT(*) FROM user WHERE email = ? AND email_verified = FALSE", "mail@mail.de").Scan(&rows)
assert.Nil(t, err)
assert.Equal(t, 1, rows)
+ var token string
+ err = db.QueryRow("SELECT t.token FROM token t INNER JOIN user u ON u.user_id = t.user_id WHERE u.email = ? AND t.type = ?", "mail@mail.de", types.TokenTypeEmailVerify).Scan(&token)
+ assert.Nil(t, err)
+ assert.NotEqual(t, "", token)
+ })
+ })
+ t.Run("SignUpVerification", func(t *testing.T) {
+ t.Run(`should fail verifying email with non existent token`, func(t *testing.T) {
+ t.Parallel()
+
+ db, basePath, ctx := setupIntegrationTest(t)
+
+ userId := uuid.New()
+
+ _, err := db.Exec(`
+ INSERT INTO user (user_id, email, email_verified, is_admin, password, salt, created_at)
+ VALUES (?, "mail@mail.de", FALSE, FALSE, ?, ?, datetime())`, userId, []byte("pass"), []byte("salt"))
+ assert.Nil(t, err)
+
+ req, err := http.NewRequestWithContext(ctx, "GET", basePath+"/auth/verify-email?token=invalid-token", nil)
+ assert.Nil(t, err)
+ resp, err := httpClient.Do(req)
+ assert.Nil(t, err)
+
+ assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
+
+ var rows int
+ err = db.QueryRow("SELECT COUNT(*) FROM user WHERE user_id = ? AND email_verified = FALSE", userId).Scan(&rows)
+ assert.Nil(t, err)
+ assert.Equal(t, 1, rows)
+ })
+ t.Run(`should fail verifying email with outdated token`, func(t *testing.T) {
+ t.Parallel()
+
+ db, basePath, ctx := setupIntegrationTest(t)
+
+ userId := uuid.New()
+ token := "my-outdated-verifying-token"
+
+ _, err := db.Exec(`
+ INSERT INTO user (user_id, email, email_verified, is_admin, password, salt, created_at)
+ VALUES (?, "mail@mail.de", FALSE, FALSE, ?, ?, datetime())`, userId, []byte("pass"), []byte("salt"))
+ assert.Nil(t, err)
+ _, err = db.Exec(`
+ INSERT INTO token (token, user_id, type, created_at, expires_at)
+ VALUES (?, ?, ?, datetime("now", "-16 minute"), datetime("now", "-1 minute"))`, token, userId, types.TokenTypeEmailVerify)
+
+ req, err := http.NewRequestWithContext(ctx, "GET", basePath+"/auth/verify-email?token="+token, nil)
+ assert.Nil(t, err)
+ resp, err := httpClient.Do(req)
+ assert.Nil(t, err)
+
+ assert.Equal(t, http.StatusBadRequest, resp.StatusCode)
+
+ var rows int
+ err = db.QueryRow("SELECT COUNT(*) FROM user WHERE user_id = ? AND email_verified = FALSE", userId).Scan(&rows)
+ assert.Nil(t, err)
+ assert.Equal(t, 1, rows)
+ })
+ t.Run(`should verify email with correct token`, func(t *testing.T) {
+ t.Parallel()
+
+ db, basePath, ctx := setupIntegrationTest(t)
+
+ userId := uuid.New()
+ token := "my-verifying-token"
+
+ _, err := db.Exec(`
+ INSERT INTO user (user_id, email, email_verified, is_admin, password, salt, created_at)
+ VALUES (?, "mail@mail.de", FALSE, FALSE, ?, ?, datetime())`, userId, []byte("pass"), []byte("salt"))
+ assert.Nil(t, err)
+ _, err = db.Exec(`
+ INSERT INTO token (token, user_id, session_id, type, created_at, expires_at)
+ VALUES (?, ?, "", ?, datetime("now"), datetime("now", "+15 minute"))`, token, userId, types.TokenTypeEmailVerify)
+
+ req, err := http.NewRequestWithContext(ctx, "GET", basePath+"/auth/verify-email?token="+token, nil)
+ assert.Nil(t, err)
+ resp, err := httpClient.Do(req)
+ assert.Nil(t, err)
+
+ assert.Equal(t, http.StatusOK, resp.StatusCode)
+
+ var rows int
+ err = db.QueryRow("SELECT COUNT(*) FROM user WHERE user_id = ? AND email_verified = TRUE", userId).Scan(&rows)
+ assert.Nil(t, err)
+ assert.Equal(t, 1, rows)
})
})
t.Run("SignOut", func(t *testing.T) {
diff --git a/template/auth/verify_response.templ b/template/auth/verify_response.templ
new file mode 100644
index 0000000..84327c3
--- /dev/null
+++ b/template/auth/verify_response.templ
@@ -0,0 +1,29 @@
+package auth
+
+templ VerifyResponseComp(isVerified bool) {
+
+ You have completed the verification process. Thank you!
+
+ Please try again by sign up process
+
+ Your email has been verified
+
+
+ Error during verification
+
+
Click here to verify your account.
-Kind regards
- - + + + + + + +Click here to finalize + your registration.
+Kind regards
+ + + }