feat(auth): enable users to delete their account #164

This commit is contained in:
2024-09-11 18:17:44 +02:00
parent 2542942d78
commit 9039998e98
5 changed files with 129 additions and 15 deletions

View File

@@ -1,6 +1,7 @@
package service
import (
"context"
"crypto/rand"
"crypto/subtle"
"database/sql"
@@ -84,6 +85,24 @@ func HandleSignUpVerifyPage(db *sql.DB) http.HandlerFunc {
}
}
func HandleDeleteAccountPage(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// An enverified email should be able to delete their account
user := utils.GetUserFromSession(db, r)
if user == nil {
utils.DoRedirect(w, r, "/auth/signin")
} else {
userComp := UserInfoComp(user)
comp := auth.DeleteAccountComp()
err := template.Layout(comp, userComp).Render(r.Context(), w)
if err != nil {
utils.LogError("Failed to render verify page", err)
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}
}
}
}
func HandleSignUpVerifyResponsePage(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
token := r.URL.Query().Get("token")
@@ -283,6 +302,48 @@ func HandleSignOutComp(db *sql.DB) http.HandlerFunc {
}
}
func HandleDeleteAccountComp(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
user := utils.GetUserFromSession(db, r)
if user == nil {
utils.DoRedirect(w, r, "/auth/signin")
return
}
_, err := db.Exec("DELETE FROM workout WHERE user_id = ?", user.Id)
if err != nil {
utils.LogError("Could not delete workouts", err)
utils.TriggerToast(w, r, "error", "Internal Server Error")
return
}
_, err = db.Exec("DELETE FROM user_token WHERE user_uuid = ?", user.Id)
if err != nil {
utils.LogError("Could not delete user tokens", err)
utils.TriggerToast(w, r, "error", "Internal Server Error")
return
}
_, err = db.Exec("DELETE FROM session WHERE user_uuid = ?", user.Id)
if err != nil {
utils.LogError("Could not delete sessions", err)
utils.TriggerToast(w, r, "error", "Internal Server Error")
return
}
_, err = db.Exec("DELETE FROM user WHERE user_uuid = ?", user.Id)
if err != nil {
utils.LogError("Could not delete user", err)
utils.TriggerToast(w, r, "error", "Internal Server Error")
return
}
go utils.SendMail(user.Email, "Account deleted", "Your account has been deleted")
utils.DoRedirect(w, r, "/")
}
}
func HandleVerifyResendComp(db *sql.DB) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
user := utils.GetUserFromSession(db, r)
@@ -298,23 +359,36 @@ func HandleVerifyResendComp(db *sql.DB) http.HandlerFunc {
}
func sendVerificationEmail(db *sql.DB, r *http.Request, userId string, email string) {
var b []byte = make([]byte, 32)
_, err := rand.Reader.Read(b)
if err != nil {
utils.LogError("Could not generate token", err)
var token string
err := db.QueryRow("SELECT token FROM user_token WHERE user_uuid = ? AND type = 'email_verify'", userId).Scan(&token)
if err != nil && err != sql.ErrNoRows {
utils.LogError("Could not get token", err)
return
}
token := base64.StdEncoding.EncodeToString(b)
_, err = db.Exec("INSERT INTO user_token (user_uuid, type, token, created_at) VALUES (?, 'email_verify', ?, datetime())", userId, token)
if err != nil {
utils.LogError("Could not insert token", err)
return
if token == "" {
var b []byte = make([]byte, 32)
_, err = rand.Reader.Read(b)
if err != nil {
utils.LogError("Could not generate token", err)
return
}
token = base64.StdEncoding.EncodeToString(b)
_, err = db.Exec("INSERT INTO user_token (user_uuid, type, token, created_at) VALUES (?, 'email_verify', ?, datetime())", userId, token)
if err != nil {
utils.LogError("Could not insert token", err)
return
}
}
var w strings.Builder
tempMail.Register(token).Render(r.Context(), &w)
err = tempMail.Register(token).Render(context.Background(), &w)
if err != nil {
utils.LogError("Could not render welcome email", err)
return
}
utils.SendMail(email, "Welcome to ME-FIT", w.String())
}