State-reset and security mitigations.
Upgrade Ruma to present. The following are intentionally benign for activation in a later commit: - Hydra backports not default. - Room version 12 not default. - Room version 12 not listed as stable. Do not enable them manually or you can brick your database. Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
@@ -6,6 +6,7 @@ mod user_can;
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use futures::{FutureExt, TryFutureExt, future::try_join};
|
||||
use ruma::{
|
||||
EventEncryptionAlgorithm, JsOption, OwnedRoomAliasId, RoomId, UserId,
|
||||
events::{
|
||||
@@ -20,12 +21,16 @@ use ruma::{
|
||||
join_rules::{JoinRule, RoomJoinRulesEventContent},
|
||||
member::RoomMemberEventContent,
|
||||
name::RoomNameEventContent,
|
||||
power_levels::{RoomPowerLevels, RoomPowerLevelsEventContent},
|
||||
topic::RoomTopicEventContent,
|
||||
},
|
||||
},
|
||||
room::RoomType,
|
||||
};
|
||||
use tuwunel_core::{Result, err};
|
||||
use tuwunel_core::{
|
||||
Result, err,
|
||||
matrix::{Event, room_version, state_res::events::RoomCreateEvent},
|
||||
};
|
||||
use tuwunel_database::Map;
|
||||
|
||||
use crate::{Dep, rooms};
|
||||
@@ -69,6 +74,31 @@ impl crate::Service for Service {
|
||||
}
|
||||
|
||||
impl Service {
|
||||
/// Gets the effective power levels of a room, regardless of if there is an
|
||||
/// `m.rooms.power_levels` state.
|
||||
pub async fn get_power_levels(&self, room_id: &RoomId) -> Result<RoomPowerLevels> {
|
||||
let create = self.get_create(room_id);
|
||||
let power_levels = self
|
||||
.room_state_get_content(room_id, &StateEventType::RoomPowerLevels, "")
|
||||
.map_ok(|c: RoomPowerLevelsEventContent| c)
|
||||
.map(Result::ok)
|
||||
.map(Ok);
|
||||
|
||||
let (create, power_levels) = try_join(create, power_levels).await?;
|
||||
|
||||
let room_version = create.room_version()?;
|
||||
let rules = room_version::rules(&room_version)?;
|
||||
let creators = create.creators(&rules.authorization)?;
|
||||
|
||||
Ok(RoomPowerLevels::new(power_levels.into(), &rules.authorization, creators))
|
||||
}
|
||||
|
||||
pub async fn get_create(&self, room_id: &RoomId) -> Result<RoomCreateEvent<impl Event>> {
|
||||
self.room_state_get(room_id, &StateEventType::RoomCreate, "")
|
||||
.await
|
||||
.map(RoomCreateEvent::new)
|
||||
}
|
||||
|
||||
pub async fn get_name(&self, room_id: &RoomId) -> Result<String> {
|
||||
self.room_state_get_content(room_id, &StateEventType::RoomName, "")
|
||||
.await
|
||||
|
||||
@@ -321,7 +321,9 @@ pub fn state_full(
|
||||
shortstatehash: ShortStateHash,
|
||||
) -> impl Stream<Item = ((StateEventType, StateKey), impl Event)> + Send + '_ {
|
||||
self.state_full_pdus(shortstatehash)
|
||||
.ready_filter_map(|pdu| Some(((pdu.kind().clone().into(), pdu.state_key()?.into()), pdu)))
|
||||
.ready_filter_map(|pdu| {
|
||||
Some(((pdu.kind().to_cow_str().into(), pdu.state_key()?.into()), pdu))
|
||||
})
|
||||
}
|
||||
|
||||
#[implement(super::Service)]
|
||||
|
||||
@@ -5,7 +5,6 @@ use ruma::{
|
||||
room::{
|
||||
history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent},
|
||||
member::{MembershipState, RoomMemberEventContent},
|
||||
power_levels::{RoomPowerLevels, RoomPowerLevelsEventContent},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -44,28 +43,18 @@ pub async fn user_can_redact(
|
||||
)));
|
||||
}
|
||||
|
||||
match self
|
||||
.room_state_get_content::<RoomPowerLevelsEventContent>(
|
||||
room_id,
|
||||
&StateEventType::RoomPowerLevels,
|
||||
"",
|
||||
)
|
||||
.await
|
||||
{
|
||||
| Ok(pl_event_content) => {
|
||||
let pl_event: RoomPowerLevels = pl_event_content.into();
|
||||
Ok(pl_event.user_can_redact_event_of_other(sender)
|
||||
|| pl_event.user_can_redact_own_event(sender)
|
||||
&& match redacting_event {
|
||||
| Ok(redacting_event) =>
|
||||
if federation {
|
||||
redacting_event.sender().server_name() == sender.server_name()
|
||||
} else {
|
||||
redacting_event.sender() == sender
|
||||
},
|
||||
| _ => false,
|
||||
})
|
||||
},
|
||||
match self.get_power_levels(room_id).await {
|
||||
| Ok(power_levels) => Ok(power_levels.user_can_redact_event_of_other(sender)
|
||||
|| power_levels.user_can_redact_own_event(sender)
|
||||
&& match redacting_event {
|
||||
| Ok(redacting_event) =>
|
||||
if federation {
|
||||
redacting_event.sender().server_name() == sender.server_name()
|
||||
} else {
|
||||
redacting_event.sender() == sender
|
||||
},
|
||||
| _ => false,
|
||||
}),
|
||||
| _ => {
|
||||
// Falling back on m.room.create to judge power level
|
||||
match self
|
||||
|
||||
Reference in New Issue
Block a user