Delete Account
+Do you really want to delete all your data? This cannot be undone!
+diff --git a/handler.go b/handler.go
index e4faa5b..20964d7 100644
--- a/handler.go
+++ b/handler.go
@@ -30,11 +30,13 @@ func getHandler(db *sql.DB) http.Handler {
// Don't use auth middleware for these routes, as it makes redirecting very difficult, if the mail is not yet verified
router.Handle("/auth/signin", service.HandleSignInPage(db))
router.Handle("/auth/signup", service.HandleSignUpPage(db))
- router.Handle("/auth/verify", service.HandleSignUpVerifyPage(db)) // Hint for the user to verify their email
+ router.Handle("/auth/verify", service.HandleSignUpVerifyPage(db)) // Hint for the user to verify their email
+ router.Handle("/auth/delete-account", service.HandleDeleteAccountPage(db))
router.Handle("/auth/verify-email", service.HandleSignUpVerifyResponsePage(db)) // The link contained in the email
router.Handle("/api/auth/signup", service.HandleSignUpComp(db))
router.Handle("/api/auth/signin", service.HandleSignInComp(db))
router.Handle("/api/auth/signout", service.HandleSignOutComp(db))
+ router.Handle("/api/auth/delete-account", service.HandleDeleteAccountComp(db))
router.Handle("/api/auth/verify-resend", service.HandleVerifyResendComp(db))
return middleware.Logging(middleware.EnableCors(router))
diff --git a/service/auth.go b/service/auth.go
index d9054fc..6cce269 100644
--- a/service/auth.go
+++ b/service/auth.go
@@ -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())
}
diff --git a/template/auth/delete_account.templ b/template/auth/delete_account.templ
new file mode 100644
index 0000000..8663752
--- /dev/null
+++ b/template/auth/delete_account.templ
@@ -0,0 +1,16 @@
+package auth
+
+templ DeleteAccountComp() {
+ Do you really want to delete all your data? This cannot be undone!Delete Account
+