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:
parent
ff92573103
commit
35b7b45ea0
6 changed files with 73 additions and 44 deletions
|
@ -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(
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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!(
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue