refactor: Represent route auth information in the type system

This commit is contained in:
Ginger
2026-05-26 13:28:23 -04:00
committed by Ellis Git
parent dabbdc7517
commit 74841b6711
78 changed files with 496 additions and 482 deletions
+1 -1
View File
@@ -13,7 +13,7 @@ pub(crate) async fn ban_room(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<rooms::ban::v1::Request>, body: Ruma<rooms::ban::v1::Request>,
) -> Result<rooms::ban::v1::Response> { ) -> Result<rooms::ban::v1::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if !services.users.is_admin(sender_user).await { if !services.users.is_admin(sender_user).await {
return Err!(Request(Forbidden("Only server administrators can use this endpoint"))); return Err!(Request(Forbidden("Only server administrators can use this endpoint")));
} }
+1 -1
View File
@@ -13,7 +13,7 @@ pub(crate) async fn list_rooms(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<rooms::list::v1::Request>, body: Ruma<rooms::list::v1::Request>,
) -> Result<rooms::list::v1::Response> { ) -> Result<rooms::list::v1::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if !services.users.is_admin(sender_user).await { if !services.users.is_admin(sender_user).await {
return Err!(Request(Forbidden("Only server administrators can use this endpoint"))); return Err!(Request(Forbidden("Only server administrators can use this endpoint")));
} }
+30 -15
View File
@@ -27,7 +27,7 @@ use ruma::{
use service::{mailer::messages, uiaa::Identity, users::HashedPassword}; use service::{mailer::messages, uiaa::Identity, users::HashedPassword};
use super::{DEVICE_ID_LENGTH, TOKEN_LENGTH}; use super::{DEVICE_ID_LENGTH, TOKEN_LENGTH};
use crate::Ruma; use crate::{Ruma, router::ClientIdentity};
pub(crate) mod register; pub(crate) mod register;
pub(crate) mod threepid; 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."))); return Err!(Request(UserInUse("User ID is not available.")));
} }
if let Some(ref info) = body.appservice_info { if let Some(ClientIdentity::Appservice { appservice_info, .. }) = &body.identity
if !info.is_user_match(&user_id) { && !appservice_info.is_user_match(&user_id)
return Err!(Request(Exclusive("Username is not in an appservice namespace."))); {
} return Err!(Request(Exclusive("Username is not in an appservice namespace.")));
} } else if services.appservice.is_exclusive_user_id(&user_id).await {
if services.appservice.is_exclusive_user_id(&user_id).await {
return Err!(Request(Exclusive("Username is reserved by an appservice."))); return Err!(Request(Exclusive("Username is reserved by an appservice.")));
} }
@@ -111,7 +109,11 @@ pub(crate) async fn change_password_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<change_password::v3::Request>, body: Ruma<change_password::v3::Request>,
) -> Result<change_password::v3::Response> { ) -> Result<change_password::v3::Response> {
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 // A signed-in user is trying to change their password, prompt them for their
// existing one // existing one
@@ -157,7 +159,12 @@ pub(crate) async fn change_password_route(
services services
.users .users
.all_device_ids(&sender_user) .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) .for_each(async |id| services.users.remove_device(&sender_user, &id).await)
.await; .await;
@@ -173,7 +180,12 @@ pub(crate) async fn change_password_route(
.await .await
.ok() .ok()
.as_ref() .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) .then_some(pushkey)
}) })
.for_each(async |pushkey| { .for_each(async |pushkey| {
@@ -241,9 +253,11 @@ pub(crate) async fn whoami_route(
State(_): State<crate::State>, State(_): State<crate::State>,
body: Ruma<whoami::v3::Request>, body: Ruma<whoami::v3::Request>,
) -> Result<whoami::v3::Response> { ) -> Result<whoami::v3::Response> {
Ok(assign!(whoami::v3::Response::new(body.sender_user().to_owned(), false), { Ok(
device_id: body.sender_device, 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` /// # `POST /_matrix/client/r0/account/deactivate`
@@ -266,8 +280,9 @@ pub(crate) async fn deactivate_route(
// Authentication for this endpoint is technically optional, // Authentication for this endpoint is technically optional,
// but we require the user to be logged in // but we require the user to be logged in
let sender_user = body let sender_user = body
.sender_user .identity
.as_ref() .as_ref()
.map(|identity| identity.sender_user())
.ok_or_else(|| err!(Request(MissingToken("Missing access token."))))?; .ok_or_else(|| err!(Request(MissingToken("Missing access token."))))?;
// Prompt the user to confirm with their password using UIAA // Prompt the user to confirm with their password using UIAA
+7 -9
View File
@@ -59,7 +59,7 @@ pub(crate) async fn register_route(
let allow_registration = let allow_registration =
services.config.allow_registration || services.firstrun.is_first_run(); 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!( info!(
?body.username, ?body.username,
?body.initial_device_display_name, ?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 // Appservices can skip auth
None None
} else { } 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 // For appservice logins, make sure that the user ID is in the appservice's
// namespace // namespace
match body.appservice_info { match body.identity {
| Some(ref info) => | Some(ref info) =>
if !info.is_user_match(&user_id) && !emergency_mode_enabled { if !info.is_user_match(&user_id) && !emergency_mode_enabled {
return Err!(Request(Exclusive( return Err!(Request(Exclusive(
@@ -125,7 +125,7 @@ pub(crate) async fn register_route(
return Err!(Request(Exclusive("Username is reserved by an appservice."))); 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 None
} else if let Some(password) = body.password.as_deref() { } else if let Some(password) = body.password.as_deref() {
Some(HashedPassword::new(password)?) Some(HashedPassword::new(password)?)
@@ -140,9 +140,7 @@ pub(crate) async fn register_route(
let mut displayname = user_id.localpart().to_owned(); let mut displayname = user_id.localpart().to_owned();
// Apply the new user displayname suffix, if it's set // Apply the new user displayname suffix, if it's set
if !services.globals.new_user_displayname_suffix().is_empty() if !services.globals.new_user_displayname_suffix().is_empty() && body.identity.is_none() {
&& body.appservice_info.is_none()
{
write!(displayname, " {}", services.server.config.new_user_displayname_suffix)?; 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(""); 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() { if !device_display_name.is_empty() {
let notice = format!( let notice = format!(
"New user \"{user_id}\" registered on this server from IP {client} and device \ "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 { for room in &services.server.config.auto_join_rooms {
let Ok(room_id) = services.rooms.alias.resolve(room).await else { let Ok(room_id) = services.rooms.alias.resolve(room).await else {
error!( error!(
+16 -9
View File
@@ -22,7 +22,7 @@ pub(crate) async fn third_party_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<get_3pids::v3::Request>, body: Ruma<get_3pids::v3::Request>,
) -> Result<get_3pids::v3::Response> { ) -> Result<get_3pids::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let mut threepids = vec![]; let mut threepids = vec![];
if let Some(email) = services if let Some(email) = services
@@ -53,6 +53,14 @@ pub(crate) async fn request_3pid_management_token_via_email_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<request_3pid_management_token_via_email::v3::Request>, body: Ruma<request_3pid_management_token_via_email::v3::Request>,
) -> Result<request_3pid_management_token_via_email::v3::Response> { ) -> Result<request_3pid_management_token_via_email::v3::Response> {
// 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() { if !services.threepid.email_requirement().may_change() {
return Err!(Request(Forbidden("You may not change your email address."))); 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), Mailbox::new(None, email),
|verification_link| messages::ChangeEmail { |verification_link| messages::ChangeEmail {
server_name: services.config.server_name.as_str(), server_name: services.config.server_name.as_str(),
user_id: body.sender_user.as_deref(), user_id: Some(sender_user),
verification_link, verification_link,
}, },
&body.client_secret, &body.client_secret,
@@ -107,8 +115,6 @@ pub(crate) async fn add_3pid_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<add_3pid::v3::Request>, body: Ruma<add_3pid::v3::Request>,
) -> Result<add_3pid::v3::Response> { ) -> Result<add_3pid::v3::Response> {
let sender_user = body.sender_user();
if !services.threepid.email_requirement().may_change() { if !services.threepid.email_requirement().may_change() {
return Err!(Request(Forbidden("You may not change your email address."))); 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 // Require password auth to add an email
let _ = services let _ = services
.uiaa .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?; .await?;
let email = services let email = services
@@ -127,7 +136,7 @@ pub(crate) async fn add_3pid_route(
services services
.threepid .threepid
.associate_localpart_email(sender_user.localpart(), &email) .associate_localpart_email(body.identity.sender_user().localpart(), &email)
.await?; .await?;
Ok(add_3pid::v3::Response::new()) Ok(add_3pid::v3::Response::new())
@@ -138,8 +147,6 @@ pub(crate) async fn delete_3pid_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<delete_3pid::v3::Request>, body: Ruma<delete_3pid::v3::Request>,
) -> Result<delete_3pid::v3::Response> { ) -> Result<delete_3pid::v3::Response> {
let sender_user = body.sender_user();
if body.medium != Medium::Email { if body.medium != Medium::Email {
return Ok(delete_3pid::v3::Response::new(ThirdPartyIdRemovalStatus::NoSupport)); return Ok(delete_3pid::v3::Response::new(ThirdPartyIdRemovalStatus::NoSupport));
} }
@@ -150,7 +157,7 @@ pub(crate) async fn delete_3pid_route(
if services if services
.threepid .threepid
.disassociate_localpart_email(sender_user.localpart()) .disassociate_localpart_email(body.identity.sender_user().localpart())
.await .await
.is_none() .is_none()
{ {
+8 -8
View File
@@ -22,9 +22,9 @@ pub(crate) async fn set_global_account_data_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<set_global_account_data::v3::Request>, body: Ruma<set_global_account_data::v3::Request>,
) -> Result<set_global_account_data::v3::Response> { ) -> Result<set_global_account_data::v3::Response> {
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."))); 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<crate::State>, State(services): State<crate::State>,
body: Ruma<set_room_account_data::v3::Request>, body: Ruma<set_room_account_data::v3::Request>,
) -> Result<set_room_account_data::v3::Response> { ) -> Result<set_room_account_data::v3::Response> {
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."))); 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<crate::State>, State(services): State<crate::State>,
body: Ruma<get_global_account_data::v3::Request>, body: Ruma<get_global_account_data::v3::Request>,
) -> Result<get_global_account_data::v3::Response> { ) -> Result<get_global_account_data::v3::Response> {
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."))); 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<crate::State>, State(services): State<crate::State>,
body: Ruma<get_room_account_data::v3::Request>, body: Ruma<get_room_account_data::v3::Request>,
) -> Result<get_room_account_data::v3::Response> { ) -> Result<get_room_account_data::v3::Response> {
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."))); return Err!(Request(Forbidden("You cannot get account data of other users.")));
} }
+6 -5
View File
@@ -12,10 +12,11 @@ pub(crate) async fn get_suspended_status(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<get_suspended::v1::Request>, body: Ruma<get_suspended::v1::Request>,
) -> Result<get_suspended::v1::Response> { ) -> Result<get_suspended::v1::Response> {
let sender_user = body.sender_user(); let (admin, active) = join(
services.users.is_admin(body.identity.sender_user()),
let (admin, active) = services.users.is_active(&body.user_id),
join(services.users.is_admin(sender_user), services.users.is_active(&body.user_id)).await; )
.await;
if !admin { if !admin {
return Err!(Request(Forbidden("Only server administrators can use this endpoint"))); 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<crate::State>, State(services): State<crate::State>,
body: Ruma<set_suspended::v1::Request>, body: Ruma<set_suspended::v1::Request>,
) -> Result<set_suspended::v1::Response> { ) -> Result<set_suspended::v1::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let (sender_admin, active, target_admin) = join3( let (sender_admin, active, target_admin) = join3(
services.users.is_admin(sender_user), services.users.is_admin(sender_user),
+4 -4
View File
@@ -11,7 +11,7 @@ pub(crate) async fn create_alias_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<create_alias::v3::Request>, body: Ruma<create_alias::v3::Request>,
) -> Result<create_alias::v3::Response> { ) -> Result<create_alias::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if services.users.is_suspended(sender_user).await? { if services.users.is_suspended(sender_user).await? {
return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
} }
@@ -19,7 +19,7 @@ pub(crate) async fn create_alias_route(
services services
.rooms .rooms
.alias .alias
.appservice_checks(&body.room_alias, &body.appservice_info) .appservice_checks(&body.room_alias, body.identity.appservice_info())
.await?; .await?;
// this isn't apart of alias_checks or delete alias route because we should // 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<crate::State>, State(services): State<crate::State>,
body: Ruma<delete_alias::v3::Request>, body: Ruma<delete_alias::v3::Request>,
) -> Result<delete_alias::v3::Response> { ) -> Result<delete_alias::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if services.users.is_suspended(sender_user).await? { if services.users.is_suspended(sender_user).await? {
return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
} }
@@ -67,7 +67,7 @@ pub(crate) async fn delete_alias_route(
services services
.rooms .rooms
.alias .alias
.appservice_checks(&body.room_alias, &body.appservice_info) .appservice_checks(&body.room_alias, body.identity.appservice_info())
.await?; .await?;
services services
+2 -4
View File
@@ -1,5 +1,5 @@
use axum::extract::State; use axum::extract::State;
use conduwuit::{Err, Result, err}; use conduwuit::{Err, Result};
use ruma::{ use ruma::{
api::{appservice::ping, client::appservice::request_ping}, api::{appservice::ping, client::appservice::request_ping},
assign, assign,
@@ -15,9 +15,7 @@ pub(crate) async fn appservice_ping(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<request_ping::v1::Request>, body: Ruma<request_ping::v1::Request>,
) -> Result<request_ping::v1::Response> { ) -> Result<request_ping::v1::Response> {
let appservice_info = body.appservice_info.as_ref().ok_or_else(|| { let appservice_info = &body.identity;
err!(Request(Forbidden("This endpoint can only be called by appservices.")))
})?;
if body.appservice_id != appservice_info.registration.id { if body.appservice_id != appservice_info.registration.id {
return Err!(Request(Forbidden( return Err!(Request(Forbidden(
+50 -26
View File
@@ -25,7 +25,7 @@ pub(crate) async fn create_backup_version_route(
) -> Result<create_backup_version::v3::Response> { ) -> Result<create_backup_version::v3::Response> {
let version = services let version = services
.key_backups .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)) Ok(create_backup_version::v3::Response::new(version))
} }
@@ -40,7 +40,7 @@ pub(crate) async fn update_backup_version_route(
) -> Result<update_backup_version::v3::Response> { ) -> Result<update_backup_version::v3::Response> {
services services
.key_backups .key_backups
.update_backup(body.sender_user(), &body.version, &body.algorithm) .update_backup(body.identity.sender_user(), &body.version, &body.algorithm)
.await?; .await?;
Ok(update_backup_version::v3::Response::new()) Ok(update_backup_version::v3::Response::new())
@@ -55,11 +55,11 @@ pub(crate) async fn get_latest_backup_info_route(
) -> Result<get_latest_backup_info::v3::Response> { ) -> Result<get_latest_backup_info::v3::Response> {
let (version, algorithm) = services let (version, algorithm) = services
.key_backups .key_backups
.get_latest_backup(body.sender_user()) .get_latest_backup(body.identity.sender_user())
.await .await
.map_err(|_| err!(Request(NotFound("Key backup does not exist."))))?; .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)) 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<get_backup_info::v3::Response> { ) -> Result<get_backup_info::v3::Response> {
let algorithm = services let algorithm = services
.key_backups .key_backups
.get_backup(body.sender_user(), &body.version) .get_backup(body.identity.sender_user(), &body.version)
.await .await
.map_err(|_| { .map_err(|_| {
err!(Request(NotFound("Key backup does not exist at version {:?}", body.version))) 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())) 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<delete_backup_version::v3::Response> { ) -> Result<delete_backup_version::v3::Response> {
services services
.key_backups .key_backups
.delete_backup(body.sender_user(), &body.version) .delete_backup(body.identity.sender_user(), &body.version)
.await; .await;
Ok(delete_backup_version::v3::Response::new()) Ok(delete_backup_version::v3::Response::new())
@@ -116,7 +117,7 @@ pub(crate) async fn add_backup_keys_route(
) -> Result<add_backup_keys::v3::Response> { ) -> Result<add_backup_keys::v3::Response> {
if services if services
.key_backups .key_backups
.get_latest_backup_version(body.sender_user()) .get_latest_backup_version(body.identity.sender_user())
.await .await
.is_ok_and(|version| version != body.version) .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 { for (session_id, key_data) in &room.sessions {
services services
.key_backups .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?; .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)) Ok(add_backup_keys::v3::Response::new(etag, count))
} }
@@ -153,7 +161,7 @@ pub(crate) async fn add_backup_keys_for_room_route(
) -> Result<add_backup_keys_for_room::v3::Response> { ) -> Result<add_backup_keys_for_room::v3::Response> {
if services if services
.key_backups .key_backups
.get_latest_backup_version(body.sender_user()) .get_latest_backup_version(body.identity.sender_user())
.await .await
.is_ok_and(|version| version != body.version) .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 { for (session_id, key_data) in &body.sessions {
services services
.key_backups .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?; .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)) 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<add_backup_keys_for_session::v3::Response> { ) -> Result<add_backup_keys_for_session::v3::Response> {
if services if services
.key_backups .key_backups
.get_latest_backup_version(body.sender_user()) .get_latest_backup_version(body.identity.sender_user())
.await .await
.is_ok_and(|version| version != body.version) .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; let mut ok_to_replace = true;
if let Some(old_key) = &services if let Some(old_key) = &services
.key_backups .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 .await
.ok() .ok()
{ {
@@ -260,7 +275,7 @@ pub(crate) async fn add_backup_keys_for_session_route(
services services
.key_backups .key_backups
.add_key( .add_key(
body.sender_user(), body.identity.sender_user(),
&body.version, &body.version,
&body.room_id, &body.room_id,
&body.session_id, &body.session_id,
@@ -269,7 +284,8 @@ pub(crate) async fn add_backup_keys_for_session_route(
.await?; .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)) Ok(add_backup_keys_for_session::v3::Response::new(etag, count))
} }
@@ -283,7 +299,7 @@ pub(crate) async fn get_backup_keys_route(
) -> Result<get_backup_keys::v3::Response> { ) -> Result<get_backup_keys::v3::Response> {
let rooms = services let rooms = services
.key_backups .key_backups
.get_all(body.sender_user(), &body.version) .get_all(body.identity.sender_user(), &body.version)
.await; .await;
Ok(get_backup_keys::v3::Response::new(rooms)) Ok(get_backup_keys::v3::Response::new(rooms))
@@ -298,7 +314,7 @@ pub(crate) async fn get_backup_keys_for_room_route(
) -> Result<get_backup_keys_for_room::v3::Response> { ) -> Result<get_backup_keys_for_room::v3::Response> {
let sessions = services let sessions = services
.key_backups .key_backups
.get_room(body.sender_user(), &body.version, &body.room_id) .get_room(body.identity.sender_user(), &body.version, &body.room_id)
.await; .await;
Ok(get_backup_keys_for_room::v3::Response::new(sessions)) 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<get_backup_keys_for_session::v3::Response> { ) -> Result<get_backup_keys_for_session::v3::Response> {
let key_data = services let key_data = services
.key_backups .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 .await
.map_err(|_| { .map_err(|_| {
err!(Request(NotFound(debug_error!("Backup key not found for this user's session.")))) 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<delete_backup_keys::v3::Response> { ) -> Result<delete_backup_keys::v3::Response> {
services services
.key_backups .key_backups
.delete_all_keys(body.sender_user(), &body.version) .delete_all_keys(body.identity.sender_user(), &body.version)
.await; .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)) Ok(delete_backup_keys::v3::Response::new(etag, count))
} }
@@ -348,10 +365,11 @@ pub(crate) async fn delete_backup_keys_for_room_route(
) -> Result<delete_backup_keys_for_room::v3::Response> { ) -> Result<delete_backup_keys_for_room::v3::Response> {
services services
.key_backups .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; .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)) 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<delete_backup_keys_for_session::v3::Response> { ) -> Result<delete_backup_keys_for_session::v3::Response> {
services services
.key_backups .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; .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)) Ok(delete_backup_keys_for_session::v3::Response::new(etag, count))
} }
+1 -5
View File
@@ -48,11 +48,7 @@ pub(crate) async fn get_capabilities_route(
json!({"enabled": services.config.forget_forced_upon_leave}), json!({"enabled": services.config.forget_forced_upon_leave}),
)?; )?;
if services if services.users.is_admin(body.identity.sender_user()).await {
.users
.is_admin(body.sender_user.as_ref().unwrap())
.await
{
// Advertise suspension API // Advertise suspension API
capabilities.set("uk.timedout.msc4323", json!({"suspend": true, "lock": false}))?; capabilities.set("uk.timedout.msc4323", json!({"suspend": true, "lock": false}))?;
} }
+3 -3
View File
@@ -37,8 +37,8 @@ pub(crate) async fn get_context_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<get_context::v3::Request>, body: Ruma<get_context::v3::Request>,
) -> Result<get_context::v3::Response> { ) -> Result<get_context::v3::Response> {
let sender = body.sender(); let sender_user = body.identity.sender_user();
let (sender_user, sender_device) = sender; let sender_device = body.identity.sender_device();
let room_id = &body.room_id; let room_id = &body.room_id;
let event_id = &body.event_id; let event_id = &body.event_id;
let filter = &body.filter; let filter = &body.filter;
@@ -143,7 +143,7 @@ pub(crate) async fn get_context_route(
let lazy_loading_context = lazy_loading::Context { let lazy_loading_context = lazy_loading::Context {
user_id: sender_user, user_id: sender_user,
device_id: Some(sender_device), device_id: sender_device,
room_id, room_id,
token: Some(base_count.into_unsigned()), token: Some(base_count.into_unsigned()),
options: Some(&filter.lazy_load_options), options: Some(&filter.lazy_load_options),
+5 -10
View File
@@ -25,16 +25,11 @@ pub(crate) async fn put_dehydrated_device_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<put_dehydrated_device::Request>, body: Ruma<put_dehydrated_device::Request>,
) -> Result<put_dehydrated_device::Response> { ) -> Result<put_dehydrated_device::Response> {
let sender_user = body let device_id = body.device_id.clone();
.sender_user
.as_deref()
.expect("AccessToken authentication required");
let device_id = body.body.device_id.clone();
services services
.users .users
.set_dehydrated_device(sender_user, body.body) .set_dehydrated_device(body.identity.sender_user(), body.body)
.await?; .await?;
Ok(put_dehydrated_device::Response::new(device_id)) Ok(put_dehydrated_device::Response::new(device_id))
@@ -49,7 +44,7 @@ pub(crate) async fn delete_dehydrated_device_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<delete_dehydrated_device::Request>, body: Ruma<delete_dehydrated_device::Request>,
) -> Result<delete_dehydrated_device::Response> { ) -> Result<delete_dehydrated_device::Response> {
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?; 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, ClientIp(client): ClientIp,
body: Ruma<get_dehydrated_device::Request>, body: Ruma<get_dehydrated_device::Request>,
) -> Result<get_dehydrated_device::Response> { ) -> Result<get_dehydrated_device::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let device = services.users.get_dehydrated_device(sender_user).await?; 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, ClientIp(client): ClientIp,
body: Ruma<get_events::Request>, body: Ruma<get_events::Request>,
) -> Result<get_events::Response> { ) -> Result<get_events::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let device_id = &body.body.device_id; let device_id = &body.body.device_id;
let existing_id = services.users.get_dehydrated_device_id(sender_user).await; let existing_id = services.users.get_dehydrated_device_id(sender_user).await;
+8 -8
View File
@@ -21,7 +21,7 @@ pub(crate) async fn get_devices_route(
) -> Result<get_devices::v3::Response> { ) -> Result<get_devices::v3::Response> {
let devices: Vec<device::Device> = services let devices: Vec<device::Device> = services
.users .users
.all_devices_metadata(body.sender_user()) .all_devices_metadata(body.identity.sender_user())
.collect() .collect()
.await; .await;
@@ -37,7 +37,7 @@ pub(crate) async fn get_device_route(
) -> Result<get_device::v3::Response> { ) -> Result<get_device::v3::Response> {
let device = services let device = services
.users .users
.get_device_metadata(body.sender_user(), &body.body.device_id) .get_device_metadata(body.identity.sender_user(), &body.body.device_id)
.await .await
.map_err(|_| err!(Request(NotFound("Device not found."))))?; .map_err(|_| err!(Request(NotFound("Device not found."))))?;
@@ -53,8 +53,8 @@ pub(crate) async fn update_device_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<update_device::v3::Request>, body: Ruma<update_device::v3::Request>,
) -> Result<update_device::v3::Response> { ) -> Result<update_device::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let appservice = body.appservice_info.as_ref(); let appservice = body.identity.appservice_info();
match services match services
.users .users
@@ -118,8 +118,8 @@ pub(crate) async fn delete_device_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<delete_device::v3::Request>, body: Ruma<delete_device::v3::Request>,
) -> Result<delete_device::v3::Response> { ) -> Result<delete_device::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let appservice = body.appservice_info.as_ref(); let appservice = body.identity.appservice_info();
// Appservices get to skip UIAA for this endpoint // Appservices get to skip UIAA for this endpoint
if appservice.is_none() { if appservice.is_none() {
@@ -154,8 +154,8 @@ pub(crate) async fn delete_devices_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<delete_devices::v3::Request>, body: Ruma<delete_devices::v3::Request>,
) -> Result<delete_devices::v3::Response> { ) -> Result<delete_devices::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let appservice = body.appservice_info.as_ref(); let appservice = body.identity.appservice_info();
// Appservices get to skip UIAA for this endpoint // Appservices get to skip UIAA for this endpoint
if appservice.is_none() { if appservice.is_none() {
+2 -2
View File
@@ -112,7 +112,7 @@ pub(crate) async fn set_room_visibility_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<set_room_visibility::v3::Request>, body: Ruma<set_room_visibility::v3::Request>,
) -> Result<set_room_visibility::v3::Response> { ) -> Result<set_room_visibility::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if !services.rooms.metadata.exists(&body.room_id).await { if !services.rooms.metadata.exists(&body.room_id).await {
// Return 404 if the room doesn't exist // Return 404 if the room doesn't exist
@@ -130,7 +130,7 @@ pub(crate) async fn set_room_visibility_route(
| room::Visibility::Public => { | room::Visibility::Public => {
if services.server.config.lockdown_public_room_directory if services.server.config.lockdown_public_room_directory
&& !services.users.is_admin(sender_user).await && !services.users.is_admin(sender_user).await
&& body.appservice_info.is_none() && !body.identity.is_appservice()
{ {
info!( info!(
"Non-admin user {sender_user} tried to publish {0} to the room directory \ "Non-admin user {sender_user} tried to publish {0} to the room directory \
+2 -2
View File
@@ -15,7 +15,7 @@ pub(crate) async fn get_filter_route(
) -> Result<get_filter::v3::Response> { ) -> Result<get_filter::v3::Response> {
services services
.users .users
.get_filter(body.sender_user(), &body.filter_id) .get_filter(body.identity.sender_user(), &body.filter_id)
.await .await
.map(get_filter::v3::Response::new) .map(get_filter::v3::Response::new)
.map_err(|_| err!(Request(NotFound("Filter not found.")))) .map_err(|_| err!(Request(NotFound("Filter not found."))))
@@ -30,7 +30,7 @@ pub(crate) async fn create_filter_route(
) -> Result<create_filter::v3::Response> { ) -> Result<create_filter::v3::Response> {
let filter_id = services let filter_id = services
.users .users
.create_filter(body.sender_user(), &body.filter); .create_filter(body.identity.sender_user(), &body.filter);
Ok(create_filter::v3::Response::new(filter_id)) Ok(create_filter::v3::Response::new(filter_id))
} }
+6 -5
View File
@@ -41,7 +41,8 @@ pub(crate) async fn upload_keys_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<upload_keys::v3::Request>, body: Ruma<upload_keys::v3::Request>,
) -> Result<upload_keys::v3::Response> { ) -> Result<upload_keys::v3::Response> {
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 { for (key_id, one_time_key) in &body.one_time_keys {
if one_time_key if one_time_key
@@ -154,7 +155,7 @@ pub(crate) async fn get_keys_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<get_keys::v3::Request>, body: Ruma<get_keys::v3::Request>,
) -> Result<get_keys::v3::Response> { ) -> Result<get_keys::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
get_keys_helper( get_keys_helper(
&services, &services,
@@ -191,7 +192,7 @@ pub(crate) async fn upload_signing_keys_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<upload_signing_keys::v3::Request>, body: Ruma<upload_signing_keys::v3::Request>,
) -> Result<upload_signing_keys::v3::Response> { ) -> Result<upload_signing_keys::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if uiaa_needed_to_upload_keys( if uiaa_needed_to_upload_keys(
services, services,
@@ -287,7 +288,7 @@ pub(crate) async fn upload_signatures_route(
return Ok(upload_signatures::v3::Response::new()); 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 (user_id, keys) in &body.signed_keys {
for (key_id, key) in keys { for (key_id, key) in keys {
@@ -340,7 +341,7 @@ pub(crate) async fn get_key_changes_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<get_key_changes::v3::Request>, body: Ruma<get_key_changes::v3::Request>,
) -> Result<get_key_changes::v3::Response> { ) -> Result<get_key_changes::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let mut device_list_updates = HashSet::new(); let mut device_list_updates = HashSet::new();
+5 -5
View File
@@ -53,7 +53,7 @@ pub(crate) async fn create_content_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<create_content::v3::Request>, body: Ruma<create_content::v3::Request>,
) -> Result<create_content::v3::Response> { ) -> Result<create_content::v3::Response> {
let user = body.sender_user(); let user = body.identity.sender_user();
if services.users.is_suspended(user).await? { if services.users.is_suspended(user).await? {
return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); 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, ClientIp(client): ClientIp,
body: Ruma<get_content_thumbnail::v1::Request>, body: Ruma<get_content_thumbnail::v1::Request>,
) -> Result<get_content_thumbnail::v1::Response> { ) -> Result<get_content_thumbnail::v1::Response> {
let user = body.sender_user(); let user = body.identity.sender_user();
let dim = Dim::from_ruma(body.width, body.height, body.method.clone())?; let dim = Dim::from_ruma(body.width, body.height, body.method.clone())?;
let mxc = Mxc { let mxc = Mxc {
@@ -142,7 +142,7 @@ pub(crate) async fn get_content_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<get_content::v1::Request>, body: Ruma<get_content::v1::Request>,
) -> Result<get_content::v1::Response> { ) -> Result<get_content::v1::Response> {
let user = body.sender_user(); let user = body.identity.sender_user();
let mxc = Mxc { let mxc = Mxc {
server_name: &body.server_name, server_name: &body.server_name,
@@ -189,7 +189,7 @@ pub(crate) async fn get_content_as_filename_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<get_content_as_filename::v1::Request>, body: Ruma<get_content_as_filename::v1::Request>,
) -> Result<get_content_as_filename::v1::Response> { ) -> Result<get_content_as_filename::v1::Response> {
let user = body.sender_user(); let user = body.identity.sender_user();
let mxc = Mxc { let mxc = Mxc {
server_name: &body.server_name, server_name: &body.server_name,
@@ -240,7 +240,7 @@ pub(crate) async fn get_media_preview_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<get_media_preview::v1::Request>, body: Ruma<get_media_preview::v1::Request>,
) -> Result<get_media_preview::v1::Response> { ) -> Result<get_media_preview::v1::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let url = &body.url; let url = &body.url;
let url = Url::parse(&body.url).map_err(|e| { let url = Url::parse(&body.url).map_err(|e| {
+1 -1
View File
@@ -56,7 +56,7 @@ pub(crate) async fn get_media_preview_legacy_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<get_media_preview::v3::Request>, body: Ruma<get_media_preview::v3::Request>,
) -> Result<get_media_preview::v3::Response> { ) -> Result<get_media_preview::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let url = &body.url; let url = &body.url;
let url = Url::parse(&body.url).map_err(|e| { let url = Url::parse(&body.url).map_err(|e| {
+1 -1
View File
@@ -15,7 +15,7 @@ pub(crate) async fn ban_user_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<ban_user::v3::Request>, body: Ruma<ban_user::v3::Request>,
) -> Result<ban_user::v3::Response> { ) -> Result<ban_user::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if sender_user == body.user_id { if sender_user == body.user_id {
return Err!(Request(Forbidden("You cannot ban yourself."))); return Err!(Request(Forbidden("You cannot ban yourself.")));
+1 -1
View File
@@ -18,7 +18,7 @@ pub(crate) async fn forget_room_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<forget_room::v3::Request>, body: Ruma<forget_room::v3::Request>,
) -> Result<forget_room::v3::Response> { ) -> Result<forget_room::v3::Response> {
let user_id = body.sender_user(); let user_id = body.identity.sender_user();
let room_id = &body.room_id; let room_id = &body.room_id;
let joined = services.rooms.state_cache.is_joined(user_id, room_id); let joined = services.rooms.state_cache.is_joined(user_id, room_id);
+1 -1
View File
@@ -29,7 +29,7 @@ pub(crate) async fn invite_user_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<invite_user::v3::Request>, body: Ruma<invite_user::v3::Request>,
) -> Result<invite_user::v3::Response> { ) -> Result<invite_user::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if services.users.is_suspended(sender_user).await? { if services.users.is_suspended(sender_user).await? {
return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
} }
+2 -2
View File
@@ -28,7 +28,7 @@ pub(crate) async fn join_room_by_id_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<join_room_by_id::v3::Request>, body: Ruma<join_room_by_id::v3::Request>,
) -> Result<join_room_by_id::v3::Response> { ) -> Result<join_room_by_id::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if services.users.is_suspended(sender_user).await? { if services.users.is_suspended(sender_user).await? {
return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); 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, ClientIp(client): ClientIp,
body: Ruma<join_room_by_id_or_alias::v3::Request>, body: Ruma<join_room_by_id_or_alias::v3::Request>,
) -> Result<join_room_by_id_or_alias::v3::Response> { ) -> Result<join_room_by_id_or_alias::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let body = &body.body; let body = &body.body;
if services.users.is_suspended(sender_user).await? { if services.users.is_suspended(sender_user).await? {
return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
+1 -1
View File
@@ -15,7 +15,7 @@ pub(crate) async fn kick_user_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<kick_user::v3::Request>, body: Ruma<kick_user::v3::Request>,
) -> Result<kick_user::v3::Response> { ) -> Result<kick_user::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if services.users.is_suspended(sender_user).await? { if services.users.is_suspended(sender_user).await? {
return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
} }
+1 -1
View File
@@ -51,7 +51,7 @@ pub(crate) async fn knock_room_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<knock_room::v3::Request>, body: Ruma<knock_room::v3::Request>,
) -> Result<knock_room::v3::Response> { ) -> Result<knock_room::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let body = &body.body; let body = &body.body;
if services.users.is_suspended(sender_user).await? { if services.users.is_suspended(sender_user).await? {
return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
+1 -1
View File
@@ -32,7 +32,7 @@ pub(crate) async fn leave_room_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<leave_room::v3::Request>, body: Ruma<leave_room::v3::Request>,
) -> Result<leave_room::v3::Response> { ) -> Result<leave_room::v3::Response> {
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() .boxed()
.await .await
.map(|()| leave_room::v3::Response::new()) .map(|()| leave_room::v3::Response::new())
+2 -2
View File
@@ -30,7 +30,7 @@ pub(crate) async fn get_member_events_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<get_member_events::v3::Request>, body: Ruma<get_member_events::v3::Request>,
) -> Result<get_member_events::v3::Response> { ) -> Result<get_member_events::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let membership = body.membership.as_ref(); let membership = body.membership.as_ref();
let not_membership = body.not_membership.as_ref(); let not_membership = body.not_membership.as_ref();
@@ -72,7 +72,7 @@ pub(crate) async fn joined_members_route(
if !services if !services
.rooms .rooms
.state_accessor .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 .await
{ {
return Err!(Request(Forbidden("You don't have permission to view this room."))); return Err!(Request(Forbidden("You don't have permission to view this room.")));
+1 -1
View File
@@ -40,7 +40,7 @@ pub(crate) async fn joined_rooms_route(
let joined_rooms = services let joined_rooms = services
.rooms .rooms
.state_cache .state_cache
.rooms_joined(body.sender_user()) .rooms_joined(body.identity.sender_user())
.collect() .collect()
.await; .await;
+1 -1
View File
@@ -14,7 +14,7 @@ pub(crate) async fn unban_user_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<unban_user::v3::Request>, body: Ruma<unban_user::v3::Request>,
) -> Result<unban_user::v3::Response> { ) -> Result<unban_user::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if services.users.is_suspended(sender_user).await? { if services.users.is_suspended(sender_user).await? {
return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
} }
+4 -15
View File
@@ -23,7 +23,7 @@ use conduwuit_service::{
}; };
use futures::{FutureExt, StreamExt, TryFutureExt, future::OptionFuture, pin_mut}; use futures::{FutureExt, StreamExt, TryFutureExt, future::OptionFuture, pin_mut};
use ruma::{ use ruma::{
DeviceId, RoomId, UserId, RoomId, UserId,
api::{ api::{
Direction, Direction,
client::{filter::RoomEventFilter, message::get_message_events}, client::{filter::RoomEventFilter, message::get_message_events},
@@ -37,7 +37,6 @@ use ruma::{
serde::Raw, serde::Raw,
}; };
use ruminuwuity::invite_permission_config::FilterLevel; use ruminuwuity::invite_permission_config::FilterLevel;
use tracing::warn;
use crate::Ruma; use crate::Ruma;
@@ -76,8 +75,8 @@ pub(crate) async fn get_message_events_route(
ClientIp(client_ip): ClientIp, ClientIp(client_ip): ClientIp,
body: Ruma<get_message_events::v3::Request>, body: Ruma<get_message_events::v3::Request>,
) -> Result<get_message_events::v3::Response> { ) -> Result<get_message_events::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let sender_device = body.sender_device.as_deref(); let sender_device = body.identity.sender_device();
let room_id = &body.room_id; let room_id = &body.room_id;
let filter = &body.filter; let filter = &body.filter;
@@ -158,17 +157,7 @@ pub(crate) async fn get_message_events_route(
let lazy_loading_context = lazy_loading::Context { let lazy_loading_context = lazy_loading::Context {
user_id: sender_user, user_id: sender_user,
device_id: sender_device.or_else(|| { device_id: sender_device,
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
}
}),
room_id, room_id,
token: Some(from.into_unsigned()), token: Some(from.into_unsigned()),
options: Some(&filter.lazy_load_options), options: Some(&filter.lazy_load_options),
+1 -1
View File
@@ -15,7 +15,7 @@ pub(crate) async fn get_mutual_rooms_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<mutual_rooms::unstable::Request>, body: Ruma<mutual_rooms::unstable::Request>,
) -> Result<mutual_rooms::unstable::Response> { ) -> Result<mutual_rooms::unstable::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if sender_user == body.user_id { if sender_user == body.user_id {
return Err!(Request(Unknown("You cannot request rooms in common with yourself."))); return Err!(Request(Unknown("You cannot request rooms in common with yourself.")));
+1 -1
View File
@@ -16,7 +16,7 @@ pub(crate) async fn create_openid_token_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<account::request_openid_token::v3::Request>, body: Ruma<account::request_openid_token::v3::Request>,
) -> Result<account::request_openid_token::v3::Response> { ) -> Result<account::request_openid_token::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if sender_user != body.user_id { if sender_user != body.user_id {
return Err!(Request(InvalidParam( return Err!(Request(InvalidParam(
+9 -3
View File
@@ -20,13 +20,19 @@ pub(crate) async fn set_presence_route(
return Err!(Request(Forbidden("Presence is disabled on this server"))); 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"))); return Err!(Request(InvalidParam("Not allowed to set presence of other users")));
} }
services services
.presence .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?; .await?;
Ok(set_presence::v3::Response::new()) Ok(set_presence::v3::Response::new())
@@ -49,7 +55,7 @@ pub(crate) async fn get_presence_route(
let has_shared_rooms = services let has_shared_rooms = services
.rooms .rooms
.state_cache .state_cache
.user_sees_user(body.sender_user(), &body.user_id) .user_sees_user(body.identity.sender_user(), &body.user_id)
.await; .await;
if has_shared_rooms { if has_shared_rooms {
+12 -6
View File
@@ -51,9 +51,12 @@ pub(crate) async fn set_profile_field_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<set_profile_field::v3::Request>, body: Ruma<set_profile_field::v3::Request>,
) -> Result<set_profile_field::v3::Response> { ) -> Result<set_profile_field::v3::Response> {
if body.user_id != body.sender_user() if body.user_id != body.identity.sender_user()
&& !(body.appservice_info.is_some() && !(body.identity.is_appservice()
|| services.admin.user_is_admin(body.sender_user()).await) || services
.admin
.user_is_admin(body.identity.sender_user())
.await)
{ {
return Err!(Request(Forbidden("You may not change other users' profile data."))); 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<crate::State>, State(services): State<crate::State>,
body: Ruma<delete_profile_field::v3::Request>, body: Ruma<delete_profile_field::v3::Request>,
) -> Result<delete_profile_field::v3::Response> { ) -> Result<delete_profile_field::v3::Response> {
if body.user_id != body.sender_user() if body.user_id != body.identity.sender_user()
&& !(body.appservice_info.is_some() && !(body.identity.is_appservice()
|| services.admin.user_is_admin(body.sender_user()).await) || services
.admin
.user_is_admin(body.identity.sender_user())
.await)
{ {
return Err!(Request(Forbidden("You may not change other users' profile data."))); return Err!(Request(Forbidden("You may not change other users' profile data.")));
} }
+13 -12
View File
@@ -30,7 +30,7 @@ pub(crate) async fn get_pushrules_all_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<get_pushrules_all::v3::Request>, body: Ruma<get_pushrules_all::v3::Request>,
) -> Result<get_pushrules_all::v3::Response> { ) -> Result<get_pushrules_all::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let Some(content_value) = services let Some(content_value) = services
.account_data .account_data
@@ -101,7 +101,7 @@ pub(crate) async fn get_pushrules_global_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<get_pushrules_global_scope::v3::Request>, body: Ruma<get_pushrules_global_scope::v3::Request>,
) -> Result<get_pushrules_global_scope::v3::Response> { ) -> Result<get_pushrules_global_scope::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let Some(content_value) = services let Some(content_value) = services
.account_data .account_data
@@ -189,7 +189,7 @@ pub(crate) async fn get_pushrule_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<get_pushrule::v3::Request>, body: Ruma<get_pushrule::v3::Request>,
) -> Result<get_pushrule::v3::Response> { ) -> Result<get_pushrule::v3::Response> {
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 // remove old deprecated mentions push rules as per MSC4210
#[allow(deprecated)] #[allow(deprecated)]
@@ -226,7 +226,7 @@ pub(crate) async fn set_pushrule_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<set_pushrule::v3::Request>, body: Ruma<set_pushrule::v3::Request>,
) -> Result<set_pushrule::v3::Response> { ) -> Result<set_pushrule::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let body = &body.body; let body = &body.body;
let mut account_data: PushRulesEvent = services let mut account_data: PushRulesEvent = services
.account_data .account_data
@@ -282,7 +282,7 @@ pub(crate) async fn get_pushrule_actions_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<get_pushrule_actions::v3::Request>, body: Ruma<get_pushrule_actions::v3::Request>,
) -> Result<get_pushrule_actions::v3::Response> { ) -> Result<get_pushrule_actions::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
// remove old deprecated mentions push rules as per MSC4210 // remove old deprecated mentions push rules as per MSC4210
#[allow(deprecated)] #[allow(deprecated)]
@@ -316,7 +316,7 @@ pub(crate) async fn set_pushrule_actions_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<set_pushrule_actions::v3::Request>, body: Ruma<set_pushrule_actions::v3::Request>,
) -> Result<set_pushrule_actions::v3::Response> { ) -> Result<set_pushrule_actions::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let mut account_data: PushRulesEvent = services let mut account_data: PushRulesEvent = services
.account_data .account_data
@@ -349,7 +349,7 @@ pub(crate) async fn get_pushrule_enabled_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<get_pushrule_enabled::v3::Request>, body: Ruma<get_pushrule_enabled::v3::Request>,
) -> Result<get_pushrule_enabled::v3::Response> { ) -> Result<get_pushrule_enabled::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
// remove old deprecated mentions push rules as per MSC4210 // remove old deprecated mentions push rules as per MSC4210
#[allow(deprecated)] #[allow(deprecated)]
@@ -383,7 +383,7 @@ pub(crate) async fn set_pushrule_enabled_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<set_pushrule_enabled::v3::Request>, body: Ruma<set_pushrule_enabled::v3::Request>,
) -> Result<set_pushrule_enabled::v3::Response> { ) -> Result<set_pushrule_enabled::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let mut account_data: PushRulesEvent = services let mut account_data: PushRulesEvent = services
.account_data .account_data
@@ -416,7 +416,7 @@ pub(crate) async fn delete_pushrule_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<delete_pushrule::v3::Request>, body: Ruma<delete_pushrule::v3::Request>,
) -> Result<delete_pushrule::v3::Response> { ) -> Result<delete_pushrule::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let mut account_data: PushRulesEvent = services let mut account_data: PushRulesEvent = services
.account_data .account_data
@@ -458,7 +458,7 @@ pub(crate) async fn get_pushers_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<get_pushers::v3::Request>, body: Ruma<get_pushers::v3::Request>,
) -> Result<get_pushers::v3::Response> { ) -> Result<get_pushers::v3::Response> {
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)) 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<crate::State>, State(services): State<crate::State>,
body: Ruma<set_pusher::v3::Request>, body: Ruma<set_pusher::v3::Request>,
) -> Result<set_pusher::v3::Response> { ) -> Result<set_pusher::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let sender_device = body.identity.expect_sender_device()?;
services services
.pusher .pusher
.set_pusher(sender_user, body.sender_device(), &body.action) .set_pusher(sender_user, sender_device, &body.action)
.await?; .await?;
Ok(set_pusher::v3::Response::new()) Ok(set_pusher::v3::Response::new())
+3 -3
View File
@@ -26,7 +26,7 @@ pub(crate) async fn set_read_marker_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<set_read_marker::v3::Request>, body: Ruma<set_read_marker::v3::Request>,
) -> Result<set_read_marker::v3::Response> { ) -> Result<set_read_marker::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if let Some(event) = &body.fully_read { if let Some(event) = &body.fully_read {
let fully_read_event = FullyReadEvent::new(FullyReadEventContent::new(event.to_owned())); 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, ClientIp(client_ip): ClientIp,
body: Ruma<create_receipt::v3::Request>, body: Ruma<create_receipt::v3::Request>,
) -> Result<create_receipt::v3::Response> { ) -> Result<create_receipt::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
services services
.users .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; .await;
if matches!( if matches!(
+2 -2
View File
@@ -17,10 +17,10 @@ pub(crate) async fn redact_event_route(
ClientIp(client_ip): ClientIp, ClientIp(client_ip): ClientIp,
body: Ruma<redact_event::v3::Request>, body: Ruma<redact_event::v3::Request>,
) -> Result<redact_event::v3::Response> { ) -> Result<redact_event::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
services services
.users .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; .await;
let body = &body.body; let body = &body.body;
if services.users.is_suspended(sender_user).await? { if services.users.is_suspended(sender_user).await? {
+3 -3
View File
@@ -28,7 +28,7 @@ pub(crate) async fn get_relating_events_with_rel_type_and_event_type_route(
) -> Result<get_relating_events_with_rel_type_and_event_type::v1::Response> { ) -> Result<get_relating_events_with_rel_type_and_event_type::v1::Response> {
paginate_relations_with_filter( paginate_relations_with_filter(
&services, &services,
body.sender_user(), body.identity.sender_user(),
&body.room_id, &body.room_id,
&body.event_id, &body.event_id,
body.event_type.clone().into(), body.event_type.clone().into(),
@@ -56,7 +56,7 @@ pub(crate) async fn get_relating_events_with_rel_type_route(
) -> Result<get_relating_events_with_rel_type::v1::Response> { ) -> Result<get_relating_events_with_rel_type::v1::Response> {
paginate_relations_with_filter( paginate_relations_with_filter(
&services, &services,
body.sender_user(), body.identity.sender_user(),
&body.room_id, &body.room_id,
&body.event_id, &body.event_id,
None, None,
@@ -84,7 +84,7 @@ pub(crate) async fn get_relating_events_route(
) -> Result<get_relating_events::v1::Response> { ) -> Result<get_relating_events::v1::Response> {
paginate_relations_with_filter( paginate_relations_with_filter(
&services, &services,
body.sender_user(), body.identity.sender_user(),
&body.room_id, &body.room_id,
&body.event_id, &body.event_id,
None, None,
+4 -4
View File
@@ -36,7 +36,7 @@ pub(crate) async fn report_room_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<report_room::v3::Request>, body: Ruma<report_room::v3::Request>,
) -> Result<report_room::v3::Response> { ) -> Result<report_room::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if services.users.is_suspended(sender_user).await? { if services.users.is_suspended(sender_user).await? {
return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
} }
@@ -92,7 +92,7 @@ pub(crate) async fn report_event_route(
body: Ruma<report_content::v3::Request>, body: Ruma<report_content::v3::Request>,
) -> Result<report_content::v3::Response> { ) -> Result<report_content::v3::Response> {
// user authentication // user authentication
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if services.users.is_suspended(sender_user).await? { if services.users.is_suspended(sender_user).await? {
return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); 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, ClientIp(client): ClientIp,
body: Ruma<report_user::v3::Request>, body: Ruma<report_user::v3::Request>,
) -> Result<report_user::v3::Response> { ) -> Result<report_user::v3::Response> {
// user authentication let sender_user = body.identity.sender_user();
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
if services.users.is_suspended(sender_user).await? { if services.users.is_suspended(sender_user).await? {
return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
} }
+1 -1
View File
@@ -15,7 +15,7 @@ pub(crate) async fn get_room_aliases_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<aliases::v3::Request>, body: Ruma<aliases::v3::Request>,
) -> Result<aliases::v3::Response> { ) -> Result<aliases::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if !services if !services
.rooms .rooms
+4 -4
View File
@@ -61,10 +61,10 @@ pub(crate) async fn create_room_route(
) -> Result<create_room::v3::Response> { ) -> Result<create_room::v3::Response> {
use create_room::v3::RoomPreset; use create_room::v3::RoomPreset;
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if !services.globals.allow_room_creation() if !services.globals.allow_room_creation()
&& body.appservice_info.is_none() && !body.identity.is_appservice()
&& !services.users.is_admin(sender_user).await && !services.users.is_admin(sender_user).await
{ {
return Err!(Request(Forbidden("Room creation has been disabled.",))); 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 if body.visibility == room::Visibility::Public
&& services.server.config.lockdown_public_room_directory && services.server.config.lockdown_public_room_directory
&& !services.users.is_admin(sender_user).await && !services.users.is_admin(sender_user).await
&& body.appservice_info.is_none() && !body.identity.is_appservice()
{ {
warn!( warn!(
"Non-admin user {sender_user} tried to publish {room_id:?} to the room directory \ "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<OwnedRoomAliasId> = match body.room_alias_name.as_ref() { let alias: Option<OwnedRoomAliasId> = match body.room_alias_name.as_ref() {
| Some(alias) => | 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, | _ => None,
}; };
+4 -4
View File
@@ -24,25 +24,25 @@ pub(crate) async fn get_room_event_route(
let visible = services let visible = services
.rooms .rooms
.state_accessor .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); .map(Ok);
let (mut event, visible) = try_join(event, visible).await?; 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."))); return Err!(Request(Forbidden("You don't have permission to view this event.")));
} }
if let Err(e) = services if let Err(e) = services
.rooms .rooms
.pdu_metadata .pdu_metadata
.add_bundled_aggregations_to_pdu(body.sender_user(), &mut event) .add_bundled_aggregations_to_pdu(body.identity.sender_user(), &mut event)
.await .await
{ {
debug_warn!("Failed to add bundled aggregations to event: {e}"); 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())) Ok(get_room_event::v3::Response::new(event.into_format()))
} }
+10 -12
View File
@@ -22,7 +22,7 @@ pub(crate) async fn room_initial_sync_route(
if !services if !services
.rooms .rooms
.state_accessor .state_accessor
.user_can_see_state_events(body.sender_user(), room_id) .user_can_see_state_events(body.identity.sender_user(), room_id)
.await .await
{ {
return Err!(Request(Forbidden("No room preview available."))); return Err!(Request(Forbidden("No room preview available.")));
@@ -31,7 +31,7 @@ pub(crate) async fn room_initial_sync_route(
let membership = services let membership = services
.rooms .rooms
.state_cache .state_cache
.user_membership(body.sender_user(), room_id) .user_membership(body.identity.sender_user(), room_id)
.map(Ok); .map(Ok);
let visibility = services.rooms.directory.visibility(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) .pdus_rev(room_id, None)
.try_take(limit) .try_take(limit)
.and_then(async |mut pdu| { .and_then(async |mut pdu| {
pdu.1.set_unsigned(body.sender_user.as_deref()); pdu.1.set_unsigned(Some(body.identity.sender_user()));
if let Some(sender_user) = body.sender_user.as_deref() { if let Err(e) = services
if let Err(e) = services .rooms
.rooms .pdu_metadata
.pdu_metadata .add_bundled_aggregations_to_pdu(body.identity.sender_user(), &mut pdu.1)
.add_bundled_aggregations_to_pdu(sender_user, &mut pdu.1) .await
.await {
{ debug_warn!("Failed to add bundled aggregations: {e}");
debug_warn!("Failed to add bundled aggregations: {e}");
}
} }
Ok(pdu) Ok(pdu)
}) })
+7 -1
View File
@@ -28,7 +28,13 @@ pub(crate) async fn get_room_summary(
let summary = services let summary = services
.rooms .rooms
.summary .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?; .await?;
match summary { match summary {
+1 -1
View File
@@ -277,7 +277,7 @@ pub(crate) async fn upgrade_room_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<upgrade_room::v3::Request>, body: Ruma<upgrade_room::v3::Request>,
) -> Result<upgrade_room::v3::Response> { ) -> Result<upgrade_room::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let (supported, forbid_unstable, is_unstable) = ( let (supported, forbid_unstable, is_unstable) = (
services.server.supported_room_version(&body.new_version), services.server.supported_room_version(&body.new_version),
+1 -1
View File
@@ -43,7 +43,7 @@ pub(crate) async fn search_events_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<Request>, body: Ruma<Request>,
) -> Result<Response> { ) -> Result<Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let next_batch = body.next_batch.as_deref(); let next_batch = body.next_batch.as_deref();
let mut result_categories = ResultCategories::new(); let mut result_categories = ResultCategories::new();
+9 -5
View File
@@ -22,16 +22,16 @@ pub(crate) async fn send_message_event_route(
ClientIp(client_ip): ClientIp, ClientIp(client_ip): ClientIp,
body: Ruma<send_message_event::v3::Request>, body: Ruma<send_message_event::v3::Request>,
) -> Result<send_message_event::v3::Response> { ) -> Result<send_message_event::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let sender_device = body.sender_device.as_deref(); let sender_device = body.identity.sender_device();
let appservice_info = body.appservice_info.as_ref();
if services.users.is_suspended(sender_user).await? { if services.users.is_suspended(sender_user).await? {
return Err!(Request(UserSuspended("You cannot perform this action while suspended."))); return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
} }
services services
.users .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; .await;
// Forbid m.room.encrypted if encryption is disabled // 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(), event_type: body.event_type.clone().into(),
content, content,
unsigned: Some(unsigned), unsigned: Some(unsigned),
timestamp: appservice_info.and(body.timestamp), timestamp: if body.identity.is_appservice() {
body.timestamp
} else {
None
},
..Default::default() ..Default::default()
}, },
sender_user, sender_user,
+6 -4
View File
@@ -146,7 +146,7 @@ pub(crate) async fn login_route(
}) => { }) => {
debug!("Got appservice login type"); 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."))); 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"))); 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 // Prompt the user to confirm with their password using UIAA
let _ = services let _ = services
@@ -286,7 +286,9 @@ pub(crate) async fn logout_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<logout::v3::Request>, body: Ruma<logout::v3::Request>,
) -> Result<logout::v3::Response> { ) -> Result<logout::v3::Response> {
let (sender_user, sender_device) = body.sender(); let sender_user = body.identity.sender_user();
let sender_device = body.identity.expect_sender_device()?;
services services
.users .users
.remove_device(sender_user, sender_device) .remove_device(sender_user, sender_device)
@@ -332,7 +334,7 @@ pub(crate) async fn logout_all_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<logout_all::v3::Request>, body: Ruma<logout_all::v3::Request>,
) -> Result<logout_all::v3::Response> { ) -> Result<logout_all::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
services services
.users .users
.all_device_ids(sender_user) .all_device_ids(sender_user)
+1 -1
View File
@@ -27,7 +27,7 @@ pub(crate) async fn get_hierarchy_route(
.rooms .rooms
.summary .summary
.get_room_hierarchy_for_user( .get_room_hierarchy_for_user(
body.sender_user(), body.identity.sender_user(),
body.room_id.clone(), body.room_id.clone(),
max_depth, max_depth,
body.suggested_only, body.suggested_only,
+5 -5
View File
@@ -38,10 +38,10 @@ pub(crate) async fn send_state_event_for_key_route(
ClientIp(ip): ClientIp, ClientIp(ip): ClientIp,
body: Ruma<send_state_event::v3::Request>, body: Ruma<send_state_event::v3::Request>,
) -> Result<send_state_event::v3::Response> { ) -> Result<send_state_event::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
services services
.users .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; .await;
if services.users.is_suspended(sender_user).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.event_type,
&body.body.body, &body.body.body,
&body.state_key, &body.state_key,
if body.appservice_info.is_some() { if body.identity.is_appservice() {
body.timestamp body.timestamp
} else { } else {
None None
@@ -91,7 +91,7 @@ pub(crate) async fn get_state_events_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<get_state_events::v3::Request>, body: Ruma<get_state_events::v3::Request>,
) -> Result<get_state_events::v3::Response> { ) -> Result<get_state_events::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if !services if !services
.rooms .rooms
@@ -125,7 +125,7 @@ pub(crate) async fn get_state_event_for_key_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<get_state_event_for_key::v3::Request>, body: Ruma<get_state_event_for_key::v3::Request>,
) -> Result<get_state_event_for_key::v3::Response> { ) -> Result<get_state_event_for_key::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
if !services if !services
.rooms .rooms
+4 -2
View File
@@ -181,7 +181,8 @@ pub(crate) async fn sync_events_route(
ClientIp(client_ip): ClientIp, ClientIp(client_ip): ClientIp,
body: Ruma<sync_events::v3::Request>, body: Ruma<sync_events::v3::Request>,
) -> Result<sync_events::v3::Response> { ) -> Result<sync_events::v3::Response> {
let (sender_user, sender_device) = body.sender(); let sender_user = body.identity.sender_user();
let sender_device = body.identity.expect_sender_device()?;
// Presence update // Presence update
if services.config.allow_local_presence { if services.config.allow_local_presence {
@@ -225,7 +226,8 @@ pub(crate) async fn build_sync_events(
services: &Services, services: &Services,
body: &Ruma<sync_events::v3::Request>, body: &Ruma<sync_events::v3::Request>,
) -> Result<sync_events::v3::Response> { ) -> Result<sync_events::v3::Response> {
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()?; let current_count = services.globals.current_count()?;
+2 -2
View File
@@ -70,8 +70,8 @@ pub(crate) async fn sync_events_v5_route(
body: Ruma<sync_events::v5::Request>, body: Ruma<sync_events::v5::Request>,
) -> Result<sync_events::v5::Response> { ) -> Result<sync_events::v5::Response> {
debug_assert!(DEFAULT_BUMP_TYPES.is_sorted(), "DEFAULT_BUMP_TYPES is not sorted"); debug_assert!(DEFAULT_BUMP_TYPES.is_sorted(), "DEFAULT_BUMP_TYPES is not sorted");
let ref sender_user = body.sender_user().to_owned(); let sender_user = body.identity.sender_user();
let ref sender_device = body.sender_device().to_owned(); let sender_device = body.identity.expect_sender_device()?;
services services
.users .users
+3 -3
View File
@@ -21,7 +21,7 @@ pub(crate) async fn update_tag_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<create_tag::v3::Request>, body: Ruma<create_tag::v3::Request>,
) -> Result<create_tag::v3::Response> { ) -> Result<create_tag::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let mut tags_event = services let mut tags_event = services
.account_data .account_data
@@ -56,7 +56,7 @@ pub(crate) async fn delete_tag_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<delete_tag::v3::Request>, body: Ruma<delete_tag::v3::Request>,
) -> Result<delete_tag::v3::Response> { ) -> Result<delete_tag::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let mut tags_event = services let mut tags_event = services
.account_data .account_data
@@ -88,7 +88,7 @@ pub(crate) async fn get_tags_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<get_tags::v3::Request>, body: Ruma<get_tags::v3::Request>,
) -> Result<get_tags::v3::Response> { ) -> Result<get_tags::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let tags_event = services let tags_event = services
.account_data .account_data
+3 -3
View File
@@ -34,14 +34,14 @@ pub(crate) async fn get_threads_route(
let threads: Vec<(PduCount, PduEvent)> = services let threads: Vec<(PduCount, PduEvent)> = services
.rooms .rooms
.threads .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? .await?
.take(limit) .take(limit)
.filter_map(|(count, pdu)| async move { .filter_map(|(count, pdu)| async move {
services services
.rooms .rooms
.state_accessor .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 .await
.then_some((count, pdu)) .then_some((count, pdu))
}) })
@@ -49,7 +49,7 @@ pub(crate) async fn get_threads_route(
if let Err(e) = services if let Err(e) = services
.rooms .rooms
.pdu_metadata .pdu_metadata
.add_bundled_aggregations_to_pdu(body.sender_user(), &mut pdu) .add_bundled_aggregations_to_pdu(body.identity.sender_user(), &mut pdu)
.await .await
{ {
debug_warn!("Failed to add bundled aggregations to thread: {e}"); debug_warn!("Failed to add bundled aggregations to thread: {e}");
+2 -2
View File
@@ -22,8 +22,8 @@ pub(crate) async fn send_event_to_device_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<send_event_to_device::v3::Request>, body: Ruma<send_event_to_device::v3::Request>,
) -> Result<send_event_to_device::v3::Response> { ) -> Result<send_event_to_device::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let sender_device = body.sender_device.as_deref(); let sender_device = body.identity.sender_device();
// Check if this is a new transaction id // Check if this is a new transaction id
if services if services
+3 -3
View File
@@ -14,13 +14,13 @@ pub(crate) async fn create_typing_event_route(
body: Ruma<create_typing_event::v3::Request>, body: Ruma<create_typing_event::v3::Request>,
) -> Result<create_typing_event::v3::Response> { ) -> Result<create_typing_event::v3::Response> {
use create_typing_event::v3::Typing; use create_typing_event::v3::Typing;
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
services services
.users .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; .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."))); return Err!(Request(Forbidden("You cannot update typing status of other users.")));
} }
+1 -1
View File
@@ -26,7 +26,7 @@ pub(crate) async fn search_users_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<search_users::v3::Request>, body: Ruma<search_users::v3::Request>,
) -> Result<search_users::v3::Response> { ) -> Result<search_users::v3::Response> {
let sender_user = body.sender_user(); let sender_user = body.identity.sender_user();
let limit = usize::try_from(body.limit) let limit = usize::try_from(body.limit)
.map_or(LIMIT_DEFAULT, usize::from) .map_or(LIMIT_DEFAULT, usize::from)
.min(LIMIT_MAX); .min(LIMIT_MAX);
+3 -13
View File
@@ -2,15 +2,13 @@ use std::time::{Duration, SystemTime};
use axum::extract::State; use axum::extract::State;
use base64::{Engine as _, engine::general_purpose}; use base64::{Engine as _, engine::general_purpose};
use conduwuit::{Err, Result, utils}; use conduwuit::{Err, Result};
use hmac::{Hmac, KeyInit, Mac}; 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 sha1::Sha1;
use crate::Ruma; use crate::Ruma;
const RANDOM_USER_ID_LENGTH: usize = 10;
type HmacSha1 = Hmac<Sha1>; type HmacSha1 = Hmac<Sha1>;
/// # `GET /_matrix/client/r0/voip/turnServer` /// # `GET /_matrix/client/r0/voip/turnServer`
@@ -35,15 +33,7 @@ pub(crate) async fn turn_server_route(
) )
.expect("time is valid"); .expect("time is valid");
let user = body.sender_user.unwrap_or_else(|| { let username: String = format!("{}:{}", expiry.get(), body.identity.sender_user());
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 mut mac = HmacSha1::new_from_slice(turn_secret.as_bytes()) let mut mac = HmacSha1::new_from_slice(turn_secret.as_bytes())
.expect("HMAC can take key of any size"); .expect("HMAC can take key of any size");
+1 -1
View File
@@ -15,7 +15,7 @@ pub(super) use conduwuit_service::state::State;
use http::{Uri, uri}; use http::{Uri, uri};
use self::handler::RouterExt; 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}; use crate::{admin, client, server};
pub fn build(router: Router<State>, server: &Server) -> Router<State> { pub fn build(router: Router<State>, server: &Server) -> Router<State> {
+13 -68
View File
@@ -6,17 +6,14 @@ use axum::{
extract::{FromRequest, Path, Query}, extract::{FromRequest, Path, Query},
}; };
use conduwuit::{Error, Result, err}; use conduwuit::{Error, Result, err};
use ruma::{ use ruma::{CanonicalJsonObject, api::IncomingRequest};
CanonicalJsonObject, DeviceId, OwnedDeviceId, OwnedServerName, OwnedUserId, ServerName,
UserId, api::IncomingRequest,
};
use serde::Deserialize; use serde::Deserialize;
use crate::{State, router::auth::CheckAuth, service::appservice::RegistrationInfo}; use crate::{State, router::auth::CheckAuth};
/// Query parameters needed to authenticate requests /// Query parameters needed to authenticate requests
#[derive(Deserialize)] #[derive(Deserialize)]
pub(super) struct AuthQueryParams { pub(crate) struct AuthQueryParams {
pub(super) user_id: Option<String>, pub(super) user_id: Option<String>,
/// Device ID for appservice device masquerading (MSC3202/MSC4190). /// Device ID for appservice device masquerading (MSC3202/MSC4190).
/// Can be provided as `device_id` or `org.matrix.msc3202.device_id`. /// 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 /// Extractor for Ruma request structs
pub(crate) struct Args<T> { pub(crate) struct Args<R: IncomingRequest<Authentication: CheckAuth> + Send + Sync + 'static> {
/// Request struct body /// Request struct body
pub(crate) body: T, pub(crate) body: R,
/// Federation server authentication: X-Matrix origin /// Parsed JSON body. None when body is not JSON.
/// None when not a federation server.
pub(crate) origin: Option<OwnedServerName>,
/// Local user authentication: user_id.
/// None when not an authenticated local user.
pub(crate) sender_user: Option<OwnedUserId>,
/// Local user authentication: device_id.
/// None when not an authenticated local user or no device.
pub(crate) sender_device: Option<OwnedDeviceId>,
/// Appservice authentication; registration info.
/// None when not an appservice.
pub(crate) appservice_info: Option<RegistrationInfo>,
/// Parsed JSON content.
/// None when body is not a valid string
pub(crate) json_body: Option<CanonicalJsonObject>, pub(crate) json_body: Option<CanonicalJsonObject>,
/// Identity of the requesting entity
pub(crate) identity: <R::Authentication as CheckAuth>::Identity,
} }
impl<T> Args<T> impl<R> Deref for Args<R>
where where
T: IncomingRequest + Send + Sync + 'static, R: IncomingRequest<Authentication: CheckAuth> + Send + Sync + 'static,
{ {
#[inline] type Target = R;
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<T> Deref for Args<T>
where
T: IncomingRequest + Send + Sync + 'static,
{
type Target = T;
fn deref(&self) -> &Self::Target { &self.body } fn deref(&self) -> &Self::Target { &self.body }
} }
@@ -145,13 +97,6 @@ where
let body = R::try_from_http_request(request, &path) let body = R::try_from_http_request(request, &path)
.map_err(|e| err!(Request(BadJson(debug_warn!("{e}")))))?; .map_err(|e| err!(Request(BadJson(debug_warn!("{e}")))))?;
Ok(Self { Ok(Self { body, json_body, identity: auth })
body,
origin: auth.origin,
sender_user: auth.sender_user,
sender_device: auth.sender_device,
appservice_info: auth.appservice_info,
json_body,
})
} }
} }
+136 -98
View File
@@ -2,7 +2,7 @@ use std::any::{Any, TypeId};
use conduwuit::{Err, Result, err}; use conduwuit::{Err, Result, err};
use ruma::{ use ruma::{
OwnedDeviceId, OwnedServerName, OwnedUserId, UserId, DeviceId, OwnedDeviceId, OwnedServerName, OwnedUserId, UserId,
api::{ api::{
IncomingRequest, IncomingRequest,
auth_scheme::{ auth_scheme::{
@@ -20,20 +20,57 @@ use service::{
use crate::{router::args::AuthQueryParams, service::appservice::RegistrationInfo}; use crate::{router::args::AuthQueryParams, service::appservice::RegistrationInfo};
#[derive(Default)] pub(crate) enum ClientIdentity {
pub(super) struct Auth { User {
pub(super) origin: Option<OwnedServerName>, sender_user: OwnedUserId,
pub(super) sender_user: Option<OwnedUserId>, sender_device: OwnedDeviceId,
pub(super) sender_device: Option<OwnedDeviceId>, },
pub(super) appservice_info: Option<RegistrationInfo>, Appservice {
sender_user: OwnedUserId,
sender_device: Option<OwnedDeviceId>,
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<R: IncomingRequest + Any, B: AsRef<[u8]> + Sync>( fn authenticate<R: IncomingRequest + Any, B: AsRef<[u8]> + Sync>(
services: &Services, services: &Services,
incoming_request: &hyper::Request<B>, incoming_request: &hyper::Request<B>,
query: AuthQueryParams, query: AuthQueryParams,
) -> impl Future<Output = Result<Auth>> + Send { ) -> impl Future<Output = Result<Self::Identity>> + Send {
async move { async move {
let route = TypeId::of::<R>(); let route = TypeId::of::<R>();
@@ -54,17 +91,19 @@ pub(super) trait CheckAuth: AuthScheme {
request: &hyper::Request<B>, request: &hyper::Request<B>,
query: AuthQueryParams, query: AuthQueryParams,
route: TypeId, route: TypeId,
) -> impl Future<Output = Result<Auth>> + Send; ) -> impl Future<Output = Result<Self::Identity>> + Send;
} }
impl CheckAuth for ServerSignatures { impl CheckAuth for ServerSignatures {
type Identity = OwnedServerName;
async fn verify<B: AsRef<[u8]> + Sync>( async fn verify<B: AsRef<[u8]> + Sync>(
services: &Services, services: &Services,
output: Self::Output, output: Self::Output,
request: &hyper::Request<B>, request: &hyper::Request<B>,
_query: AuthQueryParams, _query: AuthQueryParams,
_route: TypeId, _route: TypeId,
) -> Result<Auth> { ) -> Result<Self::Identity> {
let destination = services.globals.server_name(); let destination = services.globals.server_name();
if output if output
.destination .destination
@@ -96,10 +135,7 @@ impl CheckAuth for ServerSignatures {
))); )));
} }
Ok(Auth { Ok(output.origin)
origin: Some(output.origin.clone()),
..Default::default()
})
}, },
| Err(err) => | Err(err) =>
Err!(Request(Unauthorized(warn!("Failed to verify X-Matrix header: {err}")))), Err!(Request(Unauthorized(warn!("Failed to verify X-Matrix header: {err}")))),
@@ -108,162 +144,164 @@ impl CheckAuth for ServerSignatures {
} }
impl CheckAuth for AccessToken { impl CheckAuth for AccessToken {
type Identity = ClientIdentity;
async fn verify<B: AsRef<[u8]> + Sync>( async fn verify<B: AsRef<[u8]> + Sync>(
services: &Services, services: &Services,
output: Self::Output, output: Self::Output,
_request: &hyper::Request<B>, _request: &hyper::Request<B>,
query: AuthQueryParams, query: AuthQueryParams,
route: TypeId, route: TypeId,
) -> Result<Auth> { ) -> Result<Self::Identity> {
// Check for appservice tokens first if let Ok((sender_user, sender_device)) = services.users.find_from_token(&output).await {
// Locked users can only use /logout and /logout/all
let (sender_user, sender_device, appservice_info) = { if services
if let Ok((sender_user, sender_device)) = .users
services.users.find_from_token(&output).await .is_locked(&sender_user)
.await
.is_ok_and(std::convert::identity)
{ {
// Locked users can only use /logout and /logout/all if !(route == TypeId::of::<client::session::logout::v3::Request>()
if services || route == TypeId::of::<client::session::logout_all::v3::Request>())
.users
.is_locked(&sender_user)
.await
.is_ok_and(std::convert::identity)
{ {
if !(route == TypeId::of::<client::session::logout::v3::Request>() return Err!(Request(Unauthorized("Your account is locked.")));
|| route == TypeId::of::<client::session::logout_all::v3::Request>())
{
return Err!(Request(Unauthorized("Your account is locked.")));
}
} }
}
(Some(sender_user), Some(sender_device), None) Ok(ClientIdentity::User { sender_user, sender_device })
} else if let Ok(appservice_info) = services.appservice.find_from_token(&output).await } else if let Ok(appservice_info) = services.appservice.find_from_token(&output).await {
{ let Ok(sender_user) = query.user_id.clone().map_or_else(
let Ok(sender_user) = query.user_id.clone().map_or_else( || {
|| { UserId::parse_with_server_name(
UserId::parse_with_server_name( appservice_info.registration.sender_localpart.as_str(),
appservice_info.registration.sender_localpart.as_str(), services.globals.server_name(),
services.globals.server_name(), )
) },
}, UserId::parse,
UserId::parse, ) else {
) else { return Err!(Request(InvalidUsername("Username is invalid.")));
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) { Ok(ClientIdentity::Appservice {
return Err!(Request(Exclusive("User is not in namespace."))); sender_user,
} sender_device,
appservice_info,
// MSC3202/MSC4190: Handle device_id masquerading for appservices. })
// The device_id can be provided via `device_id` or } else {
// `org.matrix.msc3202.device_id` query parameter. return Err!(Request(Unauthorized("Invalid access token.")));
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()
})
} }
} }
impl CheckAuth for AccessTokenOptional { impl CheckAuth for AccessTokenOptional {
type Identity = Option<ClientIdentity>;
async fn verify<B: AsRef<[u8]> + Sync>( async fn verify<B: AsRef<[u8]> + Sync>(
services: &Services, services: &Services,
output: Self::Output, output: Self::Output,
request: &hyper::Request<B>, request: &hyper::Request<B>,
query: AuthQueryParams, query: AuthQueryParams,
route: TypeId, route: TypeId,
) -> Result<Auth> { ) -> Result<Self::Identity> {
match output { match output {
| Some(token) => | Some(token) =>
<AccessToken as CheckAuth>::verify(services, token, request, query, route).await, <AccessToken as CheckAuth>::verify(services, token, request, query, route)
| None => Ok(Auth::default()), .await
.map(Some),
| None => Ok(None),
} }
} }
} }
impl CheckAuth for AppserviceToken { impl CheckAuth for AppserviceToken {
type Identity = RegistrationInfo;
async fn verify<B: AsRef<[u8]> + Sync>( async fn verify<B: AsRef<[u8]> + Sync>(
services: &Services, services: &Services,
output: Self::Output, output: Self::Output,
_request: &hyper::Request<B>, _request: &hyper::Request<B>,
_query: AuthQueryParams, _query: AuthQueryParams,
_route: TypeId, _route: TypeId,
) -> Result<Auth> { ) -> Result<Self::Identity> {
let Ok(appservice_info) = services.appservice.find_from_token(&output).await else { let Ok(appservice_info) = services.appservice.find_from_token(&output).await else {
return Err!(Request(Unauthorized("Invalid appservice token."))); return Err!(Request(Unauthorized("Invalid appservice token.")));
}; };
Ok(Auth { Ok(appservice_info)
appservice_info: Some(appservice_info),
..Default::default()
})
} }
} }
impl CheckAuth for AppserviceTokenOptional { impl CheckAuth for AppserviceTokenOptional {
type Identity = Option<RegistrationInfo>;
async fn verify<B: AsRef<[u8]> + Sync>( async fn verify<B: AsRef<[u8]> + Sync>(
services: &Services, services: &Services,
output: Self::Output, output: Self::Output,
request: &hyper::Request<B>, request: &hyper::Request<B>,
query: AuthQueryParams, query: AuthQueryParams,
route: TypeId, route: TypeId,
) -> Result<Auth> { ) -> Result<Self::Identity> {
match output { match output {
| Some(token) => | Some(token) =>
<AppserviceToken as CheckAuth>::verify(services, token, request, query, route) <AppserviceToken as CheckAuth>::verify(services, token, request, query, route)
.await, .await
| None => Ok(Auth::default()), .map(Some),
| None => Ok(None),
} }
} }
} }
impl CheckAuth for NoAuthentication { impl CheckAuth for NoAuthentication {
type Identity = ();
async fn verify<B: AsRef<[u8]> + Sync>( async fn verify<B: AsRef<[u8]> + Sync>(
_services: &Services, _services: &Services,
_output: Self::Output, _output: Self::Output,
_request: &hyper::Request<B>, _request: &hyper::Request<B>,
_query: AuthQueryParams, _query: AuthQueryParams,
_route: TypeId, _route: TypeId,
) -> Result<Auth> { ) -> Result<Self::Identity> {
Ok(Auth::default()) Ok(())
} }
} }
impl CheckAuth for NoAccessToken { impl CheckAuth for NoAccessToken {
type Identity = Option<ClientIdentity>;
async fn verify<B: AsRef<[u8]> + Sync>( async fn verify<B: AsRef<[u8]> + Sync>(
services: &Services, services: &Services,
_output: Self::Output, _output: Self::Output,
request: &hyper::Request<B>, request: &hyper::Request<B>,
query: AuthQueryParams, query: AuthQueryParams,
route: TypeId, route: TypeId,
) -> Result<Auth> { ) -> Result<Self::Identity> {
// We handle these the same as AccessTokenOptional // We handle these the same as AccessTokenOptional
let token = AccessTokenOptional::extract_authentication(request).map_err(|err| { let token = AccessTokenOptional::extract_authentication(request).map_err(|err| {
err!(Request(Unauthorized(warn!("Failed to extract authorization: {}", err)))) err!(Request(Unauthorized(warn!("Failed to extract authorization: {}", err))))
+3 -3
View File
@@ -28,7 +28,7 @@ pub(crate) async fn get_backfill_route(
) -> Result<get_backfill::v1::Response> { ) -> Result<get_backfill::v1::Response> {
AccessCheck { AccessCheck {
services: &services, services: &services,
origin: body.origin(), origin: &body.identity,
room_id: &body.room_id, room_id: &body.room_id,
event_id: None, event_id: None,
} }
@@ -41,7 +41,7 @@ pub(crate) async fn get_backfill_route(
.await .await
{ {
info!( info!(
origin = body.origin().as_str(), origin = body.identity.as_str(),
"Refusing to serve backfill for room we aren't participating in" "Refusing to serve backfill for room we aren't participating in"
); );
return Err!(Request(NotFound("This server is not participating in that room."))); 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 Ok(services
.rooms .rooms
.state_accessor .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 .await
.then_some(pdu)) .then_some(pdu))
}) })
+2 -2
View File
@@ -40,7 +40,7 @@ pub(crate) async fn get_event_route(
AccessCheck { AccessCheck {
services: &services, services: &services,
origin: body.origin(), origin: &body.identity,
room_id, room_id,
event_id: Some(&body.event_id), event_id: Some(&body.event_id),
} }
@@ -54,7 +54,7 @@ pub(crate) async fn get_event_route(
.await .await
{ {
info!( info!(
origin = body.origin().as_str(), origin = body.identity.as_str(),
"Refusing to serve state for room we aren't participating in" "Refusing to serve state for room we aren't participating in"
); );
return Err!(Request(NotFound("This server is not participating in that room."))); return Err!(Request(NotFound("This server is not participating in that room.")));
+2 -2
View File
@@ -19,7 +19,7 @@ pub(crate) async fn get_event_authorization_route(
) -> Result<get_event_authorization::v1::Response> { ) -> Result<get_event_authorization::v1::Response> {
AccessCheck { AccessCheck {
services: &services, services: &services,
origin: body.origin(), origin: &body.identity,
room_id: &body.room_id, room_id: &body.room_id,
event_id: None, event_id: None,
} }
@@ -42,7 +42,7 @@ pub(crate) async fn get_event_authorization_route(
.await .await
{ {
info!( info!(
origin = body.origin().as_str(), origin = body.identity.as_str(),
"Refusing to serve state for room we aren't participating in" "Refusing to serve state for room we aren't participating in"
); );
return Err!(Request(NotFound("This server is not participating in that room."))); return Err!(Request(NotFound("This server is not participating in that room.")));
+4 -4
View File
@@ -22,7 +22,7 @@ pub(crate) async fn get_missing_events_route(
) -> Result<get_missing_events::v1::Response> { ) -> Result<get_missing_events::v1::Response> {
AccessCheck { AccessCheck {
services: &services, services: &services,
origin: body.origin(), origin: &body.identity,
room_id: &body.room_id, room_id: &body.room_id,
event_id: None, event_id: None,
} }
@@ -36,7 +36,7 @@ pub(crate) async fn get_missing_events_route(
.await .await
{ {
info!( info!(
origin = body.origin().as_str(), origin = body.identity.as_str(),
"Refusing to serve state for room we aren't participating in" "Refusing to serve state for room we aren't participating in"
); );
return Err!(Request(NotFound("This server is not participating in that room."))); 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 if !services
.rooms .rooms
.state_accessor .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 .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!({}))?; pdu.redact(&room_version, json!({}))?;
} }
+2 -2
View File
@@ -20,7 +20,7 @@ pub(crate) async fn get_hierarchy_route(
.await .await
{ {
info!( info!(
origin = body.origin().as_str(), origin = body.identity.as_str(),
"Refusing to serve state for room we aren't participating in" "Refusing to serve state for room we aren't participating in"
); );
return Err!(Request(NotFound("This server is not participating in that room."))); 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 let response = services
.rooms .rooms
.summary .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; .await;
if let Accessibility::Accessible(response) = response { if let Accessibility::Accessible(response) = response {
+4 -5
View File
@@ -32,7 +32,7 @@ pub(crate) async fn create_invite_route(
services services
.rooms .rooms
.event_handler .event_handler
.acl_check(body.origin(), &body.room_id) .acl_check(&body.identity, &body.room_id)
.await?; .await?;
if !services.server.supported_room_version(&body.room_version) { if !services.server.supported_room_version(&body.room_version) {
@@ -54,12 +54,11 @@ pub(crate) async fn create_invite_route(
if services if services
.moderation .moderation
.is_remote_server_forbidden(body.origin()) .is_remote_server_forbidden(&body.identity)
{ {
warn!( warn!(
"Received federated/remote invite from banned server {} for room ID {}. Rejecting.", "Received federated/remote invite from banned server {} for room ID {}. Rejecting.",
body.origin(), body.identity, body.room_id
body.room_id
); );
return Err!(Request(Forbidden("Server is banned on this homeserver."))); 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) .and_then(Result::ok)
.ok_or_else(|| err!(Request(InvalidParam("Invalid sender property"))))?; .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.",))); return Err!(Request(Forbidden("Sender's server does not match the origin server.",)));
} }
+6 -8
View File
@@ -30,7 +30,7 @@ use crate::Ruma;
/// # `GET /_matrix/federation/v1/make_join/{roomId}/{userId}` /// # `GET /_matrix/federation/v1/make_join/{roomId}/{userId}`
/// ///
/// Creates a join template. /// 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( pub(crate) async fn create_join_event_template_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<prepare_join_event::v1::Request>, body: Ruma<prepare_join_event::v1::Request>,
@@ -45,14 +45,14 @@ pub(crate) async fn create_join_event_template_route(
.await .await
{ {
info!( info!(
origin = body.origin().as_str(), origin = body.identity.as_str(),
room_id = %body.room_id, room_id = %body.room_id,
"Refusing to serve make_join for room we aren't participating in" "Refusing to serve make_join for room we aren't participating in"
); );
return Err!(Request(NotFound("This server is not participating in that room."))); 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."))); 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 services
.rooms .rooms
.event_handler .event_handler
.acl_check(body.origin(), &body.room_id) .acl_check(&body.identity, &body.room_id)
.await?; .await?;
if services if services
.moderation .moderation
.is_remote_server_forbidden(body.origin()) .is_remote_server_forbidden(&body.identity)
{ {
warn!( warn!(
"Server {} for remote user {} tried joining room ID {} which has a server name that \ "Server {} for remote user {} tried joining room ID {} which has a server name that \
is globally forbidden. Rejecting.", is globally forbidden. Rejecting.",
body.origin(), body.identity, &body.user_id, &body.room_id,
&body.user_id,
&body.room_id,
); );
return Err!(Request(Forbidden("Server is banned on this homeserver."))); return Err!(Request(Forbidden("Server is banned on this homeserver.")));
} }
+5 -7
View File
@@ -28,14 +28,14 @@ pub(crate) async fn create_knock_event_template_route(
.await .await
{ {
info!( info!(
origin = body.origin().as_str(), origin = body.identity.as_str(),
room_id = %body.room_id, room_id = %body.room_id,
"Refusing to serve make_knock for room we aren't participating in" "Refusing to serve make_knock for room we aren't participating in"
); );
return Err!(Request(NotFound("This server is not participating in that room."))); 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."))); 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 services
.rooms .rooms
.event_handler .event_handler
.acl_check(body.origin(), &body.room_id) .acl_check(&body.identity, &body.room_id)
.await?; .await?;
if services if services
.moderation .moderation
.is_remote_server_forbidden(body.origin()) .is_remote_server_forbidden(&body.identity)
{ {
warn!( warn!(
"Server {} for remote user {} tried knocking room ID {} which has a server name \ "Server {} for remote user {} tried knocking room ID {} which has a server name \
that is globally forbidden. Rejecting.", that is globally forbidden. Rejecting.",
body.origin(), body.identity, &body.user_id, &body.room_id,
&body.user_id,
&body.room_id,
); );
return Err!(Request(Forbidden("Server is banned on this homeserver."))); return Err!(Request(Forbidden("Server is banned on this homeserver.")));
} }
+3 -3
View File
@@ -26,13 +26,13 @@ pub(crate) async fn create_leave_event_template_route(
.await .await
{ {
info!( info!(
origin = body.origin().as_str(), origin = body.identity.as_str(),
"Refusing to serve make_leave for room we aren't participating in" "Refusing to serve make_leave for room we aren't participating in"
); );
return Err!(Request(NotFound("This server is not participating in that room."))); 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( return Err!(Request(Forbidden(
"Not allowed to leave on behalf of another server/user." "Not allowed to leave on behalf of another server/user."
))); )));
@@ -42,7 +42,7 @@ pub(crate) async fn create_leave_event_template_route(
services services
.rooms .rooms
.event_handler .event_handler
.acl_check(body.origin(), &body.room_id) .acl_check(&body.identity, &body.room_id)
.await?; .await?;
let room_version = services.rooms.state.get_room_version(&body.room_id).await?; let room_version = services.rooms.state.get_room_version(&body.room_id).await?;
+4 -4
View File
@@ -62,7 +62,7 @@ pub(crate) async fn send_transaction_message_route(
ClientIp(client): ClientIp, ClientIp(client): ClientIp,
body: Ruma<send_transaction_message::v1::Request>, body: Ruma<send_transaction_message::v1::Request>,
) -> Result<send_transaction_message::v1::Response> { ) -> Result<send_transaction_message::v1::Response> {
if body.origin() != body.body.origin { if body.identity != body.body.origin {
return Err!(Request(Forbidden( return Err!(Request(Forbidden(
"Not allowed to send transactions on behalf of other servers" "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 // Atomically check cache, join active, or start new transaction
match services match services
@@ -136,7 +136,7 @@ async fn wait_for_result(
skip_all, skip_all,
fields( fields(
id = ?body.transaction_id.as_str(), id = ?body.transaction_id.as_str(),
origin = ?body.origin() origin = ?body.identity
) )
)] )]
async fn process_inbound_transaction( async fn process_inbound_transaction(
@@ -164,7 +164,7 @@ async fn process_inbound_transaction(
.stream(); .stream();
debug!(pdus = body.pdus.len(), edus = body.edus.len(), "Processing transaction",); 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, | Ok(results) => results,
| Err(err) => { | Err(err) => {
fail_federation_txn(services, &txn_key, &sender, err); fail_federation_txn(services, &txn_key, &sender, err);
+4 -5
View File
@@ -304,7 +304,7 @@ pub(crate) async fn create_join_event_v2_route(
) -> Result<create_join_event::v2::Response> { ) -> Result<create_join_event::v2::Response> {
if services if services
.moderation .moderation
.is_remote_server_forbidden(body.origin()) .is_remote_server_forbidden(&body.identity)
{ {
return Err!(Request(Forbidden("Server is banned on this homeserver."))); return Err!(Request(Forbidden("Server is banned on this homeserver.")));
} }
@@ -314,8 +314,7 @@ pub(crate) async fn create_join_event_v2_route(
warn!( warn!(
"Server {} tried joining room ID {} through us which has a server name that is \ "Server {} tried joining room ID {} through us which has a server name that is \
globally forbidden. Rejecting.", globally forbidden. Rejecting.",
body.origin(), body.identity, &body.room_id,
&body.room_id,
); );
return Err!(Request(Forbidden(warn!( return Err!(Request(Forbidden(warn!(
"Room ID server name {server} is banned on this homeserver." "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 now = Instant::now();
let room_state = 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() .boxed()
.await?; .await?;
info!( info!(
"Finished sending a join for {} in {} in {:?}", "Finished sending a join for {} in {} in {:?}",
body.origin(), body.identity,
&body.room_id, &body.room_id,
now.elapsed() now.elapsed()
); );
+6 -8
View File
@@ -26,13 +26,12 @@ pub(crate) async fn create_knock_event_v1_route(
) -> Result<create_knock_event::v1::Response> { ) -> Result<create_knock_event::v1::Response> {
if services if services
.moderation .moderation
.is_remote_server_forbidden(body.origin()) .is_remote_server_forbidden(&body.identity)
{ {
warn!( warn!(
"Server {} tried knocking room ID {} who has a server name that is globally \ "Server {} tried knocking room ID {} who has a server name that is globally \
forbidden. Rejecting.", forbidden. Rejecting.",
body.origin(), body.identity, &body.room_id,
&body.room_id,
); );
return Err!(Request(Forbidden("Server is banned on this homeserver."))); return Err!(Request(Forbidden("Server is banned on this homeserver.")));
} }
@@ -42,8 +41,7 @@ pub(crate) async fn create_knock_event_v1_route(
warn!( warn!(
"Server {} tried knocking room ID {} which has a server name that is globally \ "Server {} tried knocking room ID {} which has a server name that is globally \
forbidden. Rejecting.", forbidden. Rejecting.",
body.origin(), body.identity, &body.room_id,
&body.room_id,
); );
return Err!(Request(Forbidden("Server is banned on this homeserver."))); return Err!(Request(Forbidden("Server is banned on this homeserver.")));
} }
@@ -60,7 +58,7 @@ pub(crate) async fn create_knock_event_v1_route(
.await .await
{ {
info!( info!(
origin = body.origin().as_str(), origin = body.identity.as_str(),
"Refusing to serve send_knock for room we aren't participating in" "Refusing to serve send_knock for room we aren't participating in"
); );
return Err!(Request(NotFound("This server is not participating in that room."))); 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 services
.rooms .rooms
.event_handler .event_handler
.acl_check(body.origin(), &body.room_id) .acl_check(&body.identity, &body.room_id)
.await?; .await?;
let room_version = services.rooms.state.get_room_version(&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?; .await?;
// check if origin server is trying to send for another server // 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."))); return Err!(Request(BadJson("Not allowed to knock on behalf of another server/user.")));
} }
+1 -1
View File
@@ -21,7 +21,7 @@ pub(crate) async fn create_leave_event_v2_route(
State(services): State<crate::State>, State(services): State<crate::State>,
body: Ruma<create_leave_event::v2::Request>, body: Ruma<create_leave_event::v2::Request>,
) -> Result<create_leave_event::v2::Response> { ) -> Result<create_leave_event::v2::Response> {
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()) Ok(create_leave_event::v2::Response::new())
} }
+2 -2
View File
@@ -17,7 +17,7 @@ pub(crate) async fn get_room_state_route(
) -> Result<get_room_state::v1::Response> { ) -> Result<get_room_state::v1::Response> {
AccessCheck { AccessCheck {
services: &services, services: &services,
origin: body.origin(), origin: &body.identity,
room_id: &body.room_id, room_id: &body.room_id,
event_id: None, event_id: None,
} }
@@ -40,7 +40,7 @@ pub(crate) async fn get_room_state_route(
.await .await
{ {
info!( info!(
origin = body.origin().as_str(), origin = body.identity.as_str(),
"Refusing to serve state for room we aren't participating in" "Refusing to serve state for room we aren't participating in"
); );
return Err!(Request(NotFound("This server is not participating in that room."))); return Err!(Request(NotFound("This server is not participating in that room.")));
+2 -2
View File
@@ -18,7 +18,7 @@ pub(crate) async fn get_room_state_ids_route(
) -> Result<get_room_state_ids::v1::Response> { ) -> Result<get_room_state_ids::v1::Response> {
AccessCheck { AccessCheck {
services: &services, services: &services,
origin: body.origin(), origin: &body.identity,
room_id: &body.room_id, room_id: &body.room_id,
event_id: None, event_id: None,
} }
@@ -41,7 +41,7 @@ pub(crate) async fn get_room_state_ids_route(
.await .await
{ {
info!( info!(
origin = body.origin().as_str(), origin = body.identity.as_str(),
"Refusing to serve state for room we aren't participating in" "Refusing to serve state for room we aren't participating in"
); );
return Err!(Request(NotFound("This server is not participating in that room."))); return Err!(Request(NotFound("This server is not participating in that room.")));
+3 -3
View File
@@ -60,13 +60,13 @@ pub(crate) async fn get_devices_route(
let master_key = services let master_key = services
.users .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 .await
.ok(); .ok();
let self_signing_key = services let self_signing_key = services
.users .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 .await
.ok(); .ok();
@@ -94,7 +94,7 @@ pub(crate) async fn get_keys_route(
&services, &services,
None, None,
&body.device_keys, &body.device_keys,
|u| Some(u.server_name()) == body.origin.as_deref(), |u| u.server_name() == body.identity,
services.globals.allow_device_name_federation(), services.globals.allow_device_name_federation(),
Duration::from_secs(0), Duration::from_secs(0),
) )
+1 -1
View File
@@ -294,7 +294,7 @@ impl Service {
pub async fn appservice_checks( pub async fn appservice_checks(
&self, &self,
room_alias: &RoomAliasId, room_alias: &RoomAliasId,
appservice_info: &Option<RegistrationInfo>, appservice_info: Option<&RegistrationInfo>,
) -> Result<()> { ) -> Result<()> {
if !self if !self
.services .services