mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-05-26 20:49:55 +00:00
refactor: Fix most errors in api/server/make_join.rs
This commit is contained in:
+48
-59
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user