From 688d4a1f719d2df4d2626453f4bc042c1874a375 Mon Sep 17 00:00:00 2001
From: KN4CK3R <admin@oldschoolhack.me>
Date: Sun, 4 Feb 2024 15:05:26 +0100
Subject: [PATCH] Unify password changing and invalidate auth tokens (#27625)

- Unify the password changing code
- Invalidate existing auth tokens when changing passwords
---
 models/auth/auth_token.go |  5 +++++
 services/user/delete.go   |  4 ++++
 services/user/update.go   | 12 +++++++++++-
 3 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/models/auth/auth_token.go b/models/auth/auth_token.go
index 65f1b169eb..81f07d1a83 100644
--- a/models/auth/auth_token.go
+++ b/models/auth/auth_token.go
@@ -54,6 +54,11 @@ func DeleteAuthTokenByID(ctx context.Context, id string) error {
 	return err
 }
 
+func DeleteAuthTokensByUserID(ctx context.Context, uid int64) error {
+	_, err := db.GetEngine(ctx).Where(builder.Eq{"user_id": uid}).Delete(&AuthToken{})
+	return err
+}
+
 func DeleteExpiredAuthTokens(ctx context.Context) error {
 	_, err := db.GetEngine(ctx).Where(builder.Lt{"expires_unix": timeutil.TimeStampNow()}).Delete(&AuthToken{})
 	return err
diff --git a/services/user/delete.go b/services/user/delete.go
index 0e9c866171..000910319a 100644
--- a/services/user/delete.go
+++ b/services/user/delete.go
@@ -187,6 +187,10 @@ func deleteUser(ctx context.Context, u *user_model.User, purge bool) (err error)
 	}
 	// ***** END: ExternalLoginUser *****
 
+	if err := auth_model.DeleteAuthTokensByUserID(ctx, u.ID); err != nil {
+		return fmt.Errorf("DeleteAuthTokensByUserID: %w", err)
+	}
+
 	if _, err = db.DeleteByID[user_model.User](ctx, u.ID); err != nil {
 		return fmt.Errorf("delete: %w", err)
 	}
diff --git a/services/user/update.go b/services/user/update.go
index 849757c8b0..cbaf90053a 100644
--- a/services/user/update.go
+++ b/services/user/update.go
@@ -183,6 +183,7 @@ func UpdateAuth(ctx context.Context, u *user_model.User, opts *UpdateAuthOptions
 		u.LoginName = opts.LoginName.Value()
 	}
 
+	deleteAuthTokens := false
 	if opts.Password.Has() && (u.IsLocal() || u.IsOAuth2()) {
 		password := opts.Password.Value()
 
@@ -199,6 +200,8 @@ func UpdateAuth(ctx context.Context, u *user_model.User, opts *UpdateAuthOptions
 		if err := u.SetPassword(password); err != nil {
 			return err
 		}
+
+		deleteAuthTokens = true
 	}
 
 	if opts.MustChangePassword.Has() {
@@ -208,5 +211,12 @@ func UpdateAuth(ctx context.Context, u *user_model.User, opts *UpdateAuthOptions
 		u.ProhibitLogin = opts.ProhibitLogin.Value()
 	}
 
-	return user_model.UpdateUserCols(ctx, u, "login_type", "login_source", "login_name", "passwd", "passwd_hash_algo", "salt", "must_change_password", "prohibit_login")
+	if err := user_model.UpdateUserCols(ctx, u, "login_type", "login_source", "login_name", "passwd", "passwd_hash_algo", "salt", "must_change_password", "prohibit_login"); err != nil {
+		return err
+	}
+
+	if deleteAuthTokens {
+		return auth_model.DeleteAuthTokensByUserID(ctx, u.ID)
+	}
+	return nil
 }