refactor: Fix most errors in api/server/make_join.rs

This commit is contained in:
Ginger
2026-04-28 09:16:52 -04:00
parent c7489fd008
commit 8871b1f74b
+48 -59
View File
@@ -1,4 +1,4 @@
use std::borrow::ToOwned; use std::{borrow::ToOwned, pin::pin};
use axum::extract::State; use axum::extract::State;
use conduwuit::{ use conduwuit::{
@@ -7,8 +7,12 @@ use conduwuit::{
use conduwuit_service::Services; use conduwuit_service::Services;
use futures::StreamExt; use futures::StreamExt;
use ruma::{ use ruma::{
OwnedUserId, RoomId, RoomVersionId, UserId, OwnedUserId, RoomId, UserId,
api::{client::error::ErrorKind, federation::membership::prepare_join_event}, api::{
error::{ErrorKind, IncompatibleRoomVersionErrorData},
federation::membership::prepare_join_event,
},
assign,
events::{ events::{
StateEventType, StateEventType,
room::{ room::{
@@ -81,15 +85,18 @@ pub(crate) async fn create_join_event_template_route(
} }
} }
let room_version_id = services.rooms.state.get_room_version(&body.room_id).await?; let room_version = services.rooms.state.get_room_version(&body.room_id).await?;
if !body.ver.contains(&room_version_id) { let room_version_rules = room_version.rules().unwrap();
if !body.ver.contains(&room_version) {
return Err(Error::BadRequest( return Err(Error::BadRequest(
ErrorKind::IncompatibleRoomVersion { room_version: room_version_id }, ErrorKind::IncompatibleRoomVersion(IncompatibleRoomVersionErrorData::new(
room_version,
)),
"Room version not supported.", "Room version not supported.",
)); ));
} }
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await; let state_lock = services.rooms.state.mutex.lock(body.room_id.as_str()).await;
let (is_invited, is_joined) = join!( let (is_invited, is_joined) = join!(
services services
.rooms .rooms
@@ -101,21 +108,15 @@ pub(crate) async fn create_join_event_template_route(
.is_joined(&body.user_id, &body.room_id) .is_joined(&body.user_id, &body.room_id)
); );
let join_authorized_via_users_server: Option<OwnedUserId> = { let join_authorized_via_users_server: Option<OwnedUserId> = {
use RoomVersionId::*;
if is_joined || is_invited { if is_joined || is_invited {
// User is already joined or invited and consequently does not need an // User is already joined or invited and consequently does not need an
// authorising user // authorising user
None None
} else if matches!(room_version_id, V1 | V2 | V3 | V4 | V5 | V6 | V7) { } else if !room_version_rules.authorization.restricted_join_rule {
// room version does not support restricted join rules // room version does not support restricted join rules
None None
} else if user_can_perform_restricted_join( } else if user_can_perform_restricted_join(&services, &body.user_id, &body.room_id)
&services, .await?
&body.user_id,
&body.room_id,
&room_version_id,
)
.await?
{ {
Some( Some(
select_authorising_user(&services, &body.room_id, &body.user_id, &state_lock) select_authorising_user(&services, &body.room_id, &body.user_id, &state_lock)
@@ -140,10 +141,12 @@ pub(crate) async fn create_join_event_template_route(
.rooms .rooms
.timeline .timeline
.create_event( .create_event(
PartialPdu::state(body.user_id.to_string(), &RoomMemberEventContent { PartialPdu::state(
join_authorized_via_users_server, body.user_id.to_string(),
..RoomMemberEventContent::new(MembershipState::Join) &assign!(RoomMemberEventContent::new(MembershipState::Join), {
}), join_authorized_via_users_server,
}),
),
&body.user_id, &body.user_id,
Some(&body.room_id), Some(&body.room_id),
&state_lock, &state_lock,
@@ -154,42 +157,38 @@ pub(crate) async fn create_join_event_template_route(
.expect("Barebones PDU should be convertible to canonical JSON"); .expect("Barebones PDU should be convertible to canonical JSON");
pdu_json.remove("event_id"); pdu_json.remove("event_id");
Ok(prepare_join_event::v1::Response { Ok(
room_version: Some(room_version_id), assign!(prepare_join_event::v1::Response::new(to_raw_value(&pdu_json).expect("CanonicalJson can be serialized to JSON")), {
event: to_raw_value(&pdu_json).expect("CanonicalJson can be serialized to JSON"), room_version: Some(room_version),
}) }),
)
} }
/// Attempts to find a user who is able to issue an invite in the target room. /// Attempts to find a user who is able to issue an invite in the target room.
pub(crate) async fn select_authorising_user( pub(crate) async fn select_authorising_user<'a>(
services: &Services, services: &Services,
room_id: &RoomId, room_id: &'a RoomId,
user_id: &UserId, user_id: &'a UserId,
state_lock: &RoomMutexGuard, state_lock: &'a RoomMutexGuard,
) -> Result<OwnedUserId> { ) -> Result<OwnedUserId> {
let auth_user = services let candidates = services.rooms.state_cache.local_users_in_room(room_id);
.rooms
.state_cache
.local_users_in_room(room_id)
.filter(|user| {
services
.rooms
.state_accessor
.user_can_invite(room_id, user, user_id, state_lock)
})
.boPartialPdu
.next()
.await
.map(ToOwned::to_owned);
match auth_user { let mut candidates = pin!(candidates);
| Some(auth_user) => Ok(auth_user),
| None => { while let Some(candidate) = candidates.next().await {
Err!(Request(UnableToGrantJoin( if services
"No user on this server is able to assist in joining." .rooms
))) .state_accessor
}, .user_can_invite(room_id, &candidate, user_id, state_lock)
.await
{
return Ok(candidate);
}
} }
Err!(Request(UnableToGrantJoin(
"No user on this server is able to assist in joining."
)))
} }
/// Checks whether the given user can join the given room via a restricted join. /// Checks whether the given user can join the given room via a restricted join.
@@ -197,17 +196,7 @@ pub(crate) async fn user_can_perform_restricted_join(
services: &Services, services: &Services,
user_id: &UserId, user_id: &UserId,
room_id: &RoomId, room_id: &RoomId,
room_version_id: &RoomVersionId,
) -> Result<bool> { ) -> Result<bool> {
use RoomVersionId::*;
// restricted rooms are not supported on <=v7
if matches!(room_version_id, V1 | V2 | V3 | V4 | V5 | V6 | V7) {
// This should be impossible as it was checked earlier on, but retain this check
// for safety.
unreachable!("user_can_perform_restricted_join got incompatible room version");
}
let Ok(join_rules_event_content) = services let Ok(join_rules_event_content) = services
.rooms .rooms
.state_accessor .state_accessor