From 7a3496869ba798e05e5978cf35ef7049fcbaa2e7 Mon Sep 17 00:00:00 2001 From: Jason Volk Date: Tue, 26 Aug 2025 19:55:44 +0000 Subject: [PATCH] Remove associated pushers on device delete. (fixes #120) Signed-off-by: Jason Volk --- src/api/client/account.rs | 28 +--------------------------- src/service/pusher/mod.rs | 24 +++++++++++++++++++++++- src/service/users/device.rs | 17 ++++++++++++++++- 3 files changed, 40 insertions(+), 29 deletions(-) diff --git a/src/api/client/account.rs b/src/api/client/account.rs index 5cccbd76..3dfbd9d5 100644 --- a/src/api/client/account.rs +++ b/src/api/client/account.rs @@ -9,10 +9,7 @@ use ruma::api::client::{ }, uiaa::{AuthFlow, AuthType, UiaaInfo}, }; -use tuwunel_core::{ - Err, Error, Result, err, info, utils, - utils::{ReadyExt, stream::BroadbandExt}, -}; +use tuwunel_core::{Err, Error, Result, err, info, utils, utils::ReadyExt}; use super::SESSION_ID_LENGTH; use crate::Ruma; @@ -93,29 +90,6 @@ pub(crate) async fn change_password_route( .ready_filter(|id| *id != body.sender_device()) .for_each(|id| services.users.remove_device(sender_user, id)) .await; - - // Remove all pushers except the ones associated with this session - services - .pusher - .get_pushkeys(sender_user) - .map(ToOwned::to_owned) - .broad_filter_map(async |pushkey| { - services - .pusher - .get_pusher_device(&pushkey) - .await - .ok() - .filter(|pusher_device| pusher_device != body.sender_device()) - .is_some() - .then_some(pushkey) - }) - .for_each(async |pushkey| { - services - .pusher - .delete_pusher(sender_user, &pushkey) - .await; - }) - .await; } info!("User {sender_user} changed their password."); diff --git a/src/service/pusher/mod.rs b/src/service/pusher/mod.rs index c0e0ed7d..37869a11 100644 --- a/src/service/pusher/mod.rs +++ b/src/service/pusher/mod.rs @@ -24,7 +24,10 @@ use tuwunel_core::{ Err, Result, debug_warn, err, matrix::Event, trace, - utils::{stream::TryIgnore, string_from_bytes}, + utils::{ + stream::{BroadbandExt, TryIgnore}, + string_from_bytes, + }, warn, }; use tuwunel_database::{Deserialized, Ignore, Interfix, Json, Map}; @@ -134,6 +137,25 @@ impl Service { .ok(); } + pub async fn get_device_pushkeys( + &self, + sender: &UserId, + device_id: &DeviceId, + ) -> Vec { + self.get_pushkeys(sender) + .map(ToOwned::to_owned) + .broad_filter_map(async |pushkey| { + self.get_pusher_device(&pushkey) + .await + .ok() + .filter(|pusher_device| pusher_device == device_id) + .is_some() + .then_some(pushkey) + }) + .collect() + .await + } + pub async fn get_pusher_device(&self, pushkey: &str) -> Result { self.db .pushkey_deviceid diff --git a/src/service/users/device.rs b/src/service/users/device.rs index 49fbdf4d..544902a5 100644 --- a/src/service/users/device.rs +++ b/src/service/users/device.rs @@ -13,7 +13,7 @@ use tuwunel_core::{ Err, Result, at, implement, utils::{ self, ReadyExt, - stream::TryIgnore, + stream::{IterStream, TryIgnore}, time::{duration_since_epoch, timepoint_from_epoch, timepoint_from_now}, }, }; @@ -70,6 +70,21 @@ pub async fn remove_device(&self, user_id: &UserId, device_id: &DeviceId) { .ready_for_each(|key| self.db.todeviceid_events.remove(key)) .await; + // Remove pushers + self.services + .pusher + .get_device_pushkeys(user_id, device_id) + .map(Vec::into_iter) + .map(IterStream::stream) + .flatten_stream() + .for_each(async |pushkey| { + self.services + .pusher + .delete_pusher(user_id, &pushkey) + .await; + }) + .await; + // TODO: Remove onetimekeys increment(&self.db.userid_devicelistversion, user_id.as_bytes());