diff --git a/src/api/admin/rooms/ban.rs b/src/api/admin/rooms/ban.rs index 9a96aad96..c24ff7691 100644 --- a/src/api/admin/rooms/ban.rs +++ b/src/api/admin/rooms/ban.rs @@ -13,7 +13,7 @@ pub(crate) async fn ban_room( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if !services.users.is_admin(sender_user).await { return Err!(Request(Forbidden("Only server administrators can use this endpoint"))); } diff --git a/src/api/admin/rooms/list.rs b/src/api/admin/rooms/list.rs index eb1a0c9c5..fe7fc0857 100644 --- a/src/api/admin/rooms/list.rs +++ b/src/api/admin/rooms/list.rs @@ -13,7 +13,7 @@ pub(crate) async fn list_rooms( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if !services.users.is_admin(sender_user).await { return Err!(Request(Forbidden("Only server administrators can use this endpoint"))); } diff --git a/src/api/client/account/mod.rs b/src/api/client/account/mod.rs index fac3ca8ab..e666cae27 100644 --- a/src/api/client/account/mod.rs +++ b/src/api/client/account/mod.rs @@ -27,7 +27,7 @@ use ruma::{ use service::{mailer::messages, uiaa::Identity, users::HashedPassword}; use super::{DEVICE_ID_LENGTH, TOKEN_LENGTH}; -use crate::Ruma; +use crate::{Ruma, router::ClientIdentity}; pub(crate) mod register; pub(crate) mod threepid; @@ -75,13 +75,11 @@ pub(crate) async fn get_register_available_route( return Err!(Request(UserInUse("User ID is not available."))); } - if let Some(ref info) = body.appservice_info { - if !info.is_user_match(&user_id) { - return Err!(Request(Exclusive("Username is not in an appservice namespace."))); - } - } - - if services.appservice.is_exclusive_user_id(&user_id).await { + if let Some(ClientIdentity::Appservice { appservice_info, .. }) = &body.identity + && !appservice_info.is_user_match(&user_id) + { + return Err!(Request(Exclusive("Username is not in an appservice namespace."))); + } else if services.appservice.is_exclusive_user_id(&user_id).await { return Err!(Request(Exclusive("Username is reserved by an appservice."))); } @@ -111,7 +109,11 @@ pub(crate) async fn change_password_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let identity = if let Some(ref user_id) = body.sender_user { + let identity = if let Some(user_id) = body + .identity + .as_ref() + .map(|identity| identity.sender_user()) + { // A signed-in user is trying to change their password, prompt them for their // existing one @@ -157,7 +159,12 @@ pub(crate) async fn change_password_route( services .users .all_device_ids(&sender_user) - .ready_filter(|id| *id != body.sender_device()) + .ready_filter(|id| { + body.identity + .as_ref() + .and_then(|identity| identity.sender_device()) + .is_none_or(|sender_device| sender_device != *id) + }) .for_each(async |id| services.users.remove_device(&sender_user, &id).await) .await; @@ -173,7 +180,12 @@ pub(crate) async fn change_password_route( .await .ok() .as_ref() - .is_some_and(|pusher_device| pusher_device != body.sender_device()) + .is_some_and(|pusher_device| { + body.identity + .as_ref() + .and_then(|identity| identity.sender_device()) + .is_none_or(|sender_device| sender_device != *pusher_device) + }) .then_some(pushkey) }) .for_each(async |pushkey| { @@ -241,9 +253,11 @@ pub(crate) async fn whoami_route( State(_): State, body: Ruma, ) -> Result { - Ok(assign!(whoami::v3::Response::new(body.sender_user().to_owned(), false), { - device_id: body.sender_device, - })) + Ok( + assign!(whoami::v3::Response::new(body.identity.sender_user().to_owned(), false), { + device_id: body.identity.sender_device().map(ToOwned::to_owned), + }), + ) } /// # `POST /_matrix/client/r0/account/deactivate` @@ -266,8 +280,9 @@ pub(crate) async fn deactivate_route( // Authentication for this endpoint is technically optional, // but we require the user to be logged in let sender_user = body - .sender_user + .identity .as_ref() + .map(|identity| identity.sender_user()) .ok_or_else(|| err!(Request(MissingToken("Missing access token."))))?; // Prompt the user to confirm with their password using UIAA diff --git a/src/api/client/account/register.rs b/src/api/client/account/register.rs index 6556fbd43..1f3d17311 100644 --- a/src/api/client/account/register.rs +++ b/src/api/client/account/register.rs @@ -59,7 +59,7 @@ pub(crate) async fn register_route( let allow_registration = services.config.allow_registration || services.firstrun.is_first_run(); - if !allow_registration && body.appservice_info.is_none() { + if !allow_registration && body.identity.is_none() { info!( ?body.username, ?body.initial_device_display_name, @@ -71,7 +71,7 @@ pub(crate) async fn register_route( ))); } - let identity = if body.appservice_info.is_some() { + let identity = if body.identity.is_some() { // Appservices can skip auth None } else { @@ -107,7 +107,7 @@ pub(crate) async fn register_route( // For appservice logins, make sure that the user ID is in the appservice's // namespace - match body.appservice_info { + match body.identity { | Some(ref info) => if !info.is_user_match(&user_id) && !emergency_mode_enabled { return Err!(Request(Exclusive( @@ -125,7 +125,7 @@ pub(crate) async fn register_route( return Err!(Request(Exclusive("Username is reserved by an appservice."))); } - let password = if body.appservice_info.is_some() { + let password = if body.identity.is_some() { None } else if let Some(password) = body.password.as_deref() { Some(HashedPassword::new(password)?) @@ -140,9 +140,7 @@ pub(crate) async fn register_route( let mut displayname = user_id.localpart().to_owned(); // Apply the new user displayname suffix, if it's set - if !services.globals.new_user_displayname_suffix().is_empty() - && body.appservice_info.is_none() - { + if !services.globals.new_user_displayname_suffix().is_empty() && body.identity.is_none() { write!(displayname, " {}", services.server.config.new_user_displayname_suffix)?; } @@ -209,7 +207,7 @@ pub(crate) async fn register_route( let device_display_name = body.initial_device_display_name.as_deref().unwrap_or(""); - if body.appservice_info.is_none() { + if body.identity.is_none() { if !device_display_name.is_empty() { let notice = format!( "New user \"{user_id}\" registered on this server from IP {client} and device \ @@ -255,7 +253,7 @@ pub(crate) async fn register_route( } } - if body.appservice_info.is_none() && !services.server.config.auto_join_rooms.is_empty() { + if body.identity.is_none() && !services.server.config.auto_join_rooms.is_empty() { for room in &services.server.config.auto_join_rooms { let Ok(room_id) = services.rooms.alias.resolve(room).await else { error!( diff --git a/src/api/client/account/threepid.rs b/src/api/client/account/threepid.rs index 9bc5b83c8..2da54b0be 100644 --- a/src/api/client/account/threepid.rs +++ b/src/api/client/account/threepid.rs @@ -22,7 +22,7 @@ pub(crate) async fn third_party_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let mut threepids = vec![]; if let Some(email) = services @@ -53,6 +53,14 @@ pub(crate) async fn request_3pid_management_token_via_email_route( State(services): State, body: Ruma, ) -> Result { + // Authentication for this endpoint is technically optional, + // but we require the user to be logged in + let sender_user = body + .identity + .as_ref() + .map(|identity| identity.sender_user()) + .ok_or_else(|| err!(Request(MissingToken("Missing access token."))))?; + if !services.threepid.email_requirement().may_change() { return Err!(Request(Forbidden("You may not change your email address."))); } @@ -76,7 +84,7 @@ pub(crate) async fn request_3pid_management_token_via_email_route( Mailbox::new(None, email), |verification_link| messages::ChangeEmail { server_name: services.config.server_name.as_str(), - user_id: body.sender_user.as_deref(), + user_id: Some(sender_user), verification_link, }, &body.client_secret, @@ -107,8 +115,6 @@ pub(crate) async fn add_3pid_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); - if !services.threepid.email_requirement().may_change() { return Err!(Request(Forbidden("You may not change your email address."))); } @@ -116,7 +122,10 @@ pub(crate) async fn add_3pid_route( // Require password auth to add an email let _ = services .uiaa - .authenticate_password(&body.auth, Some(Identity::from_user_id(sender_user))) + .authenticate_password( + &body.auth, + Some(Identity::from_user_id(body.identity.sender_user())), + ) .await?; let email = services @@ -127,7 +136,7 @@ pub(crate) async fn add_3pid_route( services .threepid - .associate_localpart_email(sender_user.localpart(), &email) + .associate_localpart_email(body.identity.sender_user().localpart(), &email) .await?; Ok(add_3pid::v3::Response::new()) @@ -138,8 +147,6 @@ pub(crate) async fn delete_3pid_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); - if body.medium != Medium::Email { return Ok(delete_3pid::v3::Response::new(ThirdPartyIdRemovalStatus::NoSupport)); } @@ -150,7 +157,7 @@ pub(crate) async fn delete_3pid_route( if services .threepid - .disassociate_localpart_email(sender_user.localpart()) + .disassociate_localpart_email(body.identity.sender_user().localpart()) .await .is_none() { diff --git a/src/api/client/account_data.rs b/src/api/client/account_data.rs index 7bad9ed89..c46aa0d02 100644 --- a/src/api/client/account_data.rs +++ b/src/api/client/account_data.rs @@ -22,9 +22,9 @@ pub(crate) async fn set_global_account_data_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); - if sender_user != body.user_id && body.appservice_info.is_none() { + if sender_user != body.user_id && !body.identity.is_appservice() { return Err!(Request(Forbidden("You cannot set account data for other users."))); } @@ -47,9 +47,9 @@ pub(crate) async fn set_room_account_data_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); - if sender_user != body.user_id && body.appservice_info.is_none() { + if sender_user != body.user_id && !body.identity.is_appservice() { return Err!(Request(Forbidden("You cannot set account data for other users."))); } @@ -72,9 +72,9 @@ pub(crate) async fn get_global_account_data_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); - if sender_user != body.user_id && body.appservice_info.is_none() { + if sender_user != body.user_id && !body.identity.is_appservice() { return Err!(Request(Forbidden("You cannot get account data of other users."))); } @@ -94,9 +94,9 @@ pub(crate) async fn get_room_account_data_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); - if sender_user != body.user_id && body.appservice_info.is_none() { + if sender_user != body.user_id && !body.identity.is_appservice() { return Err!(Request(Forbidden("You cannot get account data of other users."))); } diff --git a/src/api/client/admin/suspend.rs b/src/api/client/admin/suspend.rs index 478a5d3db..b78c0beec 100644 --- a/src/api/client/admin/suspend.rs +++ b/src/api/client/admin/suspend.rs @@ -12,10 +12,11 @@ pub(crate) async fn get_suspended_status( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); - - let (admin, active) = - join(services.users.is_admin(sender_user), services.users.is_active(&body.user_id)).await; + let (admin, active) = join( + services.users.is_admin(body.identity.sender_user()), + services.users.is_active(&body.user_id), + ) + .await; if !admin { return Err!(Request(Forbidden("Only server administrators can use this endpoint"))); } @@ -37,7 +38,7 @@ pub(crate) async fn put_suspended_status( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let (sender_admin, active, target_admin) = join3( services.users.is_admin(sender_user), diff --git a/src/api/client/alias.rs b/src/api/client/alias.rs index bad3d75b3..cb355cfd3 100644 --- a/src/api/client/alias.rs +++ b/src/api/client/alias.rs @@ -11,7 +11,7 @@ pub(crate) async fn create_alias_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if services.users.is_suspended(sender_user).await? { return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); } @@ -19,7 +19,7 @@ pub(crate) async fn create_alias_route( services .rooms .alias - .appservice_checks(&body.room_alias, &body.appservice_info) + .appservice_checks(&body.room_alias, body.identity.appservice_info()) .await?; // this isn't apart of alias_checks or delete alias route because we should @@ -59,7 +59,7 @@ pub(crate) async fn delete_alias_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if services.users.is_suspended(sender_user).await? { return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); } @@ -67,7 +67,7 @@ pub(crate) async fn delete_alias_route( services .rooms .alias - .appservice_checks(&body.room_alias, &body.appservice_info) + .appservice_checks(&body.room_alias, body.identity.appservice_info()) .await?; services diff --git a/src/api/client/appservice.rs b/src/api/client/appservice.rs index 806f3bf9b..8011a98b0 100644 --- a/src/api/client/appservice.rs +++ b/src/api/client/appservice.rs @@ -1,5 +1,5 @@ use axum::extract::State; -use conduwuit::{Err, Result, err}; +use conduwuit::{Err, Result}; use ruma::{ api::{appservice::ping, client::appservice::request_ping}, assign, @@ -15,9 +15,7 @@ pub(crate) async fn appservice_ping( State(services): State, body: Ruma, ) -> Result { - let appservice_info = body.appservice_info.as_ref().ok_or_else(|| { - err!(Request(Forbidden("This endpoint can only be called by appservices."))) - })?; + let appservice_info = &body.identity; if body.appservice_id != appservice_info.registration.id { return Err!(Request(Forbidden( diff --git a/src/api/client/backup.rs b/src/api/client/backup.rs index 9f97cb472..4c2501226 100644 --- a/src/api/client/backup.rs +++ b/src/api/client/backup.rs @@ -25,7 +25,7 @@ pub(crate) async fn create_backup_version_route( ) -> Result { let version = services .key_backups - .create_backup(body.sender_user(), &body.algorithm)?; + .create_backup(body.identity.sender_user(), &body.algorithm)?; Ok(create_backup_version::v3::Response::new(version)) } @@ -40,7 +40,7 @@ pub(crate) async fn update_backup_version_route( ) -> Result { services .key_backups - .update_backup(body.sender_user(), &body.version, &body.algorithm) + .update_backup(body.identity.sender_user(), &body.version, &body.algorithm) .await?; Ok(update_backup_version::v3::Response::new()) @@ -55,11 +55,11 @@ pub(crate) async fn get_latest_backup_info_route( ) -> Result { let (version, algorithm) = services .key_backups - .get_latest_backup(body.sender_user()) + .get_latest_backup(body.identity.sender_user()) .await .map_err(|_| err!(Request(NotFound("Key backup does not exist."))))?; - let (count, etag) = get_count_etag(&services, body.sender_user(), &version).await; + let (count, etag) = get_count_etag(&services, body.identity.sender_user(), &version).await; Ok(get_latest_backup_info::v3::Response::new(algorithm, count, etag, version)) } @@ -73,13 +73,14 @@ pub(crate) async fn get_backup_info_route( ) -> Result { let algorithm = services .key_backups - .get_backup(body.sender_user(), &body.version) + .get_backup(body.identity.sender_user(), &body.version) .await .map_err(|_| { err!(Request(NotFound("Key backup does not exist at version {:?}", body.version))) })?; - let (count, etag) = get_count_etag(&services, body.sender_user(), &body.version).await; + let (count, etag) = + get_count_etag(&services, body.identity.sender_user(), &body.version).await; Ok(get_backup_info::v3::Response::new(algorithm, count, etag, body.version.clone())) } @@ -96,7 +97,7 @@ pub(crate) async fn delete_backup_version_route( ) -> Result { services .key_backups - .delete_backup(body.sender_user(), &body.version) + .delete_backup(body.identity.sender_user(), &body.version) .await; Ok(delete_backup_version::v3::Response::new()) @@ -116,7 +117,7 @@ pub(crate) async fn add_backup_keys_route( ) -> Result { if services .key_backups - .get_latest_backup_version(body.sender_user()) + .get_latest_backup_version(body.identity.sender_user()) .await .is_ok_and(|version| version != body.version) { @@ -129,12 +130,19 @@ pub(crate) async fn add_backup_keys_route( for (session_id, key_data) in &room.sessions { services .key_backups - .add_key(body.sender_user(), &body.version, room_id, session_id, key_data) + .add_key( + body.identity.sender_user(), + &body.version, + room_id, + session_id, + key_data, + ) .await?; } } - let (count, etag) = get_count_etag(&services, body.sender_user(), &body.version).await; + let (count, etag) = + get_count_etag(&services, body.identity.sender_user(), &body.version).await; Ok(add_backup_keys::v3::Response::new(etag, count)) } @@ -153,7 +161,7 @@ pub(crate) async fn add_backup_keys_for_room_route( ) -> Result { if services .key_backups - .get_latest_backup_version(body.sender_user()) + .get_latest_backup_version(body.identity.sender_user()) .await .is_ok_and(|version| version != body.version) { @@ -165,11 +173,18 @@ pub(crate) async fn add_backup_keys_for_room_route( for (session_id, key_data) in &body.sessions { services .key_backups - .add_key(body.sender_user(), &body.version, &body.room_id, session_id, key_data) + .add_key( + body.identity.sender_user(), + &body.version, + &body.room_id, + session_id, + key_data, + ) .await?; } - let (count, etag) = get_count_etag(&services, body.sender_user(), &body.version).await; + let (count, etag) = + get_count_etag(&services, body.identity.sender_user(), &body.version).await; Ok(add_backup_keys_for_room::v3::Response::new(etag, count)) } @@ -188,7 +203,7 @@ pub(crate) async fn add_backup_keys_for_session_route( ) -> Result { if services .key_backups - .get_latest_backup_version(body.sender_user()) + .get_latest_backup_version(body.identity.sender_user()) .await .is_ok_and(|version| version != body.version) { @@ -201,7 +216,7 @@ pub(crate) async fn add_backup_keys_for_session_route( let mut ok_to_replace = true; if let Some(old_key) = &services .key_backups - .get_session(body.sender_user(), &body.version, &body.room_id, &body.session_id) + .get_session(body.identity.sender_user(), &body.version, &body.room_id, &body.session_id) .await .ok() { @@ -260,7 +275,7 @@ pub(crate) async fn add_backup_keys_for_session_route( services .key_backups .add_key( - body.sender_user(), + body.identity.sender_user(), &body.version, &body.room_id, &body.session_id, @@ -269,7 +284,8 @@ pub(crate) async fn add_backup_keys_for_session_route( .await?; } - let (count, etag) = get_count_etag(&services, body.sender_user(), &body.version).await; + let (count, etag) = + get_count_etag(&services, body.identity.sender_user(), &body.version).await; Ok(add_backup_keys_for_session::v3::Response::new(etag, count)) } @@ -283,7 +299,7 @@ pub(crate) async fn get_backup_keys_route( ) -> Result { let rooms = services .key_backups - .get_all(body.sender_user(), &body.version) + .get_all(body.identity.sender_user(), &body.version) .await; Ok(get_backup_keys::v3::Response::new(rooms)) @@ -298,7 +314,7 @@ pub(crate) async fn get_backup_keys_for_room_route( ) -> Result { let sessions = services .key_backups - .get_room(body.sender_user(), &body.version, &body.room_id) + .get_room(body.identity.sender_user(), &body.version, &body.room_id) .await; Ok(get_backup_keys_for_room::v3::Response::new(sessions)) @@ -313,7 +329,7 @@ pub(crate) async fn get_backup_keys_for_session_route( ) -> Result { let key_data = services .key_backups - .get_session(body.sender_user(), &body.version, &body.room_id, &body.session_id) + .get_session(body.identity.sender_user(), &body.version, &body.room_id, &body.session_id) .await .map_err(|_| { err!(Request(NotFound(debug_error!("Backup key not found for this user's session.")))) @@ -331,10 +347,11 @@ pub(crate) async fn delete_backup_keys_route( ) -> Result { services .key_backups - .delete_all_keys(body.sender_user(), &body.version) + .delete_all_keys(body.identity.sender_user(), &body.version) .await; - let (count, etag) = get_count_etag(&services, body.sender_user(), &body.version).await; + let (count, etag) = + get_count_etag(&services, body.identity.sender_user(), &body.version).await; Ok(delete_backup_keys::v3::Response::new(etag, count)) } @@ -348,10 +365,11 @@ pub(crate) async fn delete_backup_keys_for_room_route( ) -> Result { services .key_backups - .delete_room_keys(body.sender_user(), &body.version, &body.room_id) + .delete_room_keys(body.identity.sender_user(), &body.version, &body.room_id) .await; - let (count, etag) = get_count_etag(&services, body.sender_user(), &body.version).await; + let (count, etag) = + get_count_etag(&services, body.identity.sender_user(), &body.version).await; Ok(delete_backup_keys_for_room::v3::Response::new(etag, count)) } @@ -365,10 +383,16 @@ pub(crate) async fn delete_backup_keys_for_session_route( ) -> Result { services .key_backups - .delete_room_key(body.sender_user(), &body.version, &body.room_id, &body.session_id) + .delete_room_key( + body.identity.sender_user(), + &body.version, + &body.room_id, + &body.session_id, + ) .await; - let (count, etag) = get_count_etag(&services, body.sender_user(), &body.version).await; + let (count, etag) = + get_count_etag(&services, body.identity.sender_user(), &body.version).await; Ok(delete_backup_keys_for_session::v3::Response::new(etag, count)) } diff --git a/src/api/client/capabilities.rs b/src/api/client/capabilities.rs index 5f3cabe49..0a88790e3 100644 --- a/src/api/client/capabilities.rs +++ b/src/api/client/capabilities.rs @@ -48,11 +48,7 @@ pub(crate) async fn get_capabilities_route( json!({"enabled": services.config.forget_forced_upon_leave}), )?; - if services - .users - .is_admin(body.sender_user.as_ref().unwrap()) - .await - { + if services.users.is_admin(body.identity.sender_user()).await { // Advertise suspension API capabilities.set("uk.timedout.msc4323", json!({"suspend": true, "lock": false}))?; } diff --git a/src/api/client/context.rs b/src/api/client/context.rs index 14f540dac..f47432732 100644 --- a/src/api/client/context.rs +++ b/src/api/client/context.rs @@ -37,8 +37,8 @@ pub(crate) async fn get_context_route( State(services): State, body: Ruma, ) -> Result { - let sender = body.sender(); - let (sender_user, sender_device) = sender; + let sender_user = body.identity.sender_user(); + let sender_device = body.identity.sender_device(); let room_id = &body.room_id; let event_id = &body.event_id; let filter = &body.filter; @@ -143,7 +143,7 @@ pub(crate) async fn get_context_route( let lazy_loading_context = lazy_loading::Context { user_id: sender_user, - device_id: Some(sender_device), + device_id: sender_device, room_id, token: Some(base_count.into_unsigned()), options: Some(&filter.lazy_load_options), diff --git a/src/api/client/dehydrated_device.rs b/src/api/client/dehydrated_device.rs index 44d0654a1..a02aef537 100644 --- a/src/api/client/dehydrated_device.rs +++ b/src/api/client/dehydrated_device.rs @@ -25,16 +25,11 @@ pub(crate) async fn put_dehydrated_device_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let sender_user = body - .sender_user - .as_deref() - .expect("AccessToken authentication required"); - - let device_id = body.body.device_id.clone(); + let device_id = body.device_id.clone(); services .users - .set_dehydrated_device(sender_user, body.body) + .set_dehydrated_device(body.identity.sender_user(), body.body) .await?; Ok(put_dehydrated_device::Response::new(device_id)) @@ -49,7 +44,7 @@ pub(crate) async fn delete_dehydrated_device_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let device_id = services.users.get_dehydrated_device_id(sender_user).await?; @@ -67,7 +62,7 @@ pub(crate) async fn get_dehydrated_device_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let device = services.users.get_dehydrated_device(sender_user).await?; @@ -83,7 +78,7 @@ pub(crate) async fn get_dehydrated_events_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let device_id = &body.body.device_id; let existing_id = services.users.get_dehydrated_device_id(sender_user).await; diff --git a/src/api/client/device.rs b/src/api/client/device.rs index c51190f8b..bbfa4e2cc 100644 --- a/src/api/client/device.rs +++ b/src/api/client/device.rs @@ -21,7 +21,7 @@ pub(crate) async fn get_devices_route( ) -> Result { let devices: Vec = services .users - .all_devices_metadata(body.sender_user()) + .all_devices_metadata(body.identity.sender_user()) .collect() .await; @@ -37,7 +37,7 @@ pub(crate) async fn get_device_route( ) -> Result { let device = services .users - .get_device_metadata(body.sender_user(), &body.body.device_id) + .get_device_metadata(body.identity.sender_user(), &body.body.device_id) .await .map_err(|_| err!(Request(NotFound("Device not found."))))?; @@ -53,8 +53,8 @@ pub(crate) async fn update_device_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); - let appservice = body.appservice_info.as_ref(); + let sender_user = body.identity.sender_user(); + let appservice = body.identity.appservice_info(); match services .users @@ -118,8 +118,8 @@ pub(crate) async fn delete_device_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); - let appservice = body.appservice_info.as_ref(); + let sender_user = body.identity.sender_user(); + let appservice = body.identity.appservice_info(); // Appservices get to skip UIAA for this endpoint if appservice.is_none() { @@ -154,8 +154,8 @@ pub(crate) async fn delete_devices_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); - let appservice = body.appservice_info.as_ref(); + let sender_user = body.identity.sender_user(); + let appservice = body.identity.appservice_info(); // Appservices get to skip UIAA for this endpoint if appservice.is_none() { diff --git a/src/api/client/directory.rs b/src/api/client/directory.rs index f4dff5049..7c07679f6 100644 --- a/src/api/client/directory.rs +++ b/src/api/client/directory.rs @@ -112,7 +112,7 @@ pub(crate) async fn set_room_visibility_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if !services.rooms.metadata.exists(&body.room_id).await { // Return 404 if the room doesn't exist @@ -130,7 +130,7 @@ pub(crate) async fn set_room_visibility_route( | room::Visibility::Public => { if services.server.config.lockdown_public_room_directory && !services.users.is_admin(sender_user).await - && body.appservice_info.is_none() + && !body.identity.is_appservice() { info!( "Non-admin user {sender_user} tried to publish {0} to the room directory \ diff --git a/src/api/client/filter.rs b/src/api/client/filter.rs index 9814d3667..1d1a4b996 100644 --- a/src/api/client/filter.rs +++ b/src/api/client/filter.rs @@ -15,7 +15,7 @@ pub(crate) async fn get_filter_route( ) -> Result { services .users - .get_filter(body.sender_user(), &body.filter_id) + .get_filter(body.identity.sender_user(), &body.filter_id) .await .map(get_filter::v3::Response::new) .map_err(|_| err!(Request(NotFound("Filter not found.")))) @@ -30,7 +30,7 @@ pub(crate) async fn create_filter_route( ) -> Result { let filter_id = services .users - .create_filter(body.sender_user(), &body.filter); + .create_filter(body.identity.sender_user(), &body.filter); Ok(create_filter::v3::Response::new(filter_id)) } diff --git a/src/api/client/keys.rs b/src/api/client/keys.rs index bc05ee9db..60db77995 100644 --- a/src/api/client/keys.rs +++ b/src/api/client/keys.rs @@ -41,7 +41,8 @@ pub(crate) async fn upload_keys_route( State(services): State, body: Ruma, ) -> Result { - let (sender_user, sender_device) = body.sender(); + let sender_user = body.identity.sender_user(); + let sender_device = body.identity.expect_sender_device()?; for (key_id, one_time_key) in &body.one_time_keys { if one_time_key @@ -154,7 +155,7 @@ pub(crate) async fn get_keys_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); get_keys_helper( &services, @@ -191,7 +192,7 @@ pub(crate) async fn upload_signing_keys_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if uiaa_needed_to_upload_keys( services, @@ -287,7 +288,7 @@ pub(crate) async fn upload_signatures_route( return Ok(upload_signatures::v3::Response::new()); } - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); for (user_id, keys) in &body.signed_keys { for (key_id, key) in keys { @@ -340,7 +341,7 @@ pub(crate) async fn get_key_changes_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let mut device_list_updates = HashSet::new(); diff --git a/src/api/client/media.rs b/src/api/client/media.rs index e193f55b1..d3ef3f269 100644 --- a/src/api/client/media.rs +++ b/src/api/client/media.rs @@ -53,7 +53,7 @@ pub(crate) async fn create_content_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let user = body.sender_user(); + let user = body.identity.sender_user(); if services.users.is_suspended(user).await? { return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); } @@ -92,7 +92,7 @@ pub(crate) async fn get_content_thumbnail_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let user = body.sender_user(); + let user = body.identity.sender_user(); let dim = Dim::from_ruma(body.width, body.height, body.method.clone())?; let mxc = Mxc { @@ -142,7 +142,7 @@ pub(crate) async fn get_content_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let user = body.sender_user(); + let user = body.identity.sender_user(); let mxc = Mxc { server_name: &body.server_name, @@ -189,7 +189,7 @@ pub(crate) async fn get_content_as_filename_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let user = body.sender_user(); + let user = body.identity.sender_user(); let mxc = Mxc { server_name: &body.server_name, @@ -240,7 +240,7 @@ pub(crate) async fn get_media_preview_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let url = &body.url; let url = Url::parse(&body.url).map_err(|e| { diff --git a/src/api/client/media_legacy.rs b/src/api/client/media_legacy.rs index d3567546e..1dad361aa 100644 --- a/src/api/client/media_legacy.rs +++ b/src/api/client/media_legacy.rs @@ -56,7 +56,7 @@ pub(crate) async fn get_media_preview_legacy_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let url = &body.url; let url = Url::parse(&body.url).map_err(|e| { diff --git a/src/api/client/membership/ban.rs b/src/api/client/membership/ban.rs index d8f24239e..394b6ed5e 100644 --- a/src/api/client/membership/ban.rs +++ b/src/api/client/membership/ban.rs @@ -15,7 +15,7 @@ pub(crate) async fn ban_user_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if sender_user == body.user_id { return Err!(Request(Forbidden("You cannot ban yourself."))); diff --git a/src/api/client/membership/forget.rs b/src/api/client/membership/forget.rs index 7f3a1a57d..d5ee38fce 100644 --- a/src/api/client/membership/forget.rs +++ b/src/api/client/membership/forget.rs @@ -18,7 +18,7 @@ pub(crate) async fn forget_room_route( State(services): State, body: Ruma, ) -> Result { - let user_id = body.sender_user(); + let user_id = body.identity.sender_user(); let room_id = &body.room_id; let joined = services.rooms.state_cache.is_joined(user_id, room_id); diff --git a/src/api/client/membership/invite.rs b/src/api/client/membership/invite.rs index 509327281..74742968e 100644 --- a/src/api/client/membership/invite.rs +++ b/src/api/client/membership/invite.rs @@ -29,7 +29,7 @@ pub(crate) async fn invite_user_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if services.users.is_suspended(sender_user).await? { return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); } diff --git a/src/api/client/membership/join.rs b/src/api/client/membership/join.rs index 69183c144..d71b21a10 100644 --- a/src/api/client/membership/join.rs +++ b/src/api/client/membership/join.rs @@ -28,7 +28,7 @@ pub(crate) async fn join_room_by_id_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if services.users.is_suspended(sender_user).await? { return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); } @@ -97,7 +97,7 @@ pub(crate) async fn join_room_by_id_or_alias_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let body = &body.body; if services.users.is_suspended(sender_user).await? { return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); diff --git a/src/api/client/membership/kick.rs b/src/api/client/membership/kick.rs index 75160990a..e151e5180 100644 --- a/src/api/client/membership/kick.rs +++ b/src/api/client/membership/kick.rs @@ -15,7 +15,7 @@ pub(crate) async fn kick_user_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if services.users.is_suspended(sender_user).await? { return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); } diff --git a/src/api/client/membership/knock.rs b/src/api/client/membership/knock.rs index 3035b93f8..0238d2741 100644 --- a/src/api/client/membership/knock.rs +++ b/src/api/client/membership/knock.rs @@ -51,7 +51,7 @@ pub(crate) async fn knock_room_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let body = &body.body; if services.users.is_suspended(sender_user).await? { return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); diff --git a/src/api/client/membership/leave.rs b/src/api/client/membership/leave.rs index dbfb6c5a1..7a13f1f53 100644 --- a/src/api/client/membership/leave.rs +++ b/src/api/client/membership/leave.rs @@ -32,7 +32,7 @@ pub(crate) async fn leave_room_route( State(services): State, body: Ruma, ) -> Result { - leave_room(&services, body.sender_user(), &body.room_id, body.reason.clone()) + leave_room(&services, body.identity.sender_user(), &body.room_id, body.reason.clone()) .boxed() .await .map(|()| leave_room::v3::Response::new()) diff --git a/src/api/client/membership/members.rs b/src/api/client/membership/members.rs index 8e96b15cb..7f87e2d92 100644 --- a/src/api/client/membership/members.rs +++ b/src/api/client/membership/members.rs @@ -30,7 +30,7 @@ pub(crate) async fn get_member_events_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let membership = body.membership.as_ref(); let not_membership = body.not_membership.as_ref(); @@ -72,7 +72,7 @@ pub(crate) async fn joined_members_route( if !services .rooms .state_accessor - .user_can_see_state_events(body.sender_user(), &body.room_id) + .user_can_see_state_events(body.identity.sender_user(), &body.room_id) .await { return Err!(Request(Forbidden("You don't have permission to view this room."))); diff --git a/src/api/client/membership/mod.rs b/src/api/client/membership/mod.rs index f27d9ffc8..f6a6801d9 100644 --- a/src/api/client/membership/mod.rs +++ b/src/api/client/membership/mod.rs @@ -40,7 +40,7 @@ pub(crate) async fn joined_rooms_route( let joined_rooms = services .rooms .state_cache - .rooms_joined(body.sender_user()) + .rooms_joined(body.identity.sender_user()) .collect() .await; diff --git a/src/api/client/membership/unban.rs b/src/api/client/membership/unban.rs index 567dde528..be8c89134 100644 --- a/src/api/client/membership/unban.rs +++ b/src/api/client/membership/unban.rs @@ -14,7 +14,7 @@ pub(crate) async fn unban_user_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if services.users.is_suspended(sender_user).await? { return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); } diff --git a/src/api/client/message.rs b/src/api/client/message.rs index 50fe9501f..00f7f94d2 100644 --- a/src/api/client/message.rs +++ b/src/api/client/message.rs @@ -23,7 +23,7 @@ use conduwuit_service::{ }; use futures::{FutureExt, StreamExt, TryFutureExt, future::OptionFuture, pin_mut}; use ruma::{ - DeviceId, RoomId, UserId, + RoomId, UserId, api::{ Direction, client::{filter::RoomEventFilter, message::get_message_events}, @@ -37,7 +37,6 @@ use ruma::{ serde::Raw, }; use ruminuwuity::invite_permission_config::FilterLevel; -use tracing::warn; use crate::Ruma; @@ -76,8 +75,8 @@ pub(crate) async fn get_message_events_route( ClientIp(client_ip): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); - let sender_device = body.sender_device.as_deref(); + let sender_user = body.identity.sender_user(); + let sender_device = body.identity.sender_device(); let room_id = &body.room_id; let filter = &body.filter; @@ -158,17 +157,7 @@ pub(crate) async fn get_message_events_route( let lazy_loading_context = lazy_loading::Context { user_id: sender_user, - device_id: sender_device.or_else(|| { - if let Some(registration) = body.appservice_info.as_ref() { - Some(<&DeviceId>::from(registration.registration.id.as_str())) - } else { - warn!( - "No device_id provided and no appservice registration found, this should be \ - unreachable" - ); - None - } - }), + device_id: sender_device, room_id, token: Some(from.into_unsigned()), options: Some(&filter.lazy_load_options), diff --git a/src/api/client/mutual_rooms.rs b/src/api/client/mutual_rooms.rs index ff5fcedb2..cbec98d0e 100644 --- a/src/api/client/mutual_rooms.rs +++ b/src/api/client/mutual_rooms.rs @@ -15,7 +15,7 @@ pub(crate) async fn get_mutual_rooms_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if sender_user == body.user_id { return Err!(Request(Unknown("You cannot request rooms in common with yourself."))); diff --git a/src/api/client/openid.rs b/src/api/client/openid.rs index 4fa9d3bc6..c3149d856 100644 --- a/src/api/client/openid.rs +++ b/src/api/client/openid.rs @@ -16,7 +16,7 @@ pub(crate) async fn create_openid_token_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if sender_user != body.user_id { return Err!(Request(InvalidParam( diff --git a/src/api/client/presence.rs b/src/api/client/presence.rs index 01768a08c..07622d028 100644 --- a/src/api/client/presence.rs +++ b/src/api/client/presence.rs @@ -20,13 +20,19 @@ pub(crate) async fn set_presence_route( return Err!(Request(Forbidden("Presence is disabled on this server"))); } - if body.sender_user() != body.user_id && body.appservice_info.is_none() { + if body.identity.sender_user() != body.user_id && !body.identity.is_appservice() { return Err!(Request(InvalidParam("Not allowed to set presence of other users"))); } services .presence - .set_presence(body.sender_user(), &body.presence, None, None, body.status_msg.clone()) + .set_presence( + body.identity.sender_user(), + &body.presence, + None, + None, + body.status_msg.clone(), + ) .await?; Ok(set_presence::v3::Response::new()) @@ -49,7 +55,7 @@ pub(crate) async fn get_presence_route( let has_shared_rooms = services .rooms .state_cache - .user_sees_user(body.sender_user(), &body.user_id) + .user_sees_user(body.identity.sender_user(), &body.user_id) .await; if has_shared_rooms { diff --git a/src/api/client/profile.rs b/src/api/client/profile.rs index 4bcf7fd76..0e4f75088 100644 --- a/src/api/client/profile.rs +++ b/src/api/client/profile.rs @@ -51,9 +51,12 @@ pub(crate) async fn set_profile_field_route( State(services): State, body: Ruma, ) -> Result { - if body.user_id != body.sender_user() - && !(body.appservice_info.is_some() - || services.admin.user_is_admin(body.sender_user()).await) + if body.user_id != body.identity.sender_user() + && !(body.identity.is_appservice() + || services + .admin + .user_is_admin(body.identity.sender_user()) + .await) { return Err!(Request(Forbidden("You may not change other users' profile data."))); } @@ -72,9 +75,12 @@ pub(crate) async fn delete_profile_field_route( State(services): State, body: Ruma, ) -> Result { - if body.user_id != body.sender_user() - && !(body.appservice_info.is_some() - || services.admin.user_is_admin(body.sender_user()).await) + if body.user_id != body.identity.sender_user() + && !(body.identity.is_appservice() + || services + .admin + .user_is_admin(body.identity.sender_user()) + .await) { return Err!(Request(Forbidden("You may not change other users' profile data."))); } diff --git a/src/api/client/push.rs b/src/api/client/push.rs index c12301a11..47e79e65e 100644 --- a/src/api/client/push.rs +++ b/src/api/client/push.rs @@ -30,7 +30,7 @@ pub(crate) async fn get_pushrules_all_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let Some(content_value) = services .account_data @@ -101,7 +101,7 @@ pub(crate) async fn get_pushrules_global_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let Some(content_value) = services .account_data @@ -189,7 +189,7 @@ pub(crate) async fn get_pushrule_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user.as_ref().expect("user is authenticated"); + let sender_user = body.identity.sender_user(); // remove old deprecated mentions push rules as per MSC4210 #[allow(deprecated)] @@ -226,7 +226,7 @@ pub(crate) async fn set_pushrule_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let body = &body.body; let mut account_data: PushRulesEvent = services .account_data @@ -282,7 +282,7 @@ pub(crate) async fn get_pushrule_actions_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); // remove old deprecated mentions push rules as per MSC4210 #[allow(deprecated)] @@ -316,7 +316,7 @@ pub(crate) async fn set_pushrule_actions_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let mut account_data: PushRulesEvent = services .account_data @@ -349,7 +349,7 @@ pub(crate) async fn get_pushrule_enabled_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); // remove old deprecated mentions push rules as per MSC4210 #[allow(deprecated)] @@ -383,7 +383,7 @@ pub(crate) async fn set_pushrule_enabled_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let mut account_data: PushRulesEvent = services .account_data @@ -416,7 +416,7 @@ pub(crate) async fn delete_pushrule_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let mut account_data: PushRulesEvent = services .account_data @@ -458,7 +458,7 @@ pub(crate) async fn get_pushers_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); Ok(get_pushers::v3::Response::new(services.pusher.get_pushers(sender_user).await)) } @@ -472,11 +472,12 @@ pub(crate) async fn set_pushers_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); + let sender_device = body.identity.expect_sender_device()?; services .pusher - .set_pusher(sender_user, body.sender_device(), &body.action) + .set_pusher(sender_user, sender_device, &body.action) .await?; Ok(set_pusher::v3::Response::new()) diff --git a/src/api/client/read_marker.rs b/src/api/client/read_marker.rs index 74fd19a80..bd31eca71 100644 --- a/src/api/client/read_marker.rs +++ b/src/api/client/read_marker.rs @@ -26,7 +26,7 @@ pub(crate) async fn set_read_marker_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if let Some(event) = &body.fully_read { let fully_read_event = FullyReadEvent::new(FullyReadEventContent::new(event.to_owned())); @@ -118,10 +118,10 @@ pub(crate) async fn create_receipt_route( ClientIp(client_ip): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); services .users - .update_device_last_seen(sender_user, body.sender_device.as_deref(), client_ip) + .update_device_last_seen(sender_user, body.identity.sender_device(), client_ip) .await; if matches!( diff --git a/src/api/client/redact.rs b/src/api/client/redact.rs index 1da2ee1d4..0eb48bf0e 100644 --- a/src/api/client/redact.rs +++ b/src/api/client/redact.rs @@ -17,10 +17,10 @@ pub(crate) async fn redact_event_route( ClientIp(client_ip): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); services .users - .update_device_last_seen(sender_user, body.sender_device.as_deref(), client_ip) + .update_device_last_seen(sender_user, body.identity.sender_device(), client_ip) .await; let body = &body.body; if services.users.is_suspended(sender_user).await? { diff --git a/src/api/client/relations.rs b/src/api/client/relations.rs index b1f4465c3..53ac0de1d 100644 --- a/src/api/client/relations.rs +++ b/src/api/client/relations.rs @@ -28,7 +28,7 @@ pub(crate) async fn get_relating_events_with_rel_type_and_event_type_route( ) -> Result { paginate_relations_with_filter( &services, - body.sender_user(), + body.identity.sender_user(), &body.room_id, &body.event_id, body.event_type.clone().into(), @@ -56,7 +56,7 @@ pub(crate) async fn get_relating_events_with_rel_type_route( ) -> Result { paginate_relations_with_filter( &services, - body.sender_user(), + body.identity.sender_user(), &body.room_id, &body.event_id, None, @@ -84,7 +84,7 @@ pub(crate) async fn get_relating_events_route( ) -> Result { paginate_relations_with_filter( &services, - body.sender_user(), + body.identity.sender_user(), &body.room_id, &body.event_id, None, diff --git a/src/api/client/report.rs b/src/api/client/report.rs index 5267df110..5fe1b4a24 100644 --- a/src/api/client/report.rs +++ b/src/api/client/report.rs @@ -36,7 +36,7 @@ pub(crate) async fn report_room_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if services.users.is_suspended(sender_user).await? { return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); } @@ -92,7 +92,7 @@ pub(crate) async fn report_event_route( body: Ruma, ) -> Result { // user authentication - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if services.users.is_suspended(sender_user).await? { return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); } @@ -135,8 +135,8 @@ pub(crate) async fn report_user_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - // user authentication - let sender_user = body.sender_user.as_ref().expect("user is authenticated"); + let sender_user = body.identity.sender_user(); + if services.users.is_suspended(sender_user).await? { return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); } diff --git a/src/api/client/room/aliases.rs b/src/api/client/room/aliases.rs index 64ab722da..ac13e7e34 100644 --- a/src/api/client/room/aliases.rs +++ b/src/api/client/room/aliases.rs @@ -15,7 +15,7 @@ pub(crate) async fn get_room_aliases_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if !services .rooms diff --git a/src/api/client/room/create.rs b/src/api/client/room/create.rs index e0dc60a23..80f60ae25 100644 --- a/src/api/client/room/create.rs +++ b/src/api/client/room/create.rs @@ -61,10 +61,10 @@ pub(crate) async fn create_room_route( ) -> Result { use create_room::v3::RoomPreset; - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if !services.globals.allow_room_creation() - && body.appservice_info.is_none() + && !body.identity.is_appservice() && !services.users.is_admin(sender_user).await { return Err!(Request(Forbidden("Room creation has been disabled.",))); @@ -130,7 +130,7 @@ pub(crate) async fn create_room_route( if body.visibility == room::Visibility::Public && services.server.config.lockdown_public_room_directory && !services.users.is_admin(sender_user).await - && body.appservice_info.is_none() + && !body.identity.is_appservice() { warn!( "Non-admin user {sender_user} tried to publish {room_id:?} to the room directory \ @@ -186,7 +186,7 @@ pub(crate) async fn create_room_route( let alias: Option = match body.room_alias_name.as_ref() { | Some(alias) => - Some(room_alias_check(&services, alias, body.appservice_info.as_ref()).await?), + Some(room_alias_check(&services, alias, body.identity.appservice_info()).await?), | _ => None, }; diff --git a/src/api/client/room/event.rs b/src/api/client/room/event.rs index b592dcf52..3c3a920ae 100644 --- a/src/api/client/room/event.rs +++ b/src/api/client/room/event.rs @@ -24,25 +24,25 @@ pub(crate) async fn get_room_event_route( let visible = services .rooms .state_accessor - .user_can_see_event(body.sender_user(), room_id, event_id) + .user_can_see_event(body.identity.sender_user(), room_id, event_id) .map(Ok); let (mut event, visible) = try_join(event, visible).await?; - if !visible || is_ignored_pdu(services, &event, body.sender_user()).await? { + if !visible || is_ignored_pdu(services, &event, body.identity.sender_user()).await? { return Err!(Request(Forbidden("You don't have permission to view this event."))); } if let Err(e) = services .rooms .pdu_metadata - .add_bundled_aggregations_to_pdu(body.sender_user(), &mut event) + .add_bundled_aggregations_to_pdu(body.identity.sender_user(), &mut event) .await { debug_warn!("Failed to add bundled aggregations to event: {e}"); } - event.set_unsigned(body.sender_user.as_deref()); + event.set_unsigned(Some(body.identity.sender_user())); Ok(get_room_event::v3::Response::new(event.into_format())) } diff --git a/src/api/client/room/initial_sync.rs b/src/api/client/room/initial_sync.rs index 0306cde4e..f3f925f33 100644 --- a/src/api/client/room/initial_sync.rs +++ b/src/api/client/room/initial_sync.rs @@ -22,7 +22,7 @@ pub(crate) async fn room_initial_sync_route( if !services .rooms .state_accessor - .user_can_see_state_events(body.sender_user(), room_id) + .user_can_see_state_events(body.identity.sender_user(), room_id) .await { return Err!(Request(Forbidden("No room preview available."))); @@ -31,7 +31,7 @@ pub(crate) async fn room_initial_sync_route( let membership = services .rooms .state_cache - .user_membership(body.sender_user(), room_id) + .user_membership(body.identity.sender_user(), room_id) .map(Ok); let visibility = services.rooms.directory.visibility(room_id).map(Ok); @@ -52,16 +52,14 @@ pub(crate) async fn room_initial_sync_route( .pdus_rev(room_id, None) .try_take(limit) .and_then(async |mut pdu| { - pdu.1.set_unsigned(body.sender_user.as_deref()); - if let Some(sender_user) = body.sender_user.as_deref() { - if let Err(e) = services - .rooms - .pdu_metadata - .add_bundled_aggregations_to_pdu(sender_user, &mut pdu.1) - .await - { - debug_warn!("Failed to add bundled aggregations: {e}"); - } + pdu.1.set_unsigned(Some(body.identity.sender_user())); + if let Err(e) = services + .rooms + .pdu_metadata + .add_bundled_aggregations_to_pdu(body.identity.sender_user(), &mut pdu.1) + .await + { + debug_warn!("Failed to add bundled aggregations: {e}"); } Ok(pdu) }) diff --git a/src/api/client/room/summary.rs b/src/api/client/room/summary.rs index b6e217b43..32e60617a 100644 --- a/src/api/client/room/summary.rs +++ b/src/api/client/room/summary.rs @@ -28,7 +28,13 @@ pub(crate) async fn get_room_summary( let summary = services .rooms .summary - .get_room_summary_for_user(body.sender_user.as_deref(), &room_id, &servers) + .get_room_summary_for_user( + body.identity + .as_ref() + .map(|identity| identity.sender_user()), + &room_id, + &servers, + ) .await?; match summary { diff --git a/src/api/client/room/upgrade.rs b/src/api/client/room/upgrade.rs index aaa01add6..a3fd0c967 100644 --- a/src/api/client/room/upgrade.rs +++ b/src/api/client/room/upgrade.rs @@ -277,7 +277,7 @@ pub(crate) async fn upgrade_room_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let (supported, forbid_unstable, is_unstable) = ( services.server.supported_room_version(&body.new_version), diff --git a/src/api/client/search.rs b/src/api/client/search.rs index 7a5ad1008..811500845 100644 --- a/src/api/client/search.rs +++ b/src/api/client/search.rs @@ -43,7 +43,7 @@ pub(crate) async fn search_events_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let next_batch = body.next_batch.as_deref(); let mut result_categories = ResultCategories::new(); diff --git a/src/api/client/send.rs b/src/api/client/send.rs index feac81c86..e58a914e2 100644 --- a/src/api/client/send.rs +++ b/src/api/client/send.rs @@ -22,16 +22,16 @@ pub(crate) async fn send_message_event_route( ClientIp(client_ip): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); - let sender_device = body.sender_device.as_deref(); - let appservice_info = body.appservice_info.as_ref(); + let sender_user = body.identity.sender_user(); + let sender_device = body.identity.sender_device(); + if services.users.is_suspended(sender_user).await? { return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); } services .users - .update_device_last_seen(sender_user, body.sender_device.as_deref(), client_ip) + .update_device_last_seen(sender_user, sender_device, client_ip) .await; // Forbid m.room.encrypted if encryption is disabled @@ -83,7 +83,11 @@ pub(crate) async fn send_message_event_route( event_type: body.event_type.clone().into(), content, unsigned: Some(unsigned), - timestamp: appservice_info.and(body.timestamp), + timestamp: if body.identity.is_appservice() { + body.timestamp + } else { + None + }, ..Default::default() }, sender_user, diff --git a/src/api/client/session.rs b/src/api/client/session.rs index e292566cc..4cb90678b 100644 --- a/src/api/client/session.rs +++ b/src/api/client/session.rs @@ -146,7 +146,7 @@ pub(crate) async fn login_route( }) => { debug!("Got appservice login type"); - let Some(ref info) = body.appservice_info else { + let Some(ref info) = body.identity else { return Err!(Request(MissingToken("Missing appservice token."))); }; @@ -254,7 +254,7 @@ pub(crate) async fn login_token_route( return Err!(Request(Forbidden("Login via an existing session is not enabled"))); } - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); // Prompt the user to confirm with their password using UIAA let _ = services @@ -286,7 +286,9 @@ pub(crate) async fn logout_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let (sender_user, sender_device) = body.sender(); + let sender_user = body.identity.sender_user(); + let sender_device = body.identity.expect_sender_device()?; + services .users .remove_device(sender_user, sender_device) @@ -332,7 +334,7 @@ pub(crate) async fn logout_all_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); services .users .all_device_ids(sender_user) diff --git a/src/api/client/space.rs b/src/api/client/space.rs index 53af69b0a..6873aa969 100644 --- a/src/api/client/space.rs +++ b/src/api/client/space.rs @@ -27,7 +27,7 @@ pub(crate) async fn get_hierarchy_route( .rooms .summary .get_room_hierarchy_for_user( - body.sender_user(), + body.identity.sender_user(), body.room_id.clone(), max_depth, body.suggested_only, diff --git a/src/api/client/state.rs b/src/api/client/state.rs index 3024ad04b..95c399391 100644 --- a/src/api/client/state.rs +++ b/src/api/client/state.rs @@ -38,10 +38,10 @@ pub(crate) async fn send_state_event_for_key_route( ClientIp(ip): ClientIp, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); services .users - .update_device_last_seen(sender_user, body.sender_device.as_deref(), ip) + .update_device_last_seen(sender_user, body.identity.sender_device(), ip) .await; if services.users.is_suspended(sender_user).await? { @@ -55,7 +55,7 @@ pub(crate) async fn send_state_event_for_key_route( &body.event_type, &body.body.body, &body.state_key, - if body.appservice_info.is_some() { + if body.identity.is_appservice() { body.timestamp } else { None @@ -91,7 +91,7 @@ pub(crate) async fn get_state_events_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if !services .rooms @@ -125,7 +125,7 @@ pub(crate) async fn get_state_event_for_key_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); if !services .rooms diff --git a/src/api/client/sync/v3/mod.rs b/src/api/client/sync/v3/mod.rs index 1c3612b97..c32ed22cd 100644 --- a/src/api/client/sync/v3/mod.rs +++ b/src/api/client/sync/v3/mod.rs @@ -181,7 +181,8 @@ pub(crate) async fn sync_events_route( ClientIp(client_ip): ClientIp, body: Ruma, ) -> Result { - let (sender_user, sender_device) = body.sender(); + let sender_user = body.identity.sender_user(); + let sender_device = body.identity.expect_sender_device()?; // Presence update if services.config.allow_local_presence { @@ -225,7 +226,8 @@ pub(crate) async fn build_sync_events( services: &Services, body: &Ruma, ) -> Result { - let (syncing_user, syncing_device) = body.sender(); + let syncing_user = body.identity.sender_user(); + let syncing_device = body.identity.sender_device().expect("should have a device"); let current_count = services.globals.current_count()?; diff --git a/src/api/client/sync/v5.rs b/src/api/client/sync/v5.rs index c396cbdb9..a6c340c53 100644 --- a/src/api/client/sync/v5.rs +++ b/src/api/client/sync/v5.rs @@ -70,8 +70,8 @@ pub(crate) async fn sync_events_v5_route( body: Ruma, ) -> Result { debug_assert!(DEFAULT_BUMP_TYPES.is_sorted(), "DEFAULT_BUMP_TYPES is not sorted"); - let ref sender_user = body.sender_user().to_owned(); - let ref sender_device = body.sender_device().to_owned(); + let sender_user = body.identity.sender_user(); + let sender_device = body.identity.expect_sender_device()?; services .users diff --git a/src/api/client/tag.rs b/src/api/client/tag.rs index ec0664503..f9a8bd6d5 100644 --- a/src/api/client/tag.rs +++ b/src/api/client/tag.rs @@ -21,7 +21,7 @@ pub(crate) async fn update_tag_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let mut tags_event = services .account_data @@ -56,7 +56,7 @@ pub(crate) async fn delete_tag_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let mut tags_event = services .account_data @@ -88,7 +88,7 @@ pub(crate) async fn get_tags_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let tags_event = services .account_data diff --git a/src/api/client/threads.rs b/src/api/client/threads.rs index c58c048ea..97f9f5b73 100644 --- a/src/api/client/threads.rs +++ b/src/api/client/threads.rs @@ -34,14 +34,14 @@ pub(crate) async fn get_threads_route( let threads: Vec<(PduCount, PduEvent)> = services .rooms .threads - .threads_until(body.sender_user(), &body.room_id, from, &body.include) + .threads_until(body.identity.sender_user(), &body.room_id, from, &body.include) .await? .take(limit) .filter_map(|(count, pdu)| async move { services .rooms .state_accessor - .user_can_see_event(body.sender_user(), &body.room_id, &pdu.event_id) + .user_can_see_event(body.identity.sender_user(), &body.room_id, &pdu.event_id) .await .then_some((count, pdu)) }) @@ -49,7 +49,7 @@ pub(crate) async fn get_threads_route( if let Err(e) = services .rooms .pdu_metadata - .add_bundled_aggregations_to_pdu(body.sender_user(), &mut pdu) + .add_bundled_aggregations_to_pdu(body.identity.sender_user(), &mut pdu) .await { debug_warn!("Failed to add bundled aggregations to thread: {e}"); diff --git a/src/api/client/to_device.rs b/src/api/client/to_device.rs index b3359bdec..3aac3b58b 100644 --- a/src/api/client/to_device.rs +++ b/src/api/client/to_device.rs @@ -22,8 +22,8 @@ pub(crate) async fn send_event_to_device_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); - let sender_device = body.sender_device.as_deref(); + let sender_user = body.identity.sender_user(); + let sender_device = body.identity.sender_device(); // Check if this is a new transaction id if services diff --git a/src/api/client/typing.rs b/src/api/client/typing.rs index 189992783..5bc1fa465 100644 --- a/src/api/client/typing.rs +++ b/src/api/client/typing.rs @@ -14,13 +14,13 @@ pub(crate) async fn create_typing_event_route( body: Ruma, ) -> Result { use create_typing_event::v3::Typing; - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); services .users - .update_device_last_seen(sender_user, body.sender_device.as_deref(), ip) + .update_device_last_seen(sender_user, body.identity.sender_device(), ip) .await; - if sender_user != body.user_id && body.appservice_info.is_none() { + if sender_user != body.user_id && !body.identity.is_appservice() { return Err!(Request(Forbidden("You cannot update typing status of other users."))); } diff --git a/src/api/client/user_directory.rs b/src/api/client/user_directory.rs index 059adb224..d04dfabd8 100644 --- a/src/api/client/user_directory.rs +++ b/src/api/client/user_directory.rs @@ -26,7 +26,7 @@ pub(crate) async fn search_users_route( State(services): State, body: Ruma, ) -> Result { - let sender_user = body.sender_user(); + let sender_user = body.identity.sender_user(); let limit = usize::try_from(body.limit) .map_or(LIMIT_DEFAULT, usize::from) .min(LIMIT_MAX); diff --git a/src/api/client/voip.rs b/src/api/client/voip.rs index 1dd0ec87d..0f6c5cbdf 100644 --- a/src/api/client/voip.rs +++ b/src/api/client/voip.rs @@ -2,15 +2,13 @@ use std::time::{Duration, SystemTime}; use axum::extract::State; use base64::{Engine as _, engine::general_purpose}; -use conduwuit::{Err, Result, utils}; +use conduwuit::{Err, Result}; use hmac::{Hmac, KeyInit, Mac}; -use ruma::{SecondsSinceUnixEpoch, UserId, api::client::voip::get_turn_server_info}; +use ruma::{SecondsSinceUnixEpoch, api::client::voip::get_turn_server_info}; use sha1::Sha1; use crate::Ruma; -const RANDOM_USER_ID_LENGTH: usize = 10; - type HmacSha1 = Hmac; /// # `GET /_matrix/client/r0/voip/turnServer` @@ -35,15 +33,7 @@ pub(crate) async fn turn_server_route( ) .expect("time is valid"); - let user = body.sender_user.unwrap_or_else(|| { - UserId::parse_with_server_name( - utils::random_string(RANDOM_USER_ID_LENGTH).to_lowercase(), - &services.server.name, - ) - .unwrap() - }); - - let username: String = format!("{}:{}", expiry.get(), user); + let username: String = format!("{}:{}", expiry.get(), body.identity.sender_user()); let mut mac = HmacSha1::new_from_slice(turn_secret.as_bytes()) .expect("HMAC can take key of any size"); diff --git a/src/api/router.rs b/src/api/router.rs index da39f22a9..45da9e0c7 100644 --- a/src/api/router.rs +++ b/src/api/router.rs @@ -15,7 +15,7 @@ pub(super) use conduwuit_service::state::State; use http::{Uri, uri}; use self::handler::RouterExt; -pub(super) use self::{args::Args as Ruma, response::RumaResponse}; +pub(super) use self::{args::Args as Ruma, auth::ClientIdentity, response::RumaResponse}; use crate::{admin, client, server}; pub fn build(router: Router, server: &Server) -> Router { diff --git a/src/api/router/args.rs b/src/api/router/args.rs index c7a57b918..3f5348f3c 100644 --- a/src/api/router/args.rs +++ b/src/api/router/args.rs @@ -6,17 +6,14 @@ use axum::{ extract::{FromRequest, Path, Query}, }; use conduwuit::{Error, Result, err}; -use ruma::{ - CanonicalJsonObject, DeviceId, OwnedDeviceId, OwnedServerName, OwnedUserId, ServerName, - UserId, api::IncomingRequest, -}; +use ruma::{CanonicalJsonObject, api::IncomingRequest}; use serde::Deserialize; -use crate::{State, router::auth::CheckAuth, service::appservice::RegistrationInfo}; +use crate::{State, router::auth::CheckAuth}; /// Query parameters needed to authenticate requests #[derive(Deserialize)] -pub(super) struct AuthQueryParams { +pub(crate) struct AuthQueryParams { pub(super) user_id: Option, /// Device ID for appservice device masquerading (MSC3202/MSC4190). /// Can be provided as `device_id` or `org.matrix.msc3202.device_id`. @@ -25,67 +22,22 @@ pub(super) struct AuthQueryParams { } /// Extractor for Ruma request structs -pub(crate) struct Args { +pub(crate) struct Args + Send + Sync + 'static> { /// Request struct body - pub(crate) body: T, + pub(crate) body: R, - /// Federation server authentication: X-Matrix origin - /// None when not a federation server. - pub(crate) origin: Option, - - /// Local user authentication: user_id. - /// None when not an authenticated local user. - pub(crate) sender_user: Option, - - /// Local user authentication: device_id. - /// None when not an authenticated local user or no device. - pub(crate) sender_device: Option, - - /// Appservice authentication; registration info. - /// None when not an appservice. - pub(crate) appservice_info: Option, - - /// Parsed JSON content. - /// None when body is not a valid string + /// Parsed JSON body. None when body is not JSON. pub(crate) json_body: Option, + + /// Identity of the requesting entity + pub(crate) identity: ::Identity, } -impl Args +impl Deref for Args where - T: IncomingRequest + Send + Sync + 'static, + R: IncomingRequest + Send + Sync + 'static, { - #[inline] - pub(crate) fn sender(&self) -> (&UserId, &DeviceId) { - (self.sender_user(), self.sender_device()) - } - - #[inline] - pub(crate) fn sender_user(&self) -> &UserId { - self.sender_user - .as_deref() - .expect("user must be authenticated for this handler") - } - - #[inline] - pub(crate) fn sender_device(&self) -> &DeviceId { - self.sender_device - .as_deref() - .expect("user must be authenticated and device identified") - } - - #[inline] - pub(crate) fn origin(&self) -> &ServerName { - self.origin - .as_deref() - .expect("server must be authenticated for this handler") - } -} - -impl Deref for Args -where - T: IncomingRequest + Send + Sync + 'static, -{ - type Target = T; + type Target = R; fn deref(&self) -> &Self::Target { &self.body } } @@ -145,13 +97,6 @@ where let body = R::try_from_http_request(request, &path) .map_err(|e| err!(Request(BadJson(debug_warn!("{e}")))))?; - Ok(Self { - body, - origin: auth.origin, - sender_user: auth.sender_user, - sender_device: auth.sender_device, - appservice_info: auth.appservice_info, - json_body, - }) + Ok(Self { body, json_body, identity: auth }) } } diff --git a/src/api/router/auth.rs b/src/api/router/auth.rs index 86704151a..b2a9b9ab0 100644 --- a/src/api/router/auth.rs +++ b/src/api/router/auth.rs @@ -2,7 +2,7 @@ use std::any::{Any, TypeId}; use conduwuit::{Err, Result, err}; use ruma::{ - OwnedDeviceId, OwnedServerName, OwnedUserId, UserId, + DeviceId, OwnedDeviceId, OwnedServerName, OwnedUserId, UserId, api::{ IncomingRequest, auth_scheme::{ @@ -20,20 +20,57 @@ use service::{ use crate::{router::args::AuthQueryParams, service::appservice::RegistrationInfo}; -#[derive(Default)] -pub(super) struct Auth { - pub(super) origin: Option, - pub(super) sender_user: Option, - pub(super) sender_device: Option, - pub(super) appservice_info: Option, +pub(crate) enum ClientIdentity { + User { + sender_user: OwnedUserId, + sender_device: OwnedDeviceId, + }, + Appservice { + sender_user: OwnedUserId, + sender_device: Option, + appservice_info: RegistrationInfo, + }, } -pub(super) trait CheckAuth: AuthScheme { +impl ClientIdentity { + pub(crate) fn sender_user(&self) -> &UserId { + match self { + | Self::User { sender_user, .. } | Self::Appservice { sender_user, .. } => + sender_user, + } + } + + pub(crate) fn sender_device(&self) -> Option<&DeviceId> { + match self { + | Self::User { sender_device, .. } => Some(sender_device), + | Self::Appservice { sender_device, .. } => sender_device.as_deref(), + } + } + + pub(crate) fn expect_sender_device(&self) -> Result<&DeviceId> { + self.sender_device().ok_or_else(|| { + err!(Request(Forbidden("Appservices must masquerade to use this endpoint"))) + }) + } + + pub(crate) fn appservice_info(&self) -> Option<&RegistrationInfo> { + match self { + | Self::User { .. } => None, + | Self::Appservice { appservice_info, .. } => Some(appservice_info), + } + } + + pub(crate) fn is_appservice(&self) -> bool { matches!(self, Self::Appservice { .. }) } +} + +pub(crate) trait CheckAuth: AuthScheme { + type Identity: Send; + fn authenticate + Sync>( services: &Services, incoming_request: &hyper::Request, query: AuthQueryParams, - ) -> impl Future> + Send { + ) -> impl Future> + Send { async move { let route = TypeId::of::(); @@ -54,17 +91,19 @@ pub(super) trait CheckAuth: AuthScheme { request: &hyper::Request, query: AuthQueryParams, route: TypeId, - ) -> impl Future> + Send; + ) -> impl Future> + Send; } impl CheckAuth for ServerSignatures { + type Identity = OwnedServerName; + async fn verify + Sync>( services: &Services, output: Self::Output, request: &hyper::Request, _query: AuthQueryParams, _route: TypeId, - ) -> Result { + ) -> Result { let destination = services.globals.server_name(); if output .destination @@ -96,10 +135,7 @@ impl CheckAuth for ServerSignatures { ))); } - Ok(Auth { - origin: Some(output.origin.clone()), - ..Default::default() - }) + Ok(output.origin) }, | Err(err) => Err!(Request(Unauthorized(warn!("Failed to verify X-Matrix header: {err}")))), @@ -108,162 +144,164 @@ impl CheckAuth for ServerSignatures { } impl CheckAuth for AccessToken { + type Identity = ClientIdentity; + async fn verify + Sync>( services: &Services, output: Self::Output, _request: &hyper::Request, query: AuthQueryParams, route: TypeId, - ) -> Result { - // Check for appservice tokens first - - let (sender_user, sender_device, appservice_info) = { - if let Ok((sender_user, sender_device)) = - services.users.find_from_token(&output).await + ) -> Result { + if let Ok((sender_user, sender_device)) = services.users.find_from_token(&output).await { + // Locked users can only use /logout and /logout/all + if services + .users + .is_locked(&sender_user) + .await + .is_ok_and(std::convert::identity) { - // Locked users can only use /logout and /logout/all - if services - .users - .is_locked(&sender_user) - .await - .is_ok_and(std::convert::identity) + if !(route == TypeId::of::() + || route == TypeId::of::()) { - if !(route == TypeId::of::() - || route == TypeId::of::()) - { - return Err!(Request(Unauthorized("Your account is locked."))); - } + return Err!(Request(Unauthorized("Your account is locked."))); } + } - (Some(sender_user), Some(sender_device), None) - } else if let Ok(appservice_info) = services.appservice.find_from_token(&output).await - { - let Ok(sender_user) = query.user_id.clone().map_or_else( - || { - UserId::parse_with_server_name( - appservice_info.registration.sender_localpart.as_str(), - services.globals.server_name(), - ) - }, - UserId::parse, - ) else { - return Err!(Request(InvalidUsername("Username is invalid."))); + Ok(ClientIdentity::User { sender_user, sender_device }) + } else if let Ok(appservice_info) = services.appservice.find_from_token(&output).await { + let Ok(sender_user) = query.user_id.clone().map_or_else( + || { + UserId::parse_with_server_name( + appservice_info.registration.sender_localpart.as_str(), + services.globals.server_name(), + ) + }, + UserId::parse, + ) else { + return Err!(Request(InvalidUsername("Username is invalid."))); + }; + + if !appservice_info.is_user_match(&sender_user) { + return Err!(Request(Exclusive("User is not in namespace."))); + } + + // MSC3202/MSC4190: Handle device_id masquerading for appservices. + // The device_id can be provided via `device_id` or + // `org.matrix.msc3202.device_id` query parameter. + let sender_device = + if let Some(device_id) = query.device_id.as_deref().map(Into::into) { + // Verify the device exists for this user + if services + .users + .get_device_metadata(&sender_user, device_id) + .await + .is_err() + { + return Err!(Request(Forbidden( + "Device does not exist for user or appservice cannot masquerade as \ + this device." + ))); + } + + Some(device_id.to_owned()) + } else { + None }; - if !appservice_info.is_user_match(&sender_user) { - return Err!(Request(Exclusive("User is not in namespace."))); - } - - // MSC3202/MSC4190: Handle device_id masquerading for appservices. - // The device_id can be provided via `device_id` or - // `org.matrix.msc3202.device_id` query parameter. - let sender_device = - if let Some(device_id) = query.device_id.as_deref().map(Into::into) { - // Verify the device exists for this user - if services - .users - .get_device_metadata(&sender_user, device_id) - .await - .is_err() - { - return Err!(Request(Forbidden( - "Device does not exist for user or appservice cannot masquerade \ - as this device." - ))); - } - - Some(device_id.to_owned()) - } else { - None - }; - - (Some(sender_user), sender_device, Some(appservice_info)) - } else { - return Err!(Request(Unauthorized("Invalid access token."))); - } - }; - - Ok(Auth { - sender_user, - sender_device, - appservice_info, - ..Default::default() - }) + Ok(ClientIdentity::Appservice { + sender_user, + sender_device, + appservice_info, + }) + } else { + return Err!(Request(Unauthorized("Invalid access token."))); + } } } impl CheckAuth for AccessTokenOptional { + type Identity = Option; + async fn verify + Sync>( services: &Services, output: Self::Output, request: &hyper::Request, query: AuthQueryParams, route: TypeId, - ) -> Result { + ) -> Result { match output { | Some(token) => - ::verify(services, token, request, query, route).await, - | None => Ok(Auth::default()), + ::verify(services, token, request, query, route) + .await + .map(Some), + | None => Ok(None), } } } impl CheckAuth for AppserviceToken { + type Identity = RegistrationInfo; + async fn verify + Sync>( services: &Services, output: Self::Output, _request: &hyper::Request, _query: AuthQueryParams, _route: TypeId, - ) -> Result { + ) -> Result { let Ok(appservice_info) = services.appservice.find_from_token(&output).await else { return Err!(Request(Unauthorized("Invalid appservice token."))); }; - Ok(Auth { - appservice_info: Some(appservice_info), - ..Default::default() - }) + Ok(appservice_info) } } impl CheckAuth for AppserviceTokenOptional { + type Identity = Option; + async fn verify + Sync>( services: &Services, output: Self::Output, request: &hyper::Request, query: AuthQueryParams, route: TypeId, - ) -> Result { + ) -> Result { match output { | Some(token) => ::verify(services, token, request, query, route) - .await, - | None => Ok(Auth::default()), + .await + .map(Some), + | None => Ok(None), } } } impl CheckAuth for NoAuthentication { + type Identity = (); + async fn verify + Sync>( _services: &Services, _output: Self::Output, _request: &hyper::Request, _query: AuthQueryParams, _route: TypeId, - ) -> Result { - Ok(Auth::default()) + ) -> Result { + Ok(()) } } impl CheckAuth for NoAccessToken { + type Identity = Option; + async fn verify + Sync>( services: &Services, _output: Self::Output, request: &hyper::Request, query: AuthQueryParams, route: TypeId, - ) -> Result { + ) -> Result { // We handle these the same as AccessTokenOptional let token = AccessTokenOptional::extract_authentication(request).map_err(|err| { err!(Request(Unauthorized(warn!("Failed to extract authorization: {}", err)))) diff --git a/src/api/server/backfill.rs b/src/api/server/backfill.rs index 2359f4a49..7e0b18f00 100644 --- a/src/api/server/backfill.rs +++ b/src/api/server/backfill.rs @@ -28,7 +28,7 @@ pub(crate) async fn get_backfill_route( ) -> Result { AccessCheck { services: &services, - origin: body.origin(), + origin: &body.identity, room_id: &body.room_id, event_id: None, } @@ -41,7 +41,7 @@ pub(crate) async fn get_backfill_route( .await { info!( - origin = body.origin().as_str(), + origin = body.identity.as_str(), "Refusing to serve backfill for room we aren't participating in" ); return Err!(Request(NotFound("This server is not participating in that room."))); @@ -76,7 +76,7 @@ pub(crate) async fn get_backfill_route( Ok(services .rooms .state_accessor - .server_can_see_event(body.origin(), &pdu.room_id_or_hash(), &pdu.event_id) + .server_can_see_event(&body.identity, &pdu.room_id_or_hash(), &pdu.event_id) .await .then_some(pdu)) }) diff --git a/src/api/server/event.rs b/src/api/server/event.rs index 403fbeb47..ff82f3d00 100644 --- a/src/api/server/event.rs +++ b/src/api/server/event.rs @@ -40,7 +40,7 @@ pub(crate) async fn get_event_route( AccessCheck { services: &services, - origin: body.origin(), + origin: &body.identity, room_id, event_id: Some(&body.event_id), } @@ -54,7 +54,7 @@ pub(crate) async fn get_event_route( .await { info!( - origin = body.origin().as_str(), + origin = body.identity.as_str(), "Refusing to serve state for room we aren't participating in" ); return Err!(Request(NotFound("This server is not participating in that room."))); diff --git a/src/api/server/event_auth.rs b/src/api/server/event_auth.rs index 70caa16f0..66fae5e01 100644 --- a/src/api/server/event_auth.rs +++ b/src/api/server/event_auth.rs @@ -19,7 +19,7 @@ pub(crate) async fn get_event_authorization_route( ) -> Result { AccessCheck { services: &services, - origin: body.origin(), + origin: &body.identity, room_id: &body.room_id, event_id: None, } @@ -42,7 +42,7 @@ pub(crate) async fn get_event_authorization_route( .await { info!( - origin = body.origin().as_str(), + origin = body.identity.as_str(), "Refusing to serve state for room we aren't participating in" ); return Err!(Request(NotFound("This server is not participating in that room."))); diff --git a/src/api/server/get_missing_events.rs b/src/api/server/get_missing_events.rs index 25ec86d3d..a4915bb8b 100644 --- a/src/api/server/get_missing_events.rs +++ b/src/api/server/get_missing_events.rs @@ -22,7 +22,7 @@ pub(crate) async fn get_missing_events_route( ) -> Result { AccessCheck { services: &services, - origin: body.origin(), + origin: &body.identity, room_id: &body.room_id, event_id: None, } @@ -36,7 +36,7 @@ pub(crate) async fn get_missing_events_route( .await { info!( - origin = body.origin().as_str(), + origin = body.identity.as_str(), "Refusing to serve state for room we aren't participating in" ); return Err!(Request(NotFound("This server is not participating in that room."))); @@ -91,10 +91,10 @@ pub(crate) async fn get_missing_events_route( if !services .rooms .state_accessor - .server_can_see_event(body.origin(), &body.room_id, pdu.event_id()) + .server_can_see_event(&body.identity, &body.room_id, pdu.event_id()) .await { - debug!(%next_event_id, origin = %body.origin(), "redacting event origin cannot see"); + debug!(%next_event_id, origin = %body.identity, "redacting event origin cannot see"); pdu.redact(&room_version, json!({}))?; } diff --git a/src/api/server/hierarchy.rs b/src/api/server/hierarchy.rs index d83c0979d..342f68c38 100644 --- a/src/api/server/hierarchy.rs +++ b/src/api/server/hierarchy.rs @@ -20,7 +20,7 @@ pub(crate) async fn get_hierarchy_route( .await { info!( - origin = body.origin().as_str(), + origin = body.identity.as_str(), "Refusing to serve state for room we aren't participating in" ); return Err!(Request(NotFound("This server is not participating in that room."))); @@ -29,7 +29,7 @@ pub(crate) async fn get_hierarchy_route( let response = services .rooms .summary - .get_local_room_summary_for_server(body.origin(), &body.room_id, body.suggested_only) + .get_local_room_summary_for_server(&body.identity, &body.room_id, body.suggested_only) .await; if let Accessibility::Accessible(response) = response { diff --git a/src/api/server/invite.rs b/src/api/server/invite.rs index 2e59342f4..a029b822c 100644 --- a/src/api/server/invite.rs +++ b/src/api/server/invite.rs @@ -32,7 +32,7 @@ pub(crate) async fn create_invite_route( services .rooms .event_handler - .acl_check(body.origin(), &body.room_id) + .acl_check(&body.identity, &body.room_id) .await?; if !services.server.supported_room_version(&body.room_version) { @@ -54,12 +54,11 @@ pub(crate) async fn create_invite_route( if services .moderation - .is_remote_server_forbidden(body.origin()) + .is_remote_server_forbidden(&body.identity) { warn!( "Received federated/remote invite from banned server {} for room ID {}. Rejecting.", - body.origin(), - body.room_id + body.identity, body.room_id ); return Err!(Request(Forbidden("Server is banned on this homeserver."))); @@ -105,7 +104,7 @@ pub(crate) async fn create_invite_route( .and_then(Result::ok) .ok_or_else(|| err!(Request(InvalidParam("Invalid sender property"))))?; - if sender_user.server_name() != body.origin() { + if sender_user.server_name() != body.identity { return Err!(Request(Forbidden("Sender's server does not match the origin server.",))); } diff --git a/src/api/server/make_join.rs b/src/api/server/make_join.rs index 26a8ec7e7..2da92752b 100644 --- a/src/api/server/make_join.rs +++ b/src/api/server/make_join.rs @@ -30,7 +30,7 @@ use crate::Ruma; /// # `GET /_matrix/federation/v1/make_join/{roomId}/{userId}` /// /// Creates a join template. -#[tracing::instrument(skip_all, fields(room_id = %body.room_id, user_id = %body.user_id, origin = %body.origin()), level = "info")] +#[tracing::instrument(skip_all, fields(room_id = %body.room_id, user_id = %body.user_id, origin = %body.identity), level = "info")] pub(crate) async fn create_join_event_template_route( State(services): State, body: Ruma, @@ -45,14 +45,14 @@ pub(crate) async fn create_join_event_template_route( .await { info!( - origin = body.origin().as_str(), + origin = body.identity.as_str(), room_id = %body.room_id, "Refusing to serve make_join for room we aren't participating in" ); return Err!(Request(NotFound("This server is not participating in that room."))); } - if body.user_id.server_name() != body.origin() { + if body.user_id.server_name() != body.identity { return Err!(Request(BadJson("Not allowed to join on behalf of another server/user."))); } @@ -60,19 +60,17 @@ pub(crate) async fn create_join_event_template_route( services .rooms .event_handler - .acl_check(body.origin(), &body.room_id) + .acl_check(&body.identity, &body.room_id) .await?; if services .moderation - .is_remote_server_forbidden(body.origin()) + .is_remote_server_forbidden(&body.identity) { warn!( "Server {} for remote user {} tried joining room ID {} which has a server name that \ is globally forbidden. Rejecting.", - body.origin(), - &body.user_id, - &body.room_id, + body.identity, &body.user_id, &body.room_id, ); return Err!(Request(Forbidden("Server is banned on this homeserver."))); } diff --git a/src/api/server/make_knock.rs b/src/api/server/make_knock.rs index c25926663..d6cadf02d 100644 --- a/src/api/server/make_knock.rs +++ b/src/api/server/make_knock.rs @@ -28,14 +28,14 @@ pub(crate) async fn create_knock_event_template_route( .await { info!( - origin = body.origin().as_str(), + origin = body.identity.as_str(), room_id = %body.room_id, "Refusing to serve make_knock for room we aren't participating in" ); return Err!(Request(NotFound("This server is not participating in that room."))); } - if body.user_id.server_name() != body.origin() { + if body.user_id.server_name() != body.identity { return Err!(Request(BadJson("Not allowed to knock on behalf of another server/user."))); } @@ -43,19 +43,17 @@ pub(crate) async fn create_knock_event_template_route( services .rooms .event_handler - .acl_check(body.origin(), &body.room_id) + .acl_check(&body.identity, &body.room_id) .await?; if services .moderation - .is_remote_server_forbidden(body.origin()) + .is_remote_server_forbidden(&body.identity) { warn!( "Server {} for remote user {} tried knocking room ID {} which has a server name \ that is globally forbidden. Rejecting.", - body.origin(), - &body.user_id, - &body.room_id, + body.identity, &body.user_id, &body.room_id, ); return Err!(Request(Forbidden("Server is banned on this homeserver."))); } diff --git a/src/api/server/make_leave.rs b/src/api/server/make_leave.rs index 80a64bcca..168e235d7 100644 --- a/src/api/server/make_leave.rs +++ b/src/api/server/make_leave.rs @@ -26,13 +26,13 @@ pub(crate) async fn create_leave_event_template_route( .await { info!( - origin = body.origin().as_str(), + origin = body.identity.as_str(), "Refusing to serve make_leave for room we aren't participating in" ); return Err!(Request(NotFound("This server is not participating in that room."))); } - if body.user_id.server_name() != body.origin() { + if body.user_id.server_name() != body.identity { return Err!(Request(Forbidden( "Not allowed to leave on behalf of another server/user." ))); @@ -42,7 +42,7 @@ pub(crate) async fn create_leave_event_template_route( services .rooms .event_handler - .acl_check(body.origin(), &body.room_id) + .acl_check(&body.identity, &body.room_id) .await?; let room_version = services.rooms.state.get_room_version(&body.room_id).await?; diff --git a/src/api/server/send.rs b/src/api/server/send.rs index 4353ca4e2..3f0531287 100644 --- a/src/api/server/send.rs +++ b/src/api/server/send.rs @@ -62,7 +62,7 @@ pub(crate) async fn send_transaction_message_route( ClientIp(client): ClientIp, body: Ruma, ) -> Result { - if body.origin() != body.body.origin { + if body.identity != body.body.origin { return Err!(Request(Forbidden( "Not allowed to send transactions on behalf of other servers" ))); @@ -80,7 +80,7 @@ pub(crate) async fn send_transaction_message_route( ))); } - let txn_key = (body.origin().to_owned(), body.transaction_id.clone()); + let txn_key = (body.identity.to_owned(), body.transaction_id.clone()); // Atomically check cache, join active, or start new transaction match services @@ -136,7 +136,7 @@ async fn wait_for_result( skip_all, fields( id = ?body.transaction_id.as_str(), - origin = ?body.origin() + origin = ?body.identity ) )] async fn process_inbound_transaction( @@ -164,7 +164,7 @@ async fn process_inbound_transaction( .stream(); debug!(pdus = body.pdus.len(), edus = body.edus.len(), "Processing transaction",); - let results = match handle(&services, &client, body.origin(), pdus, edus).await { + let results = match handle(&services, &client, &body.identity, pdus, edus).await { | Ok(results) => results, | Err(err) => { fail_federation_txn(services, &txn_key, &sender, err); diff --git a/src/api/server/send_join.rs b/src/api/server/send_join.rs index d80b700bc..5498d03d3 100644 --- a/src/api/server/send_join.rs +++ b/src/api/server/send_join.rs @@ -304,7 +304,7 @@ pub(crate) async fn create_join_event_v2_route( ) -> Result { if services .moderation - .is_remote_server_forbidden(body.origin()) + .is_remote_server_forbidden(&body.identity) { return Err!(Request(Forbidden("Server is banned on this homeserver."))); } @@ -314,8 +314,7 @@ pub(crate) async fn create_join_event_v2_route( warn!( "Server {} tried joining room ID {} through us which has a server name that is \ globally forbidden. Rejecting.", - body.origin(), - &body.room_id, + body.identity, &body.room_id, ); return Err!(Request(Forbidden(warn!( "Room ID server name {server} is banned on this homeserver." @@ -325,12 +324,12 @@ pub(crate) async fn create_join_event_v2_route( let now = Instant::now(); let room_state = - create_join_event(&services, body.origin(), &body.room_id, &body.pdu, body.omit_members) + create_join_event(&services, &body.identity, &body.room_id, &body.pdu, body.omit_members) .boxed() .await?; info!( "Finished sending a join for {} in {} in {:?}", - body.origin(), + body.identity, &body.room_id, now.elapsed() ); diff --git a/src/api/server/send_knock.rs b/src/api/server/send_knock.rs index 29d9a1e31..76e8f363f 100644 --- a/src/api/server/send_knock.rs +++ b/src/api/server/send_knock.rs @@ -26,13 +26,12 @@ pub(crate) async fn create_knock_event_v1_route( ) -> Result { if services .moderation - .is_remote_server_forbidden(body.origin()) + .is_remote_server_forbidden(&body.identity) { warn!( "Server {} tried knocking room ID {} who has a server name that is globally \ forbidden. Rejecting.", - body.origin(), - &body.room_id, + body.identity, &body.room_id, ); return Err!(Request(Forbidden("Server is banned on this homeserver."))); } @@ -42,8 +41,7 @@ pub(crate) async fn create_knock_event_v1_route( warn!( "Server {} tried knocking room ID {} which has a server name that is globally \ forbidden. Rejecting.", - body.origin(), - &body.room_id, + body.identity, &body.room_id, ); return Err!(Request(Forbidden("Server is banned on this homeserver."))); } @@ -60,7 +58,7 @@ pub(crate) async fn create_knock_event_v1_route( .await { info!( - origin = body.origin().as_str(), + origin = body.identity.as_str(), "Refusing to serve send_knock for room we aren't participating in" ); return Err!(Request(NotFound("This server is not participating in that room."))); @@ -70,7 +68,7 @@ pub(crate) async fn create_knock_event_v1_route( services .rooms .event_handler - .acl_check(body.origin(), &body.room_id) + .acl_check(&body.identity, &body.room_id) .await?; let room_version = services.rooms.state.get_room_version(&body.room_id).await?; @@ -133,7 +131,7 @@ pub(crate) async fn create_knock_event_v1_route( .await?; // check if origin server is trying to send for another server - if sender.server_name() != body.origin() { + if sender.server_name() != body.identity { return Err!(Request(BadJson("Not allowed to knock on behalf of another server/user."))); } diff --git a/src/api/server/send_leave.rs b/src/api/server/send_leave.rs index 99479f93a..7b1ec9c03 100644 --- a/src/api/server/send_leave.rs +++ b/src/api/server/send_leave.rs @@ -21,7 +21,7 @@ pub(crate) async fn create_leave_event_v2_route( State(services): State, body: Ruma, ) -> Result { - create_leave_event(&services, body.origin(), &body.room_id, &body.pdu).await?; + create_leave_event(&services, &body.identity, &body.room_id, &body.pdu).await?; Ok(create_leave_event::v2::Response::new()) } diff --git a/src/api/server/state.rs b/src/api/server/state.rs index bc4d32274..709c62fb6 100644 --- a/src/api/server/state.rs +++ b/src/api/server/state.rs @@ -17,7 +17,7 @@ pub(crate) async fn get_room_state_route( ) -> Result { AccessCheck { services: &services, - origin: body.origin(), + origin: &body.identity, room_id: &body.room_id, event_id: None, } @@ -40,7 +40,7 @@ pub(crate) async fn get_room_state_route( .await { info!( - origin = body.origin().as_str(), + origin = body.identity.as_str(), "Refusing to serve state for room we aren't participating in" ); return Err!(Request(NotFound("This server is not participating in that room."))); diff --git a/src/api/server/state_ids.rs b/src/api/server/state_ids.rs index e2b852a7e..bd7414f7a 100644 --- a/src/api/server/state_ids.rs +++ b/src/api/server/state_ids.rs @@ -18,7 +18,7 @@ pub(crate) async fn get_room_state_ids_route( ) -> Result { AccessCheck { services: &services, - origin: body.origin(), + origin: &body.identity, room_id: &body.room_id, event_id: None, } @@ -41,7 +41,7 @@ pub(crate) async fn get_room_state_ids_route( .await { info!( - origin = body.origin().as_str(), + origin = body.identity.as_str(), "Refusing to serve state for room we aren't participating in" ); return Err!(Request(NotFound("This server is not participating in that room."))); diff --git a/src/api/server/user.rs b/src/api/server/user.rs index dfcafa708..ca0cf7148 100644 --- a/src/api/server/user.rs +++ b/src/api/server/user.rs @@ -60,13 +60,13 @@ pub(crate) async fn get_devices_route( let master_key = services .users - .get_master_key(None, &body.user_id, &|u| u.server_name() == body.origin()) + .get_master_key(None, &body.user_id, &|u| u.server_name() == body.identity) .await .ok(); let self_signing_key = services .users - .get_self_signing_key(None, &body.user_id, &|u| u.server_name() == body.origin()) + .get_self_signing_key(None, &body.user_id, &|u| u.server_name() == body.identity) .await .ok(); @@ -94,7 +94,7 @@ pub(crate) async fn get_keys_route( &services, None, &body.device_keys, - |u| Some(u.server_name()) == body.origin.as_deref(), + |u| u.server_name() == body.identity, services.globals.allow_device_name_federation(), Duration::from_secs(0), ) diff --git a/src/service/rooms/alias/mod.rs b/src/service/rooms/alias/mod.rs index 10fb50185..ea3e09259 100644 --- a/src/service/rooms/alias/mod.rs +++ b/src/service/rooms/alias/mod.rs @@ -294,7 +294,7 @@ impl Service { pub async fn appservice_checks( &self, room_alias: &RoomAliasId, - appservice_info: &Option, + appservice_info: Option<&RegistrationInfo>, ) -> Result<()> { if !self .services