split admin-room branch from build_and_append_pdu (fixes large stack warning)

Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
Jason Volk 2024-10-02 21:18:32 +00:00 committed by strawberry
parent 56dd0f5139
commit 89a3c80700

View file

@ -8,13 +8,13 @@ use std::{
}; };
use conduit::{ use conduit::{
debug, err, error, info, debug, err, error, implement, info,
pdu::{EventHash, PduBuilder, PduCount, PduEvent}, pdu::{EventHash, PduBuilder, PduCount, PduEvent},
utils, utils,
utils::{stream::TryIgnore, IterStream, MutexMap, MutexMapGuard, ReadyExt}, utils::{stream::TryIgnore, IterStream, MutexMap, MutexMapGuard, ReadyExt},
validated, warn, Err, Error, Result, Server, validated, warn, Err, Error, Result, Server,
}; };
use futures::{future, future::ready, Future, Stream, StreamExt, TryStreamExt}; use futures::{future, future::ready, Future, FutureExt, Stream, StreamExt, TryStreamExt};
use ruma::{ use ruma::{
api::{client::error::ErrorKind, federation}, api::{client::error::ErrorKind, federation},
canonical_json::to_canonical_value, canonical_json::to_canonical_value,
@ -858,82 +858,7 @@ impl Service {
.await?; .await?;
if self.services.admin.is_admin_room(&pdu.room_id).await { if self.services.admin.is_admin_room(&pdu.room_id).await {
match pdu.event_type() { self.check_pdu_for_admin_room(&pdu, sender).boxed().await?;
TimelineEventType::RoomEncryption => {
warn!("Encryption is not allowed in the admins room");
return Err(Error::BadRequest(
ErrorKind::forbidden(),
"Encryption is not allowed in the admins room",
));
},
TimelineEventType::RoomMember => {
let target = pdu
.state_key()
.filter(|v| v.starts_with('@'))
.unwrap_or(sender.as_str());
let server_user = &self.services.globals.server_user.to_string();
let content = serde_json::from_str::<RoomMemberEventContent>(pdu.content.get())
.map_err(|_| Error::bad_database("Invalid content in pdu"))?;
if content.membership == MembershipState::Leave {
if target == server_user {
warn!("Server user cannot leave from admins room");
return Err(Error::BadRequest(
ErrorKind::forbidden(),
"Server user cannot leave from admins room.",
));
}
let count = self
.services
.state_cache
.room_members(&pdu.room_id)
.ready_filter(|user| self.services.globals.user_is_local(user))
.ready_filter(|user| *user != target)
.boxed()
.count()
.await;
if count < 2 {
warn!("Last admin cannot leave from admins room");
return Err(Error::BadRequest(
ErrorKind::forbidden(),
"Last admin cannot leave from admins room.",
));
}
}
if content.membership == MembershipState::Ban && pdu.state_key().is_some() {
if target == server_user {
warn!("Server user cannot be banned in admins room");
return Err(Error::BadRequest(
ErrorKind::forbidden(),
"Server user cannot be banned in admins room.",
));
}
let count = self
.services
.state_cache
.room_members(&pdu.room_id)
.ready_filter(|user| self.services.globals.user_is_local(user))
.ready_filter(|user| *user != target)
.boxed()
.count()
.await;
if count < 2 {
warn!("Last admin cannot be banned in admins room");
return Err(Error::BadRequest(
ErrorKind::forbidden(),
"Last admin cannot be banned in admins room.",
));
}
}
},
_ => {},
}
} }
// If redaction event is not authorized, do not append it to the timeline // If redaction event is not authorized, do not append it to the timeline
@ -1298,6 +1223,71 @@ impl Service {
} }
} }
#[implement(Service)]
#[tracing::instrument(skip_all, level = "debug")]
async fn check_pdu_for_admin_room(&self, pdu: &PduEvent, sender: &UserId) -> Result<()> {
match pdu.event_type() {
TimelineEventType::RoomEncryption => {
return Err!(Request(Forbidden(error!("Encryption not supported in admins room."))));
},
TimelineEventType::RoomMember => {
let target = pdu
.state_key()
.filter(|v| v.starts_with('@'))
.unwrap_or(sender.as_str());
let server_user = &self.services.globals.server_user.to_string();
let content: RoomMemberEventContent = pdu.get_content()?;
match content.membership {
MembershipState::Leave => {
if target == server_user {
return Err!(Request(Forbidden(error!("Server user cannot leave the admins room."))));
}
let count = self
.services
.state_cache
.room_members(&pdu.room_id)
.ready_filter(|user| self.services.globals.user_is_local(user))
.ready_filter(|user| *user != target)
.boxed()
.count()
.await;
if count < 2 {
return Err!(Request(Forbidden(error!("Last admin cannot leave the admins room."))));
}
},
MembershipState::Ban if pdu.state_key().is_some() => {
if target == server_user {
return Err!(Request(Forbidden(error!("Server cannot be banned from admins room."))));
}
let count = self
.services
.state_cache
.room_members(&pdu.room_id)
.ready_filter(|user| self.services.globals.user_is_local(user))
.ready_filter(|user| *user != target)
.boxed()
.count()
.await;
if count < 2 {
return Err!(Request(Forbidden(error!("Last admin cannot be banned from admins room."))));
}
},
_ => {},
};
},
_ => {},
};
Ok(())
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;