From 3e1f97487fef00d85464e3e46da10a10f46f0a6a Mon Sep 17 00:00:00 2001 From: Ginger Date: Tue, 7 Apr 2026 09:59:02 -0400 Subject: [PATCH] fix: Resolve errors in recently added services --- src/service/admin/mod.rs | 9 ++++- src/service/mailer/mod.rs | 2 +- src/service/media/preview.rs | 3 +- src/service/pusher/mod.rs | 13 +++--- src/service/sending/mod.rs | 8 ++-- src/service/server_keys/util.rs | 31 ++++++++------- src/service/threepid/mod.rs | 7 +++- src/service/threepid/session.rs | 2 +- src/service/transactions/mod.rs | 9 +++-- src/service/uiaa/mod.rs | 70 ++++++++++++++++++++++----------- 10 files changed, 99 insertions(+), 55 deletions(-) diff --git a/src/service/admin/mod.rs b/src/service/admin/mod.rs index 29a0435ca..850d2874b 100644 --- a/src/service/admin/mod.rs +++ b/src/service/admin/mod.rs @@ -455,11 +455,16 @@ impl Service { } async fn handle_response(&self, content: RoomMessageEventContent) -> Result<()> { - let Some(Relation::Reply(reply )) = content.relates_to.as_ref() else { + let Some(Relation::Reply(reply)) = content.relates_to.as_ref() else { return Ok(()); }; - let Ok(pdu) = self.services.timeline.get_pdu(&reply.in_reply_to.event_id).await else { + let Ok(pdu) = self + .services + .timeline + .get_pdu(&reply.in_reply_to.event_id) + .await + else { error!( event_id = ?reply.in_reply_to.event_id, "Missing admin command in_reply_to event" diff --git a/src/service/mailer/mod.rs b/src/service/mailer/mod.rs index 9d7ad409d..c336164b5 100644 --- a/src/service/mailer/mod.rs +++ b/src/service/mailer/mod.rs @@ -68,7 +68,7 @@ impl Service { pub fn expect_mailer(&self) -> Result> { self.mailer().ok_or_else(|| { - err!(Request(FeatureDisabled("This homeserver is not configured to send email."))) + err!(Request(Unrecognized("This homeserver is not configured to send email."))) }) } } diff --git a/src/service/media/preview.rs b/src/service/media/preview.rs index 06dd06532..da3e06f16 100644 --- a/src/service/media/preview.rs +++ b/src/service/media/preview.rs @@ -16,6 +16,8 @@ use serde::Serialize; use url::Url; use super::Service; +#[cfg(feature = "url_preview")] +use crate::media::mxc::Mxc; #[derive(Serialize, Default)] pub struct UrlPreviewData { @@ -218,7 +220,6 @@ pub async fn download_audio( pub async fn download_media(&self, url: &str) -> Result<(OwnedMxcUri, usize)> { use conduwuit::utils::random_string; use http::header::CONTENT_TYPE; - use ruma::Mxc; let response = self.services.client.url_preview.get(url).send().await?; let content_type = response.headers().get(CONTENT_TYPE).cloned(); diff --git a/src/service/pusher/mod.rs b/src/service/pusher/mod.rs index c93c17637..9bc31d1f1 100644 --- a/src/service/pusher/mod.rs +++ b/src/service/pusher/mod.rs @@ -30,7 +30,8 @@ use ruma::{ }, }, push::{ - Action, HighlightTweakValue, PushConditionPowerLevelsCtx, PushConditionRoomCtx, PushFormat, Ruleset, Tweak + Action, HighlightTweakValue, PushConditionPowerLevelsCtx, PushConditionRoomCtx, + PushFormat, Ruleset, Tweak, }, room_version_rules::{AuthorizationRules, RoomPowerLevelsRules, RoomVersionRules}, serde::Raw, @@ -467,10 +468,12 @@ impl Service { if !event_id_only { if *event.kind() == TimelineEventType::RoomEncrypted - || tweaks - .iter() - .any(|t| matches!(t, Tweak::Highlight(HighlightTweakValue::Yes) | Tweak::Sound(_))) - { + || tweaks.iter().any(|t| { + matches!( + t, + Tweak::Highlight(HighlightTweakValue::Yes) | Tweak::Sound(_) + ) + }) { notify.prio = NotificationPriority::High; } else { notify.prio = NotificationPriority::Low; diff --git a/src/service/sending/mod.rs b/src/service/sending/mod.rs index a49f8d84b..ccdccbca3 100644 --- a/src/service/sending/mod.rs +++ b/src/service/sending/mod.rs @@ -22,8 +22,10 @@ use futures::{FutureExt, Stream, StreamExt}; use ruma::{ OwnedServerName, RoomId, ServerName, UserId, api::{ - OutgoingRequest, auth_scheme::{NoAuthentication, NoAccessToken, SendAccessToken}, - federation::authentication::ServerSignatures, path_builder::PathBuilder, + OutgoingRequest, + auth_scheme::{NoAccessToken, NoAuthentication, SendAccessToken}, + federation::authentication::ServerSignatures, + path_builder::PathBuilder, }, }; use tokio::{task, task::JoinSet}; @@ -348,6 +350,7 @@ impl Service { .execute_unauthenticated(dest, request) .await } + /// Send an unauthenticated federation request with no X-Matrix header. #[inline] pub async fn send_legacy_media_request<'i, T>( @@ -362,7 +365,6 @@ impl Service { > + Debug + Send, { - self.services .federation .execute_on(&self.services.client.federation, dest, request, SendAccessToken::None) diff --git a/src/service/server_keys/util.rs b/src/service/server_keys/util.rs index 98d6ec982..1706b7f80 100644 --- a/src/service/server_keys/util.rs +++ b/src/service/server_keys/util.rs @@ -1,7 +1,10 @@ use std::collections::{BTreeMap, BTreeSet}; use ruma::{ - CanonicalJsonObject, CanonicalJsonValue, IdParseError, OwnedEventId, OwnedServerName, OwnedServerSigningKeyId, RoomVersionId, UserId, canonical_json::JsonType, signatures::{JsonError, VerificationError} + CanonicalJsonObject, CanonicalJsonValue, IdParseError, OwnedEventId, OwnedServerName, + OwnedServerSigningKeyId, RoomVersionId, UserId, + canonical_json::JsonType, + signatures::{JsonError, VerificationError}, }; /// Whether the given event is an `m.room.member` invite that was created as the @@ -9,7 +12,9 @@ use ruma::{ /// /// Returns an error if the object has not the expected format of an /// `m.room.member` event. -pub(super) fn is_invite_via_third_party_id(object: &CanonicalJsonObject) -> Result { +pub(super) fn is_invite_via_third_party_id( + object: &CanonicalJsonObject, +) -> Result { let Some(CanonicalJsonValue::String(raw_type)) = object.get("type") else { return Err(JsonError::NotOfType { target: "type".to_owned(), @@ -74,10 +79,8 @@ pub fn servers_to_check_signatures( if !is_invite_via_third_party_id(object)? { match object.get("sender") { | Some(CanonicalJsonValue::String(raw_sender)) => { - let user_id = <&UserId>::try_from(raw_sender.as_str()).map_err(|source| {VerificationError::ParseIdentifier { - identifier_type: "user ID", - source, - } + let user_id = <&UserId>::try_from(raw_sender.as_str()).map_err(|source| { + VerificationError::ParseIdentifier { identifier_type: "user ID", source } })?; servers_to_check.insert(user_id.server_name().to_owned()); @@ -95,18 +98,15 @@ pub fn servers_to_check_signatures( | RoomVersionId::V1 | RoomVersionId::V2 => match object.get("event_id") { | Some(CanonicalJsonValue::String(raw_event_id)) => { let event_id: OwnedEventId = raw_event_id.parse().map_err(|source| { - VerificationError::ParseIdentifier { - identifier_type: "event ID", - source, - } + VerificationError::ParseIdentifier { identifier_type: "event ID", source } })?; let server_name = event_id .server_name() .ok_or_else(|| VerificationError::ParseIdentifier { - identifier_type: "event ID", - source: IdParseError::InvalidServerName, - })? + identifier_type: "event ID", + source: IdParseError::InvalidServerName, + })? .to_owned(); servers_to_check.insert(server_name); @@ -138,8 +138,9 @@ pub fn servers_to_check_signatures( } .into() })?; - let authorized_user = <&UserId>::try_from(authorized_user) - .map_err(|source| VerificationError::ParseIdentifier { identifier_type: "user ID", source })?; + let authorized_user = <&UserId>::try_from(authorized_user).map_err(|source| { + VerificationError::ParseIdentifier { identifier_type: "user ID", source } + })?; servers_to_check.insert(authorized_user.server_name().to_owned()); } diff --git a/src/service/threepid/mod.rs b/src/service/threepid/mod.rs index 09e8dce4d..92b1ad8ce 100644 --- a/src/service/threepid/mod.rs +++ b/src/service/threepid/mod.rs @@ -5,7 +5,10 @@ use database::{Deserialized, Map}; use governor::{DefaultKeyedRateLimiter, Quota, RateLimiter}; use lettre::{Address, message::Mailbox}; use nonzero_ext::nonzero; -use ruma::{ClientSecret, OwnedClientSecret, OwnedSessionId, SessionId, api::error::ErrorKind}; +use ruma::{ + ClientSecret, OwnedClientSecret, OwnedSessionId, SessionId, + api::error::{ErrorKind, LimitExceededErrorData}, +}; mod session; @@ -119,7 +122,7 @@ impl Service { // Check ratelimiting for the target address. if self.ratelimiter.check_key(&recipient.email).is_err() { return Err(Error::BadRequest( - ErrorKind::LimitExceeded { retry_after: None }, + ErrorKind::LimitExceeded(LimitExceededErrorData::new()), "You're sending emails too fast, try again in a few minutes.", )); } diff --git a/src/service/threepid/session.rs b/src/service/threepid/session.rs index dd1ca4674..5f3af93b2 100644 --- a/src/service/threepid/session.rs +++ b/src/service/threepid/session.rs @@ -70,7 +70,7 @@ impl ValidationSessions { #[must_use] pub(super) fn generate_session_id() -> OwnedSessionId { - OwnedSessionId::parse(utils::random_string(Self::RANDOM_SID_LENGTH)).unwrap() + SessionId::parse(utils::random_string(Self::RANDOM_SID_LENGTH)).unwrap() } pub(super) fn create_session( diff --git a/src/service/transactions/mod.rs b/src/service/transactions/mod.rs index 01dc27e55..1ee7f4000 100644 --- a/src/service/transactions/mod.rs +++ b/src/service/transactions/mod.rs @@ -13,7 +13,10 @@ use conduwuit::{Error, Result, SyncRwLock, debug_warn, warn}; use database::{Handle, Map}; use ruma::{ DeviceId, OwnedServerName, OwnedTransactionId, TransactionId, UserId, - api::{error::ErrorKind::LimitExceeded, federation::transactions::send_transaction_message}, + api::{ + error::{ErrorKind::LimitExceeded, LimitExceededErrorData}, + federation::transactions::send_transaction_message, + }, }; use tokio::sync::watch::{Receiver, Sender}; @@ -181,7 +184,7 @@ impl Service { "Got concurrent transaction request from an origin with an active transaction" ); return Err(Error::BadRequest( - LimitExceeded { retry_after: None }, + LimitExceeded(LimitExceededErrorData::default()), "Still processing another transaction from this origin", )); } @@ -201,7 +204,7 @@ impl Service { "Server is overloaded, dropping incoming transaction" ); return Err(Error::BadRequest( - LimitExceeded { retry_after: None }, + LimitExceeded(LimitExceededErrorData::default()), "Server is overloaded, try again later", )); } diff --git a/src/service/uiaa/mod.rs b/src/service/uiaa/mod.rs index 3e7d83583..b17a84e4d 100644 --- a/src/service/uiaa/mod.rs +++ b/src/service/uiaa/mod.rs @@ -10,8 +10,9 @@ use ruma::{ UserId, api::{ client::uiaa::{ - AuthData, AuthFlow, AuthType, EmailIdentity, Password, ReCaptcha, RegistrationToken, - ThirdpartyIdCredentials, UiaaInfo, UserIdentifier, MatrixUserIdentifier + AuthData, AuthFlow, AuthType, EmailIdentity, EmailUserIdentifier, + MatrixUserIdentifier, Password, ReCaptcha, RegistrationToken, + ThirdpartyIdCredentials, UiaaInfo, UserIdentifier, }, error::{ErrorKind, StandardErrorBody}, }, @@ -19,7 +20,7 @@ use ruma::{ use serde_json::value::RawValue; use tokio::sync::Mutex; -use crate::{Dep, config, globals, registration_tokens, rooms::user, threepid, users}; +use crate::{Dep, config, globals, registration_tokens, threepid, users}; pub struct Service { services: Services, @@ -91,10 +92,7 @@ macro_rules! identity_update_fn { } else if self.$field == Some($field) { Ok(()) } else { - Err(StandardErrorBody { - kind: ErrorKind::InvalidParam, - message: $error.to_owned(), - }) + Err(StandardErrorBody::new(ErrorKind::InvalidParam, $error.to_owned())) } } }; @@ -330,19 +328,23 @@ impl Service { Ok(AuthType::EmailIdentity) }, - | Err(message) => Err(StandardErrorBody { - kind: ErrorKind::ThreepidAuthFailed, - message: message.into_owned(), - }), + | Err(message) => Err(StandardErrorBody::new( + ErrorKind::ThreepidAuthFailed, + message.into_owned(), + )), } }, #[allow(clippy::useless_let_if_seq)] | AuthData::Password(Password { identifier, password, .. }) => { let user_id_or_localpart = match identifier { - | Some(UserIdentifier::Matrix(MatrixUserIdentifier{user})) => user.to_owned(), - | Some(UserIdentifier::Email(address)) => { + | UserIdentifier::Matrix(MatrixUserIdentifier { user, .. }) => + user.to_owned(), + | UserIdentifier::Email(EmailUserIdentifier { address, .. }) => { let Ok(email) = Address::try_from(address.to_owned()) else { - return Err(StandardErrorBody::new(ErrorKind::InvalidParam, "Email is malformed".to_owned())); + return Err(StandardErrorBody::new( + ErrorKind::InvalidParam, + "Email is malformed".to_owned(), + )); }; if let Some(localpart) = @@ -352,18 +354,27 @@ impl Service { localpart } else { - return Err(StandardErrorBody::new(ErrorKind::Forbidden, "Invalid identifier or password".to_owned())); + return Err(StandardErrorBody::new( + ErrorKind::Forbidden, + "Invalid identifier or password".to_owned(), + )); } }, | _ => - return Err(StandardErrorBody::new(ErrorKind::Unrecognized, "Identifier type not recognized".to_owned())), + return Err(StandardErrorBody::new( + ErrorKind::Unrecognized, + "Identifier type not recognized".to_owned(), + )), }; let Ok(user_id) = UserId::parse_with_server_name( user_id_or_localpart, self.services.globals.server_name(), ) else { - return Err(StandardErrorBody::new(ErrorKind::InvalidParam, "User ID is malformed".to_owned())); + return Err(StandardErrorBody::new( + ErrorKind::InvalidParam, + "User ID is malformed".to_owned(), + )); }; // Check if password is correct @@ -396,20 +407,29 @@ impl Service { Ok(AuthType::Password) } else { - Err(StandardErrorBody::new(ErrorKind::Forbidden, "Invalid identifier or password".to_owned())) + Err(StandardErrorBody::new( + ErrorKind::Forbidden, + "Invalid identifier or password".to_owned(), + )) } }, | AuthData::ReCaptcha(ReCaptcha { response, .. }) => { let Some(ref private_site_key) = self.services.config.recaptcha_private_site_key else { - return Err(StandardErrorBody::new(ErrorKind::Forbidden, "ReCaptcha is not configured".to_owned())); + return Err(StandardErrorBody::new( + ErrorKind::Forbidden, + "ReCaptcha is not configured".to_owned(), + )); }; match recaptcha_verify::verify_v3(private_site_key, response, None).await { | Ok(()) => Ok(AuthType::ReCaptcha), | Err(e) => { error!("ReCaptcha verification failed: {e:?}"); - Err(StandardErrorBody::new(ErrorKind::Forbidden, "ReCaptcha verification failed".to_owned())) + Err(StandardErrorBody::new( + ErrorKind::Forbidden, + "ReCaptcha verification failed".to_owned(), + )) }, } }, @@ -428,11 +448,17 @@ impl Service { Ok(AuthType::RegistrationToken) } else { - Err(StandardErrorBody::new(ErrorKind::Forbidden, "Invalid registration token".to_owned())) + Err(StandardErrorBody::new( + ErrorKind::Forbidden, + "Invalid registration token".to_owned(), + )) } }, | AuthData::Terms(_) => Ok(AuthType::Terms), - | _ => Err(StandardErrorBody::new(ErrorKind::Unrecognized, "Unsupported stage type".into())), + | _ => Err(StandardErrorBody::new( + ErrorKind::Unrecognized, + "Unsupported stage type".into(), + )), } .map(|auth_type| (auth_type, identity)) }