mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-05-26 20:49:55 +00:00
fix: Allow server admins and v12 room creators to publish rooms
This commit is contained in:
+55
-24
@@ -1,7 +1,9 @@
|
|||||||
|
use std::iter::once;
|
||||||
|
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use axum_client_ip::InsecureClientIp;
|
use axum_client_ip::InsecureClientIp;
|
||||||
use conduwuit::{
|
use conduwuit::{
|
||||||
Err, Event, Result, err, info,
|
Err, Event, Result, RoomVersion, err, info,
|
||||||
utils::{
|
utils::{
|
||||||
TryFutureExtExt,
|
TryFutureExtExt,
|
||||||
math::Expected,
|
math::Expected,
|
||||||
@@ -30,12 +32,14 @@ use ruma::{
|
|||||||
events::{
|
events::{
|
||||||
StateEventType,
|
StateEventType,
|
||||||
room::{
|
room::{
|
||||||
|
create::RoomCreateEventContent,
|
||||||
join_rules::{JoinRule, RoomJoinRulesEventContent},
|
join_rules::{JoinRule, RoomJoinRulesEventContent},
|
||||||
power_levels::{RoomPowerLevels, RoomPowerLevelsEventContent},
|
power_levels::{RoomPowerLevels, RoomPowerLevelsEventContent},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
uint,
|
uint,
|
||||||
};
|
};
|
||||||
|
use tokio::join;
|
||||||
|
|
||||||
use crate::Ruma;
|
use crate::Ruma;
|
||||||
|
|
||||||
@@ -339,35 +343,62 @@ pub(crate) async fn get_public_rooms_filtered_helper(
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether the user can publish to the room directory via power levels of
|
/// Checks whether the given user ID is allowed to publish the target room to
|
||||||
/// room history visibility event or room creator
|
/// the server's public room directory. Users are allowed to publish rooms if
|
||||||
|
/// they are server admins, room creators (in v12), or have the power level to
|
||||||
|
/// send `m.room.canonical_alias`.
|
||||||
async fn user_can_publish_room(
|
async fn user_can_publish_room(
|
||||||
services: &Services,
|
services: &Services,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
) -> Result<bool> {
|
) -> Result<bool> {
|
||||||
match services
|
if services.users.is_admin(user_id).await {
|
||||||
.rooms
|
// Server admins can always publish to their own room directory.
|
||||||
.state_accessor
|
return Ok(true);
|
||||||
.room_state_get(room_id, &StateEventType::RoomPowerLevels, "")
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
| Ok(event) => serde_json::from_str(event.content().get())
|
|
||||||
.map_err(|_| err!(Database("Invalid event content for m.room.power_levels")))
|
|
||||||
.map(|content: RoomPowerLevelsEventContent| {
|
|
||||||
RoomPowerLevels::from(content)
|
|
||||||
.user_can_send_state(user_id, StateEventType::RoomHistoryVisibility)
|
|
||||||
}),
|
|
||||||
| _ => {
|
|
||||||
match services
|
|
||||||
.rooms
|
|
||||||
.state_accessor
|
|
||||||
.room_state_get(room_id, &StateEventType::RoomCreate, "")
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
| Ok(event) => Ok(event.sender() == user_id),
|
|
||||||
| _ => Err!(Request(Forbidden("User is not allowed to publish this room"))),
|
|
||||||
}
|
}
|
||||||
|
let (create_event, room_version, power_levels_content) = join!(
|
||||||
|
services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.room_state_get(room_id, &StateEventType::RoomCreate, ""),
|
||||||
|
services.rooms.state.get_room_version(room_id),
|
||||||
|
services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.room_state_get_content::<RoomPowerLevelsEventContent>(
|
||||||
|
room_id,
|
||||||
|
&StateEventType::RoomPowerLevels,
|
||||||
|
""
|
||||||
|
)
|
||||||
|
);
|
||||||
|
let room_version = room_version
|
||||||
|
.as_ref()
|
||||||
|
.map_err(|_| err!(Request(NotFound("Unknown room"))))?;
|
||||||
|
let create_event = create_event.map_err(|_| err!(Request(NotFound("Unknown room"))))?;
|
||||||
|
if RoomVersion::new(room_version)
|
||||||
|
.expect("room version must be supported")
|
||||||
|
.explicitly_privilege_room_creators
|
||||||
|
{
|
||||||
|
let create_content: RoomCreateEventContent =
|
||||||
|
serde_json::from_str(create_event.content().get())
|
||||||
|
.map_err(|_| err!(Database("Invalid event content for m.room.create")))?;
|
||||||
|
let is_creator = create_content
|
||||||
|
.additional_creators
|
||||||
|
.unwrap_or_default()
|
||||||
|
.into_iter()
|
||||||
|
.chain(once(create_event.sender().to_owned()))
|
||||||
|
.any(|sender| sender == user_id);
|
||||||
|
if is_creator {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
match power_levels_content.map(RoomPowerLevels::from) {
|
||||||
|
| Ok(pl) => Ok(pl.user_can_send_state(user_id, StateEventType::RoomCanonicalAlias)),
|
||||||
|
| Err(e) =>
|
||||||
|
if e.is_not_found() {
|
||||||
|
Ok(create_event.sender() == user_id)
|
||||||
|
} else {
|
||||||
|
Err!(Database("Invalid event content for m.room.power_levels: {e}"))
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user