From 32fc629f57e470e20e65f4bf33cc87656a214e96 Mon Sep 17 00:00:00 2001 From: Lucca Dukic <109136188+LuccaBitfly@users.noreply.github.com> Date: Tue, 21 Jan 2025 14:45:15 +0100 Subject: [PATCH 1/3] fix: don't allow deletion of user with active subscription --- handlers/user.go | 74 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 53 insertions(+), 21 deletions(-) diff --git a/handlers/user.go b/handlers/user.go index 7d6c09f00e..630ec04451 100644 --- a/handlers/user.go +++ b/handlers/user.go @@ -975,38 +975,70 @@ func UserAuthorizeConfirmPost(w http.ResponseWriter, r *http.Request) { } } +func getHasUserActiveSubscription(userId uint64) (bool, error) { + var hasUserActiveSubscription bool + err := db.FrontendReaderDB.Get(&hasUserActiveSubscription, ` + SELECT EXISTS ( + SELECT uss.price_id + FROM users_stripe_subscriptions uss + LEFT JOIN users u ON u.stripe_customer_id = uss.customer_id + WHERE uss.active = true AND u.id = $1 + + UNION + + SELECT product_id + FROM users_app_subscriptions uas + LEFT JOIN users u ON u.id = uas.user_id + WHERE uas.active = true AND u.id = $1 + )`, userId) + if err != nil { + return false, err + } + return hasUserActiveSubscription, nil +} + func UserDeletePost(w http.ResponseWriter, r *http.Request) { logger := logger.WithField("route", r.URL.String()) - user, session, err := getUserSession(r) + user, _, err := getUserSession(r) if err != nil { logger.Errorf("error retrieving session: %v", err) http.Error(w, "Internal server error", http.StatusInternalServerError) return } - if user.Authenticated { - err := db.DeleteUserById(user.UserID) - if err != nil { - logger.Errorf("error deleting user by email for user: %v %v", user.UserID, err) - http.Redirect(w, r, "/user/settings", http.StatusSeeOther) - utils.SetFlash(w, r, "", "Error: Could not delete user.") - session.Save(r, w) - http.Redirect(w, r, "/user/settings", http.StatusSeeOther) - return - } - - Logout(w, r) - err = purgeAllSessionsForUser(r.Context(), user.UserID) - if err != nil { - utils.LogError(err, "error purging sessions for user", 0, map[string]interface{}{"userID": user.UserID}) - utils.SetFlash(w, r, authSessionName, authInternalServerErrorFlashMsg) - http.Redirect(w, r, "/login", http.StatusSeeOther) - return - } - } else { + if !user.Authenticated { utils.LogError(nil, "Trying to delete an unauthenticated user", 0) http.Redirect(w, r, "/user/settings", http.StatusSeeOther) return } + // don't allow user to delete account if they have an active subscription + hasUserActiveSubscription, err := getHasUserActiveSubscription(user.UserID) + if err != nil { + logger.Errorf("error checking if user has active subscription: %v", err) + http.Error(w, "Internal server error", http.StatusInternalServerError) + return + } + if hasUserActiveSubscription { + utils.SetFlash(w, r, authSessionName, "Error: You cannot delete your account while you have an active subscription.") + http.Redirect(w, r, "/user/settings", http.StatusSeeOther) + return + } + + err = db.DeleteUserById(user.UserID) + if err != nil { + logger.Errorf("error deleting user by email for user: %v %v", user.UserID, err) + utils.SetFlash(w, r, authSessionName, "Error: Could not delete user.") + http.Redirect(w, r, "/user/settings", http.StatusSeeOther) + return + } + + Logout(w, r) + err = purgeAllSessionsForUser(r.Context(), user.UserID) + if err != nil { + utils.LogError(err, "error purging sessions for user", 0, map[string]interface{}{"userID": user.UserID}) + utils.SetFlash(w, r, authSessionName, authInternalServerErrorFlashMsg) + http.Redirect(w, r, "/login", http.StatusSeeOther) + return + } } func UserUpdateFlagsPost(w http.ResponseWriter, r *http.Request) { From 354bc3d2b24168f47cd07c7378ac0c1af11f9f73 Mon Sep 17 00:00:00 2001 From: Lucca Dukic <109136188+LuccaBitfly@users.noreply.github.com> Date: Wed, 22 Jan 2025 10:07:48 +0100 Subject: [PATCH 2/3] feat: disable delete button for active subscription users --- handlers/user.go | 10 ++++++++++ templates/user/settings.html | 10 +++++++--- types/templates.go | 17 +++++++++-------- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/handlers/user.go b/handlers/user.go index 630ec04451..cb8ee9290a 100644 --- a/handlers/user.go +++ b/handlers/user.go @@ -115,6 +115,16 @@ func UserSettings(w http.ResponseWriter, r *http.Request) { } } + // disable delete button if user has active subscription + hasUserActiveSubscription, err := getHasUserActiveSubscription(user.UserID) + if err != nil { + logger.Errorf("Error retrieving the active subscription for user: %v %v", user.UserID, err) + utils.SetFlash(w, r, "", "Error: Something went wrong.") + http.Redirect(w, r, "/user/settings", http.StatusSeeOther) + return + } + userSettingsData.IsUserDeleteDisabled = hasUserActiveSubscription + userSettingsData.ApiStatistics.MaxDaily = &maxDaily userSettingsData.ApiStatistics.MaxMonthly = &maxMonthly diff --git a/templates/user/settings.html b/templates/user/settings.html index 2805989387..9276510118 100644 --- a/templates/user/settings.html +++ b/templates/user/settings.html @@ -460,9 +460,13 @@