2024-07-16 08:05:25 +00:00
|
|
|
use axum::extract::State;
|
2024-06-10 21:04:51 -04:00
|
|
|
use axum_client_ip::InsecureClientIp;
|
2024-08-08 17:18:30 +00:00
|
|
|
use futures::{FutureExt, StreamExt};
|
2020-07-30 18:14:47 +02:00
|
|
|
use ruma::{
|
2025-02-23 01:17:45 -05:00
|
|
|
OwnedRoomId, UserId,
|
2020-07-30 18:14:47 +02:00
|
|
|
api::client::{
|
2022-02-18 15:33:14 +01:00
|
|
|
account::{
|
2025-07-22 22:56:40 +00:00
|
|
|
ThirdPartyIdRemovalStatus, change_password, deactivate, get_3pids,
|
2024-12-15 00:05:47 -05:00
|
|
|
request_3pid_management_token_via_email, request_3pid_management_token_via_msisdn,
|
2025-02-23 01:17:45 -05:00
|
|
|
whoami,
|
2020-07-30 18:14:47 +02:00
|
|
|
},
|
2022-02-18 15:33:14 +01:00
|
|
|
uiaa::{AuthFlow, AuthType, UiaaInfo},
|
2020-07-30 18:14:47 +02:00
|
|
|
},
|
2024-09-15 12:22:46 -04:00
|
|
|
events::{
|
2025-07-22 22:56:40 +00:00
|
|
|
StateEventType,
|
2025-04-26 23:04:58 +00:00
|
|
|
room::power_levels::{RoomPowerLevels, RoomPowerLevelsEventContent},
|
2024-09-15 12:22:46 -04:00
|
|
|
},
|
2020-07-30 18:14:47 +02:00
|
|
|
};
|
2025-04-22 01:41:02 +00:00
|
|
|
use tuwunel_core::{
|
2025-07-22 22:56:40 +00:00
|
|
|
Err, Error, Result, err, info,
|
2025-04-27 09:34:07 +00:00
|
|
|
matrix::{Event, pdu::PduBuilder},
|
2025-04-22 01:41:02 +00:00
|
|
|
utils,
|
|
|
|
|
utils::{ReadyExt, stream::BroadbandExt},
|
|
|
|
|
warn,
|
|
|
|
|
};
|
|
|
|
|
use tuwunel_service::Services;
|
2020-07-30 18:14:47 +02:00
|
|
|
|
2025-07-22 22:56:40 +00:00
|
|
|
use super::SESSION_ID_LENGTH;
|
2024-07-22 07:43:51 +00:00
|
|
|
use crate::Ruma;
|
2020-07-30 18:14:47 +02:00
|
|
|
|
2020-07-31 14:40:28 +02:00
|
|
|
/// # `POST /_matrix/client/r0/account/password`
|
|
|
|
|
///
|
|
|
|
|
/// Changes the password of this account.
|
|
|
|
|
///
|
2021-08-31 19:14:37 +02:00
|
|
|
/// - Requires UIAA to verify user password
|
|
|
|
|
/// - Changes the password of the sender user
|
|
|
|
|
/// - The password hash is calculated using argon2 with 32 character salt, the
|
|
|
|
|
/// plain password is
|
|
|
|
|
/// not saved
|
|
|
|
|
///
|
|
|
|
|
/// If logout_devices is true it does the following for each device except the
|
|
|
|
|
/// sender device:
|
|
|
|
|
/// - Invalidates access token
|
|
|
|
|
/// - Deletes device metadata (device id, device display name, last seen ip,
|
|
|
|
|
/// last seen ts)
|
|
|
|
|
/// - Forgets to-device events
|
|
|
|
|
/// - Triggers device list updates
|
2024-06-17 04:12:11 +00:00
|
|
|
#[tracing::instrument(skip_all, fields(%client), name = "change_password")]
|
2024-04-22 23:48:57 -04:00
|
|
|
pub(crate) async fn change_password_route(
|
2024-12-15 00:05:47 -05:00
|
|
|
State(services): State<crate::State>,
|
|
|
|
|
InsecureClientIp(client): InsecureClientIp,
|
2024-07-16 08:05:25 +00:00
|
|
|
body: Ruma<change_password::v3::Request>,
|
2024-04-22 23:48:57 -04:00
|
|
|
) -> Result<change_password::v3::Response> {
|
2024-07-05 16:36:05 -04:00
|
|
|
// Authentication for this endpoint was made optional, but we need
|
|
|
|
|
// authentication currently
|
|
|
|
|
let sender_user = body
|
|
|
|
|
.sender_user
|
|
|
|
|
.as_ref()
|
2025-03-02 23:16:30 -05:00
|
|
|
.ok_or_else(|| err!(Request(MissingToken("Missing access token."))))?;
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2020-07-30 18:14:47 +02:00
|
|
|
let mut uiaainfo = UiaaInfo {
|
2024-12-15 00:05:47 -05:00
|
|
|
flows: vec![AuthFlow { stages: vec![AuthType::Password] }],
|
2020-07-30 18:14:47 +02:00
|
|
|
completed: Vec::new(),
|
2024-03-02 20:55:02 -05:00
|
|
|
params: Box::default(),
|
2020-07-30 18:14:47 +02:00
|
|
|
session: None,
|
|
|
|
|
auth_error: None,
|
|
|
|
|
};
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2025-02-23 01:17:45 -05:00
|
|
|
match &body.auth {
|
|
|
|
|
| Some(auth) => {
|
|
|
|
|
let (worked, uiaainfo) = services
|
|
|
|
|
.uiaa
|
2025-04-26 23:06:43 +00:00
|
|
|
.try_auth(sender_user, body.sender_device(), auth, &uiaainfo)
|
2025-02-23 01:17:45 -05:00
|
|
|
.await?;
|
2024-08-08 17:18:30 +00:00
|
|
|
|
2025-02-23 01:17:45 -05:00
|
|
|
if !worked {
|
|
|
|
|
return Err(Error::Uiaa(uiaainfo));
|
|
|
|
|
}
|
2024-08-08 17:18:30 +00:00
|
|
|
|
2025-02-23 01:17:45 -05:00
|
|
|
// Success!
|
|
|
|
|
},
|
|
|
|
|
| _ => match body.json_body {
|
2025-03-02 23:16:30 -05:00
|
|
|
| Some(ref json) => {
|
2025-02-23 01:17:45 -05:00
|
|
|
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
|
|
|
|
services
|
|
|
|
|
.uiaa
|
2025-04-26 23:06:43 +00:00
|
|
|
.create(sender_user, body.sender_device(), &uiaainfo, json);
|
2024-08-08 17:18:30 +00:00
|
|
|
|
2025-02-23 01:17:45 -05:00
|
|
|
return Err(Error::Uiaa(uiaainfo));
|
|
|
|
|
},
|
|
|
|
|
| _ => {
|
2025-03-02 23:16:30 -05:00
|
|
|
return Err!(Request(NotJson("JSON body is not valid")));
|
2025-02-23 01:17:45 -05:00
|
|
|
},
|
|
|
|
|
},
|
2020-07-30 18:14:47 +02:00
|
|
|
}
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2024-07-16 08:05:25 +00:00
|
|
|
services
|
2024-03-25 17:05:11 -04:00
|
|
|
.users
|
2025-04-19 18:48:14 +02:00
|
|
|
.set_password(sender_user, Some(&body.new_password))
|
|
|
|
|
.await?;
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2021-01-16 14:48:24 -07:00
|
|
|
if body.logout_devices {
|
|
|
|
|
// Logout all devices except the current one
|
2024-08-08 17:18:30 +00:00
|
|
|
services
|
2024-03-25 17:05:11 -04:00
|
|
|
.users
|
|
|
|
|
.all_device_ids(sender_user)
|
2025-04-26 23:06:43 +00:00
|
|
|
.ready_filter(|id| *id != body.sender_device())
|
2024-08-08 17:18:30 +00:00
|
|
|
.for_each(|id| services.users.remove_device(sender_user, id))
|
|
|
|
|
.await;
|
2025-03-19 20:55:14 -04:00
|
|
|
|
|
|
|
|
// Remove all pushers except the ones associated with this session
|
|
|
|
|
services
|
|
|
|
|
.pusher
|
|
|
|
|
.get_pushkeys(sender_user)
|
|
|
|
|
.map(ToOwned::to_owned)
|
2025-04-26 23:06:43 +00:00
|
|
|
.broad_filter_map(async |pushkey| {
|
2025-03-19 20:55:14 -04:00
|
|
|
services
|
|
|
|
|
.pusher
|
|
|
|
|
.get_pusher_device(&pushkey)
|
|
|
|
|
.await
|
|
|
|
|
.ok()
|
2025-04-26 23:06:43 +00:00
|
|
|
.filter(|pusher_device| pusher_device != body.sender_device())
|
2025-03-19 20:55:14 -04:00
|
|
|
.is_some()
|
|
|
|
|
.then_some(pushkey)
|
|
|
|
|
})
|
2025-04-26 23:06:43 +00:00
|
|
|
.for_each(async |pushkey| {
|
2025-04-22 04:42:26 +00:00
|
|
|
services
|
|
|
|
|
.pusher
|
|
|
|
|
.delete_pusher(sender_user, &pushkey)
|
|
|
|
|
.await;
|
2025-03-19 20:55:14 -04:00
|
|
|
})
|
|
|
|
|
.await;
|
2020-07-30 18:14:47 +02:00
|
|
|
}
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2024-06-10 21:04:51 -04:00
|
|
|
info!("User {sender_user} changed their password.");
|
2024-10-24 22:19:18 -04:00
|
|
|
|
2025-01-24 07:02:56 +00:00
|
|
|
if services.server.config.admin_room_notices {
|
2024-10-24 22:19:18 -04:00
|
|
|
services
|
|
|
|
|
.admin
|
2025-04-26 23:04:58 +00:00
|
|
|
.notice(&format!("User {sender_user} changed their password."))
|
|
|
|
|
.await;
|
2024-10-24 22:19:18 -04:00
|
|
|
}
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2022-02-18 15:33:14 +01:00
|
|
|
Ok(change_password::v3::Response {})
|
2020-07-30 18:14:47 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-31 14:40:28 +02:00
|
|
|
/// # `GET _matrix/client/r0/account/whoami`
|
|
|
|
|
///
|
2024-03-22 22:44:31 -04:00
|
|
|
/// Get `user_id` of the sender user.
|
2020-07-31 14:40:28 +02:00
|
|
|
///
|
2021-08-31 19:14:37 +02:00
|
|
|
/// Note: Also works for Application Services
|
2024-07-16 08:05:25 +00:00
|
|
|
pub(crate) async fn whoami_route(
|
2024-12-15 00:05:47 -05:00
|
|
|
State(services): State<crate::State>,
|
|
|
|
|
body: Ruma<whoami::v3::Request>,
|
2024-07-16 08:05:25 +00:00
|
|
|
) -> Result<whoami::v3::Response> {
|
2022-02-18 15:33:14 +01:00
|
|
|
Ok(whoami::v3::Response {
|
2025-04-26 23:06:43 +00:00
|
|
|
user_id: body.sender_user().to_owned(),
|
|
|
|
|
device_id: body.sender_device.clone(),
|
|
|
|
|
is_guest: services
|
|
|
|
|
.users
|
|
|
|
|
.is_deactivated(body.sender_user())
|
|
|
|
|
.await? && body.appservice_info.is_none(),
|
2022-01-22 16:58:32 +01:00
|
|
|
})
|
2020-07-30 18:14:47 +02:00
|
|
|
}
|
|
|
|
|
|
2020-07-31 14:40:28 +02:00
|
|
|
/// # `POST /_matrix/client/r0/account/deactivate`
|
|
|
|
|
///
|
2021-08-31 19:14:37 +02:00
|
|
|
/// Deactivate sender user account.
|
2020-07-31 14:40:28 +02:00
|
|
|
///
|
|
|
|
|
/// - Leaves all rooms and rejects all invitations
|
|
|
|
|
/// - Invalidates all access tokens
|
2021-08-31 19:14:37 +02:00
|
|
|
/// - Deletes all device metadata (device id, device display name, last seen ip,
|
|
|
|
|
/// last seen ts)
|
|
|
|
|
/// - Forgets all to-device events
|
|
|
|
|
/// - Triggers device list updates
|
2020-07-31 14:40:28 +02:00
|
|
|
/// - Removes ability to log in again
|
2024-06-17 04:12:11 +00:00
|
|
|
#[tracing::instrument(skip_all, fields(%client), name = "deactivate")]
|
2024-06-10 21:04:51 -04:00
|
|
|
pub(crate) async fn deactivate_route(
|
2024-12-15 00:05:47 -05:00
|
|
|
State(services): State<crate::State>,
|
|
|
|
|
InsecureClientIp(client): InsecureClientIp,
|
2024-07-16 08:05:25 +00:00
|
|
|
body: Ruma<deactivate::v3::Request>,
|
2024-06-10 21:04:51 -04:00
|
|
|
) -> Result<deactivate::v3::Response> {
|
2024-07-05 16:36:05 -04:00
|
|
|
// Authentication for this endpoint was made optional, but we need
|
|
|
|
|
// authentication currently
|
|
|
|
|
let sender_user = body
|
|
|
|
|
.sender_user
|
|
|
|
|
.as_ref()
|
2025-03-02 23:16:30 -05:00
|
|
|
.ok_or_else(|| err!(Request(MissingToken("Missing access token."))))?;
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2020-07-30 18:14:47 +02:00
|
|
|
let mut uiaainfo = UiaaInfo {
|
2024-12-15 00:05:47 -05:00
|
|
|
flows: vec![AuthFlow { stages: vec![AuthType::Password] }],
|
2020-07-30 18:14:47 +02:00
|
|
|
completed: Vec::new(),
|
2024-03-02 20:55:02 -05:00
|
|
|
params: Box::default(),
|
2020-07-30 18:14:47 +02:00
|
|
|
session: None,
|
|
|
|
|
auth_error: None,
|
|
|
|
|
};
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2025-02-23 01:17:45 -05:00
|
|
|
match &body.auth {
|
|
|
|
|
| Some(auth) => {
|
|
|
|
|
let (worked, uiaainfo) = services
|
|
|
|
|
.uiaa
|
2025-04-26 23:06:43 +00:00
|
|
|
.try_auth(sender_user, body.sender_device(), auth, &uiaainfo)
|
2025-02-23 01:17:45 -05:00
|
|
|
.await?;
|
2024-08-08 17:18:30 +00:00
|
|
|
|
2025-02-23 01:17:45 -05:00
|
|
|
if !worked {
|
|
|
|
|
return Err(Error::Uiaa(uiaainfo));
|
|
|
|
|
}
|
|
|
|
|
// Success!
|
|
|
|
|
},
|
|
|
|
|
| _ => match body.json_body {
|
2025-03-02 23:16:30 -05:00
|
|
|
| Some(ref json) => {
|
2025-02-23 01:17:45 -05:00
|
|
|
uiaainfo.session = Some(utils::random_string(SESSION_ID_LENGTH));
|
|
|
|
|
services
|
|
|
|
|
.uiaa
|
2025-04-26 23:06:43 +00:00
|
|
|
.create(sender_user, body.sender_device(), &uiaainfo, json);
|
2024-08-08 17:18:30 +00:00
|
|
|
|
2025-02-23 01:17:45 -05:00
|
|
|
return Err(Error::Uiaa(uiaainfo));
|
|
|
|
|
},
|
|
|
|
|
| _ => {
|
2025-03-02 23:16:30 -05:00
|
|
|
return Err!(Request(NotJson("JSON body is not valid")));
|
2025-02-23 01:17:45 -05:00
|
|
|
},
|
|
|
|
|
},
|
2020-07-30 18:14:47 +02:00
|
|
|
}
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2024-06-11 01:15:55 -04:00
|
|
|
// Remove profile pictures and display name
|
2024-07-16 08:05:25 +00:00
|
|
|
let all_joined_rooms: Vec<OwnedRoomId> = services
|
2024-06-11 01:15:55 -04:00
|
|
|
.rooms
|
|
|
|
|
.state_cache
|
|
|
|
|
.rooms_joined(sender_user)
|
2024-08-08 17:18:30 +00:00
|
|
|
.map(Into::into)
|
|
|
|
|
.collect()
|
|
|
|
|
.await;
|
2024-06-11 01:15:55 -04:00
|
|
|
|
2024-12-07 00:46:22 -05:00
|
|
|
super::update_displayname(&services, sender_user, None, &all_joined_rooms).await;
|
|
|
|
|
super::update_avatar_url(&services, sender_user, None, None, &all_joined_rooms).await;
|
2024-08-08 17:18:30 +00:00
|
|
|
|
2025-04-26 08:23:57 +00:00
|
|
|
full_user_deactivate(&services, sender_user, &all_joined_rooms)
|
|
|
|
|
.boxed()
|
|
|
|
|
.await?;
|
2024-06-10 23:55:41 -04:00
|
|
|
|
2024-06-10 21:04:51 -04:00
|
|
|
info!("User {sender_user} deactivated their account.");
|
2024-10-24 22:19:18 -04:00
|
|
|
|
2025-01-24 07:02:56 +00:00
|
|
|
if services.server.config.admin_room_notices {
|
2024-10-24 22:19:18 -04:00
|
|
|
services
|
|
|
|
|
.admin
|
2025-04-26 23:04:58 +00:00
|
|
|
.notice(&format!("User {sender_user} deactivated their account."))
|
|
|
|
|
.await;
|
2024-10-24 22:19:18 -04:00
|
|
|
}
|
2024-03-05 19:48:54 -05:00
|
|
|
|
2022-02-18 15:33:14 +01:00
|
|
|
Ok(deactivate::v3::Response {
|
2020-07-30 18:14:47 +02:00
|
|
|
id_server_unbind_result: ThirdPartyIdRemovalStatus::NoSupport,
|
2022-01-22 16:58:32 +01:00
|
|
|
})
|
2020-07-30 18:14:47 +02:00
|
|
|
}
|
2021-01-26 21:54:35 -05:00
|
|
|
|
2022-10-25 20:47:41 +00:00
|
|
|
/// # `GET _matrix/client/v3/account/3pid`
|
2021-08-09 12:29:35 -07:00
|
|
|
///
|
|
|
|
|
/// Get a list of third party identifiers associated with this account.
|
2021-08-31 19:14:37 +02:00
|
|
|
///
|
|
|
|
|
/// - Currently always returns empty list
|
2024-12-15 00:05:47 -05:00
|
|
|
pub(crate) async fn third_party_route(
|
|
|
|
|
body: Ruma<get_3pids::v3::Request>,
|
|
|
|
|
) -> Result<get_3pids::v3::Response> {
|
2025-04-22 04:42:26 +00:00
|
|
|
let _sender_user = body
|
|
|
|
|
.sender_user
|
|
|
|
|
.as_ref()
|
|
|
|
|
.expect("user is authenticated");
|
2021-01-26 21:54:35 -05:00
|
|
|
|
2022-02-18 15:33:14 +01:00
|
|
|
Ok(get_3pids::v3::Response::new(Vec::new()))
|
2021-01-26 21:54:35 -05:00
|
|
|
}
|
2022-10-25 20:47:41 +00:00
|
|
|
|
|
|
|
|
/// # `POST /_matrix/client/v3/account/3pid/email/requestToken`
|
|
|
|
|
///
|
|
|
|
|
/// "This API should be used to request validation tokens when adding an email
|
|
|
|
|
/// address to an account"
|
|
|
|
|
///
|
|
|
|
|
/// - 403 signals that The homeserver does not allow the third party identifier
|
|
|
|
|
/// as a contact option.
|
2024-04-22 23:48:57 -04:00
|
|
|
pub(crate) async fn request_3pid_management_token_via_email_route(
|
2022-12-14 13:09:10 +01:00
|
|
|
_body: Ruma<request_3pid_management_token_via_email::v3::Request>,
|
2022-10-25 20:47:41 +00:00
|
|
|
) -> Result<request_3pid_management_token_via_email::v3::Response> {
|
2025-03-02 23:16:30 -05:00
|
|
|
Err!(Request(ThreepidDenied("Third party identifiers are not implemented")))
|
2022-10-25 20:47:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// # `POST /_matrix/client/v3/account/3pid/msisdn/requestToken`
|
|
|
|
|
///
|
|
|
|
|
/// "This API should be used to request validation tokens when adding an phone
|
|
|
|
|
/// number to an account"
|
|
|
|
|
///
|
|
|
|
|
/// - 403 signals that The homeserver does not allow the third party identifier
|
|
|
|
|
/// as a contact option.
|
2024-04-22 23:48:57 -04:00
|
|
|
pub(crate) async fn request_3pid_management_token_via_msisdn_route(
|
2022-12-14 13:09:10 +01:00
|
|
|
_body: Ruma<request_3pid_management_token_via_msisdn::v3::Request>,
|
2022-10-25 20:47:41 +00:00
|
|
|
) -> Result<request_3pid_management_token_via_msisdn::v3::Response> {
|
2025-03-02 23:16:30 -05:00
|
|
|
Err!(Request(ThreepidDenied("Third party identifiers are not implemented")))
|
2022-10-25 20:47:41 +00:00
|
|
|
}
|
2024-05-22 20:57:34 -04:00
|
|
|
|
2024-09-15 12:08:07 -04:00
|
|
|
/// Runs through all the deactivation steps:
|
|
|
|
|
///
|
|
|
|
|
/// - Mark as deactivated
|
|
|
|
|
/// - Removing display name
|
|
|
|
|
/// - Removing avatar URL and blurhash
|
|
|
|
|
/// - Removing all profile data
|
2024-09-15 12:22:46 -04:00
|
|
|
/// - Leaving all rooms (and forgets all of them)
|
2024-09-15 12:08:07 -04:00
|
|
|
pub async fn full_user_deactivate(
|
2024-12-15 00:05:47 -05:00
|
|
|
services: &Services,
|
|
|
|
|
user_id: &UserId,
|
|
|
|
|
all_joined_rooms: &[OwnedRoomId],
|
2025-07-08 12:08:13 +00:00
|
|
|
) -> Result {
|
2025-04-22 04:42:26 +00:00
|
|
|
services
|
|
|
|
|
.users
|
|
|
|
|
.deactivate_account(user_id)
|
|
|
|
|
.await
|
|
|
|
|
.ok();
|
2025-04-27 02:39:28 +00:00
|
|
|
|
2024-12-07 00:46:22 -05:00
|
|
|
super::update_displayname(services, user_id, None, all_joined_rooms).await;
|
|
|
|
|
super::update_avatar_url(services, user_id, None, None, all_joined_rooms).await;
|
2024-09-15 12:08:07 -04:00
|
|
|
|
2024-08-08 17:18:30 +00:00
|
|
|
services
|
2024-09-15 12:08:07 -04:00
|
|
|
.users
|
|
|
|
|
.all_profile_keys(user_id)
|
2024-12-15 00:05:47 -05:00
|
|
|
.ready_for_each(|(profile_key, _)| {
|
2025-04-22 04:42:26 +00:00
|
|
|
services
|
|
|
|
|
.users
|
|
|
|
|
.set_profile_key(user_id, &profile_key, None);
|
2024-12-15 00:05:47 -05:00
|
|
|
})
|
2024-08-08 17:18:30 +00:00
|
|
|
.await;
|
2024-09-15 12:22:46 -04:00
|
|
|
|
|
|
|
|
for room_id in all_joined_rooms {
|
2024-08-08 17:18:30 +00:00
|
|
|
let state_lock = services.rooms.state.mutex.lock(room_id).await;
|
2024-09-15 12:22:46 -04:00
|
|
|
|
|
|
|
|
let room_power_levels = services
|
|
|
|
|
.rooms
|
|
|
|
|
.state_accessor
|
2024-12-15 00:05:47 -05:00
|
|
|
.room_state_get_content::<RoomPowerLevelsEventContent>(
|
|
|
|
|
room_id,
|
|
|
|
|
&StateEventType::RoomPowerLevels,
|
|
|
|
|
"",
|
|
|
|
|
)
|
2024-08-08 17:18:30 +00:00
|
|
|
.await
|
|
|
|
|
.ok();
|
2024-09-15 12:22:46 -04:00
|
|
|
|
2024-12-15 00:05:47 -05:00
|
|
|
let user_can_demote_self =
|
|
|
|
|
room_power_levels
|
|
|
|
|
.as_ref()
|
|
|
|
|
.is_some_and(|power_levels_content| {
|
|
|
|
|
RoomPowerLevels::from(power_levels_content.clone())
|
|
|
|
|
.user_can_change_user_power_level(user_id, user_id)
|
|
|
|
|
}) || services
|
|
|
|
|
.rooms
|
|
|
|
|
.state_accessor
|
|
|
|
|
.room_state_get(room_id, &StateEventType::RoomCreate, "")
|
|
|
|
|
.await
|
2025-04-27 09:34:07 +00:00
|
|
|
.is_ok_and(|event| event.sender() == user_id);
|
2024-09-15 12:22:46 -04:00
|
|
|
|
|
|
|
|
if user_can_demote_self {
|
|
|
|
|
let mut power_levels_content = room_power_levels.unwrap_or_default();
|
|
|
|
|
power_levels_content.users.remove(user_id);
|
|
|
|
|
|
|
|
|
|
// ignore errors so deactivation doesn't fail
|
2025-02-23 01:17:45 -05:00
|
|
|
match services
|
2024-09-15 12:22:46 -04:00
|
|
|
.rooms
|
|
|
|
|
.timeline
|
|
|
|
|
.build_and_append_pdu(
|
2024-10-04 20:25:32 +00:00
|
|
|
PduBuilder::state(String::new(), &power_levels_content),
|
2024-09-15 12:22:46 -04:00
|
|
|
user_id,
|
2024-08-08 17:18:30 +00:00
|
|
|
room_id,
|
2024-09-15 12:22:46 -04:00
|
|
|
&state_lock,
|
|
|
|
|
)
|
|
|
|
|
.await
|
|
|
|
|
{
|
2025-02-23 01:17:45 -05:00
|
|
|
| Err(e) => {
|
|
|
|
|
warn!(%room_id, %user_id, "Failed to demote user's own power level: {e}");
|
|
|
|
|
},
|
|
|
|
|
| _ => {
|
|
|
|
|
info!("Demoted {user_id} in {room_id} as part of account deactivation");
|
|
|
|
|
},
|
2024-09-15 12:22:46 -04:00
|
|
|
}
|
|
|
|
|
}
|
2024-09-15 12:08:07 -04:00
|
|
|
}
|
|
|
|
|
|
2025-04-26 08:23:57 +00:00
|
|
|
super::leave_all_rooms(services, user_id)
|
|
|
|
|
.boxed()
|
|
|
|
|
.await;
|
2024-09-15 12:22:46 -04:00
|
|
|
|
2024-09-15 12:08:07 -04:00
|
|
|
Ok(())
|
|
|
|
|
}
|