diff --git a/migration/004_user_tokens.up.sql b/migration/004_user_tokens.up.sql new file mode 100644 index 0000000..47fcd6d --- /dev/null +++ b/migration/004_user_tokens.up.sql @@ -0,0 +1,11 @@ + +-- E.G. email-verifications, password-resets, unsubscribe-from-newsletter etc. +CREATE TABLE user_token ( + user_uuid TEXT NOT NULL UNIQUE, + + type TEXT NOT NULL, + token TEXT NOT NULL UNIQUE PRIMARY KEY, + + created_at DATETIME NOT NULL, + expires_at DATETIME +); diff --git a/service/auth.go b/service/auth.go index b589a42..f2d1820 100644 --- a/service/auth.go +++ b/service/auth.go @@ -78,20 +78,38 @@ func HandleSignUpVerifyPage(db *sql.DB) http.HandlerFunc { func HandleSignUpVerifyResponsePage(db *sql.DB) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { - code := r.URL.Query().Get("code") - if code == "" { + token := r.URL.Query().Get("token") + if token == "" { utils.DoRedirect(w, r, "/auth/verify") return } - userId, err := uuid.Parse(code) + result, err := db.Exec(` + UPDATE user + SET email_verified = true, email_verified_at = datetime() + WHERE user_uuid = ( + SELECT user_uuid + FROM user_token + WHERE type = "email_verify" + AND token = ? + ); + `, token) + if err != nil { - utils.DoRedirect(w, r, "/auth/verify") + slog.Error("Could not update user: " + err.Error()) + return + } + i, err := result.RowsAffected() + if err != nil { + slog.Error("Could not get rows affected: " + err.Error()) return } - _, err = db.Exec("UPDATE user SET email_verified = true, email_verified_at = datetime() WHERE user_uuid = ?", userId) - utils.DoRedirect(w, r, "/") + if i == 0 { + utils.DoRedirect(w, r, "/") + } else { + utils.DoRedirect(w, r, "/auth/signin") + } } } @@ -268,19 +286,31 @@ func HandleVerifyResendComp(db *sql.DB) http.HandlerFunc { } func sendVerificationEmail(db *sql.DB, r *http.Request, userId string, email string) { - registerComp := tempMail.Register(userId) + var b []byte = make([]byte, 32) + _, err := rand.Reader.Read(b) + if err != nil { + slog.Error("Could not generate token: " + err.Error()) + return + } + token := base64.StdEncoding.EncodeToString(b) - var writer strings.Builder + _, err = db.Exec("INSERT INTO user_token (user_uuid, type, token, created_at) VALUES (?, 'email_verify', ?, datetime())", userId, token) + if err != nil { + slog.Error("Could not insert token: " + err.Error()) + return + } - registerComp.Render(r.Context(), &writer) - utils.SendMail(email, "Welcome to ME-FIT", writer.String()) + var w strings.Builder + tempMail.Register(token).Render(r.Context(), &w) + + utils.SendMail(email, "Welcome to ME-FIT", w.String()) } func tryCreateSessionAndSetCookie(r *http.Request, w http.ResponseWriter, db *sql.DB, user_uuid uuid.UUID) bool { var session_id_bytes []byte = make([]byte, 32) _, err := rand.Reader.Read(session_id_bytes) if err != nil { - slog.Error("Could not generate session ID: %v", err) + slog.Error("Could not generate session ID: " + err.Error()) auth.Error("Internal Server Error").Render(r.Context(), w) return false } diff --git a/template/mail/register.templ b/template/mail/register.templ index 69411c4..c8f6a0f 100644 --- a/template/mail/register.templ +++ b/template/mail/register.templ @@ -12,7 +12,7 @@ templ Register(mailCode string) {

Thank you for Sign Up!

-

Click