|
|
|
@ -23,11 +23,16 @@ use ruma::{ |
|
|
|
}, |
|
|
|
}, |
|
|
|
int, |
|
|
|
int, |
|
|
|
serde::JsonObject, |
|
|
|
serde::JsonObject, |
|
|
|
CanonicalJsonObject, OwnedRoomAliasId, RoomAliasId, RoomId, |
|
|
|
CanonicalJsonObject, CanonicalJsonValue, OwnedRoomAliasId, OwnedUserId, RoomAliasId, RoomId, |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
use serde::Deserialize; |
|
|
|
use serde_json::{json, value::to_raw_value}; |
|
|
|
use serde_json::{json, value::to_raw_value}; |
|
|
|
use std::{cmp::max, collections::BTreeMap, sync::Arc}; |
|
|
|
use std::{ |
|
|
|
use tracing::{info, warn}; |
|
|
|
cmp::max, |
|
|
|
|
|
|
|
collections::{BTreeMap, HashSet}, |
|
|
|
|
|
|
|
sync::Arc, |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
use tracing::{error, info, warn}; |
|
|
|
|
|
|
|
|
|
|
|
/// # `POST /_matrix/client/r0/createRoom`
|
|
|
|
/// # `POST /_matrix/client/r0/createRoom`
|
|
|
|
///
|
|
|
|
///
|
|
|
|
@ -142,9 +147,33 @@ pub async fn create_room_route( |
|
|
|
.expect("Supported room version must have rules.") |
|
|
|
.expect("Supported room version must have rules.") |
|
|
|
.authorization; |
|
|
|
.authorization; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut users = BTreeMap::new(); |
|
|
|
|
|
|
|
if !rules.explicitly_privilege_room_creators { |
|
|
|
|
|
|
|
users.insert(sender_user.clone(), int!(100)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Figure out preset. We need it for preset specific events
|
|
|
|
|
|
|
|
let preset = body.preset.clone().unwrap_or(match &body.visibility { |
|
|
|
|
|
|
|
room::Visibility::Private => RoomPreset::PrivateChat, |
|
|
|
|
|
|
|
room::Visibility::Public => RoomPreset::PublicChat, |
|
|
|
|
|
|
|
_ => RoomPreset::PrivateChat, // Room visibility should not be custom
|
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut additional_creators: HashSet<OwnedUserId, _> = HashSet::new(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if preset == RoomPreset::TrustedPrivateChat { |
|
|
|
|
|
|
|
if rules.additional_room_creators { |
|
|
|
|
|
|
|
additional_creators.extend(body.invite.clone()) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
for invited_user in &body.invite { |
|
|
|
|
|
|
|
users.insert(invited_user.clone(), int!(100)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
let content = match &body.creation_content { |
|
|
|
let content = match &body.creation_content { |
|
|
|
Some(content) => { |
|
|
|
Some(raw_content) => { |
|
|
|
let mut content = content |
|
|
|
let mut content = raw_content |
|
|
|
.deserialize_as_unchecked::<CanonicalJsonObject>() |
|
|
|
.deserialize_as_unchecked::<CanonicalJsonObject>() |
|
|
|
.expect("Invalid creation content"); |
|
|
|
.expect("Invalid creation content"); |
|
|
|
|
|
|
|
|
|
|
|
@ -157,6 +186,27 @@ pub async fn create_room_route( |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if rules.additional_room_creators && !additional_creators.is_empty() { |
|
|
|
|
|
|
|
#[derive(Deserialize)] |
|
|
|
|
|
|
|
struct AdditionalCreators { |
|
|
|
|
|
|
|
additional_creators: Vec<OwnedUserId>, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if let Ok(AdditionalCreators { |
|
|
|
|
|
|
|
additional_creators: ac, |
|
|
|
|
|
|
|
}) = raw_content.deserialize_as_unchecked() |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
additional_creators.extend(ac); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
content.insert( |
|
|
|
|
|
|
|
"additional_creators".into(), |
|
|
|
|
|
|
|
json!(&additional_creators).try_into().map_err(|_| { |
|
|
|
|
|
|
|
Error::BadRequest(ErrorKind::BadJson, "Invalid additional creators") |
|
|
|
|
|
|
|
})?, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
content.insert( |
|
|
|
content.insert( |
|
|
|
"room_version".into(), |
|
|
|
"room_version".into(), |
|
|
|
json!(room_version.as_str()).try_into().map_err(|_| { |
|
|
|
json!(room_version.as_str()).try_into().map_err(|_| { |
|
|
|
@ -166,24 +216,22 @@ pub async fn create_room_route( |
|
|
|
content |
|
|
|
content |
|
|
|
} |
|
|
|
} |
|
|
|
None => { |
|
|
|
None => { |
|
|
|
let content = if rules.use_room_create_sender { |
|
|
|
let content = RoomCreateEventContent { |
|
|
|
RoomCreateEventContent::new_v11() |
|
|
|
additional_creators: additional_creators.into_iter().collect(), |
|
|
|
} else { |
|
|
|
room_version, |
|
|
|
RoomCreateEventContent::new_v1(sender_user.clone()) |
|
|
|
..if rules.use_room_create_sender { |
|
|
|
|
|
|
|
RoomCreateEventContent::new_v11() |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
RoomCreateEventContent::new_v1(sender_user.clone()) |
|
|
|
|
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
let mut content = serde_json::from_str::<CanonicalJsonObject>( |
|
|
|
|
|
|
|
|
|
|
|
serde_json::from_str::<CanonicalJsonObject>( |
|
|
|
to_raw_value(&content) |
|
|
|
to_raw_value(&content) |
|
|
|
.map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Invalid creation content"))? |
|
|
|
.map_err(|_| Error::BadRequest(ErrorKind::BadJson, "Invalid creation content"))? |
|
|
|
.get(), |
|
|
|
.get(), |
|
|
|
) |
|
|
|
) |
|
|
|
.unwrap(); |
|
|
|
.expect("room create event content created by us is valid") |
|
|
|
content.insert( |
|
|
|
|
|
|
|
"room_version".into(), |
|
|
|
|
|
|
|
json!(room_version.as_str()).try_into().map_err(|_| { |
|
|
|
|
|
|
|
Error::BadRequest(ErrorKind::BadJson, "Invalid creation content") |
|
|
|
|
|
|
|
})?, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
content |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
@ -250,26 +298,9 @@ pub async fn create_room_route( |
|
|
|
.await?; |
|
|
|
.await?; |
|
|
|
|
|
|
|
|
|
|
|
// 3. Power levels
|
|
|
|
// 3. Power levels
|
|
|
|
|
|
|
|
|
|
|
|
// Figure out preset. We need it for preset specific events
|
|
|
|
|
|
|
|
let preset = body.preset.clone().unwrap_or(match &body.visibility { |
|
|
|
|
|
|
|
room::Visibility::Private => RoomPreset::PrivateChat, |
|
|
|
|
|
|
|
room::Visibility::Public => RoomPreset::PublicChat, |
|
|
|
|
|
|
|
_ => RoomPreset::PrivateChat, // Room visibility should not be custom
|
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut users = BTreeMap::new(); |
|
|
|
|
|
|
|
users.insert(sender_user.clone(), int!(100)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if preset == RoomPreset::TrustedPrivateChat { |
|
|
|
|
|
|
|
for invite_ in &body.invite { |
|
|
|
|
|
|
|
users.insert(invite_.clone(), int!(100)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut power_levels_content = serde_json::to_value(RoomPowerLevelsEventContent { |
|
|
|
let mut power_levels_content = serde_json::to_value(RoomPowerLevelsEventContent { |
|
|
|
users, |
|
|
|
users, |
|
|
|
..Default::default() |
|
|
|
..RoomPowerLevelsEventContent::new(&rules) |
|
|
|
}) |
|
|
|
}) |
|
|
|
.expect("event is valid, we just created it"); |
|
|
|
.expect("event is valid, we just created it"); |
|
|
|
|
|
|
|
|
|
|
|
@ -587,7 +618,8 @@ pub async fn upgrade_room_route( |
|
|
|
let rules = body |
|
|
|
let rules = body |
|
|
|
.new_version |
|
|
|
.new_version |
|
|
|
.rules() |
|
|
|
.rules() |
|
|
|
.expect("Supported room version must have rules."); |
|
|
|
.expect("Supported room version must have rules.") |
|
|
|
|
|
|
|
.authorization; |
|
|
|
|
|
|
|
|
|
|
|
// Create a replacement room
|
|
|
|
// Create a replacement room
|
|
|
|
let replacement_room = RoomId::new(services().globals.server_name()); |
|
|
|
let replacement_room = RoomId::new(services().globals.server_name()); |
|
|
|
@ -663,7 +695,7 @@ pub async fn upgrade_room_route( |
|
|
|
)); |
|
|
|
)); |
|
|
|
|
|
|
|
|
|
|
|
// Send a m.room.create event containing a predecessor field and the applicable room_version
|
|
|
|
// Send a m.room.create event containing a predecessor field and the applicable room_version
|
|
|
|
if rules.authorization.use_room_create_sender { |
|
|
|
if rules.use_room_create_sender { |
|
|
|
create_event_content.remove("creator"); |
|
|
|
create_event_content.remove("creator"); |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
create_event_content.insert( |
|
|
|
create_event_content.insert( |
|
|
|
@ -674,6 +706,18 @@ pub async fn upgrade_room_route( |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if rules.additional_room_creators && !body.additional_creators.is_empty() { |
|
|
|
|
|
|
|
create_event_content.insert( |
|
|
|
|
|
|
|
"additional_creators".into(), |
|
|
|
|
|
|
|
json!(&body.additional_creators).try_into().map_err(|_| { |
|
|
|
|
|
|
|
Error::BadRequest( |
|
|
|
|
|
|
|
ErrorKind::BadJson, |
|
|
|
|
|
|
|
"Failed to convert provided additional additional creators to JSON", |
|
|
|
|
|
|
|
) |
|
|
|
|
|
|
|
})?, |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
create_event_content.insert( |
|
|
|
create_event_content.insert( |
|
|
|
"room_version".into(), |
|
|
|
"room_version".into(), |
|
|
|
json!(&body.new_version) |
|
|
|
json!(&body.new_version) |
|
|
|
@ -764,7 +808,7 @@ pub async fn upgrade_room_route( |
|
|
|
|
|
|
|
|
|
|
|
// Replicate transferable state events to the new room
|
|
|
|
// Replicate transferable state events to the new room
|
|
|
|
for event_type in transferable_state_events { |
|
|
|
for event_type in transferable_state_events { |
|
|
|
let event_content = |
|
|
|
let mut event_content = |
|
|
|
match services() |
|
|
|
match services() |
|
|
|
.rooms |
|
|
|
.rooms |
|
|
|
.state_accessor |
|
|
|
.state_accessor |
|
|
|
@ -774,6 +818,31 @@ pub async fn upgrade_room_route( |
|
|
|
None => continue, // Skipping missing events.
|
|
|
|
None => continue, // Skipping missing events.
|
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if event_type == StateEventType::RoomPowerLevels && rules.explicitly_privilege_room_creators |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
let mut pl_event_content: CanonicalJsonObject = |
|
|
|
|
|
|
|
serde_json::from_str(event_content.get()).map_err(|e| { |
|
|
|
|
|
|
|
error!( |
|
|
|
|
|
|
|
"Invalid m.room.power_levels event content in room {}: {e}", |
|
|
|
|
|
|
|
body.room_id |
|
|
|
|
|
|
|
); |
|
|
|
|
|
|
|
Error::BadDatabase("Invalid m.room.power_levels event content in room") |
|
|
|
|
|
|
|
})?; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if let Some(CanonicalJsonValue::Object(users)) = pl_event_content.get_mut("users") { |
|
|
|
|
|
|
|
users.remove(sender_user.as_str()); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if rules.additional_room_creators { |
|
|
|
|
|
|
|
for user in &body.additional_creators { |
|
|
|
|
|
|
|
users.remove(user.as_str()); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
event_content = to_raw_value(&pl_event_content) |
|
|
|
|
|
|
|
.expect("Must serialize, only changes made was removing keys") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
services() |
|
|
|
services() |
|
|
|
.rooms |
|
|
|
.rooms |
|
|
|
.timeline |
|
|
|
.timeline |
|
|
|
|