fix: Resolve errors in recently added services

This commit is contained in:
Ginger
2026-04-07 09:59:02 -04:00
parent a4e64383b7
commit 3e1f97487f
10 changed files with 99 additions and 55 deletions
+7 -2
View File
@@ -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"
+1 -1
View File
@@ -68,7 +68,7 @@ impl Service {
pub fn expect_mailer(&self) -> Result<Mailer<'_>> {
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.")))
})
}
}
+2 -1
View File
@@ -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();
+8 -5
View File
@@ -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;
+5 -3
View File
@@ -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)
+16 -15
View File
@@ -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<bool, JsonError> {
pub(super) fn is_invite_via_third_party_id(
object: &CanonicalJsonObject,
) -> Result<bool, JsonError> {
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());
}
+5 -2
View File
@@ -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.",
));
}
+1 -1
View File
@@ -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(
+6 -3
View File
@@ -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",
));
}
+48 -22
View File
@@ -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))
}