Remove imported unsupported threepids when deactivating a user (#5406)

This commit is contained in:
Quentin Gliech
2026-01-13 17:30:20 +01:00
committed by GitHub
4 changed files with 70 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
{
"db_name": "PostgreSQL",
"query": "\n DELETE FROM user_unsupported_third_party_ids\n WHERE user_id = $1\n ",
"describe": {
"columns": [],
"parameters": {
"Left": [
"Uuid"
]
},
"nullable": []
},
"hash": "f0b4af5a9d6f1cc707a935fd5f34526a54ebbed8eef8f885f3a6723bc8490908"
}

View File

@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
//
@@ -434,6 +435,30 @@ impl UserRepository for PgUserRepository<'_> {
Ok(user)
}
#[tracing::instrument(
name = "db.user.delete_unsupported_threepids",
skip_all,
fields(
db.query.text,
%user.id,
),
err,
)]
async fn delete_unsupported_threepids(&mut self, user: &User) -> Result<usize, Self::Error> {
let res = sqlx::query!(
r#"
DELETE FROM user_unsupported_third_party_ids
WHERE user_id = $1
"#,
Uuid::from(user.id),
)
.traced()
.execute(&mut *self.conn)
.await?;
Ok(res.rows_affected().try_into().unwrap_or(usize::MAX))
}
#[tracing::instrument(
name = "db.user.set_can_request_admin",
skip_all,

View File

@@ -1,3 +1,4 @@
// Copyright 2025, 2026 Element Creations Ltd.
// Copyright 2024, 2025 New Vector Ltd.
// Copyright 2021-2024 The Matrix.org Foundation C.I.C.
//
@@ -295,6 +296,24 @@ pub trait UserRepository: Send + Sync {
/// Returns [`Self::Error`] if the underlying repository fails
async fn reactivate(&mut self, user: User) -> Result<User, Self::Error>;
/// Delete all the unsupported third-party IDs of a [`User`].
///
/// Those were imported by syn2mas and kept in case we wanted to support
/// them later. They still need to be cleaned up when a user deactivates
/// their account.
///
/// Returns the number of deleted third-party IDs.
///
/// # Parameters
///
/// * `user`: The [`User`] whose unsupported third-party IDs should be
/// deleted
///
/// # Errors
///
/// Returns [`Self::Error`] if the underlying repository fails
async fn delete_unsupported_threepids(&mut self, user: &User) -> Result<usize, Self::Error>;
/// Set whether a [`User`] can request admin
///
/// Returns the [`User`] with the new `can_request_admin` value
@@ -367,6 +386,7 @@ repository_impl!(UserRepository:
async fn unlock(&mut self, user: User) -> Result<User, Self::Error>;
async fn deactivate(&mut self, clock: &dyn Clock, user: User) -> Result<User, Self::Error>;
async fn reactivate(&mut self, user: User) -> Result<User, Self::Error>;
async fn delete_unsupported_threepids(&mut self, user: &User) -> Result<usize, Self::Error>;
async fn set_can_request_admin(
&mut self,
user: User,

View File

@@ -119,6 +119,17 @@ impl RunnableJob for DeactivateUserJob {
.map_err(JobError::retry)?;
info!(affected = n, "Removed all email addresses for user");
// Delete all unsupported third-party IDs for the user
let n = repo
.user()
.delete_unsupported_threepids(&user)
.await
.map_err(JobError::retry)?;
info!(
affected = n,
"Removed all unsupported third-party IDs for user"
);
// Before calling back to the homeserver, commit the changes to the database, as
// we want the user to be locked out as soon as possible
repo.save().await.map_err(JobError::retry)?;