1
0
Fork 0
mirror of https://forgejo.ellis.link/continuwuation/continuwuity.git synced 2025-09-30 18:42:05 +00:00

fix(hydra): Fix v11 room support

This commit is contained in:
nexy7574 2025-09-12 14:15:35 +01:00
parent ff92573103
commit 35b7b45ea0
No known key found for this signature in database
6 changed files with 73 additions and 44 deletions

View file

@ -194,6 +194,7 @@ pub(crate) async fn create_room_route(
// 1. The room create event
debug!("Creating room create event for {sender_user} in room {room_id:?}");
let tmp_id = room_id.as_deref();
let create_event_id = services
.rooms
.timeline
@ -205,13 +206,13 @@ pub(crate) async fn create_room_route(
..Default::default()
},
sender_user,
None,
tmp_id,
&state_lock,
)
.boxed()
.await?;
trace!("Created room create event with ID {}", create_event_id);
let room_id = match room_id {
trace!("Created room create event with ID {}", &create_event_id);
let room_id = match room_id.clone() {
| Some(room_id) => room_id,
| None => {
let as_room_id = create_event_id.as_str().replace('$', "!");
@ -287,6 +288,10 @@ pub(crate) async fn create_room_route(
}
}
}
} else {
users.insert(sender_user.to_owned(), int!(100));
creators.clear(); // If this vec is not empty, default_power_levels_content will
// treat this as a v12 room
}
let power_levels_content = default_power_levels_content(

View file

@ -587,6 +587,26 @@ where
Ok(true)
}
fn is_creator<EV>(v: &RoomVersion, c: &BTreeSet<OwnedUserId>, ce: &EV, user_id: &UserId) -> bool
where
EV: Event + Send + Sync,
{
if v.explicitly_privilege_room_creators {
c.contains(user_id)
} else if v.use_room_create_sender {
ce.sender() == user_id
} else {
#[allow(deprecated)]
let creator = from_json_str::<RoomCreateEventContent>(ce.content().get())
.unwrap()
.creator
.ok_or_else(|| serde_json::Error::missing_field("creator"))
.unwrap();
creator == user_id
}
}
// TODO deserializing the member, power, join_rules event contents is done in
// conduit just before this is called. Could they be passed in?
/// Does the user who sent this member event have required power levels to do
@ -618,9 +638,6 @@ where
E: Event + Send + Sync,
for<'a> &'a E: Event + Send,
{
fn is_creator(v: &RoomVersion, c: &BTreeSet<OwnedUserId>, user_id: &UserId) -> bool {
c.contains(user_id) && v.explicitly_privilege_room_creators
}
#[derive(Deserialize)]
struct GetThirdPartyInvite {
third_party_invite: Option<Raw<ThirdPartyInvite>>,
@ -677,6 +694,7 @@ where
target_power = Some(&Int::MAX);
}
}
trace!(?creators, "creators for room");
let mut join_rules = JoinRule::Invite;
if let Some(jr) = &join_rules_event {
@ -707,7 +725,7 @@ where
(int!(0), int!(0))
};
let user_joined = user_for_join_auth_membership == &MembershipState::Join;
let okay_power = is_creator(room_version, &creators, user_for_join_auth)
let okay_power = is_creator(room_version, &creators, create_room, user_for_join_auth)
|| auth_user_pl >= invite_level;
user_joined && okay_power
} else {
@ -715,8 +733,8 @@ where
false
};
let sender_creator = is_creator(room_version, &creators, sender);
let target_creator = is_creator(room_version, &creators, target_user);
let sender_creator = is_creator(room_version, &creators, create_room, sender);
let target_creator = is_creator(room_version, &creators, create_room, target_user);
Ok(match target_membership {
| MembershipState::Join => {
@ -732,15 +750,14 @@ where
let no_more_prev_events = prev_events.next().is_none();
if prev_event_is_create_event && no_more_prev_events {
trace!("checking if sender is a room creator for initial membership event");
let is_creator = (sender_creator && target_creator) || {
#[allow(deprecated)]
let creator = from_json_str::<RoomCreateEventContent>(create_room.content().get())?
.creator
.ok_or_else(|| serde_json::Error::missing_field("creator"))?;
creator == sender && creator == target_user
};
trace!(
sender = %sender,
target_user = %target_user,
?sender_creator,
?target_creator,
"checking if sender is a room creator for initial membership event"
);
let is_creator = sender_creator && target_creator;
if is_creator {
debug!("sender is room creator, allowing join");

View file

@ -140,7 +140,7 @@ async fn migrate(services: &Services) -> Result<()> {
if services.globals.db.database_version().await < 18 {
services.globals.db.bump_database_version(18);
info!("Migration: Bumped database version to 18")
info!("Migration: Bumped database version to 18");
}
assert_eq!(

View file

@ -196,7 +196,7 @@ async fn get_auth_chain_inner(
},
| Ok(pdu) => {
if let Some(claimed_room_id) = pdu.room_id.clone() {
if claimed_room_id != room_id.to_owned() {
if claimed_room_id != *room_id {
return Err!(Request(Forbidden(error!(
?event_id,
?room_id,

View file

@ -1,6 +1,6 @@
use std::{collections::HashSet, iter::once};
use conduwuit::{RoomVersion, trace};
use conduwuit::trace;
use conduwuit_core::{
Err, Result, implement,
matrix::{event::Event, pdu::PduBuilder},
@ -12,7 +12,6 @@ use ruma::{
events::{
TimelineEventType,
room::{
create::RoomCreateEventContent,
member::{MembershipState, RoomMemberEventContent},
redaction::RoomRedactionEventContent,
},
@ -25,7 +24,7 @@ use super::RoomMutexGuard;
/// takes a roomid_mutex_state, meaning that only this function is able to
/// mutate the room state.
#[implement(super::Service)]
#[tracing::instrument(skip(self, state_lock), level = "trace")]
#[tracing::instrument(skip(self, state_lock, pdu_builder), level = "trace")]
pub async fn build_and_append_pdu(
&self,
pdu_builder: PduBuilder,
@ -99,16 +98,11 @@ pub async fn build_and_append_pdu(
}
}
if *pdu.kind() == TimelineEventType::RoomCreate {
trace!("Running room create checks for room {room_id}");
let content: RoomCreateEventContent = pdu.get_content()?;
let room_features = RoomVersion::new(&content.room_version)?;
if room_features.room_ids_as_hashes {
// bootstrap shortid for room
self.services
.short
.get_or_create_shortroomid(&room_id)
.await;
}
trace!("Creating shortroomid for {room_id}");
self.services
.short
.get_or_create_shortroomid(&room_id)
.await;
}
// We append to state before appending the pdu, so we don't have a moment in
@ -116,6 +110,7 @@ pub async fn build_and_append_pdu(
// fail.
trace!("Appending {} state for room {room_id}", pdu.event_id());
let statehashid = self.services.state.append_to_state(&pdu, &room_id).await?;
trace!("State hash ID for {room_id}: {statehashid:?}");
trace!("Generating raw ID for PDU {}", pdu.event_id());
let pdu_id = self

View file

@ -57,18 +57,30 @@ pub async fn create_hash_and_sign_event(
timestamp,
} = pdu_builder;
// If there was no create event yet, assume we are creating a room
trace!(
"Creating event of type {} in room {}",
event_type,
room_id.as_ref().map_or("None", |id| id.as_str())
);
let room_version_id = match room_id {
| Some(room_id) => self
.services
.state
.get_room_version(room_id)
.await
.or_else(|_| from_evt(room_id.to_owned(), &event_type.clone(), &content.clone()))?,
| None => from_evt(
RoomId::new(self.services.globals.server_name()),
&event_type.clone(),
&content.clone(),
)?,
| Some(room_id) => {
trace!(%room_id, "Looking up existing room ID");
self.services
.state
.get_room_version(room_id)
.await
.or_else(|_| {
from_evt(room_id.to_owned(), &event_type.clone(), &content.clone())
})?
},
| None => {
trace!("No room ID, assuming room creation");
from_evt(
RoomId::new(self.services.globals.server_name()),
&event_type.clone(),
&content.clone(),
)?
},
};
let room_version = RoomVersion::new(&room_version_id).expect("room version is supported");