refactor: Fix errors in api/server/invite.rs

This commit is contained in:
Ginger
2026-04-28 09:16:52 -04:00
parent 15d87c00bf
commit 7f5f4df64e
2 changed files with 53 additions and 37 deletions
+39 -33
View File
@@ -8,8 +8,11 @@ use conduwuit::{
warn, warn,
}; };
use ruma::{ use ruma::{
CanonicalJsonValue, OwnedUserId, UserId, CanonicalJsonValue, UserId,
api::{client::error::ErrorKind, federation::membership::create_invite}, api::{
error::{ErrorKind, IncompatibleRoomVersionErrorData},
federation::membership::{RawStrippedState, create_invite},
},
events::room::member::{MembershipState, RoomMemberEventContent}, events::room::member::{MembershipState, RoomMemberEventContent},
serde::JsonObject, serde::JsonObject,
}; };
@@ -34,11 +37,15 @@ pub(crate) async fn create_invite_route(
if !services.server.supported_room_version(&body.room_version) { if !services.server.supported_room_version(&body.room_version) {
return Err(Error::BadRequest( return Err(Error::BadRequest(
ErrorKind::IncompatibleRoomVersion { room_version: body.room_version.clone() }, ErrorKind::IncompatibleRoomVersion(IncompatibleRoomVersionErrorData::new(
body.room_version.clone(),
)),
"Server does not support this room version.", "Server does not support this room version.",
)); ));
} }
let room_version_rules = body.room_version.rules().unwrap();
if let Some(server) = body.room_id.server_name() { if let Some(server) = body.room_id.server_name() {
if services.moderation.is_remote_server_forbidden(server) { if services.moderation.is_remote_server_forbidden(server) {
return Err!(Request(Forbidden("Server is banned on this homeserver."))); return Err!(Request(Forbidden("Server is banned on this homeserver.")));
@@ -91,21 +98,24 @@ pub(crate) async fn create_invite_route(
} }
// Ensure the sending user isn't a lying bozo // Ensure the sending user isn't a lying bozo
let sender_server = signed_event let sender_user = signed_event
.get("sender") .get("sender")
.try_into() .and_then(|v| v.as_str())
.map(UserId::server_name) .map(UserId::parse)
.map_err(|e| err!(Request(InvalidParam("Invalid sender property: {e}"))))?; .and_then(Result::ok)
if sender_server != body.origin() { .ok_or_else(|| err!(Request(InvalidParam("Invalid sender property"))))?;
if sender_user.server_name() != body.origin() {
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.",)));
} }
// Ensure the target user belongs to this server // Ensure the target user belongs to this server
let recipient_user: OwnedUserId = signed_event let recipient_user = signed_event
.get("state_key") .get("state_key")
.try_into() .and_then(|v| v.as_str())
.map(UserId::to_owned) .map(UserId::parse)
.map_err(|e| err!(Request(InvalidParam("Invalid state_key property: {e}"))))?; .and_then(Result::ok)
.ok_or_else(|| err!(Request(InvalidParam("Invalid state_key property"))))?;
if !services if !services
.globals .globals
@@ -123,20 +133,15 @@ pub(crate) async fn create_invite_route(
services services
.server_keys .server_keys
.hash_and_sign_event(&mut signed_event, &body.room_version) .hash_and_sign_event(&mut signed_event, &room_version_rules)
.map_err(|e| err!(Request(InvalidParam("Failed to sign event: {e}"))))?; .map_err(|e| err!(Request(InvalidParam("Failed to sign event: {e}"))))?;
// Generate event id // Generate event id
let event_id = gen_event_id(&signed_event, &body.room_version)?; let event_id = gen_event_id(&signed_event, &room_version_rules)?;
// Add event_id back // Add event_id back
signed_event.insert("event_id".to_owned(), CanonicalJsonValue::String(event_id.to_string())); signed_event.insert("event_id".to_owned(), CanonicalJsonValue::String(event_id.to_string()));
let sender_user: &UserId = signed_event
.get("sender")
.try_into()
.map_err(|e| err!(Request(InvalidParam("Invalid sender property: {e}"))))?;
if services.rooms.metadata.is_banned(&body.room_id).await if services.rooms.metadata.is_banned(&body.room_id).await
&& !services.users.is_admin(&recipient_user).await && !services.users.is_admin(&recipient_user).await
{ {
@@ -167,7 +172,7 @@ pub(crate) async fn create_invite_route(
let pdu: PduEvent = serde_json::from_value(event.into()) let pdu: PduEvent = serde_json::from_value(event.into())
.map_err(|e| err!(Request(BadJson("Invalid invite event PDU: {e}"))))?; .map_err(|e| err!(Request(BadJson("Invalid invite event PDU: {e}"))))?;
invite_state.push(pdu.to_format()); invite_state.push(RawStrippedState::Pdu(pdu.content.clone()));
// If we are active in the room, the remote server will notify us about the // If we are active in the room, the remote server will notify us about the
// join/invite through /send. If we are not in the room, we need to manually // join/invite through /send. If we are not in the room, we need to manually
@@ -185,8 +190,8 @@ pub(crate) async fn create_invite_route(
.mark_as_invited( .mark_as_invited(
&recipient_user, &recipient_user,
&body.room_id, &body.room_id,
sender_user, &sender_user,
Some(invite_state), invite_state,
body.via.clone(), body.via.clone(),
) )
.await?; .await?;
@@ -199,14 +204,15 @@ pub(crate) async fn create_invite_route(
for appservice in services.appservice.read().await.values() { for appservice in services.appservice.read().await.values() {
if appservice.is_user_match(&recipient_user) { if appservice.is_user_match(&recipient_user) {
let request = ruma::api::appservice::event::push_events::v1::Request { let transaction_id = general_purpose::URL_SAFE_NO_PAD
events: vec![pdu.to_format()], .encode(sha256::hash(pdu.event_id.as_bytes()))
txn_id: general_purpose::URL_SAFE_NO_PAD .into();
.encode(sha256::hash(pdu.event_id.as_bytes()))
.into(), let request = ruma::api::appservice::event::push_events::v1::Request::new(
ephemeral: Vec::new(), transaction_id,
to_device: Vec::new(), vec![pdu.to_format()],
}; );
services services
.sending .sending
.send_appservice_request(appservice.registration.clone(), request) .send_appservice_request(appservice.registration.clone(), request)
@@ -224,10 +230,10 @@ pub(crate) async fn create_invite_route(
} }
} }
Ok(create_invite::v2::Response { Ok(create_invite::v2::Response::new(
event: services services
.sending .sending
.convert_to_outgoing_federation_event(signed_event) .convert_to_outgoing_federation_event(signed_event)
.await, .await,
}) ))
} }
+14 -4
View File
@@ -5,6 +5,7 @@ use database::{Json, serialize_key};
use futures::StreamExt; use futures::StreamExt;
use ruma::{ use ruma::{
OwnedServerName, RoomId, UserId, OwnedServerName, RoomId, UserId,
api::federation::membership::RawStrippedState,
events::{ events::{
AnyStrippedStateEvent, GlobalAccountDataEventType, RoomAccountDataEventType, AnyStrippedStateEvent, GlobalAccountDataEventType, RoomAccountDataEventType,
StateEventType, StateEventType,
@@ -118,8 +119,17 @@ pub async fn update_membership(
self.mark_as_joined(user_id, room_id); self.mark_as_joined(user_id, room_id);
}, },
| MembershipState::Invite => { | MembershipState::Invite => {
let last_state = self.services.state.summary_stripped(pdu, room_id).await; #[allow(deprecated)]
self.mark_as_invited(user_id, room_id, pdu.sender(), Some(last_state), None) let last_state = self
.services
.state
.summary_stripped(pdu, room_id)
.await
.into_iter()
.map(RawStrippedState::Stripped)
.collect();
self.mark_as_invited(user_id, room_id, pdu.sender(), last_state, None)
.await?; .await?;
}, },
| MembershipState::Leave | MembershipState::Ban => { | MembershipState::Leave | MembershipState::Ban => {
@@ -332,7 +342,7 @@ pub async fn mark_as_invited(
user_id: &UserId, user_id: &UserId,
room_id: &RoomId, room_id: &RoomId,
sender_user: &UserId, sender_user: &UserId,
last_state: Option<Vec<Raw<AnyStrippedStateEvent>>>, last_state: Vec<RawStrippedState>,
invite_via: Option<Vec<OwnedServerName>>, invite_via: Option<Vec<OwnedServerName>>,
) -> Result<()> { ) -> Result<()> {
// return an error for blocked invites. ignored invites aren't handled here // return an error for blocked invites. ignored invites aren't handled here
@@ -356,7 +366,7 @@ pub async fn mark_as_invited(
self.db self.db
.userroomid_invitestate .userroomid_invitestate
.raw_put(&userroom_id, Json(last_state.unwrap_or_default())); .raw_put(&userroom_id, Json(last_state));
self.db self.db
.roomuserid_invitecount .roomuserid_invitecount
.raw_aput::<8, _, _>(&roomuser_id, self.services.globals.next_count().unwrap()); .raw_aput::<8, _, _>(&roomuser_id, self.services.globals.next_count().unwrap());