@@ -1,5 +1,5 @@
|
|||||||
array_width = 80
|
array_width = 80
|
||||||
chain_width = 60
|
chain_width = 50
|
||||||
comment_width = 80
|
comment_width = 80
|
||||||
condense_wildcard_suffixes = true
|
condense_wildcard_suffixes = true
|
||||||
style_edition = "2024"
|
style_edition = "2024"
|
||||||
|
|||||||
@@ -10,7 +10,12 @@ use crate::Context;
|
|||||||
#[implement(Context, params = "<'_>")]
|
#[implement(Context, params = "<'_>")]
|
||||||
pub(super) async fn check_all_users(&self) -> Result {
|
pub(super) async fn check_all_users(&self) -> Result {
|
||||||
let timer = tokio::time::Instant::now();
|
let timer = tokio::time::Instant::now();
|
||||||
let users = self.services.users.iter().collect::<Vec<_>>().await;
|
let users = self
|
||||||
|
.services
|
||||||
|
.users
|
||||||
|
.iter()
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.await;
|
||||||
let query_time = timer.elapsed();
|
let query_time = timer.elapsed();
|
||||||
|
|
||||||
let total = users.len();
|
let total = users.len();
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ impl Context<'_> {
|
|||||||
) -> impl Future<Output = Result> + Send + '_ + use<'_> {
|
) -> impl Future<Output = Result> + Send + '_ + use<'_> {
|
||||||
let buf = format!("{arguments}");
|
let buf = format!("{arguments}");
|
||||||
self.output.lock().then(async move |mut output| {
|
self.output.lock().then(async move |mut output| {
|
||||||
output.write_all(buf.as_bytes()).map_err(Into::into).await
|
output
|
||||||
|
.write_all(buf.as_bytes())
|
||||||
|
.map_err(Into::into)
|
||||||
|
.await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +36,10 @@ impl Context<'_> {
|
|||||||
s: &'a str,
|
s: &'a str,
|
||||||
) -> impl Future<Output = Result> + Send + 'a {
|
) -> impl Future<Output = Result> + Send + 'a {
|
||||||
self.output.lock().then(async move |mut output| {
|
self.output.lock().then(async move |mut output| {
|
||||||
output.write_all(s.as_bytes()).map_err(Into::into).await
|
output
|
||||||
|
.write_all(s.as_bytes())
|
||||||
|
.map_err(Into::into)
|
||||||
|
.await
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,13 @@ pub(super) async fn echo(&self, message: Vec<String>) -> Result {
|
|||||||
|
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn get_auth_chain(&self, event_id: OwnedEventId) -> Result {
|
pub(super) async fn get_auth_chain(&self, event_id: OwnedEventId) -> Result {
|
||||||
let Ok(event) = self.services.rooms.timeline.get_pdu_json(&event_id).await else {
|
let Ok(event) = self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.timeline
|
||||||
|
.get_pdu_json(&event_id)
|
||||||
|
.await
|
||||||
|
else {
|
||||||
return Err!("Event not found.");
|
return Err!("Event not found.");
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -103,7 +109,12 @@ pub(super) async fn get_pdu(&self, event_id: OwnedEventId) -> Result {
|
|||||||
|
|
||||||
if pdu_json.is_err() {
|
if pdu_json.is_err() {
|
||||||
outlier = true;
|
outlier = true;
|
||||||
pdu_json = self.services.rooms.timeline.get_pdu_json(&event_id).await;
|
pdu_json = self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.timeline
|
||||||
|
.get_pdu_json(&event_id)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
match pdu_json {
|
match pdu_json {
|
||||||
@@ -361,7 +372,11 @@ pub(super) async fn force_device_list_updates(&self) -> Result {
|
|||||||
self.services
|
self.services
|
||||||
.users
|
.users
|
||||||
.stream()
|
.stream()
|
||||||
.for_each(|user_id| self.services.users.mark_device_key_update(user_id))
|
.for_each(|user_id| {
|
||||||
|
self.services
|
||||||
|
.users
|
||||||
|
.mark_device_key_update(user_id)
|
||||||
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
write!(self, "Marked all devices for all users as having new keys to update").await
|
write!(self, "Marked all devices for all users as having new keys to update").await
|
||||||
@@ -407,7 +422,10 @@ pub(super) async fn change_log_level(&self, filter: Option<String>, reset: bool)
|
|||||||
.reload
|
.reload
|
||||||
.reload(&new_filter_layer, Some(handles))
|
.reload(&new_filter_layer, Some(handles))
|
||||||
{
|
{
|
||||||
| Ok(()) => return self.write_str("Successfully changed log level").await,
|
| Ok(()) =>
|
||||||
|
return self
|
||||||
|
.write_str("Successfully changed log level")
|
||||||
|
.await,
|
||||||
| Err(e) =>
|
| Err(e) =>
|
||||||
return Err!("Failed to modify and reload the global tracing log level: {e}"),
|
return Err!("Failed to modify and reload the global tracing log level: {e}"),
|
||||||
}
|
}
|
||||||
@@ -449,7 +467,12 @@ pub(super) async fn verify_json(&self) -> Result {
|
|||||||
let string = self.body[1..self.body.len().checked_sub(1).unwrap()].join("\n");
|
let string = self.body[1..self.body.len().checked_sub(1).unwrap()].join("\n");
|
||||||
match serde_json::from_str::<CanonicalJsonObject>(&string) {
|
match serde_json::from_str::<CanonicalJsonObject>(&string) {
|
||||||
| Err(e) => return Err!("Invalid json: {e}"),
|
| Err(e) => return Err!("Invalid json: {e}"),
|
||||||
| Ok(value) => match self.services.server_keys.verify_json(&value, None).await {
|
| Ok(value) => match self
|
||||||
|
.services
|
||||||
|
.server_keys
|
||||||
|
.verify_json(&value, None)
|
||||||
|
.await
|
||||||
|
{
|
||||||
| Err(e) => return Err!("Signature verification failed: {e}"),
|
| Err(e) => return Err!("Signature verification failed: {e}"),
|
||||||
| Ok(()) => write!(self, "Signature correct"),
|
| Ok(()) => write!(self, "Signature correct"),
|
||||||
},
|
},
|
||||||
@@ -461,10 +484,20 @@ pub(super) async fn verify_json(&self) -> Result {
|
|||||||
pub(super) async fn verify_pdu(&self, event_id: OwnedEventId) -> Result {
|
pub(super) async fn verify_pdu(&self, event_id: OwnedEventId) -> Result {
|
||||||
use ruma::signatures::Verified;
|
use ruma::signatures::Verified;
|
||||||
|
|
||||||
let mut event = self.services.rooms.timeline.get_pdu_json(&event_id).await?;
|
let mut event = self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.timeline
|
||||||
|
.get_pdu_json(&event_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
event.remove("event_id");
|
event.remove("event_id");
|
||||||
let msg = match self.services.server_keys.verify_event(&event, None).await {
|
let msg = match self
|
||||||
|
.services
|
||||||
|
.server_keys
|
||||||
|
.verify_event(&event, None)
|
||||||
|
.await
|
||||||
|
{
|
||||||
| Err(e) => return Err(e),
|
| Err(e) => return Err(e),
|
||||||
| Ok(Verified::Signatures) => "signatures OK, but content hash failed (redaction).",
|
| Ok(Verified::Signatures) => "signatures OK, but content hash failed (redaction).",
|
||||||
| Ok(Verified::All) => "signatures and hashes OK.",
|
| Ok(Verified::All) => "signatures and hashes OK.",
|
||||||
@@ -548,7 +581,12 @@ pub(super) async fn force_set_room_state_from_server(
|
|||||||
.await
|
.await
|
||||||
.map_err(|_| err!(Database("Failed to find the latest PDU in database")))?;
|
.map_err(|_| err!(Database("Failed to find the latest PDU in database")))?;
|
||||||
|
|
||||||
let room_version = self.services.rooms.state.get_room_version(&room_id).await?;
|
let room_version = self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.get_room_version(&room_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let mut state: HashMap<u64, OwnedEventId> = HashMap::new();
|
let mut state: HashMap<u64, OwnedEventId> = HashMap::new();
|
||||||
|
|
||||||
@@ -610,11 +648,14 @@ pub(super) async fn force_set_room_state_from_server(
|
|||||||
}
|
}
|
||||||
|
|
||||||
info!("Going through auth_chain response");
|
info!("Going through auth_chain response");
|
||||||
for result in remote_state_response.auth_chain.iter().map(|pdu| {
|
for result in remote_state_response
|
||||||
self.services
|
.auth_chain
|
||||||
.server_keys
|
.iter()
|
||||||
.validate_and_add_event_id(pdu, &room_version)
|
.map(|pdu| {
|
||||||
}) {
|
self.services
|
||||||
|
.server_keys
|
||||||
|
.validate_and_add_event_id(pdu, &room_version)
|
||||||
|
}) {
|
||||||
let Ok((event_id, value)) = result.await else {
|
let Ok((event_id, value)) = result.await else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
@@ -644,7 +685,13 @@ pub(super) async fn force_set_room_state_from_server(
|
|||||||
.save_state(room_id.clone().as_ref(), new_room_state)
|
.save_state(room_id.clone().as_ref(), new_room_state)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let state_lock = self.services.rooms.state.mutex.lock(&*room_id).await;
|
let state_lock = self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.mutex
|
||||||
|
.lock(&*room_id)
|
||||||
|
.await;
|
||||||
|
|
||||||
self.services
|
self.services
|
||||||
.rooms
|
.rooms
|
||||||
@@ -775,17 +822,22 @@ pub(super) async fn memory_stats(&self, opts: Option<String>) -> Result {
|
|||||||
#[cfg(tokio_unstable)]
|
#[cfg(tokio_unstable)]
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn runtime_metrics(&self) -> Result {
|
pub(super) async fn runtime_metrics(&self) -> Result {
|
||||||
let out = self.services.server.metrics.runtime_metrics().map_or_else(
|
let out = self
|
||||||
|| "Runtime metrics are not available.".to_owned(),
|
.services
|
||||||
|metrics| {
|
.server
|
||||||
format!(
|
.metrics
|
||||||
"```rs\nnum_workers: {}\nnum_alive_tasks: {}\nglobal_queue_depth: {}\n```",
|
.runtime_metrics()
|
||||||
metrics.num_workers(),
|
.map_or_else(
|
||||||
metrics.num_alive_tasks(),
|
|| "Runtime metrics are not available.".to_owned(),
|
||||||
metrics.global_queue_depth()
|
|metrics| {
|
||||||
)
|
format!(
|
||||||
},
|
"```rs\nnum_workers: {}\nnum_alive_tasks: {}\nglobal_queue_depth: {}\n```",
|
||||||
);
|
metrics.num_workers(),
|
||||||
|
metrics.num_alive_tasks(),
|
||||||
|
metrics.global_queue_depth()
|
||||||
|
)
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
self.write_str(&out).await
|
self.write_str(&out).await
|
||||||
}
|
}
|
||||||
@@ -800,10 +852,15 @@ pub(super) async fn runtime_metrics(&self) -> Result {
|
|||||||
#[cfg(tokio_unstable)]
|
#[cfg(tokio_unstable)]
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn runtime_interval(&self) -> Result {
|
pub(super) async fn runtime_interval(&self) -> Result {
|
||||||
let out = self.services.server.metrics.runtime_interval().map_or_else(
|
let out = self
|
||||||
|| "Runtime metrics are not available.".to_owned(),
|
.services
|
||||||
|metrics| format!("```rs\n{metrics:#?}\n```"),
|
.server
|
||||||
);
|
.metrics
|
||||||
|
.runtime_interval()
|
||||||
|
.map_or_else(
|
||||||
|
|| "Runtime metrics are not available.".to_owned(),
|
||||||
|
|metrics| format!("```rs\n{metrics:#?}\n```"),
|
||||||
|
);
|
||||||
|
|
||||||
self.write_str(&out).await
|
self.write_str(&out).await
|
||||||
}
|
}
|
||||||
@@ -871,7 +928,12 @@ pub(super) async fn database_stats(
|
|||||||
|
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn database_files(&self, map: Option<String>, level: Option<i32>) -> Result {
|
pub(super) async fn database_files(&self, map: Option<String>, level: Option<i32>) -> Result {
|
||||||
let mut files: Vec<_> = self.services.db.db.file_list().collect::<Result<_>>()?;
|
let mut files: Vec<_> = self
|
||||||
|
.services
|
||||||
|
.db
|
||||||
|
.db
|
||||||
|
.file_list()
|
||||||
|
.collect::<Result<_>>()?;
|
||||||
|
|
||||||
files.sort_by_key(|f| f.name.clone());
|
files.sort_by_key(|f| f.name.clone());
|
||||||
|
|
||||||
@@ -883,7 +945,11 @@ pub(super) async fn database_files(&self, map: Option<String>, level: Option<i32
|
|||||||
map.as_deref()
|
map.as_deref()
|
||||||
.is_none_or(|map| map == file.column_family_name)
|
.is_none_or(|map| map == file.column_family_name)
|
||||||
})
|
})
|
||||||
.filter(|file| level.as_ref().is_none_or(|&level| level == file.level))
|
.filter(|file| {
|
||||||
|
level
|
||||||
|
.as_ref()
|
||||||
|
.is_none_or(|&level| level == file.level)
|
||||||
|
})
|
||||||
.try_stream()
|
.try_stream()
|
||||||
.try_for_each(|file| {
|
.try_for_each(|file| {
|
||||||
writeln!(
|
writeln!(
|
||||||
|
|||||||
@@ -8,13 +8,19 @@ use crate::{admin_command, get_room_info};
|
|||||||
|
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn disable_room(&self, room_id: OwnedRoomId) -> Result {
|
pub(super) async fn disable_room(&self, room_id: OwnedRoomId) -> Result {
|
||||||
self.services.rooms.metadata.disable_room(&room_id, true);
|
self.services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.disable_room(&room_id, true);
|
||||||
self.write_str("Room disabled.").await
|
self.write_str("Room disabled.").await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn enable_room(&self, room_id: OwnedRoomId) -> Result {
|
pub(super) async fn enable_room(&self, room_id: OwnedRoomId) -> Result {
|
||||||
self.services.rooms.metadata.disable_room(&room_id, false);
|
self.services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.disable_room(&room_id, false);
|
||||||
self.write_str("Room enabled.").await
|
self.write_str("Room enabled.").await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,13 @@ pub(super) async fn delete(
|
|||||||
let mut mxc_urls = Vec::with_capacity(4);
|
let mut mxc_urls = Vec::with_capacity(4);
|
||||||
|
|
||||||
// parsing the PDU for any MXC URLs begins here
|
// parsing the PDU for any MXC URLs begins here
|
||||||
match self.services.rooms.timeline.get_pdu_json(&event_id).await {
|
match self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.timeline
|
||||||
|
.get_pdu_json(&event_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
| Ok(event_json) => {
|
| Ok(event_json) => {
|
||||||
if let Some(content_key) = event_json.get("content") {
|
if let Some(content_key) = event_json.get("content") {
|
||||||
debug!("Event ID has \"content\".");
|
debug!("Event ID has \"content\".");
|
||||||
@@ -255,7 +261,11 @@ pub(super) async fn delete_past_remote_media(
|
|||||||
pub(super) async fn delete_all_from_user(&self, username: String) -> Result {
|
pub(super) async fn delete_all_from_user(&self, username: String) -> Result {
|
||||||
let user_id = parse_local_user_id(self.services, &username)?;
|
let user_id = parse_local_user_id(self.services, &username)?;
|
||||||
|
|
||||||
let deleted_count = self.services.media.delete_from_user(&user_id).await?;
|
let deleted_count = self
|
||||||
|
.services
|
||||||
|
.media
|
||||||
|
.delete_from_user(&user_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
self.write_str(&format!("Deleted {deleted_count} total files.",))
|
self.write_str(&format!("Deleted {deleted_count} total files.",))
|
||||||
.await
|
.await
|
||||||
@@ -294,7 +304,10 @@ pub(super) async fn delete_all_from_server(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if mxc_server_name != server_name
|
if mxc_server_name != server_name
|
||||||
|| (self.services.globals.server_is_ours(mxc_server_name)
|
|| (self
|
||||||
|
.services
|
||||||
|
.globals
|
||||||
|
.server_is_ours(mxc_server_name)
|
||||||
&& !yes_i_want_to_delete_local_media)
|
&& !yes_i_want_to_delete_local_media)
|
||||||
{
|
{
|
||||||
trace!("skipping MXC URI {mxc}");
|
trace!("skipping MXC URI {mxc}");
|
||||||
@@ -323,7 +336,8 @@ pub(super) async fn get_file_info(&self, mxc: OwnedMxcUri) -> Result {
|
|||||||
let mxc: Mxc<'_> = mxc.as_str().try_into()?;
|
let mxc: Mxc<'_> = mxc.as_str().try_into()?;
|
||||||
let metadata = self.services.media.get_metadata(&mxc).await;
|
let metadata = self.services.media.get_metadata(&mxc).await;
|
||||||
|
|
||||||
self.write_str(&format!("```\n{metadata:#?}\n```")).await
|
self.write_str(&format!("```\n{metadata:#?}\n```"))
|
||||||
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
|
|||||||
@@ -69,7 +69,10 @@ async fn process_command(services: Arc<Services>, input: &CommandInput) -> Proce
|
|||||||
let (result, mut logs) = process(&context, command, &args).await;
|
let (result, mut logs) = process(&context, command, &args).await;
|
||||||
|
|
||||||
let output = &mut context.output.lock().await;
|
let output = &mut context.output.lock().await;
|
||||||
output.flush().await.expect("final flush of output stream");
|
output
|
||||||
|
.flush()
|
||||||
|
.await
|
||||||
|
.expect("final flush of output stream");
|
||||||
|
|
||||||
let output =
|
let output =
|
||||||
String::from_utf8(take(output.get_mut())).expect("invalid utf8 in command output stream");
|
String::from_utf8(take(output.get_mut())).expect("invalid utf8 in command output stream");
|
||||||
@@ -79,7 +82,8 @@ async fn process_command(services: Arc<Services>, input: &CommandInput) -> Proce
|
|||||||
Ok(Some(reply(RoomMessageEventContent::notice_markdown(output), context.reply_id))),
|
Ok(Some(reply(RoomMessageEventContent::notice_markdown(output), context.reply_id))),
|
||||||
|
|
||||||
| Ok(()) => {
|
| Ok(()) => {
|
||||||
logs.write_str(output.as_str()).expect("output buffer");
|
logs.write_str(output.as_str())
|
||||||
|
.expect("output buffer");
|
||||||
Ok(Some(reply(RoomMessageEventContent::notice_markdown(logs), context.reply_id)))
|
Ok(Some(reply(RoomMessageEventContent::notice_markdown(logs), context.reply_id)))
|
||||||
},
|
},
|
||||||
| Err(error) => {
|
| Err(error) => {
|
||||||
@@ -172,8 +176,14 @@ fn parse<'a>(
|
|||||||
services: &Arc<Services>,
|
services: &Arc<Services>,
|
||||||
input: &'a CommandInput,
|
input: &'a CommandInput,
|
||||||
) -> Result<(AdminCommand, Vec<String>, Vec<&'a str>), CommandOutput> {
|
) -> Result<(AdminCommand, Vec<String>, Vec<&'a str>), CommandOutput> {
|
||||||
let lines = input.command.lines().filter(|line| !line.trim().is_empty());
|
let lines = input
|
||||||
let command_line = lines.clone().next().expect("command missing first line");
|
.command
|
||||||
|
.lines()
|
||||||
|
.filter(|line| !line.trim().is_empty());
|
||||||
|
let command_line = lines
|
||||||
|
.clone()
|
||||||
|
.next()
|
||||||
|
.expect("command missing first line");
|
||||||
let body = lines.skip(1).collect();
|
let body = lines.skip(1).collect();
|
||||||
match parse_command(command_line) {
|
match parse_command(command_line) {
|
||||||
| Ok((command, args)) => Ok((command, args, body)),
|
| Ok((command, args)) => Ok((command, args, body)),
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ pub(super) async fn process(subcommand: AppserviceCommand, context: &Context<'_>
|
|||||||
match subcommand {
|
match subcommand {
|
||||||
| AppserviceCommand::GetRegistration { appservice_id } => {
|
| AppserviceCommand::GetRegistration { appservice_id } => {
|
||||||
let timer = tokio::time::Instant::now();
|
let timer = tokio::time::Instant::now();
|
||||||
let results = services.appservice.get_registration(&appservice_id).await;
|
let results = services
|
||||||
|
.appservice
|
||||||
|
.get_registration(&appservice_id)
|
||||||
|
.await;
|
||||||
|
|
||||||
let query_time = timer.elapsed();
|
let query_time = timer.elapsed();
|
||||||
|
|
||||||
@@ -32,7 +35,11 @@ pub(super) async fn process(subcommand: AppserviceCommand, context: &Context<'_>
|
|||||||
},
|
},
|
||||||
| AppserviceCommand::All => {
|
| AppserviceCommand::All => {
|
||||||
let timer = tokio::time::Instant::now();
|
let timer = tokio::time::Instant::now();
|
||||||
let results: Vec<_> = services.appservice.iter_db_ids().try_collect().await?;
|
let results: Vec<_> = services
|
||||||
|
.appservice
|
||||||
|
.iter_db_ids()
|
||||||
|
.try_collect()
|
||||||
|
.await?;
|
||||||
let query_time = timer.elapsed();
|
let query_time = timer.elapsed();
|
||||||
|
|
||||||
write!(context, "Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```")
|
write!(context, "Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```")
|
||||||
|
|||||||
@@ -39,7 +39,10 @@ pub(super) async fn process(subcommand: GlobalsCommand, context: &Context<'_>) -
|
|||||||
},
|
},
|
||||||
| GlobalsCommand::SigningKeysFor { origin } => {
|
| GlobalsCommand::SigningKeysFor { origin } => {
|
||||||
let timer = tokio::time::Instant::now();
|
let timer = tokio::time::Instant::now();
|
||||||
let results = services.server_keys.verify_keys_for(&origin).await;
|
let results = services
|
||||||
|
.server_keys
|
||||||
|
.verify_keys_for(&origin)
|
||||||
|
.await;
|
||||||
let query_time = timer.elapsed();
|
let query_time = timer.elapsed();
|
||||||
|
|
||||||
write!(context, "Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```")
|
write!(context, "Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```")
|
||||||
|
|||||||
@@ -194,8 +194,13 @@ pub(super) async fn compact(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let range = (
|
let range = (
|
||||||
start.as_ref().map(String::as_bytes).map(Into::into),
|
start
|
||||||
stop.as_ref().map(String::as_bytes).map(Into::into),
|
.as_ref()
|
||||||
|
.map(String::as_bytes)
|
||||||
|
.map(Into::into),
|
||||||
|
stop.as_ref()
|
||||||
|
.map(String::as_bytes)
|
||||||
|
.map(Into::into),
|
||||||
);
|
);
|
||||||
|
|
||||||
let options = Options {
|
let options = Options {
|
||||||
@@ -429,7 +434,13 @@ pub(super) async fn raw_get(&self, map: String, key: String) -> Result {
|
|||||||
|
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn raw_maps(&self) -> Result {
|
pub(super) async fn raw_maps(&self) -> Result {
|
||||||
let list: Vec<_> = self.services.db.iter().map(at!(0)).copied().collect();
|
let list: Vec<_> = self
|
||||||
|
.services
|
||||||
|
.db
|
||||||
|
.iter()
|
||||||
|
.map(at!(0))
|
||||||
|
.copied()
|
||||||
|
.collect();
|
||||||
|
|
||||||
self.write_str(&format!("{list:#?}")).await
|
self.write_str(&format!("{list:#?}")).await
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,12 @@ async fn destinations_cache(&self, server_name: Option<OwnedServerName>) -> Resu
|
|||||||
writeln!(self, "| Server Name | Destination | Hostname | Expires |").await?;
|
writeln!(self, "| Server Name | Destination | Hostname | Expires |").await?;
|
||||||
writeln!(self, "| ----------- | ----------- | -------- | ------- |").await?;
|
writeln!(self, "| ----------- | ----------- | -------- | ------- |").await?;
|
||||||
|
|
||||||
let mut destinations = self.services.resolver.cache.destinations().boxed();
|
let mut destinations = self
|
||||||
|
.services
|
||||||
|
.resolver
|
||||||
|
.cache
|
||||||
|
.destinations()
|
||||||
|
.boxed();
|
||||||
|
|
||||||
while let Some((name, CachedDest { dest, host, expire })) = destinations.next().await {
|
while let Some((name, CachedDest { dest, host, expire })) = destinations.next().await {
|
||||||
if let Some(server_name) = server_name.as_ref() {
|
if let Some(server_name) = server_name.as_ref() {
|
||||||
|
|||||||
@@ -30,7 +30,11 @@ pub(super) async fn process(subcommand: RoomAliasCommand, context: &Context<'_>)
|
|||||||
match subcommand {
|
match subcommand {
|
||||||
| RoomAliasCommand::ResolveLocalAlias { alias } => {
|
| RoomAliasCommand::ResolveLocalAlias { alias } => {
|
||||||
let timer = tokio::time::Instant::now();
|
let timer = tokio::time::Instant::now();
|
||||||
let results = services.rooms.alias.resolve_local_alias(&alias).await;
|
let results = services
|
||||||
|
.rooms
|
||||||
|
.alias
|
||||||
|
.resolve_local_alias(&alias)
|
||||||
|
.await;
|
||||||
let query_time = timer.elapsed();
|
let query_time = timer.elapsed();
|
||||||
|
|
||||||
write!(context, "Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```")
|
write!(context, "Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```")
|
||||||
|
|||||||
@@ -182,7 +182,11 @@ pub(super) async fn process(subcommand: RoomStateCacheCommand, context: &Context
|
|||||||
},
|
},
|
||||||
| RoomStateCacheCommand::RoomJoinedCount { room_id } => {
|
| RoomStateCacheCommand::RoomJoinedCount { room_id } => {
|
||||||
let timer = tokio::time::Instant::now();
|
let timer = tokio::time::Instant::now();
|
||||||
let results = services.rooms.state_cache.room_joined_count(&room_id).await;
|
let results = services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.room_joined_count(&room_id)
|
||||||
|
.await;
|
||||||
let query_time = timer.elapsed();
|
let query_time = timer.elapsed();
|
||||||
|
|
||||||
context
|
context
|
||||||
|
|||||||
@@ -25,7 +25,12 @@ pub(crate) enum RoomTimelineCommand {
|
|||||||
|
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn last(&self, room_id: OwnedRoomOrAliasId) -> Result {
|
pub(super) async fn last(&self, room_id: OwnedRoomOrAliasId) -> Result {
|
||||||
let room_id = self.services.rooms.alias.resolve(&room_id).await?;
|
let room_id = self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.alias
|
||||||
|
.resolve(&room_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let result = self
|
let result = self
|
||||||
.services
|
.services
|
||||||
@@ -44,7 +49,12 @@ pub(super) async fn pdus(
|
|||||||
from: Option<String>,
|
from: Option<String>,
|
||||||
limit: Option<usize>,
|
limit: Option<usize>,
|
||||||
) -> Result {
|
) -> Result {
|
||||||
let room_id = self.services.rooms.alias.resolve(&room_id).await?;
|
let room_id = self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.alias
|
||||||
|
.resolve(&room_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let from: Option<PduCount> = from.as_deref().map(str::parse).transpose()?;
|
let from: Option<PduCount> = from.as_deref().map(str::parse).transpose()?;
|
||||||
|
|
||||||
|
|||||||
@@ -223,7 +223,11 @@ pub(super) async fn process(subcommand: SendingCommand, context: &Context<'_>) -
|
|||||||
},
|
},
|
||||||
| SendingCommand::GetLatestEduCount { server_name } => {
|
| SendingCommand::GetLatestEduCount { server_name } => {
|
||||||
let timer = tokio::time::Instant::now();
|
let timer = tokio::time::Instant::now();
|
||||||
let results = services.sending.db.get_latest_educount(&server_name).await;
|
let results = services
|
||||||
|
.sending
|
||||||
|
.db
|
||||||
|
.get_latest_educount(&server_name)
|
||||||
|
.await;
|
||||||
let query_time = timer.elapsed();
|
let query_time = timer.elapsed();
|
||||||
|
|
||||||
context
|
context
|
||||||
|
|||||||
@@ -31,9 +31,19 @@ pub(super) async fn short_event_id(&self, event_id: OwnedEventId) -> Result {
|
|||||||
|
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn short_room_id(&self, room_id: OwnedRoomOrAliasId) -> Result {
|
pub(super) async fn short_room_id(&self, room_id: OwnedRoomOrAliasId) -> Result {
|
||||||
let room_id = self.services.rooms.alias.resolve(&room_id).await?;
|
let room_id = self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.alias
|
||||||
|
.resolve(&room_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let shortid = self.services.rooms.short.get_shortroomid(&room_id).await?;
|
let shortid = self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.short
|
||||||
|
.get_shortroomid(&room_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
self.write_str(&format!("{shortid:#?}")).await
|
self.write_str(&format!("{shortid:#?}")).await
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -155,7 +155,11 @@ async fn get_room_backups(
|
|||||||
#[admin_command]
|
#[admin_command]
|
||||||
async fn get_all_backups(&self, user_id: OwnedUserId, version: String) -> Result {
|
async fn get_all_backups(&self, user_id: OwnedUserId, version: String) -> Result {
|
||||||
let timer = tokio::time::Instant::now();
|
let timer = tokio::time::Instant::now();
|
||||||
let result = self.services.key_backups.get_all(&user_id, &version).await;
|
let result = self
|
||||||
|
.services
|
||||||
|
.key_backups
|
||||||
|
.get_all(&user_id, &version)
|
||||||
|
.await;
|
||||||
let query_time = timer.elapsed();
|
let query_time = timer.elapsed();
|
||||||
|
|
||||||
self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
|
self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
|
||||||
@@ -193,7 +197,11 @@ async fn get_latest_backup_version(&self, user_id: OwnedUserId) -> Result {
|
|||||||
#[admin_command]
|
#[admin_command]
|
||||||
async fn get_latest_backup(&self, user_id: OwnedUserId) -> Result {
|
async fn get_latest_backup(&self, user_id: OwnedUserId) -> Result {
|
||||||
let timer = tokio::time::Instant::now();
|
let timer = tokio::time::Instant::now();
|
||||||
let result = self.services.key_backups.get_latest_backup(&user_id).await;
|
let result = self
|
||||||
|
.services
|
||||||
|
.key_backups
|
||||||
|
.get_latest_backup(&user_id)
|
||||||
|
.await;
|
||||||
let query_time = timer.elapsed();
|
let query_time = timer.elapsed();
|
||||||
|
|
||||||
self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
|
self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
|
||||||
@@ -203,7 +211,13 @@ async fn get_latest_backup(&self, user_id: OwnedUserId) -> Result {
|
|||||||
#[admin_command]
|
#[admin_command]
|
||||||
async fn iter_users(&self) -> Result {
|
async fn iter_users(&self) -> Result {
|
||||||
let timer = tokio::time::Instant::now();
|
let timer = tokio::time::Instant::now();
|
||||||
let result: Vec<OwnedUserId> = self.services.users.stream().map(Into::into).collect().await;
|
let result: Vec<OwnedUserId> = self
|
||||||
|
.services
|
||||||
|
.users
|
||||||
|
.stream()
|
||||||
|
.map(Into::into)
|
||||||
|
.collect()
|
||||||
|
.await;
|
||||||
|
|
||||||
let query_time = timer.elapsed();
|
let query_time = timer.elapsed();
|
||||||
|
|
||||||
@@ -296,7 +310,11 @@ async fn get_device_metadata(&self, user_id: OwnedUserId, device_id: OwnedDevice
|
|||||||
#[admin_command]
|
#[admin_command]
|
||||||
async fn get_devices_version(&self, user_id: OwnedUserId) -> Result {
|
async fn get_devices_version(&self, user_id: OwnedUserId) -> Result {
|
||||||
let timer = tokio::time::Instant::now();
|
let timer = tokio::time::Instant::now();
|
||||||
let device = self.services.users.get_devicelist_version(&user_id).await;
|
let device = self
|
||||||
|
.services
|
||||||
|
.users
|
||||||
|
.get_devicelist_version(&user_id)
|
||||||
|
.await;
|
||||||
let query_time = timer.elapsed();
|
let query_time = timer.elapsed();
|
||||||
|
|
||||||
self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{device:#?}\n```"))
|
self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{device:#?}\n```"))
|
||||||
@@ -334,7 +352,11 @@ async fn get_device_keys(&self, user_id: OwnedUserId, device_id: OwnedDeviceId)
|
|||||||
#[admin_command]
|
#[admin_command]
|
||||||
async fn get_user_signing_key(&self, user_id: OwnedUserId) -> Result {
|
async fn get_user_signing_key(&self, user_id: OwnedUserId) -> Result {
|
||||||
let timer = tokio::time::Instant::now();
|
let timer = tokio::time::Instant::now();
|
||||||
let result = self.services.users.get_user_signing_key(&user_id).await;
|
let result = self
|
||||||
|
.services
|
||||||
|
.users
|
||||||
|
.get_user_signing_key(&user_id)
|
||||||
|
.await;
|
||||||
let query_time = timer.elapsed();
|
let query_time = timer.elapsed();
|
||||||
|
|
||||||
self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
|
self.write_str(&format!("Query completed in {query_time:?}:\n\n```rs\n{result:#?}\n```"))
|
||||||
|
|||||||
@@ -60,7 +60,14 @@ pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) ->
|
|||||||
};
|
};
|
||||||
match command {
|
match command {
|
||||||
| RoomAliasCommand::Set { force, room_id, .. } => {
|
| RoomAliasCommand::Set { force, room_id, .. } => {
|
||||||
match (force, services.rooms.alias.resolve_local_alias(&room_alias).await) {
|
match (
|
||||||
|
force,
|
||||||
|
services
|
||||||
|
.rooms
|
||||||
|
.alias
|
||||||
|
.resolve_local_alias(&room_alias)
|
||||||
|
.await,
|
||||||
|
) {
|
||||||
| (true, Ok(id)) => {
|
| (true, Ok(id)) => {
|
||||||
match services.rooms.alias.set_alias(
|
match services.rooms.alias.set_alias(
|
||||||
&room_alias,
|
&room_alias,
|
||||||
@@ -93,7 +100,12 @@ pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) ->
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
| RoomAliasCommand::Remove { .. } => {
|
| RoomAliasCommand::Remove { .. } => {
|
||||||
match services.rooms.alias.resolve_local_alias(&room_alias).await {
|
match services
|
||||||
|
.rooms
|
||||||
|
.alias
|
||||||
|
.resolve_local_alias(&room_alias)
|
||||||
|
.await
|
||||||
|
{
|
||||||
| Err(_) => Err!("Alias isn't in use."),
|
| Err(_) => Err!("Alias isn't in use."),
|
||||||
| Ok(id) => match services
|
| Ok(id) => match services
|
||||||
.rooms
|
.rooms
|
||||||
@@ -103,14 +115,24 @@ pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) ->
|
|||||||
{
|
{
|
||||||
| Err(err) => Err!("Failed to remove alias: {err}"),
|
| Err(err) => Err!("Failed to remove alias: {err}"),
|
||||||
| Ok(()) =>
|
| Ok(()) =>
|
||||||
context.write_str(&format!("Removed alias from {id}")).await,
|
context
|
||||||
|
.write_str(&format!("Removed alias from {id}"))
|
||||||
|
.await,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
| RoomAliasCommand::Which { .. } => {
|
| RoomAliasCommand::Which { .. } => {
|
||||||
match services.rooms.alias.resolve_local_alias(&room_alias).await {
|
match services
|
||||||
|
.rooms
|
||||||
|
.alias
|
||||||
|
.resolve_local_alias(&room_alias)
|
||||||
|
.await
|
||||||
|
{
|
||||||
| Err(_) => Err!("Alias isn't in use."),
|
| Err(_) => Err!("Alias isn't in use."),
|
||||||
| Ok(id) => context.write_str(&format!("Alias resolves to {id}")).await,
|
| Ok(id) =>
|
||||||
|
context
|
||||||
|
.write_str(&format!("Alias resolves to {id}"))
|
||||||
|
.await,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
| RoomAliasCommand::List { .. } => unreachable!(),
|
| RoomAliasCommand::List { .. } => unreachable!(),
|
||||||
@@ -126,11 +148,13 @@ pub(super) async fn process(command: RoomAliasCommand, context: &Context<'_>) ->
|
|||||||
.collect()
|
.collect()
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let plain_list = aliases.iter().fold(String::new(), |mut output, alias| {
|
let plain_list = aliases
|
||||||
writeln!(output, "- {alias}")
|
.iter()
|
||||||
.expect("should be able to write to string buffer");
|
.fold(String::new(), |mut output, alias| {
|
||||||
output
|
writeln!(output, "- {alias}")
|
||||||
});
|
.expect("should be able to write to string buffer");
|
||||||
|
output
|
||||||
|
});
|
||||||
|
|
||||||
let plain = format!("Aliases for {room_id}:\n{plain_list}");
|
let plain = format!("Aliases for {room_id}:\n{plain_list}");
|
||||||
context.write_str(&plain).await
|
context.write_str(&plain).await
|
||||||
|
|||||||
@@ -20,11 +20,23 @@ pub(super) async fn list_rooms(
|
|||||||
.metadata
|
.metadata
|
||||||
.iter_ids()
|
.iter_ids()
|
||||||
.filter_map(|room_id| async move {
|
.filter_map(|room_id| async move {
|
||||||
(!exclude_disabled || !self.services.rooms.metadata.is_disabled(room_id).await)
|
(!exclude_disabled
|
||||||
|
|| !self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.is_disabled(room_id)
|
||||||
|
.await)
|
||||||
.then_some(room_id)
|
.then_some(room_id)
|
||||||
})
|
})
|
||||||
.filter_map(|room_id| async move {
|
.filter_map(|room_id| async move {
|
||||||
(!exclude_banned || !self.services.rooms.metadata.is_banned(room_id).await)
|
(!exclude_banned
|
||||||
|
|| !self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.is_banned(room_id)
|
||||||
|
.await)
|
||||||
.then_some(room_id)
|
.then_some(room_id)
|
||||||
})
|
})
|
||||||
.then(|room_id| get_room_info(self.services, room_id))
|
.then(|room_id| get_room_info(self.services, room_id))
|
||||||
@@ -62,7 +74,12 @@ pub(super) async fn list_rooms(
|
|||||||
|
|
||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn exists(&self, room_id: OwnedRoomId) -> Result {
|
pub(super) async fn exists(&self, room_id: OwnedRoomId) -> Result {
|
||||||
let result = self.services.rooms.metadata.exists(&room_id).await;
|
let result = self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.exists(&room_id)
|
||||||
|
.await;
|
||||||
|
|
||||||
self.write_str(&format!("{result}")).await
|
self.write_str(&format!("{result}")).await
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -70,7 +70,10 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
|||||||
};
|
};
|
||||||
|
|
||||||
debug!("Room specified is a room ID, banning room ID");
|
debug!("Room specified is a room ID, banning room ID");
|
||||||
self.services.rooms.metadata.ban_room(room_id, true);
|
self.services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.ban_room(room_id, true);
|
||||||
|
|
||||||
room_id.to_owned()
|
room_id.to_owned()
|
||||||
} else if room.is_room_alias_id() {
|
} else if room.is_room_alias_id() {
|
||||||
@@ -128,7 +131,10 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
self.services.rooms.metadata.ban_room(&room_id, true);
|
self.services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.ban_room(&room_id, true);
|
||||||
|
|
||||||
room_id
|
room_id
|
||||||
} else {
|
} else {
|
||||||
@@ -159,7 +165,10 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
|||||||
warn!("Failed to leave room: {e}");
|
warn!("Failed to leave room: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
self.services.rooms.state_cache.forget(&room_id, user_id);
|
self.services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.forget(&room_id, user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.services
|
self.services
|
||||||
@@ -178,9 +187,15 @@ async fn ban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
// unpublish from room directory
|
// unpublish from room directory
|
||||||
self.services.rooms.directory.set_not_public(&room_id);
|
self.services
|
||||||
|
.rooms
|
||||||
|
.directory
|
||||||
|
.set_not_public(&room_id);
|
||||||
|
|
||||||
self.services.rooms.metadata.disable_room(&room_id, true);
|
self.services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.disable_room(&room_id, true);
|
||||||
|
|
||||||
self.write_str(
|
self.write_str(
|
||||||
"Room banned, removed all our local users, and disabled incoming federation with room.",
|
"Room banned, removed all our local users, and disabled incoming federation with room.",
|
||||||
@@ -302,7 +317,10 @@ async fn ban_list_of_rooms(&self) -> Result {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for room_id in room_ids {
|
for room_id in room_ids {
|
||||||
self.services.rooms.metadata.ban_room(&room_id, true);
|
self.services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.ban_room(&room_id, true);
|
||||||
|
|
||||||
debug!("Banned {room_id} successfully");
|
debug!("Banned {room_id} successfully");
|
||||||
room_ban_count = room_ban_count.saturating_add(1);
|
room_ban_count = room_ban_count.saturating_add(1);
|
||||||
@@ -327,7 +345,10 @@ async fn ban_list_of_rooms(&self) -> Result {
|
|||||||
warn!("Failed to leave room: {e}");
|
warn!("Failed to leave room: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
self.services.rooms.state_cache.forget(&room_id, user_id);
|
self.services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.forget(&room_id, user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove any local aliases, ignore errors
|
// remove any local aliases, ignore errors
|
||||||
@@ -347,9 +368,15 @@ async fn ban_list_of_rooms(&self) -> Result {
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
// unpublish from room directory, ignore errors
|
// unpublish from room directory, ignore errors
|
||||||
self.services.rooms.directory.set_not_public(&room_id);
|
self.services
|
||||||
|
.rooms
|
||||||
|
.directory
|
||||||
|
.set_not_public(&room_id);
|
||||||
|
|
||||||
self.services.rooms.metadata.disable_room(&room_id, true);
|
self.services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.disable_room(&room_id, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.write_str(&format!(
|
self.write_str(&format!(
|
||||||
@@ -374,7 +401,10 @@ async fn unban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
|||||||
};
|
};
|
||||||
|
|
||||||
debug!("Room specified is a room ID, unbanning room ID");
|
debug!("Room specified is a room ID, unbanning room ID");
|
||||||
self.services.rooms.metadata.ban_room(room_id, false);
|
self.services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.ban_room(room_id, false);
|
||||||
|
|
||||||
room_id.to_owned()
|
room_id.to_owned()
|
||||||
} else if room.is_room_alias_id() {
|
} else if room.is_room_alias_id() {
|
||||||
@@ -430,7 +460,10 @@ async fn unban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
self.services.rooms.metadata.ban_room(&room_id, false);
|
self.services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.ban_room(&room_id, false);
|
||||||
|
|
||||||
room_id
|
room_id
|
||||||
} else {
|
} else {
|
||||||
@@ -441,7 +474,10 @@ async fn unban_room(&self, room: OwnedRoomOrAliasId) -> Result {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
self.services.rooms.metadata.disable_room(&room_id, false);
|
self.services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.disable_room(&room_id, false);
|
||||||
self.write_str("Room unbanned and federation re-enabled.")
|
self.write_str("Room unbanned and federation re-enabled.")
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,14 @@ pub(super) async fn create_user(&self, username: String, password: Option<String
|
|||||||
.new_user_displayname_suffix
|
.new_user_displayname_suffix
|
||||||
.is_empty()
|
.is_empty()
|
||||||
{
|
{
|
||||||
write!(displayname, " {}", self.services.server.config.new_user_displayname_suffix)?;
|
write!(
|
||||||
|
displayname,
|
||||||
|
" {}",
|
||||||
|
self.services
|
||||||
|
.server
|
||||||
|
.config
|
||||||
|
.new_user_displayname_suffix
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.services
|
self.services
|
||||||
@@ -106,7 +113,13 @@ pub(super) async fn create_user(&self, username: String, password: Option<String
|
|||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if !self.services.server.config.auto_join_rooms.is_empty() {
|
if !self
|
||||||
|
.services
|
||||||
|
.server
|
||||||
|
.config
|
||||||
|
.auto_join_rooms
|
||||||
|
.is_empty()
|
||||||
|
{
|
||||||
for room in &self.services.server.config.auto_join_rooms {
|
for room in &self.services.server.config.auto_join_rooms {
|
||||||
let Ok(room_id) = self.services.rooms.alias.resolve(room).await else {
|
let Ok(room_id) = self.services.rooms.alias.resolve(room).await else {
|
||||||
error!(
|
error!(
|
||||||
@@ -178,7 +191,10 @@ pub(super) async fn create_user(&self, username: String, password: Option<String
|
|||||||
.await
|
.await
|
||||||
.is_ok_and(is_equal_to!(1))
|
.is_ok_and(is_equal_to!(1))
|
||||||
{
|
{
|
||||||
self.services.admin.make_user_admin(&user_id).await?;
|
self.services
|
||||||
|
.admin
|
||||||
|
.make_user_admin(&user_id)
|
||||||
|
.await?;
|
||||||
warn!("Granting {user_id} admin privileges as the first user");
|
warn!("Granting {user_id} admin privileges as the first user");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -199,7 +215,10 @@ pub(super) async fn deactivate(&self, no_leave_rooms: bool, user_id: String) ->
|
|||||||
return Err!("Not allowed to deactivate the server service account.",);
|
return Err!("Not allowed to deactivate the server service account.",);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.services.users.deactivate_account(&user_id).await?;
|
self.services
|
||||||
|
.users
|
||||||
|
.deactivate_account(&user_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
if !no_leave_rooms {
|
if !no_leave_rooms {
|
||||||
self.services
|
self.services
|
||||||
@@ -312,7 +331,12 @@ pub(super) async fn deactivate_all(&self, no_leave_rooms: bool, force: bool) ->
|
|||||||
let mut deactivation_count: usize = 0;
|
let mut deactivation_count: usize = 0;
|
||||||
|
|
||||||
for user_id in user_ids {
|
for user_id in user_ids {
|
||||||
match self.services.users.deactivate_account(&user_id).await {
|
match self
|
||||||
|
.services
|
||||||
|
.users
|
||||||
|
.deactivate_account(&user_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
| Err(e) => {
|
| Err(e) => {
|
||||||
self.services
|
self.services
|
||||||
.admin
|
.admin
|
||||||
@@ -640,7 +664,12 @@ pub(super) async fn force_leave_room(
|
|||||||
room_id: OwnedRoomOrAliasId,
|
room_id: OwnedRoomOrAliasId,
|
||||||
) -> Result {
|
) -> Result {
|
||||||
let user_id = parse_local_user_id(self.services, &user_id)?;
|
let user_id = parse_local_user_id(self.services, &user_id)?;
|
||||||
let room_id = self.services.rooms.alias.resolve(&room_id).await?;
|
let room_id = self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.alias
|
||||||
|
.resolve(&room_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
self.services.globals.user_is_local(&user_id),
|
self.services.globals.user_is_local(&user_id),
|
||||||
@@ -666,14 +695,25 @@ pub(super) async fn force_leave_room(
|
|||||||
#[admin_command]
|
#[admin_command]
|
||||||
pub(super) async fn force_demote(&self, user_id: String, room_id: OwnedRoomOrAliasId) -> Result {
|
pub(super) async fn force_demote(&self, user_id: String, room_id: OwnedRoomOrAliasId) -> Result {
|
||||||
let user_id = parse_local_user_id(self.services, &user_id)?;
|
let user_id = parse_local_user_id(self.services, &user_id)?;
|
||||||
let room_id = self.services.rooms.alias.resolve(&room_id).await?;
|
let room_id = self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.alias
|
||||||
|
.resolve(&room_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
self.services.globals.user_is_local(&user_id),
|
self.services.globals.user_is_local(&user_id),
|
||||||
"Parsed user_id must be a local user"
|
"Parsed user_id must be a local user"
|
||||||
);
|
);
|
||||||
|
|
||||||
let state_lock = self.services.rooms.state.mutex.lock(&room_id).await;
|
let state_lock = self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.mutex
|
||||||
|
.lock(&room_id)
|
||||||
|
.await;
|
||||||
|
|
||||||
let room_power_levels: Option<RoomPowerLevelsEventContent> = self
|
let room_power_levels: Option<RoomPowerLevelsEventContent> = self
|
||||||
.services
|
.services
|
||||||
@@ -730,7 +770,10 @@ pub(super) async fn make_user_admin(&self, user_id: String) -> Result {
|
|||||||
"Parsed user_id must be a local user"
|
"Parsed user_id must be a local user"
|
||||||
);
|
);
|
||||||
|
|
||||||
self.services.admin.make_user_admin(&user_id).await?;
|
self.services
|
||||||
|
.admin
|
||||||
|
.make_user_admin(&user_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
self.write_str(&format!("{user_id} has been granted admin privileges.",))
|
self.write_str(&format!("{user_id} has been granted admin privileges.",))
|
||||||
.await
|
.await
|
||||||
@@ -793,7 +836,10 @@ pub(super) async fn delete_room_tag(
|
|||||||
content: TagEventContent { tags: BTreeMap::new() },
|
content: TagEventContent { tags: BTreeMap::new() },
|
||||||
});
|
});
|
||||||
|
|
||||||
tags_event.content.tags.remove(&tag.clone().into());
|
tags_event
|
||||||
|
.content
|
||||||
|
.tags
|
||||||
|
.remove(&tag.clone().into());
|
||||||
|
|
||||||
self.services
|
self.services
|
||||||
.account_data
|
.account_data
|
||||||
@@ -858,7 +904,13 @@ pub(super) async fn redact_event(&self, event_id: OwnedEventId) -> Result {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let redaction_event_id = {
|
let redaction_event_id = {
|
||||||
let state_lock = self.services.rooms.state.mutex.lock(&room_id).await;
|
let state_lock = self
|
||||||
|
.services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.mutex
|
||||||
|
.lock(&room_id)
|
||||||
|
.await;
|
||||||
|
|
||||||
self.services
|
self.services
|
||||||
.rooms
|
.rooms
|
||||||
|
|||||||
@@ -57,11 +57,20 @@ pub(crate) async fn get_register_available_route(
|
|||||||
body: Ruma<get_username_availability::v3::Request>,
|
body: Ruma<get_username_availability::v3::Request>,
|
||||||
) -> Result<get_username_availability::v3::Response> {
|
) -> Result<get_username_availability::v3::Response> {
|
||||||
// workaround for https://github.com/matrix-org/matrix-appservice-irc/issues/1780 due to inactivity of fixing the issue
|
// workaround for https://github.com/matrix-org/matrix-appservice-irc/issues/1780 due to inactivity of fixing the issue
|
||||||
let is_matrix_appservice_irc = body.appservice_info.as_ref().is_some_and(|appservice| {
|
let is_matrix_appservice_irc = body
|
||||||
appservice.registration.id == "irc"
|
.appservice_info
|
||||||
|| appservice.registration.id.contains("matrix-appservice-irc")
|
.as_ref()
|
||||||
|| appservice.registration.id.contains("matrix_appservice_irc")
|
.is_some_and(|appservice| {
|
||||||
});
|
appservice.registration.id == "irc"
|
||||||
|
|| appservice
|
||||||
|
.registration
|
||||||
|
.id
|
||||||
|
.contains("matrix-appservice-irc")
|
||||||
|
|| appservice
|
||||||
|
.registration
|
||||||
|
.id
|
||||||
|
.contains("matrix_appservice_irc")
|
||||||
|
});
|
||||||
|
|
||||||
if services
|
if services
|
||||||
.globals
|
.globals
|
||||||
@@ -114,7 +123,11 @@ pub(crate) async fn get_register_available_route(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if services.appservice.is_exclusive_user_id(&user_id).await {
|
if services
|
||||||
|
.appservice
|
||||||
|
.is_exclusive_user_id(&user_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
return Err!(Request(Exclusive("Username is reserved by an appservice.")));
|
return Err!(Request(Exclusive("Username is reserved by an appservice.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,7 +188,9 @@ pub(crate) async fn register_route(
|
|||||||
info!(
|
info!(
|
||||||
"Guest registration disabled / registration enabled with token configured, \
|
"Guest registration disabled / registration enabled with token configured, \
|
||||||
rejecting guest registration attempt, initial device name: \"{}\"",
|
rejecting guest registration attempt, initial device name: \"{}\"",
|
||||||
body.initial_device_display_name.as_deref().unwrap_or("")
|
body.initial_device_display_name
|
||||||
|
.as_deref()
|
||||||
|
.unwrap_or("")
|
||||||
);
|
);
|
||||||
return Err!(Request(GuestAccessForbidden("Guest registration is disabled.")));
|
return Err!(Request(GuestAccessForbidden("Guest registration is disabled.")));
|
||||||
}
|
}
|
||||||
@@ -186,7 +201,9 @@ pub(crate) async fn register_route(
|
|||||||
warn!(
|
warn!(
|
||||||
"Guest account attempted to register before a real admin user has been registered, \
|
"Guest account attempted to register before a real admin user has been registered, \
|
||||||
rejecting registration. Guest's initial device name: \"{}\"",
|
rejecting registration. Guest's initial device name: \"{}\"",
|
||||||
body.initial_device_display_name.as_deref().unwrap_or("")
|
body.initial_device_display_name
|
||||||
|
.as_deref()
|
||||||
|
.unwrap_or("")
|
||||||
);
|
);
|
||||||
return Err!(Request(Forbidden("Registration is temporarily disabled.")));
|
return Err!(Request(Forbidden("Registration is temporarily disabled.")));
|
||||||
}
|
}
|
||||||
@@ -195,13 +212,24 @@ pub(crate) async fn register_route(
|
|||||||
| (Some(username), false) => {
|
| (Some(username), false) => {
|
||||||
// workaround for https://github.com/matrix-org/matrix-appservice-irc/issues/1780 due to inactivity of fixing the issue
|
// workaround for https://github.com/matrix-org/matrix-appservice-irc/issues/1780 due to inactivity of fixing the issue
|
||||||
let is_matrix_appservice_irc =
|
let is_matrix_appservice_irc =
|
||||||
body.appservice_info.as_ref().is_some_and(|appservice| {
|
body.appservice_info
|
||||||
appservice.registration.id == "irc"
|
.as_ref()
|
||||||
|| appservice.registration.id.contains("matrix-appservice-irc")
|
.is_some_and(|appservice| {
|
||||||
|| appservice.registration.id.contains("matrix_appservice_irc")
|
appservice.registration.id == "irc"
|
||||||
});
|
|| appservice
|
||||||
|
.registration
|
||||||
|
.id
|
||||||
|
.contains("matrix-appservice-irc")
|
||||||
|
|| appservice
|
||||||
|
.registration
|
||||||
|
.id
|
||||||
|
.contains("matrix_appservice_irc")
|
||||||
|
});
|
||||||
|
|
||||||
if services.globals.forbidden_usernames().is_match(username)
|
if services
|
||||||
|
.globals
|
||||||
|
.forbidden_usernames()
|
||||||
|
.is_match(username)
|
||||||
&& !emergency_mode_enabled
|
&& !emergency_mode_enabled
|
||||||
{
|
{
|
||||||
return Err!(Request(Forbidden("Username is forbidden")));
|
return Err!(Request(Forbidden("Username is forbidden")));
|
||||||
@@ -270,7 +298,10 @@ pub(crate) async fn register_route(
|
|||||||
return Err!(Request(MissingToken("Missing appservice token.")));
|
return Err!(Request(MissingToken("Missing appservice token.")));
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
} else if services.appservice.is_exclusive_user_id(&user_id).await && !emergency_mode_enabled
|
} else if services
|
||||||
|
.appservice
|
||||||
|
.is_exclusive_user_id(&user_id)
|
||||||
|
.await && !emergency_mode_enabled
|
||||||
{
|
{
|
||||||
return Err!(Request(Exclusive("Username is reserved by an appservice.")));
|
return Err!(Request(Exclusive("Username is reserved by an appservice.")));
|
||||||
}
|
}
|
||||||
@@ -348,7 +379,10 @@ pub(crate) async fn register_route(
|
|||||||
|
|
||||||
// If `new_user_displayname_suffix` is set, registration will push whatever
|
// If `new_user_displayname_suffix` is set, registration will push whatever
|
||||||
// content is set to the user's display name with a space before it
|
// content is set to the user's display name with a space before it
|
||||||
if !services.globals.new_user_displayname_suffix().is_empty()
|
if !services
|
||||||
|
.globals
|
||||||
|
.new_user_displayname_suffix()
|
||||||
|
.is_empty()
|
||||||
&& body.appservice_info.is_none()
|
&& body.appservice_info.is_none()
|
||||||
{
|
{
|
||||||
write!(displayname, " {}", services.server.config.new_user_displayname_suffix)
|
write!(displayname, " {}", services.server.config.new_user_displayname_suffix)
|
||||||
@@ -365,7 +399,9 @@ pub(crate) async fn register_route(
|
|||||||
.update(
|
.update(
|
||||||
None,
|
None,
|
||||||
&user_id,
|
&user_id,
|
||||||
GlobalAccountDataEventType::PushRules.to_string().into(),
|
GlobalAccountDataEventType::PushRules
|
||||||
|
.to_string()
|
||||||
|
.into(),
|
||||||
&serde_json::to_value(ruma::events::push_rules::PushRulesEvent {
|
&serde_json::to_value(ruma::events::push_rules::PushRulesEvent {
|
||||||
content: ruma::events::push_rules::PushRulesEventContent {
|
content: ruma::events::push_rules::PushRulesEventContent {
|
||||||
global: push::Ruleset::server_default(&user_id),
|
global: push::Ruleset::server_default(&user_id),
|
||||||
@@ -411,7 +447,10 @@ pub(crate) async fn register_route(
|
|||||||
|
|
||||||
debug_info!(%user_id, %device_id, "User account was created");
|
debug_info!(%user_id, %device_id, "User account was created");
|
||||||
|
|
||||||
let device_display_name = body.initial_device_display_name.as_deref().unwrap_or("");
|
let device_display_name = body
|
||||||
|
.initial_device_display_name
|
||||||
|
.as_deref()
|
||||||
|
.unwrap_or("");
|
||||||
|
|
||||||
// log in conduit admin channel if a non-guest user registered
|
// log in conduit admin channel if a non-guest user registered
|
||||||
if body.appservice_info.is_none() && !is_guest {
|
if body.appservice_info.is_none() && !is_guest {
|
||||||
@@ -651,7 +690,10 @@ pub(crate) async fn change_password_route(
|
|||||||
.then_some(pushkey)
|
.then_some(pushkey)
|
||||||
})
|
})
|
||||||
.for_each(|pushkey| async move {
|
.for_each(|pushkey| async move {
|
||||||
services.pusher.delete_pusher(sender_user, &pushkey).await;
|
services
|
||||||
|
.pusher
|
||||||
|
.delete_pusher(sender_user, &pushkey)
|
||||||
|
.await;
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
@@ -680,7 +722,10 @@ pub(crate) async fn whoami_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<whoami::v3::Request>,
|
body: Ruma<whoami::v3::Request>,
|
||||||
) -> Result<whoami::v3::Response> {
|
) -> Result<whoami::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
let device_id = body.sender_device.clone();
|
let device_id = body.sender_device.clone();
|
||||||
|
|
||||||
Ok(whoami::v3::Response {
|
Ok(whoami::v3::Response {
|
||||||
@@ -790,7 +835,10 @@ pub(crate) async fn deactivate_route(
|
|||||||
pub(crate) async fn third_party_route(
|
pub(crate) async fn third_party_route(
|
||||||
body: Ruma<get_3pids::v3::Request>,
|
body: Ruma<get_3pids::v3::Request>,
|
||||||
) -> Result<get_3pids::v3::Response> {
|
) -> Result<get_3pids::v3::Response> {
|
||||||
let _sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let _sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
Ok(get_3pids::v3::Response::new(Vec::new()))
|
Ok(get_3pids::v3::Response::new(Vec::new()))
|
||||||
}
|
}
|
||||||
@@ -850,7 +898,11 @@ pub async fn full_user_deactivate(
|
|||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
all_joined_rooms: &[OwnedRoomId],
|
all_joined_rooms: &[OwnedRoomId],
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
services.users.deactivate_account(user_id).await.ok();
|
services
|
||||||
|
.users
|
||||||
|
.deactivate_account(user_id)
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
super::update_displayname(services, user_id, None, all_joined_rooms).await;
|
super::update_displayname(services, user_id, None, all_joined_rooms).await;
|
||||||
super::update_avatar_url(services, user_id, None, None, all_joined_rooms).await;
|
super::update_avatar_url(services, user_id, None, None, all_joined_rooms).await;
|
||||||
|
|
||||||
@@ -858,7 +910,9 @@ pub async fn full_user_deactivate(
|
|||||||
.users
|
.users
|
||||||
.all_profile_keys(user_id)
|
.all_profile_keys(user_id)
|
||||||
.ready_for_each(|(profile_key, _)| {
|
.ready_for_each(|(profile_key, _)| {
|
||||||
services.users.set_profile_key(user_id, &profile_key, None);
|
services
|
||||||
|
.users
|
||||||
|
.set_profile_key(user_id, &profile_key, None);
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,10 @@ pub(crate) async fn create_alias_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<create_alias::v3::Request>,
|
body: Ruma<create_alias::v3::Request>,
|
||||||
) -> Result<create_alias::v3::Response> {
|
) -> Result<create_alias::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
services
|
services
|
||||||
.rooms
|
.rooms
|
||||||
@@ -62,7 +65,10 @@ pub(crate) async fn delete_alias_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<delete_alias::v3::Request>,
|
body: Ruma<delete_alias::v3::Request>,
|
||||||
) -> Result<delete_alias::v3::Response> {
|
) -> Result<delete_alias::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
services
|
services
|
||||||
.rooms
|
.rooms
|
||||||
@@ -90,7 +96,11 @@ pub(crate) async fn get_alias_route(
|
|||||||
) -> Result<get_alias::v3::Response> {
|
) -> Result<get_alias::v3::Response> {
|
||||||
let room_alias = body.body.room_alias;
|
let room_alias = body.body.room_alias;
|
||||||
|
|
||||||
let Ok((room_id, servers)) = services.rooms.alias.resolve_alias(&room_alias, None).await
|
let Ok((room_id, servers)) = services
|
||||||
|
.rooms
|
||||||
|
.alias
|
||||||
|
.resolve_alias(&room_alias, None)
|
||||||
|
.await
|
||||||
else {
|
else {
|
||||||
return Err!(Request(NotFound("Room with alias not found.")));
|
return Err!(Request(NotFound("Room with alias not found.")));
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,7 +26,11 @@ pub(crate) async fn get_capabilities_route(
|
|||||||
|
|
||||||
let mut capabilities = Capabilities::default();
|
let mut capabilities = Capabilities::default();
|
||||||
capabilities.room_versions = RoomVersionsCapability {
|
capabilities.room_versions = RoomVersionsCapability {
|
||||||
default: services.server.config.default_room_version.clone(),
|
default: services
|
||||||
|
.server
|
||||||
|
.config
|
||||||
|
.default_room_version
|
||||||
|
.clone(),
|
||||||
available,
|
available,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,9 @@ pub(crate) async fn get_context_route(
|
|||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let (base_event, events_before, events_after): (_, Vec<_>, Vec<_>) =
|
let (base_event, events_before, events_after): (_, Vec<_>, Vec<_>) =
|
||||||
join3(base_event, events_before, events_after).boxed().await;
|
join3(base_event, events_before, events_after)
|
||||||
|
.boxed()
|
||||||
|
.await;
|
||||||
|
|
||||||
let lazy_loading_context = lazy_loading::Context {
|
let lazy_loading_context = lazy_loading::Context {
|
||||||
user_id: sender_user,
|
user_id: sender_user,
|
||||||
@@ -138,7 +140,12 @@ pub(crate) async fn get_context_route(
|
|||||||
.rooms
|
.rooms
|
||||||
.state_accessor
|
.state_accessor
|
||||||
.pdu_shortstatehash(state_at)
|
.pdu_shortstatehash(state_at)
|
||||||
.or_else(|_| services.rooms.state.get_room_shortstatehash(room_id))
|
.or_else(|_| {
|
||||||
|
services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.get_room_shortstatehash(room_id)
|
||||||
|
})
|
||||||
.map_ok(|shortstatehash| {
|
.map_ok(|shortstatehash| {
|
||||||
services
|
services
|
||||||
.rooms
|
.rooms
|
||||||
@@ -177,14 +184,20 @@ pub(crate) async fn get_context_route(
|
|||||||
Some(event_id)
|
Some(event_id)
|
||||||
})
|
})
|
||||||
.broad_filter_map(|event_id: &OwnedEventId| {
|
.broad_filter_map(|event_id: &OwnedEventId| {
|
||||||
services.rooms.timeline.get_pdu(event_id.as_ref()).ok()
|
services
|
||||||
|
.rooms
|
||||||
|
.timeline
|
||||||
|
.get_pdu(event_id.as_ref())
|
||||||
|
.ok()
|
||||||
})
|
})
|
||||||
.map(PduEvent::into_state_event)
|
.map(PduEvent::into_state_event)
|
||||||
.collect()
|
.collect()
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
Ok(get_context::v3::Response {
|
Ok(get_context::v3::Response {
|
||||||
event: base_event.map(at!(1)).map(PduEvent::into_room_event),
|
event: base_event
|
||||||
|
.map(at!(1))
|
||||||
|
.map(PduEvent::into_room_event),
|
||||||
|
|
||||||
start: events_before
|
start: events_before
|
||||||
.last()
|
.last()
|
||||||
|
|||||||
@@ -21,7 +21,10 @@ pub(crate) async fn get_devices_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<get_devices::v3::Request>,
|
body: Ruma<get_devices::v3::Request>,
|
||||||
) -> Result<get_devices::v3::Response> {
|
) -> Result<get_devices::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let devices: Vec<device::Device> = services
|
let devices: Vec<device::Device> = services
|
||||||
.users
|
.users
|
||||||
@@ -39,7 +42,10 @@ pub(crate) async fn get_device_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<get_device::v3::Request>,
|
body: Ruma<get_device::v3::Request>,
|
||||||
) -> Result<get_device::v3::Response> {
|
) -> Result<get_device::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let device = services
|
let device = services
|
||||||
.users
|
.users
|
||||||
@@ -69,7 +75,9 @@ pub(crate) async fn update_device_route(
|
|||||||
{
|
{
|
||||||
| Ok(mut device) => {
|
| Ok(mut device) => {
|
||||||
device.display_name.clone_from(&body.display_name);
|
device.display_name.clone_from(&body.display_name);
|
||||||
device.last_seen_ip.clone_from(&Some(client.to_string()));
|
device
|
||||||
|
.last_seen_ip
|
||||||
|
.clone_from(&Some(client.to_string()));
|
||||||
device
|
device
|
||||||
.last_seen_ts
|
.last_seen_ts
|
||||||
.clone_from(&Some(MilliSecondsSinceUnixEpoch::now()));
|
.clone_from(&Some(MilliSecondsSinceUnixEpoch::now()));
|
||||||
@@ -213,7 +221,10 @@ pub(crate) async fn delete_devices_route(
|
|||||||
enabled"
|
enabled"
|
||||||
);
|
);
|
||||||
for device_id in &body.devices {
|
for device_id in &body.devices {
|
||||||
services.users.remove_device(sender_user, device_id).await;
|
services
|
||||||
|
.users
|
||||||
|
.remove_device(sender_user, device_id)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(delete_devices::v3::Response {});
|
return Ok(delete_devices::v3::Response {});
|
||||||
@@ -256,7 +267,10 @@ pub(crate) async fn delete_devices_route(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for device_id in &body.devices {
|
for device_id in &body.devices {
|
||||||
services.users.remove_device(sender_user, device_id).await;
|
services
|
||||||
|
.users
|
||||||
|
.remove_device(sender_user, device_id)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(delete_devices::v3::Response {})
|
Ok(delete_devices::v3::Response {})
|
||||||
|
|||||||
@@ -137,7 +137,12 @@ pub(crate) async fn set_room_visibility_route(
|
|||||||
) -> Result<set_room_visibility::v3::Response> {
|
) -> Result<set_room_visibility::v3::Response> {
|
||||||
let sender_user = body.sender_user();
|
let sender_user = body.sender_user();
|
||||||
|
|
||||||
if !services.rooms.metadata.exists(&body.room_id).await {
|
if !services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.exists(&body.room_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
// Return 404 if the room doesn't exist
|
// Return 404 if the room doesn't exist
|
||||||
return Err!(Request(NotFound("Room not found")));
|
return Err!(Request(NotFound("Room not found")));
|
||||||
}
|
}
|
||||||
@@ -158,7 +163,10 @@ pub(crate) async fn set_room_visibility_route(
|
|||||||
|
|
||||||
match &body.visibility {
|
match &body.visibility {
|
||||||
| room::Visibility::Public => {
|
| room::Visibility::Public => {
|
||||||
if services.server.config.lockdown_public_room_directory
|
if services
|
||||||
|
.server
|
||||||
|
.config
|
||||||
|
.lockdown_public_room_directory
|
||||||
&& !services.users.is_admin(sender_user).await
|
&& !services.users.is_admin(sender_user).await
|
||||||
&& body.appservice_info.is_none()
|
&& body.appservice_info.is_none()
|
||||||
{
|
{
|
||||||
@@ -197,7 +205,10 @@ pub(crate) async fn set_room_visibility_route(
|
|||||||
}
|
}
|
||||||
info!("{sender_user} made {0} public to the room directory", body.room_id);
|
info!("{sender_user} made {0} public to the room directory", body.room_id);
|
||||||
},
|
},
|
||||||
| room::Visibility::Private => services.rooms.directory.set_not_public(&body.room_id),
|
| room::Visibility::Private => services
|
||||||
|
.rooms
|
||||||
|
.directory
|
||||||
|
.set_not_public(&body.room_id),
|
||||||
| _ => {
|
| _ => {
|
||||||
return Err!(Request(InvalidParam("Room visibility type is not supported.",)));
|
return Err!(Request(InvalidParam("Room visibility type is not supported.",)));
|
||||||
},
|
},
|
||||||
@@ -213,13 +224,23 @@ pub(crate) async fn get_room_visibility_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<get_room_visibility::v3::Request>,
|
body: Ruma<get_room_visibility::v3::Request>,
|
||||||
) -> Result<get_room_visibility::v3::Response> {
|
) -> Result<get_room_visibility::v3::Response> {
|
||||||
if !services.rooms.metadata.exists(&body.room_id).await {
|
if !services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.exists(&body.room_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
// Return 404 if the room doesn't exist
|
// Return 404 if the room doesn't exist
|
||||||
return Err!(Request(NotFound("Room not found")));
|
return Err!(Request(NotFound("Room not found")));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(get_room_visibility::v3::Response {
|
Ok(get_room_visibility::v3::Response {
|
||||||
visibility: if services.rooms.directory.is_public_room(&body.room_id).await {
|
visibility: if services
|
||||||
|
.rooms
|
||||||
|
.directory
|
||||||
|
.is_public_room(&body.room_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
room::Visibility::Public
|
room::Visibility::Public
|
||||||
} else {
|
} else {
|
||||||
room::Visibility::Private
|
room::Visibility::Private
|
||||||
@@ -332,9 +353,15 @@ pub(crate) async fn get_public_rooms_filtered_helper(
|
|||||||
.unwrap_or_else(|_| uint!(0))
|
.unwrap_or_else(|_| uint!(0))
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
let chunk: Vec<_> = all_rooms.into_iter().skip(num_since).take(limit).collect();
|
let chunk: Vec<_> = all_rooms
|
||||||
|
.into_iter()
|
||||||
|
.skip(num_since)
|
||||||
|
.take(limit)
|
||||||
|
.collect();
|
||||||
|
|
||||||
let prev_batch = num_since.ne(&0).then_some(format!("p{num_since}"));
|
let prev_batch = num_since
|
||||||
|
.ne(&0)
|
||||||
|
.then_some(format!("p{num_since}"));
|
||||||
|
|
||||||
let next_batch = chunk
|
let next_batch = chunk
|
||||||
.len()
|
.len()
|
||||||
@@ -383,9 +410,17 @@ async fn user_can_publish_room(
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn public_rooms_chunk(services: &Services, room_id: OwnedRoomId) -> PublicRoomsChunk {
|
async fn public_rooms_chunk(services: &Services, room_id: OwnedRoomId) -> PublicRoomsChunk {
|
||||||
let name = services.rooms.state_accessor.get_name(&room_id).ok();
|
let name = services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.get_name(&room_id)
|
||||||
|
.ok();
|
||||||
|
|
||||||
let room_type = services.rooms.state_accessor.get_room_type(&room_id).ok();
|
let room_type = services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.get_room_type(&room_id)
|
||||||
|
.ok();
|
||||||
|
|
||||||
let canonical_alias = services
|
let canonical_alias = services
|
||||||
.rooms
|
.rooms
|
||||||
@@ -395,9 +430,16 @@ async fn public_rooms_chunk(services: &Services, room_id: OwnedRoomId) -> Public
|
|||||||
|
|
||||||
let avatar_url = services.rooms.state_accessor.get_avatar(&room_id);
|
let avatar_url = services.rooms.state_accessor.get_avatar(&room_id);
|
||||||
|
|
||||||
let topic = services.rooms.state_accessor.get_room_topic(&room_id).ok();
|
let topic = services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.get_room_topic(&room_id)
|
||||||
|
.ok();
|
||||||
|
|
||||||
let world_readable = services.rooms.state_accessor.is_world_readable(&room_id);
|
let world_readable = services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.is_world_readable(&room_id);
|
||||||
|
|
||||||
let join_rule = services
|
let join_rule = services
|
||||||
.rooms
|
.rooms
|
||||||
@@ -410,9 +452,15 @@ async fn public_rooms_chunk(services: &Services, room_id: OwnedRoomId) -> Public
|
|||||||
| _ => "invite".into(),
|
| _ => "invite".into(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let guest_can_join = services.rooms.state_accessor.guest_can_join(&room_id);
|
let guest_can_join = services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.guest_can_join(&room_id);
|
||||||
|
|
||||||
let num_joined_members = services.rooms.state_cache.room_joined_count(&room_id);
|
let num_joined_members = services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.room_joined_count(&room_id);
|
||||||
|
|
||||||
let (
|
let (
|
||||||
(avatar_url, canonical_alias, guest_can_join, join_rule, name),
|
(avatar_url, canonical_alias, guest_can_join, join_rule, name),
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ pub(crate) async fn get_filter_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<get_filter::v3::Request>,
|
body: Ruma<get_filter::v3::Request>,
|
||||||
) -> Result<get_filter::v3::Response> {
|
) -> Result<get_filter::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
services
|
services
|
||||||
.users
|
.users
|
||||||
@@ -30,9 +33,14 @@ pub(crate) async fn create_filter_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<create_filter::v3::Request>,
|
body: Ruma<create_filter::v3::Request>,
|
||||||
) -> Result<create_filter::v3::Response> {
|
) -> Result<create_filter::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let filter_id = services.users.create_filter(sender_user, &body.filter);
|
let filter_id = services
|
||||||
|
.users
|
||||||
|
.create_filter(sender_user, &body.filter);
|
||||||
|
|
||||||
Ok(create_filter::v3::Response::new(filter_id))
|
Ok(create_filter::v3::Response::new(filter_id))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -126,7 +126,10 @@ pub(crate) async fn get_keys_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<get_keys::v3::Request>,
|
body: Ruma<get_keys::v3::Request>,
|
||||||
) -> Result<get_keys::v3::Response> {
|
) -> Result<get_keys::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
get_keys_helper(
|
get_keys_helper(
|
||||||
&services,
|
&services,
|
||||||
@@ -157,8 +160,14 @@ pub(crate) async fn upload_signing_keys_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<upload_signing_keys::v3::Request>,
|
body: Ruma<upload_signing_keys::v3::Request>,
|
||||||
) -> Result<upload_signing_keys::v3::Response> {
|
) -> Result<upload_signing_keys::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
let sender_device = body
|
||||||
|
.sender_device
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
// UIAA
|
// UIAA
|
||||||
let mut uiaainfo = UiaaInfo {
|
let mut uiaainfo = UiaaInfo {
|
||||||
@@ -373,7 +382,10 @@ pub(crate) async fn get_key_changes_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<get_key_changes::v3::Request>,
|
body: Ruma<get_key_changes::v3::Request>,
|
||||||
) -> Result<get_key_changes::v3::Response> {
|
) -> Result<get_key_changes::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let mut device_list_updates = HashSet::new();
|
let mut device_list_updates = HashSet::new();
|
||||||
|
|
||||||
@@ -396,7 +408,11 @@ pub(crate) async fn get_key_changes_route(
|
|||||||
.await,
|
.await,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut rooms_joined = services.rooms.state_cache.rooms_joined(sender_user).boxed();
|
let mut rooms_joined = services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.rooms_joined(sender_user)
|
||||||
|
.boxed();
|
||||||
|
|
||||||
while let Some(room_id) = rooms_joined.next().await {
|
while let Some(room_id) = rooms_joined.next().await {
|
||||||
device_list_updates.extend(
|
device_list_updates.extend(
|
||||||
@@ -449,7 +465,11 @@ where
|
|||||||
let mut devices = services.users.all_device_ids(user_id).boxed();
|
let mut devices = services.users.all_device_ids(user_id).boxed();
|
||||||
|
|
||||||
while let Some(device_id) = devices.next().await {
|
while let Some(device_id) = devices.next().await {
|
||||||
if let Ok(mut keys) = services.users.get_device_keys(user_id, device_id).await {
|
if let Ok(mut keys) = services
|
||||||
|
.users
|
||||||
|
.get_device_keys(user_id, device_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
let metadata = services
|
let metadata = services
|
||||||
.users
|
.users
|
||||||
.get_device_metadata(user_id, device_id)
|
.get_device_metadata(user_id, device_id)
|
||||||
@@ -469,7 +489,11 @@ where
|
|||||||
} else {
|
} else {
|
||||||
for device_id in device_ids {
|
for device_id in device_ids {
|
||||||
let mut container = BTreeMap::new();
|
let mut container = BTreeMap::new();
|
||||||
if let Ok(mut keys) = services.users.get_device_keys(user_id, device_id).await {
|
if let Ok(mut keys) = services
|
||||||
|
.users
|
||||||
|
.get_device_keys(user_id, device_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
let metadata = services
|
let metadata = services
|
||||||
.users
|
.users
|
||||||
.get_device_metadata(user_id, device_id)
|
.get_device_metadata(user_id, device_id)
|
||||||
@@ -545,7 +569,9 @@ where
|
|||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
let (_, mut our_master_key) = parse_master_key(&user, &our_master_key)?;
|
let (_, mut our_master_key) = parse_master_key(&user, &our_master_key)?;
|
||||||
master_key.signatures.append(&mut our_master_key.signatures);
|
master_key
|
||||||
|
.signatures
|
||||||
|
.append(&mut our_master_key.signatures);
|
||||||
}
|
}
|
||||||
let json = serde_json::to_value(master_key).expect("to_value always works");
|
let json = serde_json::to_value(master_key).expect("to_value always works");
|
||||||
let raw = serde_json::from_value(json).expect("Raw::from_value always works");
|
let raw = serde_json::from_value(json).expect("Raw::from_value always works");
|
||||||
@@ -588,7 +614,9 @@ fn add_unsigned_device_display_name(
|
|||||||
if let Some(display_name) = metadata.display_name {
|
if let Some(display_name) = metadata.display_name {
|
||||||
let mut object = keys.deserialize_as::<serde_json::Map<String, serde_json::Value>>()?;
|
let mut object = keys.deserialize_as::<serde_json::Map<String, serde_json::Value>>()?;
|
||||||
|
|
||||||
let unsigned = object.entry("unsigned").or_insert_with(|| json!({}));
|
let unsigned = object
|
||||||
|
.entry("unsigned")
|
||||||
|
.or_insert_with(|| json!({}));
|
||||||
if let serde_json::Value::Object(unsigned_object) = unsigned {
|
if let serde_json::Value::Object(unsigned_object) = unsigned {
|
||||||
if include_display_names {
|
if include_display_names {
|
||||||
unsigned_object.insert("device_display_name".to_owned(), display_name.into());
|
unsigned_object.insert("device_display_name".to_owned(), display_name.into());
|
||||||
|
|||||||
@@ -51,7 +51,10 @@ pub(crate) async fn create_content_route(
|
|||||||
InsecureClientIp(client): InsecureClientIp,
|
InsecureClientIp(client): InsecureClientIp,
|
||||||
body: Ruma<create_content::v3::Request>,
|
body: Ruma<create_content::v3::Request>,
|
||||||
) -> Result<create_content::v3::Response> {
|
) -> Result<create_content::v3::Response> {
|
||||||
let user = body.sender_user.as_ref().expect("user is authenticated");
|
let user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let filename = body.filename.as_deref();
|
let filename = body.filename.as_deref();
|
||||||
let content_type = body.content_type.as_deref();
|
let content_type = body.content_type.as_deref();
|
||||||
@@ -94,7 +97,10 @@ pub(crate) async fn get_content_thumbnail_route(
|
|||||||
InsecureClientIp(client): InsecureClientIp,
|
InsecureClientIp(client): InsecureClientIp,
|
||||||
body: Ruma<get_content_thumbnail::v1::Request>,
|
body: Ruma<get_content_thumbnail::v1::Request>,
|
||||||
) -> Result<get_content_thumbnail::v1::Response> {
|
) -> Result<get_content_thumbnail::v1::Response> {
|
||||||
let user = body.sender_user.as_ref().expect("user is authenticated");
|
let user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let dim = Dim::from_ruma(body.width, body.height, body.method.clone())?;
|
let dim = Dim::from_ruma(body.width, body.height, body.method.clone())?;
|
||||||
let mxc = Mxc {
|
let mxc = Mxc {
|
||||||
@@ -131,7 +137,10 @@ pub(crate) async fn get_content_route(
|
|||||||
InsecureClientIp(client): InsecureClientIp,
|
InsecureClientIp(client): InsecureClientIp,
|
||||||
body: Ruma<get_content::v1::Request>,
|
body: Ruma<get_content::v1::Request>,
|
||||||
) -> Result<get_content::v1::Response> {
|
) -> Result<get_content::v1::Response> {
|
||||||
let user = body.sender_user.as_ref().expect("user is authenticated");
|
let user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let mxc = Mxc {
|
let mxc = Mxc {
|
||||||
server_name: &body.server_name,
|
server_name: &body.server_name,
|
||||||
@@ -167,7 +176,10 @@ pub(crate) async fn get_content_as_filename_route(
|
|||||||
InsecureClientIp(client): InsecureClientIp,
|
InsecureClientIp(client): InsecureClientIp,
|
||||||
body: Ruma<get_content_as_filename::v1::Request>,
|
body: Ruma<get_content_as_filename::v1::Request>,
|
||||||
) -> Result<get_content_as_filename::v1::Response> {
|
) -> Result<get_content_as_filename::v1::Response> {
|
||||||
let user = body.sender_user.as_ref().expect("user is authenticated");
|
let user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let mxc = Mxc {
|
let mxc = Mxc {
|
||||||
server_name: &body.server_name,
|
server_name: &body.server_name,
|
||||||
@@ -203,7 +215,10 @@ pub(crate) async fn get_media_preview_route(
|
|||||||
InsecureClientIp(client): InsecureClientIp,
|
InsecureClientIp(client): InsecureClientIp,
|
||||||
body: Ruma<get_media_preview::v1::Request>,
|
body: Ruma<get_media_preview::v1::Request>,
|
||||||
) -> Result<get_media_preview::v1::Response> {
|
) -> Result<get_media_preview::v1::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let url = &body.url;
|
let url = &body.url;
|
||||||
let url = Url::parse(&body.url).map_err(|e| {
|
let url = Url::parse(&body.url).map_err(|e| {
|
||||||
|
|||||||
@@ -55,7 +55,10 @@ pub(crate) async fn get_media_preview_legacy_route(
|
|||||||
InsecureClientIp(client): InsecureClientIp,
|
InsecureClientIp(client): InsecureClientIp,
|
||||||
body: Ruma<get_media_preview::v3::Request>,
|
body: Ruma<get_media_preview::v3::Request>,
|
||||||
) -> Result<get_media_preview::v3::Response> {
|
) -> Result<get_media_preview::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let url = &body.url;
|
let url = &body.url;
|
||||||
let url = Url::parse(&body.url).map_err(|e| {
|
let url = Url::parse(&body.url).map_err(|e| {
|
||||||
@@ -70,11 +73,15 @@ pub(crate) async fn get_media_preview_legacy_route(
|
|||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let preview = services.media.get_url_preview(&url).await.map_err(|e| {
|
let preview = services
|
||||||
err!(Request(Unknown(
|
.media
|
||||||
debug_error!(%sender_user, %url, "Failed to fetch a URL preview: {e}")
|
.get_url_preview(&url)
|
||||||
)))
|
.await
|
||||||
})?;
|
.map_err(|e| {
|
||||||
|
err!(Request(Unknown(
|
||||||
|
debug_error!(%sender_user, %url, "Failed to fetch a URL preview: {e}")
|
||||||
|
)))
|
||||||
|
})?;
|
||||||
|
|
||||||
serde_json::value::to_raw_value(&preview)
|
serde_json::value::to_raw_value(&preview)
|
||||||
.map(get_media_preview::v3::Response::from_raw_value)
|
.map(get_media_preview::v3::Response::from_raw_value)
|
||||||
|
|||||||
@@ -85,14 +85,22 @@ async fn banned_room_check(
|
|||||||
|| services
|
|| services
|
||||||
.config
|
.config
|
||||||
.forbidden_remote_server_names
|
.forbidden_remote_server_names
|
||||||
.is_match(room_id.server_name().expect("legacy room mxid").host())
|
.is_match(
|
||||||
{
|
room_id
|
||||||
|
.server_name()
|
||||||
|
.expect("legacy room mxid")
|
||||||
|
.host(),
|
||||||
|
) {
|
||||||
warn!(
|
warn!(
|
||||||
"User {user_id} who is not an admin attempted to send an invite for or \
|
"User {user_id} who is not an admin attempted to send an invite for or \
|
||||||
attempted to join a banned room or banned room server name: {room_id}"
|
attempted to join a banned room or banned room server name: {room_id}"
|
||||||
);
|
);
|
||||||
|
|
||||||
if services.server.config.auto_deactivate_banned_room_attempts {
|
if services
|
||||||
|
.server
|
||||||
|
.config
|
||||||
|
.auto_deactivate_banned_room_attempts
|
||||||
|
{
|
||||||
warn!(
|
warn!(
|
||||||
"Automatically deactivating user {user_id} due to attempted banned room join"
|
"Automatically deactivating user {user_id} due to attempted banned room join"
|
||||||
);
|
);
|
||||||
@@ -131,7 +139,11 @@ async fn banned_room_check(
|
|||||||
name {server_name} that is globally forbidden. Rejecting.",
|
name {server_name} that is globally forbidden. Rejecting.",
|
||||||
);
|
);
|
||||||
|
|
||||||
if services.server.config.auto_deactivate_banned_room_attempts {
|
if services
|
||||||
|
.server
|
||||||
|
.config
|
||||||
|
.auto_deactivate_banned_room_attempts
|
||||||
|
{
|
||||||
warn!(
|
warn!(
|
||||||
"Automatically deactivating user {user_id} due to attempted banned room join"
|
"Automatically deactivating user {user_id} due to attempted banned room join"
|
||||||
);
|
);
|
||||||
@@ -247,7 +259,10 @@ pub(crate) async fn join_room_by_id_or_alias_route(
|
|||||||
InsecureClientIp(client): InsecureClientIp,
|
InsecureClientIp(client): InsecureClientIp,
|
||||||
body: Ruma<join_room_by_id_or_alias::v3::Request>,
|
body: Ruma<join_room_by_id_or_alias::v3::Request>,
|
||||||
) -> Result<join_room_by_id_or_alias::v3::Response> {
|
) -> Result<join_room_by_id_or_alias::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_deref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_deref()
|
||||||
|
.expect("user is authenticated");
|
||||||
let appservice_info = &body.appservice_info;
|
let appservice_info = &body.appservice_info;
|
||||||
let body = body.body;
|
let body = body.body;
|
||||||
|
|
||||||
@@ -513,9 +528,12 @@ pub(crate) async fn invite_user_route(
|
|||||||
|
|
||||||
match &body.recipient {
|
match &body.recipient {
|
||||||
| invite_user::v3::InvitationRecipient::UserId { user_id } => {
|
| invite_user::v3::InvitationRecipient::UserId { user_id } => {
|
||||||
let sender_ignored_recipient = services.users.user_is_ignored(sender_user, user_id);
|
let sender_ignored_recipient = services
|
||||||
let recipient_ignored_by_sender =
|
.users
|
||||||
services.users.user_is_ignored(user_id, sender_user);
|
.user_is_ignored(sender_user, user_id);
|
||||||
|
let recipient_ignored_by_sender = services
|
||||||
|
.users
|
||||||
|
.user_is_ignored(user_id, sender_user);
|
||||||
|
|
||||||
let (sender_ignored_recipient, recipient_ignored_by_sender) =
|
let (sender_ignored_recipient, recipient_ignored_by_sender) =
|
||||||
join!(sender_ignored_recipient, recipient_ignored_by_sender);
|
join!(sender_ignored_recipient, recipient_ignored_by_sender);
|
||||||
@@ -567,7 +585,12 @@ pub(crate) async fn kick_user_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<kick_user::v3::Request>,
|
body: Ruma<kick_user::v3::Request>,
|
||||||
) -> Result<kick_user::v3::Response> {
|
) -> Result<kick_user::v3::Response> {
|
||||||
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
let state_lock = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.mutex
|
||||||
|
.lock(&body.room_id)
|
||||||
|
.await;
|
||||||
|
|
||||||
let Ok(event) = services
|
let Ok(event) = services
|
||||||
.rooms
|
.rooms
|
||||||
@@ -626,7 +649,12 @@ pub(crate) async fn ban_user_route(
|
|||||||
return Err!(Request(Forbidden("You cannot ban yourself.")));
|
return Err!(Request(Forbidden("You cannot ban yourself.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
let state_lock = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.mutex
|
||||||
|
.lock(&body.room_id)
|
||||||
|
.await;
|
||||||
|
|
||||||
let current_member_content = services
|
let current_member_content = services
|
||||||
.rooms
|
.rooms
|
||||||
@@ -667,7 +695,12 @@ pub(crate) async fn unban_user_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<unban_user::v3::Request>,
|
body: Ruma<unban_user::v3::Request>,
|
||||||
) -> Result<unban_user::v3::Response> {
|
) -> Result<unban_user::v3::Response> {
|
||||||
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
let state_lock = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.mutex
|
||||||
|
.lock(&body.room_id)
|
||||||
|
.await;
|
||||||
|
|
||||||
let current_member_content = services
|
let current_member_content = services
|
||||||
.rooms
|
.rooms
|
||||||
@@ -722,9 +755,18 @@ pub(crate) async fn forget_room_route(
|
|||||||
let user_id = body.sender_user();
|
let user_id = body.sender_user();
|
||||||
let room_id = &body.room_id;
|
let room_id = &body.room_id;
|
||||||
|
|
||||||
let joined = services.rooms.state_cache.is_joined(user_id, room_id);
|
let joined = services
|
||||||
let knocked = services.rooms.state_cache.is_knocked(user_id, room_id);
|
.rooms
|
||||||
let invited = services.rooms.state_cache.is_invited(user_id, room_id);
|
.state_cache
|
||||||
|
.is_joined(user_id, room_id);
|
||||||
|
let knocked = services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.is_knocked(user_id, room_id);
|
||||||
|
let invited = services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.is_invited(user_id, room_id);
|
||||||
|
|
||||||
pin_mut!(joined, knocked, invited);
|
pin_mut!(joined, knocked, invited);
|
||||||
if joined.or(knocked).or(invited).await {
|
if joined.or(knocked).or(invited).await {
|
||||||
@@ -745,8 +787,17 @@ pub(crate) async fn forget_room_route(
|
|||||||
.map(|member| member.membership)
|
.map(|member| member.membership)
|
||||||
.is_ok_and(is_matching!(MembershipState::Leave | MembershipState::Ban));
|
.is_ok_and(is_matching!(MembershipState::Leave | MembershipState::Ban));
|
||||||
|
|
||||||
if non_membership || services.rooms.state_cache.is_left(user_id, room_id).await {
|
if non_membership
|
||||||
services.rooms.state_cache.forget(room_id, user_id);
|
|| services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.is_left(user_id, room_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
|
services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.forget(room_id, user_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(forget_room::v3::Response::new())
|
Ok(forget_room::v3::Response::new())
|
||||||
@@ -791,7 +842,10 @@ fn membership_filter(
|
|||||||
| Some(_) | None => MembershipState::Leave,
|
| Some(_) | None => MembershipState::Leave,
|
||||||
};
|
};
|
||||||
|
|
||||||
let evt_membership = pdu.get_content::<RoomMemberEventContent>().ok()?.membership;
|
let evt_membership = pdu
|
||||||
|
.get_content::<RoomMemberEventContent>()
|
||||||
|
.ok()?
|
||||||
|
.membership;
|
||||||
|
|
||||||
if for_membership.is_some() && not_membership.is_some() {
|
if for_membership.is_some() && not_membership.is_some() {
|
||||||
if membership_state_filter != evt_membership
|
if membership_state_filter != evt_membership
|
||||||
@@ -912,7 +966,13 @@ pub async fn join_room_by_id_helper(
|
|||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
&& appservice_info.is_none();
|
&& appservice_info.is_none();
|
||||||
|
|
||||||
if user_is_guest && !services.rooms.state_accessor.guest_can_join(room_id).await {
|
if user_is_guest
|
||||||
|
&& !services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.guest_can_join(room_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
return Err!(Request(Forbidden("Guests are not allowed to join this room")));
|
return Err!(Request(Forbidden("Guests are not allowed to join this room")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -999,7 +1059,10 @@ async fn join_room_by_id_helper_remote(
|
|||||||
return Err!(BadServerResponse("Remote room version is not supported by conduwuit"));
|
return Err!(BadServerResponse("Remote room version is not supported by conduwuit"));
|
||||||
};
|
};
|
||||||
|
|
||||||
if !services.server.supported_room_version(&room_version_id) {
|
if !services
|
||||||
|
.server
|
||||||
|
.supported_room_version(&room_version_id)
|
||||||
|
{
|
||||||
return Err!(BadServerResponse(
|
return Err!(BadServerResponse(
|
||||||
"Remote room version {room_version_id} is not supported by conduwuit"
|
"Remote room version {room_version_id} is not supported by conduwuit"
|
||||||
));
|
));
|
||||||
@@ -1198,7 +1261,10 @@ async fn join_room_by_id_helper_remote(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
services.rooms.outlier.add_pdu_outlier(&event_id, &value);
|
services
|
||||||
|
.rooms
|
||||||
|
.outlier
|
||||||
|
.add_pdu_outlier(&event_id, &value);
|
||||||
if let Some(state_key) = &pdu.state_key {
|
if let Some(state_key) = &pdu.state_key {
|
||||||
let shortstatekey = services
|
let shortstatekey = services
|
||||||
.rooms
|
.rooms
|
||||||
@@ -1229,7 +1295,10 @@ async fn join_room_by_id_helper_remote(
|
|||||||
})
|
})
|
||||||
.ready_filter_map(Result::ok)
|
.ready_filter_map(Result::ok)
|
||||||
.ready_for_each(|(event_id, value)| {
|
.ready_for_each(|(event_id, value)| {
|
||||||
services.rooms.outlier.add_pdu_outlier(&event_id, &value);
|
services
|
||||||
|
.rooms
|
||||||
|
.outlier
|
||||||
|
.add_pdu_outlier(&event_id, &value);
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@@ -1238,10 +1307,20 @@ async fn join_room_by_id_helper_remote(
|
|||||||
debug!("Running send_join auth check");
|
debug!("Running send_join auth check");
|
||||||
let fetch_state = &state;
|
let fetch_state = &state;
|
||||||
let state_fetch = |k: StateEventType, s: StateKey| async move {
|
let state_fetch = |k: StateEventType, s: StateKey| async move {
|
||||||
let shortstatekey = services.rooms.short.get_shortstatekey(&k, &s).await.ok()?;
|
let shortstatekey = services
|
||||||
|
.rooms
|
||||||
|
.short
|
||||||
|
.get_shortstatekey(&k, &s)
|
||||||
|
.await
|
||||||
|
.ok()?;
|
||||||
|
|
||||||
let event_id = fetch_state.get(&shortstatekey)?;
|
let event_id = fetch_state.get(&shortstatekey)?;
|
||||||
services.rooms.timeline.get_pdu(event_id).await.ok()
|
services
|
||||||
|
.rooms
|
||||||
|
.timeline
|
||||||
|
.get_pdu(event_id)
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
};
|
};
|
||||||
|
|
||||||
let auth_check = state_res::event_auth::auth_check(
|
let auth_check = state_res::event_auth::auth_check(
|
||||||
@@ -1436,7 +1515,10 @@ async fn join_room_by_id_helper_local(
|
|||||||
return Err!(BadServerResponse("Remote room version is not supported by conduwuit"));
|
return Err!(BadServerResponse("Remote room version is not supported by conduwuit"));
|
||||||
};
|
};
|
||||||
|
|
||||||
if !services.server.supported_room_version(&room_version_id) {
|
if !services
|
||||||
|
.server
|
||||||
|
.supported_room_version(&room_version_id)
|
||||||
|
{
|
||||||
return Err!(BadServerResponse(
|
return Err!(BadServerResponse(
|
||||||
"Remote room version {room_version_id} is not supported by conduwuit"
|
"Remote room version {room_version_id} is not supported by conduwuit"
|
||||||
));
|
));
|
||||||
@@ -1572,7 +1654,10 @@ async fn make_join_request(
|
|||||||
federation::membership::prepare_join_event::v1::Request {
|
federation::membership::prepare_join_event::v1::Request {
|
||||||
room_id: room_id.to_owned(),
|
room_id: room_id.to_owned(),
|
||||||
user_id: sender_user.to_owned(),
|
user_id: sender_user.to_owned(),
|
||||||
ver: services.server.supported_room_versions().collect(),
|
ver: services
|
||||||
|
.server
|
||||||
|
.supported_room_versions()
|
||||||
|
.collect(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
@@ -1667,7 +1752,11 @@ pub(crate) async fn invite_helper(
|
|||||||
(pdu, pdu_json, invite_room_state)
|
(pdu, pdu_json, invite_room_state)
|
||||||
};
|
};
|
||||||
|
|
||||||
let room_version_id = services.rooms.state.get_room_version(room_id).await?;
|
let room_version_id = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.get_room_version(room_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let response = services
|
let response = services
|
||||||
.sending
|
.sending
|
||||||
@@ -1723,7 +1812,10 @@ pub(crate) async fn invite_helper(
|
|||||||
err!(Request(InvalidParam("Could not accept incoming PDU as timeline event.")))
|
err!(Request(InvalidParam("Could not accept incoming PDU as timeline event.")))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
return services.sending.send_pdu_room(room_id, &pdu_id).await;
|
return services
|
||||||
|
.sending
|
||||||
|
.send_pdu_room(room_id, &pdu_id)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
if !services
|
if !services
|
||||||
@@ -1797,7 +1889,10 @@ pub async fn leave_all_rooms(services: &Services, user_id: &UserId) {
|
|||||||
warn!(%user_id, "Failed to leave {room_id} remotely: {e}");
|
warn!(%user_id, "Failed to leave {room_id} remotely: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
services.rooms.state_cache.forget(&room_id, user_id);
|
services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.forget(&room_id, user_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1856,7 +1951,10 @@ pub async fn leave_room(
|
|||||||
|
|
||||||
// Ask a remote server if we don't have this room and are not knocking on it
|
// Ask a remote server if we don't have this room and are not knocking on it
|
||||||
if dont_have_room.and(not_knocked).await {
|
if dont_have_room.and(not_knocked).await {
|
||||||
if let Err(e) = remote_leave_room(services, user_id, room_id).boxed().await {
|
if let Err(e) = remote_leave_room(services, user_id, room_id)
|
||||||
|
.boxed()
|
||||||
|
.await
|
||||||
|
{
|
||||||
warn!(%user_id, "Failed to leave room {room_id} remotely: {e}");
|
warn!(%user_id, "Failed to leave room {room_id} remotely: {e}");
|
||||||
// Don't tell the client about this error
|
// Don't tell the client about this error
|
||||||
}
|
}
|
||||||
@@ -1865,8 +1963,18 @@ pub async fn leave_room(
|
|||||||
.rooms
|
.rooms
|
||||||
.state_cache
|
.state_cache
|
||||||
.invite_state(user_id, room_id)
|
.invite_state(user_id, room_id)
|
||||||
.or_else(|_| services.rooms.state_cache.knock_state(user_id, room_id))
|
.or_else(|_| {
|
||||||
.or_else(|_| services.rooms.state_cache.left_state(user_id, room_id))
|
services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.knock_state(user_id, room_id)
|
||||||
|
})
|
||||||
|
.or_else(|_| {
|
||||||
|
services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.left_state(user_id, room_id)
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
@@ -2029,7 +2137,10 @@ async fn remote_leave_room(
|
|||||||
)));
|
)));
|
||||||
};
|
};
|
||||||
|
|
||||||
if !services.server.supported_room_version(&room_version_id) {
|
if !services
|
||||||
|
.server
|
||||||
|
.supported_room_version(&room_version_id)
|
||||||
|
{
|
||||||
return Err!(BadServerResponse(warn!(
|
return Err!(BadServerResponse(warn!(
|
||||||
"Remote room version {room_version_id} for {room_id} is not supported by conduwuit",
|
"Remote room version {room_version_id} for {room_id} is not supported by conduwuit",
|
||||||
)));
|
)));
|
||||||
@@ -2186,7 +2297,11 @@ async fn knock_room_helper_local(
|
|||||||
) -> Result {
|
) -> Result {
|
||||||
debug_info!("We can knock locally");
|
debug_info!("We can knock locally");
|
||||||
|
|
||||||
let room_version_id = services.rooms.state.get_room_version(room_id).await?;
|
let room_version_id = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.get_room_version(room_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
if matches!(
|
if matches!(
|
||||||
room_version_id,
|
room_version_id,
|
||||||
@@ -2237,7 +2352,10 @@ async fn knock_room_helper_local(
|
|||||||
|
|
||||||
let room_version_id = make_knock_response.room_version;
|
let room_version_id = make_knock_response.room_version;
|
||||||
|
|
||||||
if !services.server.supported_room_version(&room_version_id) {
|
if !services
|
||||||
|
.server
|
||||||
|
.supported_room_version(&room_version_id)
|
||||||
|
{
|
||||||
return Err!(BadServerResponse(
|
return Err!(BadServerResponse(
|
||||||
"Remote room version {room_version_id} is not supported by conduwuit"
|
"Remote room version {room_version_id} is not supported by conduwuit"
|
||||||
));
|
));
|
||||||
@@ -2367,7 +2485,10 @@ async fn knock_room_helper_remote(
|
|||||||
|
|
||||||
let room_version_id = make_knock_response.room_version;
|
let room_version_id = make_knock_response.room_version;
|
||||||
|
|
||||||
if !services.server.supported_room_version(&room_version_id) {
|
if !services
|
||||||
|
.server
|
||||||
|
.supported_room_version(&room_version_id)
|
||||||
|
{
|
||||||
return Err!(BadServerResponse(
|
return Err!(BadServerResponse(
|
||||||
"Remote room version {room_version_id} is not supported by conduwuit"
|
"Remote room version {room_version_id} is not supported by conduwuit"
|
||||||
));
|
));
|
||||||
@@ -2481,7 +2602,10 @@ async fn knock_room_helper_remote(
|
|||||||
.get_or_create_shortstatekey(&event_type, &state_key)
|
.get_or_create_shortstatekey(&event_type, &state_key)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
services.rooms.outlier.add_pdu_outlier(&event_id, &event);
|
services
|
||||||
|
.rooms
|
||||||
|
.outlier
|
||||||
|
.add_pdu_outlier(&event_id, &event);
|
||||||
state_map.insert(shortstatekey, event_id.clone());
|
state_map.insert(shortstatekey, event_id.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2489,7 +2613,11 @@ async fn knock_room_helper_remote(
|
|||||||
let compressed: CompressedState = services
|
let compressed: CompressedState = services
|
||||||
.rooms
|
.rooms
|
||||||
.state_compressor
|
.state_compressor
|
||||||
.compress_state_events(state_map.iter().map(|(ssk, eid)| (ssk, eid.borrow())))
|
.compress_state_events(
|
||||||
|
state_map
|
||||||
|
.iter()
|
||||||
|
.map(|(ssk, eid)| (ssk, eid.borrow())),
|
||||||
|
)
|
||||||
.collect()
|
.collect()
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@@ -2582,7 +2710,10 @@ async fn make_knock_request(
|
|||||||
federation::knock::create_knock_event_template::v1::Request {
|
federation::knock::create_knock_event_template::v1::Request {
|
||||||
room_id: room_id.to_owned(),
|
room_id: room_id.to_owned(),
|
||||||
user_id: sender_user.to_owned(),
|
user_id: sender_user.to_owned(),
|
||||||
ver: services.server.supported_room_versions().collect(),
|
ver: services
|
||||||
|
.server
|
||||||
|
.supported_room_versions()
|
||||||
|
.collect(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|||||||
@@ -258,7 +258,9 @@ pub(crate) async fn is_ignored_pdu(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ignored_type = IGNORED_MESSAGE_TYPES.binary_search(&pdu.kind).is_ok();
|
let ignored_type = IGNORED_MESSAGE_TYPES
|
||||||
|
.binary_search(&pdu.kind)
|
||||||
|
.is_ok();
|
||||||
|
|
||||||
let ignored_server = services
|
let ignored_server = services
|
||||||
.config
|
.config
|
||||||
@@ -266,7 +268,11 @@ pub(crate) async fn is_ignored_pdu(
|
|||||||
.is_match(pdu.sender().server_name().host());
|
.is_match(pdu.sender().server_name().host());
|
||||||
|
|
||||||
if ignored_type
|
if ignored_type
|
||||||
&& (ignored_server || services.users.user_is_ignored(&pdu.sender, user_id).await)
|
&& (ignored_server
|
||||||
|
|| services
|
||||||
|
.users
|
||||||
|
.user_is_ignored(&pdu.sender, user_id)
|
||||||
|
.await)
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,10 @@ pub(crate) async fn create_openid_token_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<account::request_openid_token::v3::Request>,
|
body: Ruma<account::request_openid_token::v3::Request>,
|
||||||
) -> Result<account::request_openid_token::v3::Response> {
|
) -> Result<account::request_openid_token::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
if sender_user != &body.user_id {
|
if sender_user != &body.user_id {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
|
|||||||
@@ -50,7 +50,11 @@ pub(crate) async fn get_presence_route(
|
|||||||
.await;
|
.await;
|
||||||
|
|
||||||
if has_shared_rooms {
|
if has_shared_rooms {
|
||||||
if let Ok(presence) = services.presence.get_presence(&body.user_id).await {
|
if let Ok(presence) = services
|
||||||
|
.presence
|
||||||
|
.get_presence(&body.user_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
presence_event = Some(presence);
|
presence_event = Some(presence);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,10 @@ pub(crate) async fn set_displayname_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<set_display_name::v3::Request>,
|
body: Ruma<set_display_name::v3::Request>,
|
||||||
) -> Result<set_display_name::v3::Response> {
|
) -> Result<set_display_name::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
if *sender_user != body.user_id && body.appservice_info.is_none() {
|
if *sender_user != body.user_id && body.appservice_info.is_none() {
|
||||||
return Err!(Request(Forbidden("You cannot update the profile of another user")));
|
return Err!(Request(Forbidden("You cannot update the profile of another user")));
|
||||||
@@ -111,7 +114,11 @@ pub(crate) async fn get_displayname_route(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(get_display_name::v3::Response {
|
Ok(get_display_name::v3::Response {
|
||||||
displayname: services.users.displayname(&body.user_id).await.ok(),
|
displayname: services
|
||||||
|
.users
|
||||||
|
.displayname(&body.user_id)
|
||||||
|
.await
|
||||||
|
.ok(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,7 +131,10 @@ pub(crate) async fn set_avatar_url_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<set_avatar_url::v3::Request>,
|
body: Ruma<set_avatar_url::v3::Request>,
|
||||||
) -> Result<set_avatar_url::v3::Response> {
|
) -> Result<set_avatar_url::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
if *sender_user != body.user_id && body.appservice_info.is_none() {
|
if *sender_user != body.user_id && body.appservice_info.is_none() {
|
||||||
return Err!(Request(Forbidden("You cannot update the profile of another user")));
|
return Err!(Request(Forbidden("You cannot update the profile of another user")));
|
||||||
@@ -212,7 +222,11 @@ pub(crate) async fn get_avatar_url_route(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Ok(get_avatar_url::v3::Response {
|
Ok(get_avatar_url::v3::Response {
|
||||||
avatar_url: services.users.avatar_url(&body.user_id).await.ok(),
|
avatar_url: services
|
||||||
|
.users
|
||||||
|
.avatar_url(&body.user_id)
|
||||||
|
.await
|
||||||
|
.ok(),
|
||||||
blurhash: services.users.blurhash(&body.user_id).await.ok(),
|
blurhash: services.users.blurhash(&body.user_id).await.ok(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -295,9 +309,17 @@ pub(crate) async fn get_profile_route(
|
|||||||
custom_profile_fields.remove("m.tz");
|
custom_profile_fields.remove("m.tz");
|
||||||
|
|
||||||
Ok(get_profile::v3::Response {
|
Ok(get_profile::v3::Response {
|
||||||
avatar_url: services.users.avatar_url(&body.user_id).await.ok(),
|
avatar_url: services
|
||||||
|
.users
|
||||||
|
.avatar_url(&body.user_id)
|
||||||
|
.await
|
||||||
|
.ok(),
|
||||||
blurhash: services.users.blurhash(&body.user_id).await.ok(),
|
blurhash: services.users.blurhash(&body.user_id).await.ok(),
|
||||||
displayname: services.users.displayname(&body.user_id).await.ok(),
|
displayname: services
|
||||||
|
.users
|
||||||
|
.displayname(&body.user_id)
|
||||||
|
.await
|
||||||
|
.ok(),
|
||||||
tz: services.users.timezone(&body.user_id).await.ok(),
|
tz: services.users.timezone(&body.user_id).await.ok(),
|
||||||
custom_profile_fields,
|
custom_profile_fields,
|
||||||
})
|
})
|
||||||
@@ -324,7 +346,9 @@ pub async fn update_displayname(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
services.users.set_displayname(user_id, displayname.clone());
|
services
|
||||||
|
.users
|
||||||
|
.set_displayname(user_id, displayname.clone());
|
||||||
|
|
||||||
// Send a new join membership event into all joined rooms
|
// Send a new join membership event into all joined rooms
|
||||||
let avatar_url = ¤t_avatar_url;
|
let avatar_url = ¤t_avatar_url;
|
||||||
@@ -376,8 +400,12 @@ pub async fn update_avatar_url(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
services.users.set_avatar_url(user_id, avatar_url.clone());
|
services
|
||||||
services.users.set_blurhash(user_id, blurhash.clone());
|
.users
|
||||||
|
.set_avatar_url(user_id, avatar_url.clone());
|
||||||
|
services
|
||||||
|
.users
|
||||||
|
.set_blurhash(user_id, blurhash.clone());
|
||||||
|
|
||||||
// Send a new join membership event into all joined rooms
|
// Send a new join membership event into all joined rooms
|
||||||
let avatar_url = &avatar_url;
|
let avatar_url = &avatar_url;
|
||||||
|
|||||||
@@ -84,7 +84,9 @@ pub(crate) async fn get_pushrules_all_route(
|
|||||||
.update(
|
.update(
|
||||||
None,
|
None,
|
||||||
sender_user,
|
sender_user,
|
||||||
GlobalAccountDataEventType::PushRules.to_string().into(),
|
GlobalAccountDataEventType::PushRules
|
||||||
|
.to_string()
|
||||||
|
.into(),
|
||||||
&serde_json::to_value(PushRulesEvent {
|
&serde_json::to_value(PushRulesEvent {
|
||||||
content: PushRulesEventContent { global: global_ruleset.clone() },
|
content: PushRulesEventContent { global: global_ruleset.clone() },
|
||||||
})
|
})
|
||||||
@@ -106,7 +108,10 @@ pub(crate) async fn get_pushrules_global_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<get_pushrules_global_scope::v3::Request>,
|
body: Ruma<get_pushrules_global_scope::v3::Request>,
|
||||||
) -> Result<get_pushrules_global_scope::v3::Response> {
|
) -> Result<get_pushrules_global_scope::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let Some(content_value) = services
|
let Some(content_value) = services
|
||||||
.account_data
|
.account_data
|
||||||
@@ -123,7 +128,9 @@ pub(crate) async fn get_pushrules_global_route(
|
|||||||
.update(
|
.update(
|
||||||
None,
|
None,
|
||||||
sender_user,
|
sender_user,
|
||||||
GlobalAccountDataEventType::PushRules.to_string().into(),
|
GlobalAccountDataEventType::PushRules
|
||||||
|
.to_string()
|
||||||
|
.into(),
|
||||||
&serde_json::to_value(PushRulesEvent {
|
&serde_json::to_value(PushRulesEvent {
|
||||||
content: PushRulesEventContent {
|
content: PushRulesEventContent {
|
||||||
global: Ruleset::server_default(sender_user),
|
global: Ruleset::server_default(sender_user),
|
||||||
@@ -177,7 +184,9 @@ pub(crate) async fn get_pushrules_global_route(
|
|||||||
.update(
|
.update(
|
||||||
None,
|
None,
|
||||||
sender_user,
|
sender_user,
|
||||||
GlobalAccountDataEventType::PushRules.to_string().into(),
|
GlobalAccountDataEventType::PushRules
|
||||||
|
.to_string()
|
||||||
|
.into(),
|
||||||
&serde_json::to_value(PushRulesEvent {
|
&serde_json::to_value(PushRulesEvent {
|
||||||
content: PushRulesEventContent { global: global_ruleset.clone() },
|
content: PushRulesEventContent { global: global_ruleset.clone() },
|
||||||
})
|
})
|
||||||
@@ -197,7 +206,10 @@ pub(crate) async fn get_pushrule_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<get_pushrule::v3::Request>,
|
body: Ruma<get_pushrule::v3::Request>,
|
||||||
) -> Result<get_pushrule::v3::Response> {
|
) -> Result<get_pushrule::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
// remove old deprecated mentions push rules as per MSC4210
|
// remove old deprecated mentions push rules as per MSC4210
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
@@ -234,7 +246,10 @@ pub(crate) async fn set_pushrule_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<set_pushrule::v3::Request>,
|
body: Ruma<set_pushrule::v3::Request>,
|
||||||
) -> Result<set_pushrule::v3::Response> {
|
) -> Result<set_pushrule::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
let body = body.body;
|
let body = body.body;
|
||||||
|
|
||||||
let mut account_data: PushRulesEvent = services
|
let mut account_data: PushRulesEvent = services
|
||||||
@@ -280,7 +295,9 @@ pub(crate) async fn set_pushrule_route(
|
|||||||
.update(
|
.update(
|
||||||
None,
|
None,
|
||||||
sender_user,
|
sender_user,
|
||||||
GlobalAccountDataEventType::PushRules.to_string().into(),
|
GlobalAccountDataEventType::PushRules
|
||||||
|
.to_string()
|
||||||
|
.into(),
|
||||||
&serde_json::to_value(account_data).expect("to json value always works"),
|
&serde_json::to_value(account_data).expect("to json value always works"),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -295,7 +312,10 @@ pub(crate) async fn get_pushrule_actions_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<get_pushrule_actions::v3::Request>,
|
body: Ruma<get_pushrule_actions::v3::Request>,
|
||||||
) -> Result<get_pushrule_actions::v3::Response> {
|
) -> Result<get_pushrule_actions::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
// remove old deprecated mentions push rules as per MSC4210
|
// remove old deprecated mentions push rules as per MSC4210
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
@@ -329,7 +349,10 @@ pub(crate) async fn set_pushrule_actions_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<set_pushrule_actions::v3::Request>,
|
body: Ruma<set_pushrule_actions::v3::Request>,
|
||||||
) -> Result<set_pushrule_actions::v3::Response> {
|
) -> Result<set_pushrule_actions::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let mut account_data: PushRulesEvent = services
|
let mut account_data: PushRulesEvent = services
|
||||||
.account_data
|
.account_data
|
||||||
@@ -351,7 +374,9 @@ pub(crate) async fn set_pushrule_actions_route(
|
|||||||
.update(
|
.update(
|
||||||
None,
|
None,
|
||||||
sender_user,
|
sender_user,
|
||||||
GlobalAccountDataEventType::PushRules.to_string().into(),
|
GlobalAccountDataEventType::PushRules
|
||||||
|
.to_string()
|
||||||
|
.into(),
|
||||||
&serde_json::to_value(account_data).expect("to json value always works"),
|
&serde_json::to_value(account_data).expect("to json value always works"),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -366,7 +391,10 @@ pub(crate) async fn get_pushrule_enabled_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<get_pushrule_enabled::v3::Request>,
|
body: Ruma<get_pushrule_enabled::v3::Request>,
|
||||||
) -> Result<get_pushrule_enabled::v3::Response> {
|
) -> Result<get_pushrule_enabled::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
// remove old deprecated mentions push rules as per MSC4210
|
// remove old deprecated mentions push rules as per MSC4210
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
@@ -400,7 +428,10 @@ pub(crate) async fn set_pushrule_enabled_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<set_pushrule_enabled::v3::Request>,
|
body: Ruma<set_pushrule_enabled::v3::Request>,
|
||||||
) -> Result<set_pushrule_enabled::v3::Response> {
|
) -> Result<set_pushrule_enabled::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let mut account_data: PushRulesEvent = services
|
let mut account_data: PushRulesEvent = services
|
||||||
.account_data
|
.account_data
|
||||||
@@ -422,7 +453,9 @@ pub(crate) async fn set_pushrule_enabled_route(
|
|||||||
.update(
|
.update(
|
||||||
None,
|
None,
|
||||||
sender_user,
|
sender_user,
|
||||||
GlobalAccountDataEventType::PushRules.to_string().into(),
|
GlobalAccountDataEventType::PushRules
|
||||||
|
.to_string()
|
||||||
|
.into(),
|
||||||
&serde_json::to_value(account_data).expect("to json value always works"),
|
&serde_json::to_value(account_data).expect("to json value always works"),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -437,7 +470,10 @@ pub(crate) async fn delete_pushrule_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<delete_pushrule::v3::Request>,
|
body: Ruma<delete_pushrule::v3::Request>,
|
||||||
) -> Result<delete_pushrule::v3::Response> {
|
) -> Result<delete_pushrule::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let mut account_data: PushRulesEvent = services
|
let mut account_data: PushRulesEvent = services
|
||||||
.account_data
|
.account_data
|
||||||
@@ -468,7 +504,9 @@ pub(crate) async fn delete_pushrule_route(
|
|||||||
.update(
|
.update(
|
||||||
None,
|
None,
|
||||||
sender_user,
|
sender_user,
|
||||||
GlobalAccountDataEventType::PushRules.to_string().into(),
|
GlobalAccountDataEventType::PushRules
|
||||||
|
.to_string()
|
||||||
|
.into(),
|
||||||
&serde_json::to_value(account_data).expect("to json value always works"),
|
&serde_json::to_value(account_data).expect("to json value always works"),
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
@@ -483,7 +521,10 @@ pub(crate) async fn get_pushers_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<get_pushers::v3::Request>,
|
body: Ruma<get_pushers::v3::Request>,
|
||||||
) -> Result<get_pushers::v3::Response> {
|
) -> Result<get_pushers::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
Ok(get_pushers::v3::Response {
|
Ok(get_pushers::v3::Response {
|
||||||
pushers: services.pusher.get_pushers(sender_user).await,
|
pushers: services.pusher.get_pushers(sender_user).await,
|
||||||
@@ -499,7 +540,10 @@ pub(crate) async fn set_pushers_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<set_pusher::v3::Request>,
|
body: Ruma<set_pusher::v3::Request>,
|
||||||
) -> Result<set_pusher::v3::Response> {
|
) -> Result<set_pusher::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
services
|
services
|
||||||
.pusher
|
.pusher
|
||||||
@@ -520,7 +564,9 @@ async fn recreate_push_rules_and_return(
|
|||||||
.update(
|
.update(
|
||||||
None,
|
None,
|
||||||
sender_user,
|
sender_user,
|
||||||
GlobalAccountDataEventType::PushRules.to_string().into(),
|
GlobalAccountDataEventType::PushRules
|
||||||
|
.to_string()
|
||||||
|
.into(),
|
||||||
&serde_json::to_value(PushRulesEvent {
|
&serde_json::to_value(PushRulesEvent {
|
||||||
content: PushRulesEventContent {
|
content: PushRulesEventContent {
|
||||||
global: Ruleset::server_default(sender_user),
|
global: Ruleset::server_default(sender_user),
|
||||||
|
|||||||
@@ -15,10 +15,18 @@ pub(crate) async fn redact_event_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<redact_event::v3::Request>,
|
body: Ruma<redact_event::v3::Request>,
|
||||||
) -> Result<redact_event::v3::Response> {
|
) -> Result<redact_event::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
let body = body.body;
|
let body = body.body;
|
||||||
|
|
||||||
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
let state_lock = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.mutex
|
||||||
|
.lock(&body.room_id)
|
||||||
|
.await;
|
||||||
|
|
||||||
let event_id = services
|
let event_id = services
|
||||||
.rooms
|
.rooms
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ pub(crate) async fn report_room_route(
|
|||||||
body: Ruma<report_room::v3::Request>,
|
body: Ruma<report_room::v3::Request>,
|
||||||
) -> Result<report_room::v3::Response> {
|
) -> Result<report_room::v3::Response> {
|
||||||
// user authentication
|
// user authentication
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"Received room report by user {sender_user} for room {} with reason: \"{}\"",
|
"Received room report by user {sender_user} for room {} with reason: \"{}\"",
|
||||||
@@ -38,7 +41,11 @@ pub(crate) async fn report_room_route(
|
|||||||
body.reason.as_deref().unwrap_or("")
|
body.reason.as_deref().unwrap_or("")
|
||||||
);
|
);
|
||||||
|
|
||||||
if body.reason.as_ref().is_some_and(|s| s.len() > 750) {
|
if body
|
||||||
|
.reason
|
||||||
|
.as_ref()
|
||||||
|
.is_some_and(|s| s.len() > 750)
|
||||||
|
{
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
"Reason too long, should be 750 characters or fewer",
|
"Reason too long, should be 750 characters or fewer",
|
||||||
@@ -84,7 +91,10 @@ pub(crate) async fn report_event_route(
|
|||||||
body: Ruma<report_content::v3::Request>,
|
body: Ruma<report_content::v3::Request>,
|
||||||
) -> Result<report_content::v3::Response> {
|
) -> Result<report_content::v3::Response> {
|
||||||
// user authentication
|
// user authentication
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
"Received event report by user {sender_user} for room {} and event ID {}, with reason: \
|
"Received event report by user {sender_user} for room {} and event ID {}, with reason: \
|
||||||
@@ -97,7 +107,12 @@ pub(crate) async fn report_event_route(
|
|||||||
delay_response().await;
|
delay_response().await;
|
||||||
|
|
||||||
// check if we know about the reported event ID or if it's invalid
|
// check if we know about the reported event ID or if it's invalid
|
||||||
let Ok(pdu) = services.rooms.timeline.get_pdu(&body.event_id).await else {
|
let Ok(pdu) = services
|
||||||
|
.rooms
|
||||||
|
.timeline
|
||||||
|
.get_pdu(&body.event_id)
|
||||||
|
.await
|
||||||
|
else {
|
||||||
return Err!(Request(NotFound("Event ID is not known to us or Event ID is invalid")));
|
return Err!(Request(NotFound("Event ID is not known to us or Event ID is invalid")));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,10 @@ pub(crate) async fn get_room_aliases_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<aliases::v3::Request>,
|
body: Ruma<aliases::v3::Request>,
|
||||||
) -> Result<aliases::v3::Response> {
|
) -> Result<aliases::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
if !services
|
if !services
|
||||||
.rooms
|
.rooms
|
||||||
|
|||||||
@@ -58,7 +58,10 @@ pub(crate) async fn create_room_route(
|
|||||||
) -> Result<create_room::v3::Response> {
|
) -> Result<create_room::v3::Response> {
|
||||||
use create_room::v3::RoomPreset;
|
use create_room::v3::RoomPreset;
|
||||||
|
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
if !services.globals.allow_room_creation()
|
if !services.globals.allow_room_creation()
|
||||||
&& body.appservice_info.is_none()
|
&& body.appservice_info.is_none()
|
||||||
@@ -76,7 +79,13 @@ pub(crate) async fn create_room_route(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// check if room ID doesn't already exist instead of erroring on auth check
|
// check if room ID doesn't already exist instead of erroring on auth check
|
||||||
if services.rooms.short.get_shortroomid(&room_id).await.is_ok() {
|
if services
|
||||||
|
.rooms
|
||||||
|
.short
|
||||||
|
.get_shortroomid(&room_id)
|
||||||
|
.await
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::RoomInUse,
|
ErrorKind::RoomInUse,
|
||||||
"Room with that custom room ID already exists",
|
"Room with that custom room ID already exists",
|
||||||
@@ -84,7 +93,10 @@ pub(crate) async fn create_room_route(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if body.visibility == room::Visibility::Public
|
if body.visibility == room::Visibility::Public
|
||||||
&& services.server.config.lockdown_public_room_directory
|
&& services
|
||||||
|
.server
|
||||||
|
.config
|
||||||
|
.lockdown_public_room_directory
|
||||||
&& !services.users.is_admin(sender_user).await
|
&& !services.users.is_admin(sender_user).await
|
||||||
&& body.appservice_info.is_none()
|
&& body.appservice_info.is_none()
|
||||||
{
|
{
|
||||||
@@ -123,7 +135,10 @@ pub(crate) async fn create_room_route(
|
|||||||
|
|
||||||
let room_version = match body.room_version.clone() {
|
let room_version = match body.room_version.clone() {
|
||||||
| Some(room_version) =>
|
| Some(room_version) =>
|
||||||
if services.server.supported_room_version(&room_version) {
|
if services
|
||||||
|
.server
|
||||||
|
.supported_room_version(&room_version)
|
||||||
|
{
|
||||||
room_version
|
room_version
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
@@ -131,7 +146,11 @@ pub(crate) async fn create_room_route(
|
|||||||
"This server does not support that room version.",
|
"This server does not support that room version.",
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
| None => services.server.config.default_room_version.clone(),
|
| None => services
|
||||||
|
.server
|
||||||
|
.config
|
||||||
|
.default_room_version
|
||||||
|
.clone(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let create_content = match &body.creation_content {
|
let create_content = match &body.creation_content {
|
||||||
@@ -160,9 +179,11 @@ pub(crate) async fn create_room_route(
|
|||||||
}
|
}
|
||||||
content.insert(
|
content.insert(
|
||||||
"room_version".into(),
|
"room_version".into(),
|
||||||
json!(room_version.as_str()).try_into().map_err(|_| {
|
json!(room_version.as_str())
|
||||||
Error::BadRequest(ErrorKind::BadJson, "Invalid creation content")
|
.try_into()
|
||||||
})?,
|
.map_err(|_| {
|
||||||
|
Error::BadRequest(ErrorKind::BadJson, "Invalid creation content")
|
||||||
|
})?,
|
||||||
);
|
);
|
||||||
content
|
content
|
||||||
},
|
},
|
||||||
@@ -231,18 +252,29 @@ pub(crate) async fn create_room_route(
|
|||||||
// 3. Power levels
|
// 3. Power levels
|
||||||
|
|
||||||
// Figure out preset. We need it for preset specific events
|
// Figure out preset. We need it for preset specific events
|
||||||
let preset = body.preset.clone().unwrap_or(match &body.visibility {
|
let preset = body
|
||||||
| room::Visibility::Public => RoomPreset::PublicChat,
|
.preset
|
||||||
| _ => RoomPreset::PrivateChat, // Room visibility should not be custom
|
.clone()
|
||||||
});
|
.unwrap_or(match &body.visibility {
|
||||||
|
| room::Visibility::Public => RoomPreset::PublicChat,
|
||||||
|
| _ => RoomPreset::PrivateChat, // Room visibility should not be custom
|
||||||
|
});
|
||||||
|
|
||||||
let mut users = BTreeMap::from_iter([(sender_user.clone(), int!(100))]);
|
let mut users = BTreeMap::from_iter([(sender_user.clone(), int!(100))]);
|
||||||
|
|
||||||
if preset == RoomPreset::TrustedPrivateChat {
|
if preset == RoomPreset::TrustedPrivateChat {
|
||||||
for invite in &body.invite {
|
for invite in &body.invite {
|
||||||
if services.users.user_is_ignored(sender_user, invite).await {
|
if services
|
||||||
|
.users
|
||||||
|
.user_is_ignored(sender_user, invite)
|
||||||
|
.await
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
} else if services.users.user_is_ignored(invite, sender_user).await {
|
} else if services
|
||||||
|
.users
|
||||||
|
.user_is_ignored(invite, sender_user)
|
||||||
|
.await
|
||||||
|
{
|
||||||
// silently drop the invite to the recipient if they've been ignored by the
|
// silently drop the invite to the recipient if they've been ignored by the
|
||||||
// sender, pretend it worked
|
// sender, pretend it worked
|
||||||
continue;
|
continue;
|
||||||
@@ -353,10 +385,12 @@ pub(crate) async fn create_room_route(
|
|||||||
|
|
||||||
// 6. Events listed in initial_state
|
// 6. Events listed in initial_state
|
||||||
for event in &body.initial_state {
|
for event in &body.initial_state {
|
||||||
let mut pdu_builder = event.deserialize_as::<PduBuilder>().map_err(|e| {
|
let mut pdu_builder = event
|
||||||
warn!("Invalid initial state event: {:?}", e);
|
.deserialize_as::<PduBuilder>()
|
||||||
Error::BadRequest(ErrorKind::InvalidParam, "Invalid initial state event.")
|
.map_err(|e| {
|
||||||
})?;
|
warn!("Invalid initial state event: {:?}", e);
|
||||||
|
Error::BadRequest(ErrorKind::InvalidParam, "Invalid initial state event.")
|
||||||
|
})?;
|
||||||
|
|
||||||
debug_info!("Room creation initial state event: {event:?}");
|
debug_info!("Room creation initial state event: {event:?}");
|
||||||
|
|
||||||
@@ -370,7 +404,9 @@ pub(crate) async fn create_room_route(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Implicit state key defaults to ""
|
// Implicit state key defaults to ""
|
||||||
pdu_builder.state_key.get_or_insert_with(StateKey::new);
|
pdu_builder
|
||||||
|
.state_key
|
||||||
|
.get_or_insert_with(StateKey::new);
|
||||||
|
|
||||||
// Silently skip encryption events if they are not allowed
|
// Silently skip encryption events if they are not allowed
|
||||||
if pdu_builder.event_type == TimelineEventType::RoomEncryption
|
if pdu_builder.event_type == TimelineEventType::RoomEncryption
|
||||||
@@ -419,9 +455,17 @@ pub(crate) async fn create_room_route(
|
|||||||
// 8. Events implied by invite (and TODO: invite_3pid)
|
// 8. Events implied by invite (and TODO: invite_3pid)
|
||||||
drop(state_lock);
|
drop(state_lock);
|
||||||
for user_id in &body.invite {
|
for user_id in &body.invite {
|
||||||
if services.users.user_is_ignored(sender_user, user_id).await {
|
if services
|
||||||
|
.users
|
||||||
|
.user_is_ignored(sender_user, user_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
} else if services.users.user_is_ignored(user_id, sender_user).await {
|
} else if services
|
||||||
|
.users
|
||||||
|
.user_is_ignored(user_id, sender_user)
|
||||||
|
.await
|
||||||
|
{
|
||||||
// silently drop the invite to the recipient if they've been ignored by the
|
// silently drop the invite to the recipient if they've been ignored by the
|
||||||
// sender, pretend it worked
|
// sender, pretend it worked
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -43,7 +43,11 @@ pub(crate) async fn room_initial_sync_route(
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let messages = PaginationChunk {
|
let messages = PaginationChunk {
|
||||||
start: events.last().map(at!(0)).as_ref().map(ToString::to_string),
|
start: events
|
||||||
|
.last()
|
||||||
|
.map(at!(0))
|
||||||
|
.as_ref()
|
||||||
|
.map(ToString::to_string),
|
||||||
|
|
||||||
end: events
|
end: events
|
||||||
.first()
|
.first()
|
||||||
@@ -64,7 +68,12 @@ pub(crate) async fn room_initial_sync_route(
|
|||||||
account_data: None,
|
account_data: None,
|
||||||
state: state.into(),
|
state: state.into(),
|
||||||
messages: messages.chunk.is_empty().or_some(messages),
|
messages: messages.chunk.is_empty().or_some(messages),
|
||||||
visibility: services.rooms.directory.visibility(room_id).await.into(),
|
visibility: services
|
||||||
|
.rooms
|
||||||
|
.directory
|
||||||
|
.visibility(room_id)
|
||||||
|
.await
|
||||||
|
.into(),
|
||||||
membership: services
|
membership: services
|
||||||
.rooms
|
.rooms
|
||||||
.state_cache
|
.state_cache
|
||||||
|
|||||||
@@ -102,7 +102,9 @@ async fn room_summary_response(
|
|||||||
room_version: room.room_version,
|
room_version: room.room_version,
|
||||||
encryption: room.encryption,
|
encryption: room.encryption,
|
||||||
allowed_room_ids: room.allowed_room_ids,
|
allowed_room_ids: room.allowed_room_ids,
|
||||||
membership: sender_user.is_some().then_some(MembershipState::Leave),
|
membership: sender_user
|
||||||
|
.is_some()
|
||||||
|
.then_some(MembershipState::Leave),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,9 +114,18 @@ async fn local_room_summary_response(
|
|||||||
sender_user: Option<&UserId>,
|
sender_user: Option<&UserId>,
|
||||||
) -> Result<get_summary::msc3266::Response> {
|
) -> Result<get_summary::msc3266::Response> {
|
||||||
trace!(?sender_user, "Sending local room summary response for {room_id:?}");
|
trace!(?sender_user, "Sending local room summary response for {room_id:?}");
|
||||||
let join_rule = services.rooms.state_accessor.get_join_rules(room_id);
|
let join_rule = services
|
||||||
let world_readable = services.rooms.state_accessor.is_world_readable(room_id);
|
.rooms
|
||||||
let guest_can_join = services.rooms.state_accessor.guest_can_join(room_id);
|
.state_accessor
|
||||||
|
.get_join_rules(room_id);
|
||||||
|
let world_readable = services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.is_world_readable(room_id);
|
||||||
|
let guest_can_join = services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.guest_can_join(room_id);
|
||||||
|
|
||||||
let (join_rule, world_readable, guest_can_join) =
|
let (join_rule, world_readable, guest_can_join) =
|
||||||
join3(join_rule, world_readable, guest_can_join).await;
|
join3(join_rule, world_readable, guest_can_join).await;
|
||||||
@@ -137,11 +148,23 @@ async fn local_room_summary_response(
|
|||||||
.get_canonical_alias(room_id)
|
.get_canonical_alias(room_id)
|
||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
let name = services.rooms.state_accessor.get_name(room_id).ok();
|
let name = services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.get_name(room_id)
|
||||||
|
.ok();
|
||||||
|
|
||||||
let topic = services.rooms.state_accessor.get_room_topic(room_id).ok();
|
let topic = services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.get_room_topic(room_id)
|
||||||
|
.ok();
|
||||||
|
|
||||||
let room_type = services.rooms.state_accessor.get_room_type(room_id).ok();
|
let room_type = services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.get_room_type(room_id)
|
||||||
|
.ok();
|
||||||
|
|
||||||
let avatar_url = services
|
let avatar_url = services
|
||||||
.rooms
|
.rooms
|
||||||
@@ -149,7 +172,11 @@ async fn local_room_summary_response(
|
|||||||
.get_avatar(room_id)
|
.get_avatar(room_id)
|
||||||
.map(|res| res.into_option().unwrap_or_default().url);
|
.map(|res| res.into_option().unwrap_or_default().url);
|
||||||
|
|
||||||
let room_version = services.rooms.state.get_room_version(room_id).ok();
|
let room_version = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.get_room_version(room_id)
|
||||||
|
.ok();
|
||||||
|
|
||||||
let encryption = services
|
let encryption = services
|
||||||
.rooms
|
.rooms
|
||||||
@@ -208,7 +235,10 @@ async fn local_room_summary_response(
|
|||||||
room_version,
|
room_version,
|
||||||
encryption,
|
encryption,
|
||||||
membership,
|
membership,
|
||||||
allowed_room_ids: join_rule.allowed_rooms().map(Into::into).collect(),
|
allowed_room_ids: join_rule
|
||||||
|
.allowed_rooms()
|
||||||
|
.map(Into::into)
|
||||||
|
.collect(),
|
||||||
join_rule: join_rule.into(),
|
join_rule: join_rule.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -292,10 +322,16 @@ where
|
|||||||
.rooms
|
.rooms
|
||||||
.state_accessor
|
.state_accessor
|
||||||
.user_can_see_state_events(sender_user, room_id);
|
.user_can_see_state_events(sender_user, room_id);
|
||||||
let is_guest = services.users.is_deactivated(sender_user).unwrap_or(false);
|
let is_guest = services
|
||||||
let user_in_allowed_restricted_room = allowed_room_ids
|
.users
|
||||||
.stream()
|
.is_deactivated(sender_user)
|
||||||
.any(|room| services.rooms.state_cache.is_joined(sender_user, room));
|
.unwrap_or(false);
|
||||||
|
let user_in_allowed_restricted_room = allowed_room_ids.stream().any(|room| {
|
||||||
|
services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.is_joined(sender_user, room)
|
||||||
|
});
|
||||||
|
|
||||||
let (user_can_see_state_events, is_guest, user_in_allowed_restricted_room) =
|
let (user_can_see_state_events, is_guest, user_in_allowed_restricted_room) =
|
||||||
join3(user_can_see_state_events, is_guest, user_in_allowed_restricted_room)
|
join3(user_can_see_state_events, is_guest, user_in_allowed_restricted_room)
|
||||||
|
|||||||
@@ -54,9 +54,15 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
TRANSFERABLE_STATE_EVENTS.is_sorted(),
|
TRANSFERABLE_STATE_EVENTS.is_sorted(),
|
||||||
"TRANSFERABLE_STATE_EVENTS is not sorted"
|
"TRANSFERABLE_STATE_EVENTS is not sorted"
|
||||||
);
|
);
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
if !services.server.supported_room_version(&body.new_version) {
|
if !services
|
||||||
|
.server
|
||||||
|
.supported_room_version(&body.new_version)
|
||||||
|
{
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::UnsupportedRoomVersion,
|
ErrorKind::UnsupportedRoomVersion,
|
||||||
"This server does not support that room version.",
|
"This server does not support that room version.",
|
||||||
@@ -72,7 +78,12 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
.get_or_create_shortroomid(&replacement_room)
|
.get_or_create_shortroomid(&replacement_room)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
let state_lock = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.mutex
|
||||||
|
.lock(&body.room_id)
|
||||||
|
.await;
|
||||||
|
|
||||||
// Send a m.room.tombstone event to the old room to indicate that it is not
|
// Send a m.room.tombstone event to the old room to indicate that it is not
|
||||||
// intended to be used any further Fail if the sender does not have the required
|
// intended to be used any further Fail if the sender does not have the required
|
||||||
@@ -93,7 +104,12 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
|
|
||||||
// Change lock to replacement room
|
// Change lock to replacement room
|
||||||
drop(state_lock);
|
drop(state_lock);
|
||||||
let state_lock = services.rooms.state.mutex.lock(&replacement_room).await;
|
let state_lock = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.mutex
|
||||||
|
.lock(&replacement_room)
|
||||||
|
.await;
|
||||||
|
|
||||||
// Get the old room creation event
|
// Get the old room creation event
|
||||||
let mut create_event_content: CanonicalJsonObject = services
|
let mut create_event_content: CanonicalJsonObject = services
|
||||||
|
|||||||
@@ -110,7 +110,12 @@ async fn category_room_events(
|
|||||||
limit,
|
limit,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (count, results) = services.rooms.search.search_pdus(&query).await.ok()?;
|
let (count, results) = services
|
||||||
|
.rooms
|
||||||
|
.search
|
||||||
|
.search_pdus(&query)
|
||||||
|
.await
|
||||||
|
.ok()?;
|
||||||
|
|
||||||
results
|
results
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
@@ -201,8 +206,12 @@ async fn check_room_visible(
|
|||||||
let check_visible = search.filter.rooms.is_some();
|
let check_visible = search.filter.rooms.is_some();
|
||||||
let check_state = check_visible && search.include_state.is_some_and(is_true!());
|
let check_state = check_visible && search.include_state.is_some_and(is_true!());
|
||||||
|
|
||||||
let is_joined =
|
let is_joined = !check_visible
|
||||||
!check_visible || services.rooms.state_cache.is_joined(user_id, room_id).await;
|
|| services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.is_joined(user_id, room_id)
|
||||||
|
.await;
|
||||||
|
|
||||||
let state_visible = !check_state
|
let state_visible = !check_state
|
||||||
|| services
|
|| services
|
||||||
|
|||||||
@@ -30,10 +30,19 @@ pub(crate) async fn send_message_event_route(
|
|||||||
return Err!(Request(Forbidden("Encryption has been disabled")));
|
return Err!(Request(Forbidden("Encryption has been disabled")));
|
||||||
}
|
}
|
||||||
|
|
||||||
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
let state_lock = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.mutex
|
||||||
|
.lock(&body.room_id)
|
||||||
|
.await;
|
||||||
|
|
||||||
if body.event_type == MessageLikeEventType::CallInvite
|
if body.event_type == MessageLikeEventType::CallInvite
|
||||||
&& services.rooms.directory.is_public_room(&body.room_id).await
|
&& services
|
||||||
|
.rooms
|
||||||
|
.directory
|
||||||
|
.is_public_room(&body.room_id)
|
||||||
|
.await
|
||||||
{
|
{
|
||||||
return Err!(Request(Forbidden("Room call invites are not allowed in public rooms")));
|
return Err!(Request(Forbidden("Room call invites are not allowed in public rooms")));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,9 @@ pub(crate) async fn login_route(
|
|||||||
)?;
|
)?;
|
||||||
|
|
||||||
if !services.globals.user_is_local(&user_id)
|
if !services.globals.user_is_local(&user_id)
|
||||||
|| !services.globals.user_is_local(&lowercased_user_id)
|
|| !services
|
||||||
|
.globals
|
||||||
|
.user_is_local(&lowercased_user_id)
|
||||||
{
|
{
|
||||||
return Err!(Request(Unknown("User ID does not belong to this homeserver")));
|
return Err!(Request(Unknown("User ID does not belong to this homeserver")));
|
||||||
}
|
}
|
||||||
@@ -149,7 +151,10 @@ pub(crate) async fn login_route(
|
|||||||
if !services.server.config.login_via_existing_session {
|
if !services.server.config.login_via_existing_session {
|
||||||
return Err!(Request(Unknown("Token login is not enabled.")));
|
return Err!(Request(Unknown("Token login is not enabled.")));
|
||||||
}
|
}
|
||||||
services.users.find_from_login_token(token).await?
|
services
|
||||||
|
.users
|
||||||
|
.find_from_login_token(token)
|
||||||
|
.await?
|
||||||
},
|
},
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
| login::v3::LoginInfo::ApplicationService(login::v3::ApplicationService {
|
| login::v3::LoginInfo::ApplicationService(login::v3::ApplicationService {
|
||||||
@@ -312,7 +317,9 @@ pub(crate) async fn login_token_route(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let login_token = utils::random_string(TOKEN_LENGTH);
|
let login_token = utils::random_string(TOKEN_LENGTH);
|
||||||
let expires_in = services.users.create_login_token(sender_user, &login_token);
|
let expires_in = services
|
||||||
|
.users
|
||||||
|
.create_login_token(sender_user, &login_token);
|
||||||
|
|
||||||
Ok(get_login_token::v1::Response {
|
Ok(get_login_token::v1::Response {
|
||||||
expires_in: Duration::from_millis(expires_in),
|
expires_in: Duration::from_millis(expires_in),
|
||||||
@@ -335,8 +342,14 @@ pub(crate) async fn logout_route(
|
|||||||
InsecureClientIp(client): InsecureClientIp,
|
InsecureClientIp(client): InsecureClientIp,
|
||||||
body: Ruma<logout::v3::Request>,
|
body: Ruma<logout::v3::Request>,
|
||||||
) -> Result<logout::v3::Response> {
|
) -> Result<logout::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
let sender_device = body
|
||||||
|
.sender_device
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
services
|
services
|
||||||
.users
|
.users
|
||||||
@@ -365,12 +378,19 @@ pub(crate) async fn logout_all_route(
|
|||||||
InsecureClientIp(client): InsecureClientIp,
|
InsecureClientIp(client): InsecureClientIp,
|
||||||
body: Ruma<logout_all::v3::Request>,
|
body: Ruma<logout_all::v3::Request>,
|
||||||
) -> Result<logout_all::v3::Response> {
|
) -> Result<logout_all::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
services
|
services
|
||||||
.users
|
.users
|
||||||
.all_device_ids(sender_user)
|
.all_device_ids(sender_user)
|
||||||
.for_each(|device_id| services.users.remove_device(sender_user, device_id))
|
.for_each(|device_id| {
|
||||||
|
services
|
||||||
|
.users
|
||||||
|
.remove_device(sender_user, device_id)
|
||||||
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
Ok(logout_all::v3::Response::new())
|
Ok(logout_all::v3::Response::new())
|
||||||
|
|||||||
@@ -73,7 +73,10 @@ pub(crate) async fn get_state_events_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<get_state_events::v3::Request>,
|
body: Ruma<get_state_events::v3::Request>,
|
||||||
) -> Result<get_state_events::v3::Response> {
|
) -> Result<get_state_events::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
if !services
|
if !services
|
||||||
.rooms
|
.rooms
|
||||||
|
|||||||
@@ -51,7 +51,11 @@ async fn load_timeline(
|
|||||||
|
|
||||||
// Take the last events for the timeline
|
// Take the last events for the timeline
|
||||||
pin_mut!(non_timeline_pdus);
|
pin_mut!(non_timeline_pdus);
|
||||||
let timeline_pdus: Vec<_> = non_timeline_pdus.by_ref().take(limit).collect().await;
|
let timeline_pdus: Vec<_> = non_timeline_pdus
|
||||||
|
.by_ref()
|
||||||
|
.take(limit)
|
||||||
|
.collect()
|
||||||
|
.await;
|
||||||
|
|
||||||
let timeline_pdus: Vec<_> = timeline_pdus.into_iter().rev().collect();
|
let timeline_pdus: Vec<_> = timeline_pdus.into_iter().rev().collect();
|
||||||
|
|
||||||
|
|||||||
@@ -480,7 +480,10 @@ async fn handle_left_room(
|
|||||||
|
|
||||||
let mut left_state_events = Vec::new();
|
let mut left_state_events = Vec::new();
|
||||||
|
|
||||||
let since_shortstatehash = services.rooms.user.get_token_shortstatehash(room_id, since);
|
let since_shortstatehash = services
|
||||||
|
.rooms
|
||||||
|
.user
|
||||||
|
.get_token_shortstatehash(room_id, since);
|
||||||
|
|
||||||
let since_state_ids: HashMap<_, OwnedEventId> = since_shortstatehash
|
let since_state_ids: HashMap<_, OwnedEventId> = since_shortstatehash
|
||||||
.map_ok(|since_shortstatehash| {
|
.map_ok(|since_shortstatehash| {
|
||||||
@@ -640,7 +643,11 @@ async fn load_joined_room(
|
|||||||
let (timeline_pdus, limited) = timeline;
|
let (timeline_pdus, limited) = timeline;
|
||||||
let initial = since_shortstatehash.is_none();
|
let initial = since_shortstatehash.is_none();
|
||||||
let lazy_loading_enabled = filter.room.state.lazy_load_options.is_enabled()
|
let lazy_loading_enabled = filter.room.state.lazy_load_options.is_enabled()
|
||||||
|| filter.room.timeline.lazy_load_options.is_enabled();
|
|| filter
|
||||||
|
.room
|
||||||
|
.timeline
|
||||||
|
.lazy_load_options
|
||||||
|
.is_enabled();
|
||||||
|
|
||||||
let lazy_loading_context = &lazy_loading::Context {
|
let lazy_loading_context = &lazy_loading::Context {
|
||||||
user_id: sender_user,
|
user_id: sender_user,
|
||||||
@@ -652,7 +659,12 @@ async fn load_joined_room(
|
|||||||
|
|
||||||
// Reset lazy loading because this is an initial sync
|
// Reset lazy loading because this is an initial sync
|
||||||
let lazy_load_reset: OptionFuture<_> = initial
|
let lazy_load_reset: OptionFuture<_> = initial
|
||||||
.then(|| services.rooms.lazy_loading.reset(lazy_loading_context))
|
.then(|| {
|
||||||
|
services
|
||||||
|
.rooms
|
||||||
|
.lazy_loading
|
||||||
|
.reset(lazy_loading_context)
|
||||||
|
})
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
lazy_load_reset.await;
|
lazy_load_reset.await;
|
||||||
@@ -964,15 +976,23 @@ async fn calculate_state_initial(
|
|||||||
.ready_filter_map(|((event_type, state_key), event_id)| {
|
.ready_filter_map(|((event_type, state_key), event_id)| {
|
||||||
let lazy = !full_state
|
let lazy = !full_state
|
||||||
&& event_type == StateEventType::RoomMember
|
&& event_type == StateEventType::RoomMember
|
||||||
&& state_key.as_str().try_into().is_ok_and(|user_id: &UserId| {
|
&& state_key
|
||||||
sender_user != user_id
|
.as_str()
|
||||||
&& witness.is_some_and(|witness| !witness.contains(user_id))
|
.try_into()
|
||||||
});
|
.is_ok_and(|user_id: &UserId| {
|
||||||
|
sender_user != user_id
|
||||||
|
&& witness.is_some_and(|witness| !witness.contains(user_id))
|
||||||
|
});
|
||||||
|
|
||||||
lazy.or_some(event_id)
|
lazy.or_some(event_id)
|
||||||
})
|
})
|
||||||
.broad_filter_map(|event_id: OwnedEventId| async move {
|
.broad_filter_map(|event_id: OwnedEventId| async move {
|
||||||
services.rooms.timeline.get_pdu(&event_id).await.ok()
|
services
|
||||||
|
.rooms
|
||||||
|
.timeline
|
||||||
|
.get_pdu(&event_id)
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
.map(Ok);
|
.map(Ok);
|
||||||
@@ -1085,7 +1105,12 @@ async fn calculate_state_incremental<'a>(
|
|||||||
.ok()
|
.ok()
|
||||||
})
|
})
|
||||||
.broad_filter_map(|event_id: OwnedEventId| async move {
|
.broad_filter_map(|event_id: OwnedEventId| async move {
|
||||||
services.rooms.timeline.get_pdu(&event_id).await.ok()
|
services
|
||||||
|
.rooms
|
||||||
|
.timeline
|
||||||
|
.get_pdu(&event_id)
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.await;
|
.await;
|
||||||
@@ -1118,7 +1143,9 @@ async fn calculate_state_incremental<'a>(
|
|||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let send_member_count = state_events.iter().any(|event| event.kind == RoomMember);
|
let send_member_count = state_events
|
||||||
|
.iter()
|
||||||
|
.any(|event| event.kind == RoomMember);
|
||||||
|
|
||||||
let (joined_member_count, invited_member_count, heroes) = if send_member_count {
|
let (joined_member_count, invited_member_count, heroes) = if send_member_count {
|
||||||
calculate_counts(services, room_id, sender_user).await?
|
calculate_counts(services, room_id, sender_user).await?
|
||||||
@@ -1205,8 +1232,11 @@ async fn fold_hero(
|
|||||||
sender_user: &UserId,
|
sender_user: &UserId,
|
||||||
pdu: PduEvent,
|
pdu: PduEvent,
|
||||||
) -> Vec<OwnedUserId> {
|
) -> Vec<OwnedUserId> {
|
||||||
let Some(user_id): Option<&UserId> =
|
let Some(user_id): Option<&UserId> = pdu
|
||||||
pdu.state_key.as_deref().map(TryInto::try_into).flat_ok()
|
.state_key
|
||||||
|
.as_deref()
|
||||||
|
.map(TryInto::try_into)
|
||||||
|
.flat_ok()
|
||||||
else {
|
else {
|
||||||
return heroes;
|
return heroes;
|
||||||
};
|
};
|
||||||
@@ -1229,8 +1259,14 @@ async fn fold_hero(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let (is_invited, is_joined) = join(
|
let (is_invited, is_joined) = join(
|
||||||
services.rooms.state_cache.is_invited(user_id, room_id),
|
services
|
||||||
services.rooms.state_cache.is_joined(user_id, room_id),
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.is_invited(user_id, room_id),
|
||||||
|
services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.is_joined(user_id, room_id),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
|||||||
@@ -53,8 +53,14 @@ pub(crate) async fn sync_events_v4_route(
|
|||||||
body: Ruma<sync_events::v4::Request>,
|
body: Ruma<sync_events::v4::Request>,
|
||||||
) -> Result<sync_events::v4::Response> {
|
) -> Result<sync_events::v4::Response> {
|
||||||
debug_assert!(DEFAULT_BUMP_TYPES.is_sorted(), "DEFAULT_BUMP_TYPES is not sorted");
|
debug_assert!(DEFAULT_BUMP_TYPES.is_sorted(), "DEFAULT_BUMP_TYPES is not sorted");
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
let sender_device = body
|
||||||
|
.sender_device
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
let mut body = body.body;
|
let mut body = body.body;
|
||||||
|
|
||||||
// Setup watchers, so if there's no response, we can wait for them
|
// Setup watchers, so if there's no response, we can wait for them
|
||||||
@@ -80,7 +86,9 @@ pub(crate) async fn sync_events_v4_route(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if globalsince == 0 {
|
if globalsince == 0 {
|
||||||
services.sync.forget_sync_request_connection(&db_key);
|
services
|
||||||
|
.sync
|
||||||
|
.forget_sync_request_connection(&db_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get sticky parameters from cache
|
// Get sticky parameters from cache
|
||||||
@@ -113,8 +121,14 @@ pub(crate) async fn sync_events_v4_route(
|
|||||||
.collect()
|
.collect()
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let all_invited_rooms: Vec<&RoomId> = all_invited_rooms.iter().map(AsRef::as_ref).collect();
|
let all_invited_rooms: Vec<&RoomId> = all_invited_rooms
|
||||||
let all_knocked_rooms: Vec<&RoomId> = all_knocked_rooms.iter().map(AsRef::as_ref).collect();
|
.iter()
|
||||||
|
.map(AsRef::as_ref)
|
||||||
|
.collect();
|
||||||
|
let all_knocked_rooms: Vec<&RoomId> = all_knocked_rooms
|
||||||
|
.iter()
|
||||||
|
.map(AsRef::as_ref)
|
||||||
|
.collect();
|
||||||
|
|
||||||
let all_rooms: Vec<&RoomId> = all_joined_rooms
|
let all_rooms: Vec<&RoomId> = all_joined_rooms
|
||||||
.iter()
|
.iter()
|
||||||
@@ -123,8 +137,14 @@ pub(crate) async fn sync_events_v4_route(
|
|||||||
.chain(all_knocked_rooms.iter().map(AsRef::as_ref))
|
.chain(all_knocked_rooms.iter().map(AsRef::as_ref))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let all_joined_rooms = all_joined_rooms.iter().map(AsRef::as_ref).collect();
|
let all_joined_rooms = all_joined_rooms
|
||||||
let all_invited_rooms = all_invited_rooms.iter().map(AsRef::as_ref).collect();
|
.iter()
|
||||||
|
.map(AsRef::as_ref)
|
||||||
|
.collect();
|
||||||
|
let all_invited_rooms = all_invited_rooms
|
||||||
|
.iter()
|
||||||
|
.map(AsRef::as_ref)
|
||||||
|
.collect();
|
||||||
|
|
||||||
if body.extensions.to_device.enabled.unwrap_or(false) {
|
if body.extensions.to_device.enabled.unwrap_or(false) {
|
||||||
services
|
services
|
||||||
@@ -143,7 +163,12 @@ pub(crate) async fn sync_events_v4_route(
|
|||||||
global: Vec::new(),
|
global: Vec::new(),
|
||||||
rooms: BTreeMap::new(),
|
rooms: BTreeMap::new(),
|
||||||
};
|
};
|
||||||
if body.extensions.account_data.enabled.unwrap_or(false) {
|
if body
|
||||||
|
.extensions
|
||||||
|
.account_data
|
||||||
|
.enabled
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
account_data.global = services
|
account_data.global = services
|
||||||
.account_data
|
.account_data
|
||||||
.changes_since(None, sender_user, globalsince, Some(next_batch))
|
.changes_since(None, sender_user, globalsince, Some(next_batch))
|
||||||
@@ -179,8 +204,11 @@ pub(crate) async fn sync_events_v4_route(
|
|||||||
|
|
||||||
for room_id in &all_joined_rooms {
|
for room_id in &all_joined_rooms {
|
||||||
let room_id: &&RoomId = room_id;
|
let room_id: &&RoomId = room_id;
|
||||||
let Ok(current_shortstatehash) =
|
let Ok(current_shortstatehash) = services
|
||||||
services.rooms.state.get_room_shortstatehash(room_id).await
|
.rooms
|
||||||
|
.state
|
||||||
|
.get_room_shortstatehash(room_id)
|
||||||
|
.await
|
||||||
else {
|
else {
|
||||||
error!("Room {room_id} has no state");
|
error!("Room {room_id} has no state");
|
||||||
continue;
|
continue;
|
||||||
@@ -373,13 +401,16 @@ pub(crate) async fn sync_events_v4_route(
|
|||||||
Vec::new()
|
Vec::new()
|
||||||
};
|
};
|
||||||
|
|
||||||
new_known_rooms.extend(room_ids.clone().into_iter().map(ToOwned::to_owned));
|
new_known_rooms.extend(
|
||||||
|
room_ids
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(ToOwned::to_owned),
|
||||||
|
);
|
||||||
for room_id in &room_ids {
|
for room_id in &room_ids {
|
||||||
let todo_room = todo_rooms.entry((*room_id).to_owned()).or_insert((
|
let todo_room = todo_rooms
|
||||||
BTreeSet::new(),
|
.entry((*room_id).to_owned())
|
||||||
0_usize,
|
.or_insert((BTreeSet::new(), 0_usize, u64::MAX));
|
||||||
u64::MAX,
|
|
||||||
));
|
|
||||||
|
|
||||||
let limit: usize = list
|
let limit: usize = list
|
||||||
.room_details
|
.room_details
|
||||||
@@ -409,7 +440,10 @@ pub(crate) async fn sync_events_v4_route(
|
|||||||
op: SlidingOp::Sync,
|
op: SlidingOp::Sync,
|
||||||
range: Some(r),
|
range: Some(r),
|
||||||
index: None,
|
index: None,
|
||||||
room_ids: room_ids.into_iter().map(ToOwned::to_owned).collect(),
|
room_ids: room_ids
|
||||||
|
.into_iter()
|
||||||
|
.map(ToOwned::to_owned)
|
||||||
|
.collect(),
|
||||||
room_id: None,
|
room_id: None,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -575,7 +609,10 @@ pub(crate) async fn sync_events_v4_route(
|
|||||||
|
|
||||||
if roomsince != &0
|
if roomsince != &0
|
||||||
&& timeline_pdus.is_empty()
|
&& timeline_pdus.is_empty()
|
||||||
&& account_data.rooms.get(room_id).is_some_and(Vec::is_empty)
|
&& account_data
|
||||||
|
.rooms
|
||||||
|
.get(room_id)
|
||||||
|
.is_some_and(Vec::is_empty)
|
||||||
&& receipt_size == 0
|
&& receipt_size == 0
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
@@ -610,8 +647,9 @@ pub(crate) async fn sync_events_v4_route(
|
|||||||
|
|
||||||
for (_, pdu) in timeline_pdus {
|
for (_, pdu) in timeline_pdus {
|
||||||
let ts = MilliSecondsSinceUnixEpoch(pdu.origin_server_ts);
|
let ts = MilliSecondsSinceUnixEpoch(pdu.origin_server_ts);
|
||||||
if DEFAULT_BUMP_TYPES.binary_search(&pdu.kind).is_ok()
|
if DEFAULT_BUMP_TYPES
|
||||||
&& timestamp.is_none_or(|time| time <= ts)
|
.binary_search(&pdu.kind)
|
||||||
|
.is_ok() && timestamp.is_none_or(|time| time <= ts)
|
||||||
{
|
{
|
||||||
timestamp = Some(ts);
|
timestamp = Some(ts);
|
||||||
}
|
}
|
||||||
@@ -658,7 +696,11 @@ pub(crate) async fn sync_events_v4_route(
|
|||||||
| Ordering::Greater => {
|
| Ordering::Greater => {
|
||||||
let firsts = heroes[1..]
|
let firsts = heroes[1..]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|h| h.name.clone().unwrap_or_else(|| h.user_id.to_string()))
|
.map(|h| {
|
||||||
|
h.name
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| h.user_id.to_string())
|
||||||
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
|
||||||
@@ -694,7 +736,12 @@ pub(crate) async fn sync_events_v4_route(
|
|||||||
.or(name),
|
.or(name),
|
||||||
avatar: match heroes_avatar {
|
avatar: match heroes_avatar {
|
||||||
| Some(heroes_avatar) => ruma::JsOption::Some(heroes_avatar),
|
| Some(heroes_avatar) => ruma::JsOption::Some(heroes_avatar),
|
||||||
| _ => match services.rooms.state_accessor.get_avatar(room_id).await {
|
| _ => match services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.get_avatar(room_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
| ruma::JsOption::Some(avatar) => ruma::JsOption::from_option(avatar.url),
|
| ruma::JsOption::Some(avatar) => ruma::JsOption::from_option(avatar.url),
|
||||||
| ruma::JsOption::Null => ruma::JsOption::Null,
|
| ruma::JsOption::Null => ruma::JsOption::Null,
|
||||||
| ruma::JsOption::Undefined => ruma::JsOption::Undefined,
|
| ruma::JsOption::Undefined => ruma::JsOption::Undefined,
|
||||||
@@ -817,9 +864,16 @@ async fn filter_rooms<'a>(
|
|||||||
.iter()
|
.iter()
|
||||||
.stream()
|
.stream()
|
||||||
.filter_map(|r| async move {
|
.filter_map(|r| async move {
|
||||||
let room_type = services.rooms.state_accessor.get_room_type(r).await;
|
let room_type = services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.get_room_type(r)
|
||||||
|
.await;
|
||||||
|
|
||||||
if room_type.as_ref().is_err_and(|e| !e.is_not_found()) {
|
if room_type
|
||||||
|
.as_ref()
|
||||||
|
.is_err_and(|e| !e.is_not_found())
|
||||||
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -63,8 +63,14 @@ pub(crate) async fn sync_events_v5_route(
|
|||||||
body: Ruma<sync_events::v5::Request>,
|
body: Ruma<sync_events::v5::Request>,
|
||||||
) -> Result<sync_events::v5::Response> {
|
) -> Result<sync_events::v5::Response> {
|
||||||
debug_assert!(DEFAULT_BUMP_TYPES.is_sorted(), "DEFAULT_BUMP_TYPES is not sorted");
|
debug_assert!(DEFAULT_BUMP_TYPES.is_sorted(), "DEFAULT_BUMP_TYPES is not sorted");
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
let sender_device = body
|
||||||
|
.sender_device
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
let mut body = body.body;
|
let mut body = body.body;
|
||||||
|
|
||||||
// Setup watchers, so if there's no response, we can wait for them
|
// Setup watchers, so if there's no response, we can wait for them
|
||||||
@@ -90,7 +96,9 @@ pub(crate) async fn sync_events_v5_route(
|
|||||||
|
|
||||||
// Client / User requested an initial sync
|
// Client / User requested an initial sync
|
||||||
if globalsince == 0 {
|
if globalsince == 0 {
|
||||||
services.sync.forget_snake_sync_connection(&snake_key);
|
services
|
||||||
|
.sync
|
||||||
|
.forget_snake_sync_connection(&snake_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get sticky parameters from cache
|
// Get sticky parameters from cache
|
||||||
@@ -191,7 +199,11 @@ pub(crate) async fn sync_events_v5_route(
|
|||||||
if response.rooms.iter().all(|(id, r)| {
|
if response.rooms.iter().all(|(id, r)| {
|
||||||
r.timeline.is_empty()
|
r.timeline.is_empty()
|
||||||
&& r.required_state.is_empty()
|
&& r.required_state.is_empty()
|
||||||
&& !response.extensions.receipts.rooms.contains_key(id)
|
&& !response
|
||||||
|
.extensions
|
||||||
|
.receipts
|
||||||
|
.rooms
|
||||||
|
.contains_key(id)
|
||||||
}) && response
|
}) && response
|
||||||
.extensions
|
.extensions
|
||||||
.to_device
|
.to_device
|
||||||
@@ -322,8 +334,11 @@ where
|
|||||||
let room_ids =
|
let room_ids =
|
||||||
active_rooms[usize_from_ruma(range.0)..usize_from_ruma(range.1)].to_vec();
|
active_rooms[usize_from_ruma(range.0)..usize_from_ruma(range.1)].to_vec();
|
||||||
|
|
||||||
let new_rooms: BTreeSet<OwnedRoomId> =
|
let new_rooms: BTreeSet<OwnedRoomId> = room_ids
|
||||||
room_ids.clone().into_iter().map(From::from).collect();
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.map(From::from)
|
||||||
|
.collect();
|
||||||
|
|
||||||
new_known_rooms.extend(new_rooms);
|
new_known_rooms.extend(new_rooms);
|
||||||
//new_known_rooms.extend(room_ids..cloned());
|
//new_known_rooms.extend(room_ids..cloned());
|
||||||
@@ -394,7 +409,10 @@ where
|
|||||||
let mut invite_state = None;
|
let mut invite_state = None;
|
||||||
let (timeline_pdus, limited);
|
let (timeline_pdus, limited);
|
||||||
let new_room_id: &RoomId = (*room_id).as_ref();
|
let new_room_id: &RoomId = (*room_id).as_ref();
|
||||||
if all_invited_rooms.clone().any(is_equal_to!(new_room_id)) {
|
if all_invited_rooms
|
||||||
|
.clone()
|
||||||
|
.any(is_equal_to!(new_room_id))
|
||||||
|
{
|
||||||
// TODO: figure out a timestamp we can use for remote invites
|
// TODO: figure out a timestamp we can use for remote invites
|
||||||
invite_state = services
|
invite_state = services
|
||||||
.rooms
|
.rooms
|
||||||
@@ -521,8 +539,9 @@ where
|
|||||||
|
|
||||||
for (_, pdu) in timeline_pdus {
|
for (_, pdu) in timeline_pdus {
|
||||||
let ts = pdu.origin_server_ts;
|
let ts = pdu.origin_server_ts;
|
||||||
if DEFAULT_BUMP_TYPES.binary_search(&pdu.kind).is_ok()
|
if DEFAULT_BUMP_TYPES
|
||||||
&& timestamp.is_none_or(|time| time <= ts)
|
.binary_search(&pdu.kind)
|
||||||
|
.is_ok() && timestamp.is_none_or(|time| time <= ts)
|
||||||
{
|
{
|
||||||
timestamp = Some(ts);
|
timestamp = Some(ts);
|
||||||
}
|
}
|
||||||
@@ -569,7 +588,11 @@ where
|
|||||||
| Ordering::Greater => {
|
| Ordering::Greater => {
|
||||||
let firsts = heroes[1..]
|
let firsts = heroes[1..]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|h| h.name.clone().unwrap_or_else(|| h.user_id.to_string()))
|
.map(|h| {
|
||||||
|
h.name
|
||||||
|
.clone()
|
||||||
|
.unwrap_or_else(|| h.user_id.to_string())
|
||||||
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
|
||||||
@@ -605,7 +628,12 @@ where
|
|||||||
.or(name),
|
.or(name),
|
||||||
avatar: match heroes_avatar {
|
avatar: match heroes_avatar {
|
||||||
| Some(heroes_avatar) => ruma::JsOption::Some(heroes_avatar),
|
| Some(heroes_avatar) => ruma::JsOption::Some(heroes_avatar),
|
||||||
| _ => match services.rooms.state_accessor.get_avatar(room_id).await {
|
| _ => match services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.get_avatar(room_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
| ruma::JsOption::Some(avatar) => ruma::JsOption::from_option(avatar.url),
|
| ruma::JsOption::Some(avatar) => ruma::JsOption::from_option(avatar.url),
|
||||||
| ruma::JsOption::Null => ruma::JsOption::Null,
|
| ruma::JsOption::Null => ruma::JsOption::Null,
|
||||||
| ruma::JsOption::Undefined => ruma::JsOption::Undefined,
|
| ruma::JsOption::Undefined => ruma::JsOption::Undefined,
|
||||||
@@ -674,7 +702,12 @@ async fn collect_account_data(
|
|||||||
rooms: BTreeMap::new(),
|
rooms: BTreeMap::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
if !body.extensions.account_data.enabled.unwrap_or(false) {
|
if !body
|
||||||
|
.extensions
|
||||||
|
.account_data
|
||||||
|
.enabled
|
||||||
|
.unwrap_or(false)
|
||||||
|
{
|
||||||
return sync_events::v5::response::AccountData::default();
|
return sync_events::v5::response::AccountData::default();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -732,8 +765,11 @@ where
|
|||||||
);
|
);
|
||||||
|
|
||||||
for room_id in all_joined_rooms {
|
for room_id in all_joined_rooms {
|
||||||
let Ok(current_shortstatehash) =
|
let Ok(current_shortstatehash) = services
|
||||||
services.rooms.state.get_room_shortstatehash(room_id).await
|
.rooms
|
||||||
|
.state
|
||||||
|
.get_room_shortstatehash(room_id)
|
||||||
|
.await
|
||||||
else {
|
else {
|
||||||
error!("Room {room_id} has no state");
|
error!("Room {room_id} has no state");
|
||||||
continue;
|
continue;
|
||||||
@@ -934,9 +970,16 @@ where
|
|||||||
Rooms: Stream<Item = &'a RoomId> + Send + 'a,
|
Rooms: Stream<Item = &'a RoomId> + Send + 'a,
|
||||||
{
|
{
|
||||||
rooms.filter_map(async |room_id| {
|
rooms.filter_map(async |room_id| {
|
||||||
let room_type = services.rooms.state_accessor.get_room_type(room_id).await;
|
let room_type = services
|
||||||
|
.rooms
|
||||||
|
.state_accessor
|
||||||
|
.get_room_type(room_id)
|
||||||
|
.await;
|
||||||
|
|
||||||
if room_type.as_ref().is_err_and(|e| !e.is_not_found()) {
|
if room_type
|
||||||
|
.as_ref()
|
||||||
|
.is_err_and(|e| !e.is_not_found())
|
||||||
|
{
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,10 @@ pub(crate) async fn update_tag_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<create_tag::v3::Request>,
|
body: Ruma<create_tag::v3::Request>,
|
||||||
) -> Result<create_tag::v3::Response> {
|
) -> Result<create_tag::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let mut tags_event = services
|
let mut tags_event = services
|
||||||
.account_data
|
.account_data
|
||||||
@@ -58,7 +61,10 @@ pub(crate) async fn delete_tag_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<delete_tag::v3::Request>,
|
body: Ruma<delete_tag::v3::Request>,
|
||||||
) -> Result<delete_tag::v3::Response> {
|
) -> Result<delete_tag::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let mut tags_event = services
|
let mut tags_event = services
|
||||||
.account_data
|
.account_data
|
||||||
@@ -68,7 +74,10 @@ pub(crate) async fn delete_tag_route(
|
|||||||
content: TagEventContent { tags: BTreeMap::new() },
|
content: TagEventContent { tags: BTreeMap::new() },
|
||||||
});
|
});
|
||||||
|
|
||||||
tags_event.content.tags.remove(&body.tag.clone().into());
|
tags_event
|
||||||
|
.content
|
||||||
|
.tags
|
||||||
|
.remove(&body.tag.clone().into());
|
||||||
|
|
||||||
services
|
services
|
||||||
.account_data
|
.account_data
|
||||||
@@ -92,7 +101,10 @@ pub(crate) async fn get_tags_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<get_tags::v3::Request>,
|
body: Ruma<get_tags::v3::Request>,
|
||||||
) -> Result<get_tags::v3::Response> {
|
) -> Result<get_tags::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
let tags_event = services
|
let tags_event = services
|
||||||
.account_data
|
.account_data
|
||||||
|
|||||||
@@ -21,7 +21,10 @@ pub(crate) async fn send_event_to_device_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<send_event_to_device::v3::Request>,
|
body: Ruma<send_event_to_device::v3::Request>,
|
||||||
) -> Result<send_event_to_device::v3::Response> {
|
) -> Result<send_event_to_device::v3::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
let sender_device = body.sender_device.as_deref();
|
let sender_device = body.sender_device.as_deref();
|
||||||
|
|
||||||
// Check if this is a new transaction id
|
// Check if this is a new transaction id
|
||||||
|
|||||||
@@ -30,7 +30,10 @@ pub(crate) async fn create_typing_event_route(
|
|||||||
match body.state {
|
match body.state {
|
||||||
| Typing::Yes(duration) => {
|
| Typing::Yes(duration) => {
|
||||||
let duration = utils::clamp(
|
let duration = utils::clamp(
|
||||||
duration.as_millis().try_into().unwrap_or(u64::MAX),
|
duration
|
||||||
|
.as_millis()
|
||||||
|
.try_into()
|
||||||
|
.unwrap_or(u64::MAX),
|
||||||
services
|
services
|
||||||
.server
|
.server
|
||||||
.config
|
.config
|
||||||
|
|||||||
@@ -69,7 +69,10 @@ pub(crate) async fn delete_timezone_key_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<delete_timezone_key::unstable::Request>,
|
body: Ruma<delete_timezone_key::unstable::Request>,
|
||||||
) -> Result<delete_timezone_key::unstable::Response> {
|
) -> Result<delete_timezone_key::unstable::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
if *sender_user != body.user_id && body.appservice_info.is_none() {
|
if *sender_user != body.user_id && body.appservice_info.is_none() {
|
||||||
return Err!(Request(Forbidden("You cannot update the profile of another user")));
|
return Err!(Request(Forbidden("You cannot update the profile of another user")));
|
||||||
@@ -97,13 +100,18 @@ pub(crate) async fn set_timezone_key_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<set_timezone_key::unstable::Request>,
|
body: Ruma<set_timezone_key::unstable::Request>,
|
||||||
) -> Result<set_timezone_key::unstable::Response> {
|
) -> Result<set_timezone_key::unstable::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
if *sender_user != body.user_id && body.appservice_info.is_none() {
|
if *sender_user != body.user_id && body.appservice_info.is_none() {
|
||||||
return Err!(Request(Forbidden("You cannot update the profile of another user")));
|
return Err!(Request(Forbidden("You cannot update the profile of another user")));
|
||||||
}
|
}
|
||||||
|
|
||||||
services.users.set_timezone(&body.user_id, body.tz.clone());
|
services
|
||||||
|
.users
|
||||||
|
.set_timezone(&body.user_id, body.tz.clone());
|
||||||
|
|
||||||
if services.config.allow_local_presence {
|
if services.config.allow_local_presence {
|
||||||
// Presence update
|
// Presence update
|
||||||
@@ -125,7 +133,10 @@ pub(crate) async fn set_profile_key_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<set_profile_key::unstable::Request>,
|
body: Ruma<set_profile_key::unstable::Request>,
|
||||||
) -> Result<set_profile_key::unstable::Response> {
|
) -> Result<set_profile_key::unstable::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
if *sender_user != body.user_id && body.appservice_info.is_none() {
|
if *sender_user != body.user_id && body.appservice_info.is_none() {
|
||||||
return Err!(Request(Forbidden("You cannot update the profile of another user")));
|
return Err!(Request(Forbidden("You cannot update the profile of another user")));
|
||||||
@@ -218,7 +229,10 @@ pub(crate) async fn delete_profile_key_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<delete_profile_key::unstable::Request>,
|
body: Ruma<delete_profile_key::unstable::Request>,
|
||||||
) -> Result<delete_profile_key::unstable::Response> {
|
) -> Result<delete_profile_key::unstable::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body
|
||||||
|
.sender_user
|
||||||
|
.as_ref()
|
||||||
|
.expect("user is authenticated");
|
||||||
|
|
||||||
if *sender_user != body.user_id && body.appservice_info.is_none() {
|
if *sender_user != body.user_id && body.appservice_info.is_none() {
|
||||||
return Err!(Request(Forbidden("You cannot update the profile of another user")));
|
return Err!(Request(Forbidden("You cannot update the profile of another user")));
|
||||||
|
|||||||
@@ -37,7 +37,12 @@ pub(crate) async fn search_users_route(
|
|||||||
let mut users = services
|
let mut users = services
|
||||||
.users
|
.users
|
||||||
.stream()
|
.stream()
|
||||||
.ready_filter(|user_id| user_id.as_str().to_lowercase().contains(&search_term))
|
.ready_filter(|user_id| {
|
||||||
|
user_id
|
||||||
|
.as_str()
|
||||||
|
.to_lowercase()
|
||||||
|
.contains(&search_term)
|
||||||
|
})
|
||||||
.map(ToOwned::to_owned)
|
.map(ToOwned::to_owned)
|
||||||
.broad_filter_map(async |user_id| {
|
.broad_filter_map(async |user_id| {
|
||||||
let display_name = services.users.displayname(&user_id).await.ok();
|
let display_name = services.users.displayname(&user_id).await.ok();
|
||||||
|
|||||||
@@ -45,15 +45,30 @@ pub(crate) async fn well_known_support(
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.map(ToString::to_string);
|
.map(ToString::to_string);
|
||||||
|
|
||||||
let role = services.server.config.well_known.support_role.clone();
|
let role = services
|
||||||
|
.server
|
||||||
|
.config
|
||||||
|
.well_known
|
||||||
|
.support_role
|
||||||
|
.clone();
|
||||||
|
|
||||||
// support page or role must be either defined for this to be valid
|
// support page or role must be either defined for this to be valid
|
||||||
if support_page.is_none() && role.is_none() {
|
if support_page.is_none() && role.is_none() {
|
||||||
return Err(Error::BadRequest(ErrorKind::NotFound, "Not found."));
|
return Err(Error::BadRequest(ErrorKind::NotFound, "Not found."));
|
||||||
}
|
}
|
||||||
|
|
||||||
let email_address = services.server.config.well_known.support_email.clone();
|
let email_address = services
|
||||||
let matrix_id = services.server.config.well_known.support_mxid.clone();
|
.server
|
||||||
|
.config
|
||||||
|
.well_known
|
||||||
|
.support_email
|
||||||
|
.clone();
|
||||||
|
let matrix_id = services
|
||||||
|
.server
|
||||||
|
.config
|
||||||
|
.well_known
|
||||||
|
.support_mxid
|
||||||
|
.clone();
|
||||||
|
|
||||||
// if a role is specified, an email address or matrix id is required
|
// if a role is specified, an email address or matrix id is required
|
||||||
if role.is_some() && (email_address.is_none() && matrix_id.is_none()) {
|
if role.is_some() && (email_address.is_none() && matrix_id.is_none()) {
|
||||||
|
|||||||
@@ -140,9 +140,13 @@ fn into_http_request(request: &Request, body: Bytes) -> hyper::Request<Bytes> {
|
|||||||
.uri(request.parts.uri.clone())
|
.uri(request.parts.uri.clone())
|
||||||
.method(request.parts.method.clone());
|
.method(request.parts.method.clone());
|
||||||
|
|
||||||
*http_request.headers_mut().expect("mutable http headers") = request.parts.headers.clone();
|
*http_request
|
||||||
|
.headers_mut()
|
||||||
|
.expect("mutable http headers") = request.parts.headers.clone();
|
||||||
|
|
||||||
let http_request = http_request.body(body).expect("http request body");
|
let http_request = http_request
|
||||||
|
.body(body)
|
||||||
|
.expect("http request body");
|
||||||
|
|
||||||
let headers = http_request.headers();
|
let headers = http_request.headers();
|
||||||
let method = http_request.method();
|
let method = http_request.method();
|
||||||
|
|||||||
@@ -93,7 +93,11 @@ pub(super) async fn auth(
|
|||||||
| &get_display_name::v3::Request::METADATA
|
| &get_display_name::v3::Request::METADATA
|
||||||
| &get_avatar_url::v3::Request::METADATA
|
| &get_avatar_url::v3::Request::METADATA
|
||||||
| &get_timezone_key::unstable::Request::METADATA => {
|
| &get_timezone_key::unstable::Request::METADATA => {
|
||||||
if services.server.config.require_auth_for_profile_requests {
|
if services
|
||||||
|
.server
|
||||||
|
.config
|
||||||
|
.require_auth_for_profile_requests
|
||||||
|
{
|
||||||
match token {
|
match token {
|
||||||
| Token::Appservice(_) | Token::User(_) => {
|
| Token::Appservice(_) | Token::User(_) => {
|
||||||
// we should have validated the token above
|
// we should have validated the token above
|
||||||
|
|||||||
@@ -23,7 +23,11 @@ where
|
|||||||
.inspect_err(|e| error!("response error: {e}"))
|
.inspect_err(|e| error!("response error: {e}"))
|
||||||
.map_or_else(
|
.map_or_else(
|
||||||
|_| StatusCode::INTERNAL_SERVER_ERROR.into_response(),
|
|_| StatusCode::INTERNAL_SERVER_ERROR.into_response(),
|
||||||
|r| r.map(BytesMut::freeze).map(Full::new).into_response(),
|
|r| {
|
||||||
|
r.map(BytesMut::freeze)
|
||||||
|
.map(Full::new)
|
||||||
|
.into_response()
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,8 +49,19 @@ pub(crate) async fn get_event_authorization_route(
|
|||||||
.auth_chain
|
.auth_chain
|
||||||
.event_ids_iter(room_id, once(body.event_id.borrow()))
|
.event_ids_iter(room_id, once(body.event_id.borrow()))
|
||||||
.ready_filter_map(Result::ok)
|
.ready_filter_map(Result::ok)
|
||||||
.filter_map(|id| async move { services.rooms.timeline.get_pdu_json(&id).await.ok() })
|
.filter_map(|id| async move {
|
||||||
.then(|pdu| services.sending.convert_to_outgoing_federation_event(pdu))
|
services
|
||||||
|
.rooms
|
||||||
|
.timeline
|
||||||
|
.get_pdu_json(&id)
|
||||||
|
.await
|
||||||
|
.ok()
|
||||||
|
})
|
||||||
|
.then(|pdu| {
|
||||||
|
services
|
||||||
|
.sending
|
||||||
|
.convert_to_outgoing_federation_event(pdu)
|
||||||
|
})
|
||||||
.collect()
|
.collect()
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,12 @@ pub(crate) async fn get_missing_events_route(
|
|||||||
|
|
||||||
let mut i: usize = 0;
|
let mut i: usize = 0;
|
||||||
while i < queued_events.len() && events.len() < limit {
|
while i < queued_events.len() && events.len() < limit {
|
||||||
let Ok(pdu) = services.rooms.timeline.get_pdu(&queued_events[i]).await else {
|
let Ok(pdu) = services
|
||||||
|
.rooms
|
||||||
|
.timeline
|
||||||
|
.get_pdu(&queued_events[i])
|
||||||
|
.await
|
||||||
|
else {
|
||||||
debug!(
|
debug!(
|
||||||
?body.origin,
|
?body.origin,
|
||||||
"Event {} does not exist locally, skipping", &queued_events[i]
|
"Event {} does not exist locally, skipping", &queued_events[i]
|
||||||
|
|||||||
@@ -17,7 +17,12 @@ pub(crate) async fn get_hierarchy_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<get_hierarchy::v1::Request>,
|
body: Ruma<get_hierarchy::v1::Request>,
|
||||||
) -> Result<get_hierarchy::v1::Response> {
|
) -> Result<get_hierarchy::v1::Response> {
|
||||||
if !services.rooms.metadata.exists(&body.room_id).await {
|
if !services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.exists(&body.room_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
return Err!(Request(NotFound("Room does not exist.")));
|
return Err!(Request(NotFound("Room does not exist.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,8 +65,15 @@ pub(crate) async fn get_hierarchy_route(
|
|||||||
.unzip()
|
.unzip()
|
||||||
.map(|(children, inaccessible_children): (Vec<_>, Vec<_>)| {
|
.map(|(children, inaccessible_children): (Vec<_>, Vec<_>)| {
|
||||||
(
|
(
|
||||||
children.into_iter().flatten().map(Into::into).collect(),
|
children
|
||||||
inaccessible_children.into_iter().flatten().collect(),
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.map(Into::into)
|
||||||
|
.collect(),
|
||||||
|
inaccessible_children
|
||||||
|
.into_iter()
|
||||||
|
.flatten()
|
||||||
|
.collect(),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.await;
|
.await;
|
||||||
|
|||||||
@@ -29,7 +29,10 @@ pub(crate) async fn create_invite_route(
|
|||||||
.acl_check(body.origin(), &body.room_id)
|
.acl_check(body.origin(), &body.room_id)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if !services.server.supported_room_version(&body.room_version) {
|
if !services
|
||||||
|
.server
|
||||||
|
.supported_room_version(&body.room_version)
|
||||||
|
{
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::IncompatibleRoomVersion { room_version: body.room_version.clone() },
|
ErrorKind::IncompatibleRoomVersion { room_version: body.room_version.clone() },
|
||||||
"Server does not support this room version.",
|
"Server does not support this room version.",
|
||||||
@@ -69,7 +72,10 @@ pub(crate) async fn create_invite_route(
|
|||||||
.map(UserId::to_owned)
|
.map(UserId::to_owned)
|
||||||
.map_err(|e| err!(Request(InvalidParam("Invalid state_key property: {e}"))))?;
|
.map_err(|e| err!(Request(InvalidParam("Invalid state_key property: {e}"))))?;
|
||||||
|
|
||||||
if !services.globals.server_is_ours(invited_user.server_name()) {
|
if !services
|
||||||
|
.globals
|
||||||
|
.server_is_ours(invited_user.server_name())
|
||||||
|
{
|
||||||
return Err!(Request(InvalidParam("User does not belong to this homeserver.")));
|
return Err!(Request(InvalidParam("User does not belong to this homeserver.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,8 +102,11 @@ pub(crate) async fn create_invite_route(
|
|||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|e| err!(Request(InvalidParam("Invalid sender property: {e}"))))?;
|
.map_err(|e| err!(Request(InvalidParam("Invalid sender property: {e}"))))?;
|
||||||
|
|
||||||
if services.rooms.metadata.is_banned(&body.room_id).await
|
if services
|
||||||
&& !services.users.is_admin(&invited_user).await
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.is_banned(&body.room_id)
|
||||||
|
.await && !services.users.is_admin(&invited_user).await
|
||||||
{
|
{
|
||||||
return Err!(Request(Forbidden("This room is banned on this homeserver.")));
|
return Err!(Request(Forbidden("This room is banned on this homeserver.")));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,10 @@ pub(crate) async fn get_server_keys_route(
|
|||||||
) -> Result<impl IntoResponse> {
|
) -> Result<impl IntoResponse> {
|
||||||
let server_name = services.globals.server_name();
|
let server_name = services.globals.server_name();
|
||||||
let active_key_id = services.server_keys.active_key_id();
|
let active_key_id = services.server_keys.active_key_id();
|
||||||
let mut all_keys = services.server_keys.verify_keys_for(server_name).await;
|
let mut all_keys = services
|
||||||
|
.server_keys
|
||||||
|
.verify_keys_for(server_name)
|
||||||
|
.await;
|
||||||
|
|
||||||
let verify_keys = all_keys
|
let verify_keys = all_keys
|
||||||
.remove_entry(active_key_id)
|
.remove_entry(active_key_id)
|
||||||
|
|||||||
@@ -26,7 +26,12 @@ pub(crate) async fn create_join_event_template_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<prepare_join_event::v1::Request>,
|
body: Ruma<prepare_join_event::v1::Request>,
|
||||||
) -> Result<prepare_join_event::v1::Response> {
|
) -> Result<prepare_join_event::v1::Response> {
|
||||||
if !services.rooms.metadata.exists(&body.room_id).await {
|
if !services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.exists(&body.room_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
return Err!(Request(NotFound("Room is unknown to this server.")));
|
return Err!(Request(NotFound("Room is unknown to this server.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,7 +73,11 @@ pub(crate) async fn create_join_event_template_route(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let room_version_id = services.rooms.state.get_room_version(&body.room_id).await?;
|
let room_version_id = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.get_room_version(&body.room_id)
|
||||||
|
.await?;
|
||||||
if !body.ver.contains(&room_version_id) {
|
if !body.ver.contains(&room_version_id) {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::IncompatibleRoomVersion { room_version: room_version_id },
|
ErrorKind::IncompatibleRoomVersion { room_version: room_version_id },
|
||||||
@@ -76,7 +85,12 @@ pub(crate) async fn create_join_event_template_route(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
let state_lock = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.mutex
|
||||||
|
.lock(&body.room_id)
|
||||||
|
.await;
|
||||||
|
|
||||||
let join_authorized_via_users_server: Option<OwnedUserId> = {
|
let join_authorized_via_users_server: Option<OwnedUserId> = {
|
||||||
use RoomVersionId::*;
|
use RoomVersionId::*;
|
||||||
@@ -157,7 +171,12 @@ pub(crate) async fn user_can_perform_restricted_join(
|
|||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if services.rooms.state_cache.is_joined(user_id, room_id).await {
|
if services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.is_joined(user_id, room_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
// joining user is already joined, there is nothing we need to do
|
// joining user is already joined, there is nothing we need to do
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
@@ -196,7 +215,12 @@ pub(crate) async fn user_can_perform_restricted_join(
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
.stream()
|
.stream()
|
||||||
.any(|m| services.rooms.state_cache.is_joined(user_id, &m.room_id))
|
.any(|m| {
|
||||||
|
services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.is_joined(user_id, &m.room_id)
|
||||||
|
})
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
Ok(true)
|
Ok(true)
|
||||||
|
|||||||
@@ -17,7 +17,12 @@ pub(crate) async fn create_knock_event_template_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<create_knock_event_template::v1::Request>,
|
body: Ruma<create_knock_event_template::v1::Request>,
|
||||||
) -> Result<create_knock_event_template::v1::Response> {
|
) -> Result<create_knock_event_template::v1::Response> {
|
||||||
if !services.rooms.metadata.exists(&body.room_id).await {
|
if !services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.exists(&body.room_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
return Err!(Request(NotFound("Room is unknown to this server.")));
|
return Err!(Request(NotFound("Room is unknown to this server.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +62,11 @@ pub(crate) async fn create_knock_event_template_route(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let room_version_id = services.rooms.state.get_room_version(&body.room_id).await?;
|
let room_version_id = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.get_room_version(&body.room_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
if matches!(room_version_id, V1 | V2 | V3 | V4 | V5 | V6) {
|
if matches!(room_version_id, V1 | V2 | V3 | V4 | V5 | V6) {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
@@ -73,7 +82,12 @@ pub(crate) async fn create_knock_event_template_route(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
let state_lock = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.mutex
|
||||||
|
.lock(&body.room_id)
|
||||||
|
.await;
|
||||||
|
|
||||||
if let Ok(membership) = services
|
if let Ok(membership) = services
|
||||||
.rooms
|
.rooms
|
||||||
|
|||||||
@@ -16,7 +16,12 @@ pub(crate) async fn create_leave_event_template_route(
|
|||||||
State(services): State<crate::State>,
|
State(services): State<crate::State>,
|
||||||
body: Ruma<prepare_leave_event::v1::Request>,
|
body: Ruma<prepare_leave_event::v1::Request>,
|
||||||
) -> Result<prepare_leave_event::v1::Response> {
|
) -> Result<prepare_leave_event::v1::Response> {
|
||||||
if !services.rooms.metadata.exists(&body.room_id).await {
|
if !services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.exists(&body.room_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
return Err!(Request(NotFound("Room is unknown to this server.")));
|
return Err!(Request(NotFound("Room is unknown to this server.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,8 +38,17 @@ pub(crate) async fn create_leave_event_template_route(
|
|||||||
.acl_check(body.origin(), &body.room_id)
|
.acl_check(body.origin(), &body.room_id)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let room_version_id = services.rooms.state.get_room_version(&body.room_id).await?;
|
let room_version_id = services
|
||||||
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
.rooms
|
||||||
|
.state
|
||||||
|
.get_room_version(&body.room_id)
|
||||||
|
.await?;
|
||||||
|
let state_lock = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.mutex
|
||||||
|
.lock(&body.room_id)
|
||||||
|
.await;
|
||||||
|
|
||||||
let (_pdu, mut pdu_json) = services
|
let (_pdu, mut pdu_json) = services
|
||||||
.rooms
|
.rooms
|
||||||
|
|||||||
@@ -73,7 +73,10 @@ pub(crate) async fn get_profile_information_route(
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !services.globals.server_is_ours(body.user_id.server_name()) {
|
if !services
|
||||||
|
.globals
|
||||||
|
.server_is_ours(body.user_id.server_name())
|
||||||
|
{
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
"User does not belong to this server.",
|
"User does not belong to this server.",
|
||||||
@@ -88,10 +91,18 @@ pub(crate) async fn get_profile_information_route(
|
|||||||
|
|
||||||
match &body.field {
|
match &body.field {
|
||||||
| Some(ProfileField::DisplayName) => {
|
| Some(ProfileField::DisplayName) => {
|
||||||
displayname = services.users.displayname(&body.user_id).await.ok();
|
displayname = services
|
||||||
|
.users
|
||||||
|
.displayname(&body.user_id)
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
},
|
},
|
||||||
| Some(ProfileField::AvatarUrl) => {
|
| Some(ProfileField::AvatarUrl) => {
|
||||||
avatar_url = services.users.avatar_url(&body.user_id).await.ok();
|
avatar_url = services
|
||||||
|
.users
|
||||||
|
.avatar_url(&body.user_id)
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
blurhash = services.users.blurhash(&body.user_id).await.ok();
|
blurhash = services.users.blurhash(&body.user_id).await.ok();
|
||||||
},
|
},
|
||||||
| Some(custom_field) => {
|
| Some(custom_field) => {
|
||||||
@@ -104,8 +115,16 @@ pub(crate) async fn get_profile_information_route(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
| None => {
|
| None => {
|
||||||
displayname = services.users.displayname(&body.user_id).await.ok();
|
displayname = services
|
||||||
avatar_url = services.users.avatar_url(&body.user_id).await.ok();
|
.users
|
||||||
|
.displayname(&body.user_id)
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
|
avatar_url = services
|
||||||
|
.users
|
||||||
|
.avatar_url(&body.user_id)
|
||||||
|
.await
|
||||||
|
.ok();
|
||||||
blurhash = services.users.blurhash(&body.user_id).await.ok();
|
blurhash = services.users.blurhash(&body.user_id).await.ok();
|
||||||
tz = services.users.timezone(&body.user_id).await.ok();
|
tz = services.users.timezone(&body.user_id).await.ok();
|
||||||
custom_profile_fields = services
|
custom_profile_fields = services
|
||||||
|
|||||||
@@ -92,7 +92,12 @@ pub(crate) async fn send_transaction_message_route(
|
|||||||
.pdus
|
.pdus
|
||||||
.iter()
|
.iter()
|
||||||
.stream()
|
.stream()
|
||||||
.broad_then(|pdu| services.rooms.event_handler.parse_incoming_pdu(pdu))
|
.broad_then(|pdu| {
|
||||||
|
services
|
||||||
|
.rooms
|
||||||
|
.event_handler
|
||||||
|
.parse_incoming_pdu(pdu)
|
||||||
|
})
|
||||||
.inspect_err(|e| debug_warn!("Could not parse PDU: {e}"))
|
.inspect_err(|e| debug_warn!("Could not parse PDU: {e}"))
|
||||||
.ready_filter_map(Result::ok);
|
.ready_filter_map(Result::ok);
|
||||||
|
|
||||||
@@ -215,7 +220,11 @@ async fn handle_edu(services: &Services, client: &IpAddr, origin: &ServerName, e
|
|||||||
| Edu::Presence(presence) if services.server.config.allow_incoming_presence =>
|
| Edu::Presence(presence) if services.server.config.allow_incoming_presence =>
|
||||||
handle_edu_presence(services, client, origin, presence).await,
|
handle_edu_presence(services, client, origin, presence).await,
|
||||||
|
|
||||||
| Edu::Receipt(receipt) if services.server.config.allow_incoming_read_receipts =>
|
| Edu::Receipt(receipt)
|
||||||
|
if services
|
||||||
|
.server
|
||||||
|
.config
|
||||||
|
.allow_incoming_read_receipts =>
|
||||||
handle_edu_receipt(services, client, origin, receipt).await,
|
handle_edu_receipt(services, client, origin, receipt).await,
|
||||||
|
|
||||||
| Edu::Typing(typing) if services.server.config.allow_incoming_typing =>
|
| Edu::Typing(typing) if services.server.config.allow_incoming_typing =>
|
||||||
@@ -454,7 +463,10 @@ async fn handle_edu_device_list_update(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
services.users.mark_device_key_update(&user_id).await;
|
services
|
||||||
|
.users
|
||||||
|
.mark_device_key_update(&user_id)
|
||||||
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn handle_edu_direct_to_device(
|
async fn handle_edu_direct_to_device(
|
||||||
|
|||||||
@@ -53,7 +53,11 @@ async fn create_join_event(
|
|||||||
|
|
||||||
// We do not add the event_id field to the pdu here because of signature and
|
// We do not add the event_id field to the pdu here because of signature and
|
||||||
// hashes checks
|
// hashes checks
|
||||||
let room_version_id = services.rooms.state.get_room_version(room_id).await?;
|
let room_version_id = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.get_room_version(room_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let Ok((event_id, mut value)) = gen_event_id_canonical_json(pdu, &room_version_id) else {
|
let Ok((event_id, mut value)) = gen_event_id_canonical_json(pdu, &room_version_id) else {
|
||||||
// Event could not be converted to canonical json
|
// Event could not be converted to canonical json
|
||||||
@@ -239,7 +243,11 @@ async fn create_join_event(
|
|||||||
.auth_chain
|
.auth_chain
|
||||||
.event_ids_iter(room_id, starting_events)
|
.event_ids_iter(room_id, starting_events)
|
||||||
.broad_and_then(|event_id| async move {
|
.broad_and_then(|event_id| async move {
|
||||||
services.rooms.timeline.get_pdu_json(&event_id).await
|
services
|
||||||
|
.rooms
|
||||||
|
.timeline
|
||||||
|
.get_pdu_json(&event_id)
|
||||||
|
.await
|
||||||
})
|
})
|
||||||
.broad_and_then(|pdu| {
|
.broad_and_then(|pdu| {
|
||||||
services
|
services
|
||||||
@@ -251,7 +259,10 @@ async fn create_join_event(
|
|||||||
.boxed()
|
.boxed()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
services.sending.send_pdu_room(room_id, &pdu_id).await?;
|
services
|
||||||
|
.sending
|
||||||
|
.send_pdu_room(room_id, &pdu_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
Ok(create_join_event::v1::RoomState {
|
Ok(create_join_event::v1::RoomState {
|
||||||
auth_chain,
|
auth_chain,
|
||||||
|
|||||||
@@ -55,7 +55,12 @@ pub(crate) async fn create_knock_event_v1_route(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !services.rooms.metadata.exists(&body.room_id).await {
|
if !services
|
||||||
|
.rooms
|
||||||
|
.metadata
|
||||||
|
.exists(&body.room_id)
|
||||||
|
.await
|
||||||
|
{
|
||||||
return Err!(Request(NotFound("Room is unknown to this server.")));
|
return Err!(Request(NotFound("Room is unknown to this server.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +71,11 @@ pub(crate) async fn create_knock_event_v1_route(
|
|||||||
.acl_check(body.origin(), &body.room_id)
|
.acl_check(body.origin(), &body.room_id)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let room_version_id = services.rooms.state.get_room_version(&body.room_id).await?;
|
let room_version_id = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.get_room_version(&body.room_id)
|
||||||
|
.await?;
|
||||||
|
|
||||||
if matches!(room_version_id, V1 | V2 | V3 | V4 | V5 | V6) {
|
if matches!(room_version_id, V1 | V2 | V3 | V4 | V5 | V6) {
|
||||||
return Err!(Request(Forbidden("Room version does not support knocking.")));
|
return Err!(Request(Forbidden("Room version does not support knocking.")));
|
||||||
|
|||||||
@@ -59,7 +59,11 @@ async fn create_leave_event(
|
|||||||
|
|
||||||
// We do not add the event_id field to the pdu here because of signature and
|
// We do not add the event_id field to the pdu here because of signature and
|
||||||
// hashes checks
|
// hashes checks
|
||||||
let room_version_id = services.rooms.state.get_room_version(room_id).await?;
|
let room_version_id = services
|
||||||
|
.rooms
|
||||||
|
.state
|
||||||
|
.get_room_version(room_id)
|
||||||
|
.await?;
|
||||||
let Ok((event_id, value)) = gen_event_id_canonical_json(pdu, &room_version_id) else {
|
let Ok((event_id, value)) = gen_event_id_canonical_json(pdu, &room_version_id) else {
|
||||||
// Event could not be converted to canonical json
|
// Event could not be converted to canonical json
|
||||||
return Err!(Request(BadJson("Could not convert event to canonical json.")));
|
return Err!(Request(BadJson("Could not convert event to canonical json.")));
|
||||||
|
|||||||
@@ -43,11 +43,10 @@ pub(super) async fn check(&self) -> Result {
|
|||||||
let server_can_see: OptionFuture<_> = self
|
let server_can_see: OptionFuture<_> = self
|
||||||
.event_id
|
.event_id
|
||||||
.map(|event_id| {
|
.map(|event_id| {
|
||||||
self.services.rooms.state_accessor.server_can_see_event(
|
self.services
|
||||||
self.origin,
|
.rooms
|
||||||
self.room_id,
|
.state_accessor
|
||||||
event_id,
|
.server_can_see_event(self.origin, self.room_id, event_id)
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
|
|||||||
@@ -369,7 +369,11 @@ where
|
|||||||
fn key(name: &str) -> Result<Key> {
|
fn key(name: &str) -> Result<Key> {
|
||||||
// tikv asserts the output buffer length is tight to the number of required mibs
|
// tikv asserts the output buffer length is tight to the number of required mibs
|
||||||
// so we slice that down here.
|
// so we slice that down here.
|
||||||
let segs = name.chars().filter(is_equal_to!(&'.')).count().try_add(1)?;
|
let segs = name
|
||||||
|
.chars()
|
||||||
|
.filter(is_equal_to!(&'.'))
|
||||||
|
.count()
|
||||||
|
.try_add(1)?;
|
||||||
|
|
||||||
let name = self::name(name)?;
|
let name = self::name(name)?;
|
||||||
let mut buf = [0_usize; KEY_SEGS];
|
let mut buf = [0_usize; KEY_SEGS];
|
||||||
|
|||||||
@@ -150,15 +150,18 @@ pub fn check(config: &Config) -> Result {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if we can read the token file path, and check if the file is empty
|
// check if we can read the token file path, and check if the file is empty
|
||||||
if config.registration_token_file.as_ref().is_some_and(|path| {
|
if config
|
||||||
let Ok(token) = std::fs::read_to_string(path).inspect_err(|e| {
|
.registration_token_file
|
||||||
error!("Failed to read the registration token file: {e}");
|
.as_ref()
|
||||||
}) else {
|
.is_some_and(|path| {
|
||||||
return true;
|
let Ok(token) = std::fs::read_to_string(path).inspect_err(|e| {
|
||||||
};
|
error!("Failed to read the registration token file: {e}");
|
||||||
|
}) else {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
token == String::new()
|
token == String::new()
|
||||||
}) {
|
}) {
|
||||||
return Err!(Config(
|
return Err!(Config(
|
||||||
"registration_token_file",
|
"registration_token_file",
|
||||||
"Registration token file was specified but is empty or failed to be read"
|
"Registration token file was specified but is empty or failed to be read"
|
||||||
|
|||||||
@@ -2218,8 +2218,12 @@ fn default_admin_room_tag() -> String { "m.server_notice".to_owned() }
|
|||||||
fn parallelism_scaled_f64(val: f64) -> f64 { val * (sys::available_parallelism() as f64) }
|
fn parallelism_scaled_f64(val: f64) -> f64 { val * (sys::available_parallelism() as f64) }
|
||||||
|
|
||||||
fn parallelism_scaled_u32(val: u32) -> u32 {
|
fn parallelism_scaled_u32(val: u32) -> u32 {
|
||||||
let val = val.try_into().expect("failed to cast u32 to usize");
|
let val = val
|
||||||
parallelism_scaled(val).try_into().unwrap_or(u32::MAX)
|
.try_into()
|
||||||
|
.expect("failed to cast u32 to usize");
|
||||||
|
parallelism_scaled(val)
|
||||||
|
.try_into()
|
||||||
|
.unwrap_or(u32::MAX)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parallelism_scaled(val: usize) -> usize { val.saturating_mul(sys::available_parallelism()) }
|
fn parallelism_scaled(val: usize) -> usize { val.saturating_mul(sys::available_parallelism()) }
|
||||||
|
|||||||
@@ -46,7 +46,10 @@ impl ProxyConfig {
|
|||||||
| Self::Global { url } => Some(Proxy::all(url)?),
|
| Self::Global { url } => Some(Proxy::all(url)?),
|
||||||
| Self::ByDomain(proxies) => Some(Proxy::custom(move |url| {
|
| Self::ByDomain(proxies) => Some(Proxy::custom(move |url| {
|
||||||
// first matching proxy
|
// first matching proxy
|
||||||
proxies.iter().find_map(|proxy| proxy.for_url(url)).cloned()
|
proxies
|
||||||
|
.iter()
|
||||||
|
.find_map(|proxy| proxy.for_url(url))
|
||||||
|
.cloned()
|
||||||
})),
|
})),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,9 @@ pub fn trap() {
|
|||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn panic_str(p: &Box<dyn Any + Send>) -> &'static str {
|
pub fn panic_str(p: &Box<dyn Any + Send>) -> &'static str {
|
||||||
p.downcast_ref::<&str>().copied().unwrap_or_default()
|
p.downcast_ref::<&str>()
|
||||||
|
.copied()
|
||||||
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
|
|||||||
@@ -184,7 +184,9 @@ impl Error {
|
|||||||
| Self::Request(kind, _, code) => response::status_code(kind, *code),
|
| Self::Request(kind, _, code) => response::status_code(kind, *code),
|
||||||
| Self::BadRequest(kind, ..) => response::bad_request_code(kind),
|
| Self::BadRequest(kind, ..) => response::bad_request_code(kind),
|
||||||
| Self::FeatureDisabled(..) => response::bad_request_code(&self.kind()),
|
| Self::FeatureDisabled(..) => response::bad_request_code(&self.kind()),
|
||||||
| Self::Reqwest(error) => error.status().unwrap_or(StatusCode::INTERNAL_SERVER_ERROR),
|
| Self::Reqwest(error) => error
|
||||||
|
.status()
|
||||||
|
.unwrap_or(StatusCode::INTERNAL_SERVER_ERROR),
|
||||||
| Self::Conflict(_) => StatusCode::CONFLICT,
|
| Self::Conflict(_) => StatusCode::CONFLICT,
|
||||||
| Self::Io(error) => response::io_error_code(error.kind()),
|
| Self::Io(error) => response::io_error_code(error.kind()),
|
||||||
| _ => StatusCode::INTERNAL_SERVER_ERROR,
|
| _ => StatusCode::INTERNAL_SERVER_ERROR,
|
||||||
|
|||||||
@@ -20,7 +20,11 @@ impl axum::response::IntoResponse for Error {
|
|||||||
.inspect_err(|e| error!("error response error: {e}"))
|
.inspect_err(|e| error!("error response error: {e}"))
|
||||||
.map_or_else(
|
.map_or_else(
|
||||||
|_| StatusCode::INTERNAL_SERVER_ERROR.into_response(),
|
|_| StatusCode::INTERNAL_SERVER_ERROR.into_response(),
|
||||||
|r| r.map(BytesMut::freeze).map(Full::new).into_response(),
|
|r| {
|
||||||
|
r.map(BytesMut::freeze)
|
||||||
|
.map(Full::new)
|
||||||
|
.into_response()
|
||||||
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,10 @@ static DEPENDENCIES: OnceLock<DepsSet> = OnceLock::new();
|
|||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn dependencies_names() -> Vec<&'static str> {
|
pub fn dependencies_names() -> Vec<&'static str> {
|
||||||
dependencies().keys().map(String::as_str).collect()
|
dependencies()
|
||||||
|
.keys()
|
||||||
|
.map(String::as_str)
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dependencies() -> &'static DepsSet {
|
pub fn dependencies() -> &'static DepsSet {
|
||||||
|
|||||||
@@ -25,7 +25,8 @@ type RoomVersion = (RoomVersionId, RoomVersionStability);
|
|||||||
impl crate::Server {
|
impl crate::Server {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn supported_room_version(&self, version: &RoomVersionId) -> bool {
|
pub fn supported_room_version(&self, version: &RoomVersionId) -> bool {
|
||||||
self.supported_room_versions().any(is_equal_to!(*version))
|
self.supported_room_versions()
|
||||||
|
.any(is_equal_to!(*version))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|||||||
@@ -20,10 +20,19 @@ impl Data<'_> {
|
|||||||
pub fn level(&self) -> Level { *self.event.metadata().level() }
|
pub fn level(&self) -> Level { *self.event.metadata().level() }
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn mod_name(&self) -> &str { self.event.metadata().module_path().unwrap_or_default() }
|
pub fn mod_name(&self) -> &str {
|
||||||
|
self.event
|
||||||
|
.metadata()
|
||||||
|
.module_path()
|
||||||
|
.unwrap_or_default()
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn span_name(&self) -> &str { self.current.metadata().map_or(EMPTY, |s| s.name()) }
|
pub fn span_name(&self) -> &str {
|
||||||
|
self.current
|
||||||
|
.metadata()
|
||||||
|
.map_or(EMPTY, |s| s.name())
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn message(&self) -> &str {
|
pub fn message(&self) -> &str {
|
||||||
|
|||||||
@@ -103,8 +103,10 @@ where
|
|||||||
writer: Writer<'_>,
|
writer: Writer<'_>,
|
||||||
event: &Event<'_>,
|
event: &Event<'_>,
|
||||||
) -> Result<(), std::fmt::Error> {
|
) -> Result<(), std::fmt::Error> {
|
||||||
let is_debug =
|
let is_debug = cfg!(debug_assertions)
|
||||||
cfg!(debug_assertions) && event.fields().any(|field| field.name() == "_debug");
|
&& event
|
||||||
|
.fields()
|
||||||
|
.any(|field| field.name() == "_debug");
|
||||||
|
|
||||||
match *event.metadata().level() {
|
match *event.metadata().level() {
|
||||||
| Level::ERROR if !is_debug => self.pretty.format_event(ctx, writer, event),
|
| Level::ERROR if !is_debug => self.pretty.format_event(ctx, writer, event),
|
||||||
|
|||||||
@@ -56,7 +56,9 @@ impl LogLevelReloadHandles {
|
|||||||
.iter()
|
.iter()
|
||||||
.filter(|(name, _)| names.is_some_and(|names| names.contains(&name.as_str())))
|
.filter(|(name, _)| names.is_some_and(|names| names.contains(&name.as_str())))
|
||||||
.for_each(|(_, handle)| {
|
.for_each(|(_, handle)| {
|
||||||
_ = handle.reload(new_value.clone()).or_else(error::else_log);
|
_ = handle
|
||||||
|
.reload(new_value.clone())
|
||||||
|
.or_else(error::else_log);
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@@ -58,7 +58,11 @@ fn matches_sender(&self, filter: &RoomEventFilter) -> bool {
|
|||||||
#[implement(super::Pdu)]
|
#[implement(super::Pdu)]
|
||||||
fn matches_type(&self, filter: &RoomEventFilter) -> bool {
|
fn matches_type(&self, filter: &RoomEventFilter) -> bool {
|
||||||
let event_type = &self.kind.to_cow_str();
|
let event_type = &self.kind.to_cow_str();
|
||||||
if filter.not_types.iter().any(is_equal_to!(event_type)) {
|
if filter
|
||||||
|
.not_types
|
||||||
|
.iter()
|
||||||
|
.any(is_equal_to!(event_type))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,11 @@ impl From<Id> for RawId {
|
|||||||
match id.shorteventid {
|
match id.shorteventid {
|
||||||
| Count::Normal(shorteventid) => {
|
| Count::Normal(shorteventid) => {
|
||||||
vec.extend(shorteventid.to_be_bytes());
|
vec.extend(shorteventid.to_be_bytes());
|
||||||
Self::Normal(vec.as_ref().try_into().expect("RawVec into RawId::Normal"))
|
Self::Normal(
|
||||||
|
vec.as_ref()
|
||||||
|
.try_into()
|
||||||
|
.expect("RawVec into RawId::Normal"),
|
||||||
|
)
|
||||||
},
|
},
|
||||||
| Count::Backfilled(shorteventid) => {
|
| Count::Backfilled(shorteventid) => {
|
||||||
vec.extend(0_u64.to_be_bytes());
|
vec.extend(0_u64.to_be_bytes());
|
||||||
|
|||||||
@@ -102,7 +102,8 @@ where
|
|||||||
#[implement(Pdu)]
|
#[implement(Pdu)]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn get_unsigned_as_value(&self) -> JsonValue {
|
pub fn get_unsigned_as_value(&self) -> JsonValue {
|
||||||
self.get_unsigned::<JsonValue>().unwrap_or_default()
|
self.get_unsigned::<JsonValue>()
|
||||||
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[implement(Pdu)]
|
#[implement(Pdu)]
|
||||||
|
|||||||
@@ -104,7 +104,10 @@ pub fn auth_types_for_event(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if membership == MembershipState::Invite {
|
if membership == MembershipState::Invite {
|
||||||
if let Some(Ok(t_id)) = content.third_party_invite.map(|t| t.deserialize()) {
|
if let Some(Ok(t_id)) = content
|
||||||
|
.third_party_invite
|
||||||
|
.map(|t| t.deserialize())
|
||||||
|
{
|
||||||
let key =
|
let key =
|
||||||
(StateEventType::RoomThirdPartyInvite, t_id.signed.token.into());
|
(StateEventType::RoomThirdPartyInvite, t_id.signed.token.into());
|
||||||
if !auth_types.contains(&key) {
|
if !auth_types.contains(&key) {
|
||||||
@@ -564,9 +567,12 @@ fn valid_membership_change(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let power_levels_event_id = power_levels_event.as_ref().map(Event::event_id);
|
let power_levels_event_id = power_levels_event.as_ref().map(Event::event_id);
|
||||||
let sender_membership_event_id = sender_membership_event.as_ref().map(Event::event_id);
|
let sender_membership_event_id = sender_membership_event
|
||||||
let target_user_membership_event_id =
|
.as_ref()
|
||||||
target_user_membership_event.as_ref().map(Event::event_id);
|
.map(Event::event_id);
|
||||||
|
let target_user_membership_event_id = target_user_membership_event
|
||||||
|
.as_ref()
|
||||||
|
.map(Event::event_id);
|
||||||
|
|
||||||
let user_for_join_auth_is_valid = if let Some(user_for_join_auth) = user_for_join_auth {
|
let user_for_join_auth_is_valid = if let Some(user_for_join_auth) = user_for_join_auth {
|
||||||
// Is the authorised user allowed to invite users into this room
|
// Is the authorised user allowed to invite users into this room
|
||||||
@@ -725,7 +731,9 @@ fn valid_membership_change(
|
|||||||
allow
|
allow
|
||||||
} else if !sender_is_joined
|
} else if !sender_is_joined
|
||||||
|| target_user_current_membership == MembershipState::Ban
|
|| target_user_current_membership == MembershipState::Ban
|
||||||
&& sender_power.filter(|&p| p < &power_levels.ban).is_some()
|
&& sender_power
|
||||||
|
.filter(|&p| p < &power_levels.ban)
|
||||||
|
.is_some()
|
||||||
{
|
{
|
||||||
warn!(
|
warn!(
|
||||||
?target_user_membership_event_id,
|
?target_user_membership_event_id,
|
||||||
@@ -734,8 +742,9 @@ fn valid_membership_change(
|
|||||||
);
|
);
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
let allow = sender_power.filter(|&p| p >= &power_levels.kick).is_some()
|
let allow = sender_power
|
||||||
&& target_power < sender_power;
|
.filter(|&p| p >= &power_levels.kick)
|
||||||
|
.is_some() && target_power < sender_power;
|
||||||
if !allow {
|
if !allow {
|
||||||
warn!(
|
warn!(
|
||||||
?target_user_membership_event_id,
|
?target_user_membership_event_id,
|
||||||
@@ -750,8 +759,9 @@ fn valid_membership_change(
|
|||||||
warn!(?sender_membership_event_id, "Can't ban user if sender is not joined");
|
warn!(?sender_membership_event_id, "Can't ban user if sender is not joined");
|
||||||
false
|
false
|
||||||
} else {
|
} else {
|
||||||
let allow = sender_power.filter(|&p| p >= &power_levels.ban).is_some()
|
let allow = sender_power
|
||||||
&& target_power < sender_power;
|
.filter(|&p| p >= &power_levels.ban)
|
||||||
|
.is_some() && target_power < sender_power;
|
||||||
if !allow {
|
if !allow {
|
||||||
warn!(
|
warn!(
|
||||||
?target_user_membership_event_id,
|
?target_user_membership_event_id,
|
||||||
@@ -829,7 +839,9 @@ fn can_send_event(event: impl Event, ple: Option<impl Event>, user_level: Int) -
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if event.state_key().is_some_and(|k| k.starts_with('@'))
|
if event
|
||||||
|
.state_key()
|
||||||
|
.is_some_and(|k| k.starts_with('@'))
|
||||||
&& event.state_key() != Some(event.sender().as_str())
|
&& event.state_key() != Some(event.sender().as_str())
|
||||||
{
|
{
|
||||||
return false; // permission required to post in this room
|
return false; // permission required to post in this room
|
||||||
@@ -1040,13 +1052,17 @@ fn get_send_level(
|
|||||||
.and_then(|ple| {
|
.and_then(|ple| {
|
||||||
from_json_str::<RoomPowerLevelsEventContent>(ple.content().get())
|
from_json_str::<RoomPowerLevelsEventContent>(ple.content().get())
|
||||||
.map(|content| {
|
.map(|content| {
|
||||||
content.events.get(e_type).copied().unwrap_or_else(|| {
|
content
|
||||||
if state_key.is_some() {
|
.events
|
||||||
content.state_default
|
.get(e_type)
|
||||||
} else {
|
.copied()
|
||||||
content.events_default
|
.unwrap_or_else(|| {
|
||||||
}
|
if state_key.is_some() {
|
||||||
})
|
content.state_default
|
||||||
|
} else {
|
||||||
|
content.events_default
|
||||||
|
}
|
||||||
|
})
|
||||||
})
|
})
|
||||||
.ok()
|
.ok()
|
||||||
})
|
})
|
||||||
@@ -1135,13 +1151,21 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_ban_pass() {
|
fn test_ban_pass() {
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
let events = INITIAL_EVENTS();
|
let events = INITIAL_EVENTS();
|
||||||
|
|
||||||
let auth_events = events
|
let auth_events = events
|
||||||
.values()
|
.values()
|
||||||
.map(|ev| (ev.event_type().with_state_key(ev.state_key().unwrap()), ev.clone()))
|
.map(|ev| {
|
||||||
|
(
|
||||||
|
ev.event_type()
|
||||||
|
.with_state_key(ev.state_key().unwrap()),
|
||||||
|
ev.clone(),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect::<StateMap<_>>();
|
.collect::<StateMap<_>>();
|
||||||
|
|
||||||
let requester = to_pdu_event(
|
let requester = to_pdu_event(
|
||||||
@@ -1180,13 +1204,21 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_join_non_creator() {
|
fn test_join_non_creator() {
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
let events = INITIAL_EVENTS_CREATE_ROOM();
|
let events = INITIAL_EVENTS_CREATE_ROOM();
|
||||||
|
|
||||||
let auth_events = events
|
let auth_events = events
|
||||||
.values()
|
.values()
|
||||||
.map(|ev| (ev.event_type().with_state_key(ev.state_key().unwrap()), ev.clone()))
|
.map(|ev| {
|
||||||
|
(
|
||||||
|
ev.event_type()
|
||||||
|
.with_state_key(ev.state_key().unwrap()),
|
||||||
|
ev.clone(),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect::<StateMap<_>>();
|
.collect::<StateMap<_>>();
|
||||||
|
|
||||||
let requester = to_pdu_event(
|
let requester = to_pdu_event(
|
||||||
@@ -1225,13 +1257,21 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_join_creator() {
|
fn test_join_creator() {
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
let events = INITIAL_EVENTS_CREATE_ROOM();
|
let events = INITIAL_EVENTS_CREATE_ROOM();
|
||||||
|
|
||||||
let auth_events = events
|
let auth_events = events
|
||||||
.values()
|
.values()
|
||||||
.map(|ev| (ev.event_type().with_state_key(ev.state_key().unwrap()), ev.clone()))
|
.map(|ev| {
|
||||||
|
(
|
||||||
|
ev.event_type()
|
||||||
|
.with_state_key(ev.state_key().unwrap()),
|
||||||
|
ev.clone(),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect::<StateMap<_>>();
|
.collect::<StateMap<_>>();
|
||||||
|
|
||||||
let requester = to_pdu_event(
|
let requester = to_pdu_event(
|
||||||
@@ -1270,13 +1310,21 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_ban_fail() {
|
fn test_ban_fail() {
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
let events = INITIAL_EVENTS();
|
let events = INITIAL_EVENTS();
|
||||||
|
|
||||||
let auth_events = events
|
let auth_events = events
|
||||||
.values()
|
.values()
|
||||||
.map(|ev| (ev.event_type().with_state_key(ev.state_key().unwrap()), ev.clone()))
|
.map(|ev| {
|
||||||
|
(
|
||||||
|
ev.event_type()
|
||||||
|
.with_state_key(ev.state_key().unwrap()),
|
||||||
|
ev.clone(),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect::<StateMap<_>>();
|
.collect::<StateMap<_>>();
|
||||||
|
|
||||||
let requester = to_pdu_event(
|
let requester = to_pdu_event(
|
||||||
@@ -1315,7 +1363,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_restricted_join_rule() {
|
fn test_restricted_join_rule() {
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
let mut events = INITIAL_EVENTS();
|
let mut events = INITIAL_EVENTS();
|
||||||
*events.get_mut(&event_id("IJR")).unwrap() = to_pdu_event(
|
*events.get_mut(&event_id("IJR")).unwrap() = to_pdu_event(
|
||||||
@@ -1338,7 +1388,13 @@ mod tests {
|
|||||||
|
|
||||||
let auth_events = events
|
let auth_events = events
|
||||||
.values()
|
.values()
|
||||||
.map(|ev| (ev.event_type().with_state_key(ev.state_key().unwrap()), ev.clone()))
|
.map(|ev| {
|
||||||
|
(
|
||||||
|
ev.event_type()
|
||||||
|
.with_state_key(ev.state_key().unwrap()),
|
||||||
|
ev.clone(),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect::<StateMap<_>>();
|
.collect::<StateMap<_>>();
|
||||||
|
|
||||||
let requester = to_pdu_event(
|
let requester = to_pdu_event(
|
||||||
@@ -1395,7 +1451,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_knock() {
|
fn test_knock() {
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
let mut events = INITIAL_EVENTS();
|
let mut events = INITIAL_EVENTS();
|
||||||
*events.get_mut(&event_id("IJR")).unwrap() = to_pdu_event(
|
*events.get_mut(&event_id("IJR")).unwrap() = to_pdu_event(
|
||||||
@@ -1410,7 +1468,13 @@ mod tests {
|
|||||||
|
|
||||||
let auth_events = events
|
let auth_events = events
|
||||||
.values()
|
.values()
|
||||||
.map(|ev| (ev.event_type().with_state_key(ev.state_key().unwrap()), ev.clone()))
|
.map(|ev| {
|
||||||
|
(
|
||||||
|
ev.event_type()
|
||||||
|
.with_state_key(ev.state_key().unwrap()),
|
||||||
|
ev.clone(),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect::<StateMap<_>>();
|
.collect::<StateMap<_>>();
|
||||||
|
|
||||||
let requester = to_pdu_event(
|
let requester = to_pdu_event(
|
||||||
|
|||||||
@@ -429,7 +429,10 @@ where
|
|||||||
|
|
||||||
reverse_graph.entry(node).or_default();
|
reverse_graph.entry(node).or_default();
|
||||||
for edge in edges {
|
for edge in edges {
|
||||||
reverse_graph.entry(edge).or_default().insert(node);
|
reverse_graph
|
||||||
|
.entry(edge)
|
||||||
|
.or_default()
|
||||||
|
.insert(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -710,7 +713,9 @@ where
|
|||||||
.iter()
|
.iter()
|
||||||
.stream()
|
.stream()
|
||||||
.broad_filter_map(async |ev_id| {
|
.broad_filter_map(async |ev_id| {
|
||||||
fetch_event(ev_id.clone()).await.map(|event| (event, ev_id))
|
fetch_event(ev_id.clone())
|
||||||
|
.await
|
||||||
|
.map(|event| (event, ev_id))
|
||||||
})
|
})
|
||||||
.broad_filter_map(|(event, ev_id)| {
|
.broad_filter_map(|(event, ev_id)| {
|
||||||
get_mainline_depth(Some(event.clone()), &mainline_map, fetch_event)
|
get_mainline_depth(Some(event.clone()), &mainline_map, fetch_event)
|
||||||
@@ -782,7 +787,11 @@ async fn add_event_and_auth_chain_to_graph<E, F, Fut>(
|
|||||||
while let Some(eid) = state.pop() {
|
while let Some(eid) = state.pop() {
|
||||||
graph.entry(eid.clone()).or_default();
|
graph.entry(eid.clone()).or_default();
|
||||||
let event = fetch_event(eid.clone()).await;
|
let event = fetch_event(eid.clone()).await;
|
||||||
let auth_events = event.as_ref().map(Event::auth_events).into_iter().flatten();
|
let auth_events = event
|
||||||
|
.as_ref()
|
||||||
|
.map(Event::auth_events)
|
||||||
|
.into_iter()
|
||||||
|
.flatten();
|
||||||
|
|
||||||
// Prefer the store to event as the store filters dedups the events
|
// Prefer the store to event as the store filters dedups the events
|
||||||
for aid in auth_events {
|
for aid in auth_events {
|
||||||
@@ -792,7 +801,10 @@ async fn add_event_and_auth_chain_to_graph<E, F, Fut>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We just inserted this at the start of the while loop
|
// We just inserted this at the start of the while loop
|
||||||
graph.get_mut(eid.borrow()).unwrap().insert(aid.to_owned());
|
graph
|
||||||
|
.get_mut(eid.borrow())
|
||||||
|
.unwrap()
|
||||||
|
.insert(aid.to_owned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -890,13 +902,21 @@ mod tests {
|
|||||||
use futures::future::ready;
|
use futures::future::ready;
|
||||||
|
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
let events = INITIAL_EVENTS();
|
let events = INITIAL_EVENTS();
|
||||||
|
|
||||||
let event_map = events
|
let event_map = events
|
||||||
.values()
|
.values()
|
||||||
.map(|ev| (ev.event_type().with_state_key(ev.state_key().unwrap()), ev.clone()))
|
.map(|ev| {
|
||||||
|
(
|
||||||
|
ev.event_type()
|
||||||
|
.with_state_key(ev.state_key().unwrap()),
|
||||||
|
ev.clone(),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect::<StateMap<_>>();
|
.collect::<StateMap<_>>();
|
||||||
|
|
||||||
let auth_chain: HashSet<OwnedEventId> = HashSet::new();
|
let auth_chain: HashSet<OwnedEventId> = HashSet::new();
|
||||||
@@ -965,7 +985,9 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn ban_vs_power_level() {
|
async fn ban_vs_power_level() {
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let events = &[
|
let events = &[
|
||||||
@@ -1015,7 +1037,9 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn topic_basic() {
|
async fn topic_basic() {
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let events = &[
|
let events = &[
|
||||||
@@ -1080,7 +1104,9 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn topic_reset() {
|
async fn topic_reset() {
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let events = &[
|
let events = &[
|
||||||
@@ -1130,7 +1156,9 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn join_rule_evasion() {
|
async fn join_rule_evasion() {
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let events = &[
|
let events = &[
|
||||||
@@ -1163,7 +1191,9 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn offtopic_power_level() {
|
async fn offtopic_power_level() {
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let events = &[
|
let events = &[
|
||||||
@@ -1199,7 +1229,10 @@ mod tests {
|
|||||||
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
|
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let expected_state_ids = vec!["PC"].into_iter().map(event_id).collect::<Vec<_>>();
|
let expected_state_ids = vec!["PC"]
|
||||||
|
.into_iter()
|
||||||
|
.map(event_id)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
do_check(events, edges, expected_state_ids).await;
|
do_check(events, edges, expected_state_ids).await;
|
||||||
}
|
}
|
||||||
@@ -1207,7 +1240,9 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn topic_setting() {
|
async fn topic_setting() {
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let events = &[
|
let events = &[
|
||||||
@@ -1289,7 +1324,9 @@ mod tests {
|
|||||||
use futures::future::ready;
|
use futures::future::ready;
|
||||||
|
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut store = TestStore::<PduEvent>(hashmap! {});
|
let mut store = TestStore::<PduEvent>(hashmap! {});
|
||||||
@@ -1332,7 +1369,9 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_lexicographical_sort() {
|
async fn test_lexicographical_sort() {
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let graph = hashmap! {
|
let graph = hashmap! {
|
||||||
@@ -1361,7 +1400,9 @@ mod tests {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn ban_with_auth_chains() {
|
async fn ban_with_auth_chains() {
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
let ban = BAN_STATE_SET();
|
let ban = BAN_STATE_SET();
|
||||||
|
|
||||||
@@ -1383,7 +1424,9 @@ mod tests {
|
|||||||
use futures::future::ready;
|
use futures::future::ready;
|
||||||
|
|
||||||
let _ = tracing::subscriber::set_default(
|
let _ = tracing::subscriber::set_default(
|
||||||
tracing_subscriber::fmt().with_test_writer().finish(),
|
tracing_subscriber::fmt()
|
||||||
|
.with_test_writer()
|
||||||
|
.finish(),
|
||||||
);
|
);
|
||||||
let init = INITIAL_EVENTS();
|
let init = INITIAL_EVENTS();
|
||||||
let ban = BAN_STATE_SET();
|
let ban = BAN_STATE_SET();
|
||||||
@@ -1402,7 +1445,13 @@ mod tests {
|
|||||||
inner.get(&event_id("PA")).unwrap(),
|
inner.get(&event_id("PA")).unwrap(),
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|ev| (ev.event_type().with_state_key(ev.state_key().unwrap()), ev.event_id.clone()))
|
.map(|ev| {
|
||||||
|
(
|
||||||
|
ev.event_type()
|
||||||
|
.with_state_key(ev.state_key().unwrap()),
|
||||||
|
ev.event_id.clone(),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect::<StateMap<_>>();
|
.collect::<StateMap<_>>();
|
||||||
|
|
||||||
let state_set_b = [
|
let state_set_b = [
|
||||||
@@ -1415,7 +1464,13 @@ mod tests {
|
|||||||
inner.get(&event_id("PA")).unwrap(),
|
inner.get(&event_id("PA")).unwrap(),
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|ev| (ev.event_type().with_state_key(ev.state_key().unwrap()), ev.event_id.clone()))
|
.map(|ev| {
|
||||||
|
(
|
||||||
|
ev.event_type()
|
||||||
|
.with_state_key(ev.state_key().unwrap()),
|
||||||
|
ev.event_id.clone(),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect::<StateMap<_>>();
|
.collect::<StateMap<_>>();
|
||||||
|
|
||||||
let ev_map = &store.0;
|
let ev_map = &store.0;
|
||||||
@@ -1479,7 +1534,10 @@ mod tests {
|
|||||||
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
|
.map(|list| list.into_iter().map(event_id).collect::<Vec<_>>())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let expected_state_ids = vec!["JR"].into_iter().map(event_id).collect::<Vec<_>>();
|
let expected_state_ids = vec!["JR"]
|
||||||
|
.into_iter()
|
||||||
|
.map(event_id)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
do_check(&join_rule.values().cloned().collect::<Vec<_>>(), edges, expected_state_ids)
|
do_check(&join_rule.values().cloned().collect::<Vec<_>>(), edges, expected_state_ids)
|
||||||
.await;
|
.await;
|
||||||
|
|||||||
@@ -206,12 +206,16 @@ pub(crate) async fn do_check(
|
|||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
|
||||||
let key = ev.event_type().with_state_key(ev.state_key().unwrap());
|
let key = ev
|
||||||
|
.event_type()
|
||||||
|
.with_state_key(ev.state_key().unwrap());
|
||||||
|
|
||||||
expected_state.insert(key, node);
|
expected_state.insert(key, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
let start_state = state_at_event.get(event_id!("$START:foo")).unwrap();
|
let start_state = state_at_event
|
||||||
|
.get(event_id!("$START:foo"))
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let end_state = state_at_event
|
let end_state = state_at_event
|
||||||
.get(event_id!("$END:foo"))
|
.get(event_id!("$END:foo"))
|
||||||
@@ -340,21 +344,33 @@ impl TestStore<PduEvent> {
|
|||||||
let state_at_bob = [&create_event, &alice_mem, &join_rules, &bob_mem]
|
let state_at_bob = [&create_event, &alice_mem, &join_rules, &bob_mem]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| {
|
.map(|e| {
|
||||||
(e.event_type().with_state_key(e.state_key().unwrap()), e.event_id().to_owned())
|
(
|
||||||
|
e.event_type()
|
||||||
|
.with_state_key(e.state_key().unwrap()),
|
||||||
|
e.event_id().to_owned(),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.collect::<StateMap<_>>();
|
.collect::<StateMap<_>>();
|
||||||
|
|
||||||
let state_at_charlie = [&create_event, &alice_mem, &join_rules, &charlie_mem]
|
let state_at_charlie = [&create_event, &alice_mem, &join_rules, &charlie_mem]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| {
|
.map(|e| {
|
||||||
(e.event_type().with_state_key(e.state_key().unwrap()), e.event_id().to_owned())
|
(
|
||||||
|
e.event_type()
|
||||||
|
.with_state_key(e.state_key().unwrap()),
|
||||||
|
e.event_id().to_owned(),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.collect::<StateMap<_>>();
|
.collect::<StateMap<_>>();
|
||||||
|
|
||||||
let expected = [&create_event, &alice_mem, &join_rules, &bob_mem, &charlie_mem]
|
let expected = [&create_event, &alice_mem, &join_rules, &bob_mem, &charlie_mem]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|e| {
|
.map(|e| {
|
||||||
(e.event_type().with_state_key(e.state_key().unwrap()), e.event_id().to_owned())
|
(
|
||||||
|
e.event_type()
|
||||||
|
.with_state_key(e.state_key().unwrap()),
|
||||||
|
e.event_id().to_owned(),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.collect::<StateMap<_>>();
|
.collect::<StateMap<_>>();
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,9 @@ impl Metrics {
|
|||||||
let runtime_monitor = runtime.as_ref().map(RuntimeMonitor::new);
|
let runtime_monitor = runtime.as_ref().map(RuntimeMonitor::new);
|
||||||
|
|
||||||
#[cfg(tokio_unstable)]
|
#[cfg(tokio_unstable)]
|
||||||
let runtime_intervals = runtime_monitor.as_ref().map(RuntimeMonitor::intervals);
|
let runtime_intervals = runtime_monitor
|
||||||
|
.as_ref()
|
||||||
|
.map(RuntimeMonitor::intervals);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
_runtime: runtime.clone(),
|
_runtime: runtime.clone(),
|
||||||
|
|||||||
@@ -27,7 +27,10 @@ pub fn to_name(path: &OsStr) -> Result<String> {
|
|||||||
.expect("path file stem")
|
.expect("path file stem")
|
||||||
.to_str()
|
.to_str()
|
||||||
.expect("name string");
|
.expect("name string");
|
||||||
let name = name.strip_prefix("lib").unwrap_or(name).to_owned();
|
let name = name
|
||||||
|
.strip_prefix("lib")
|
||||||
|
.unwrap_or(name)
|
||||||
|
.to_owned();
|
||||||
|
|
||||||
Ok(name)
|
Ok(name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,9 @@ pub fn from_str(str: &str) -> Result<usize> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn pretty(bytes: usize) -> String {
|
pub fn pretty(bytes: usize) -> String {
|
||||||
let bytes: u64 = bytes.try_into().expect("failed to convert usize to u64");
|
let bytes: u64 = bytes
|
||||||
|
.try_into()
|
||||||
|
.expect("failed to convert usize to u64");
|
||||||
|
|
||||||
ByteSize::b(bytes).display().iec().to_string()
|
ByteSize::b(bytes).display().iec().to_string()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -73,7 +73,9 @@ where
|
|||||||
|
|
||||||
Ok(Guard::<Key, Val> {
|
Ok(Guard::<Key, Val> {
|
||||||
map: Arc::clone(&self.map),
|
map: Arc::clone(&self.map),
|
||||||
val: val.try_lock_owned().map_err(|_| err!("would yield"))?,
|
val: val
|
||||||
|
.try_lock_owned()
|
||||||
|
.map_err(|_| err!("would yield"))?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +99,9 @@ where
|
|||||||
|
|
||||||
Ok(Guard::<Key, Val> {
|
Ok(Guard::<Key, Val> {
|
||||||
map: Arc::clone(&self.map),
|
map: Arc::clone(&self.map),
|
||||||
val: val.try_lock_owned().map_err(|_| err!("would yield"))?,
|
val: val
|
||||||
|
.try_lock_owned()
|
||||||
|
.map_err(|_| err!("would yield"))?,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,9 @@ impl<T> UnwrapInfallible<T> for Result<T, Infallible> {
|
|||||||
fn unwrap_infallible(self) -> T {
|
fn unwrap_infallible(self) -> T {
|
||||||
// SAFETY: Branchless unwrap for errors that can never happen. In debug
|
// SAFETY: Branchless unwrap for errors that can never happen. In debug
|
||||||
// mode this is asserted.
|
// mode this is asserted.
|
||||||
unsafe { self.debug_inspect_err(error::infallible).unwrap_unchecked() }
|
unsafe {
|
||||||
|
self.debug_inspect_err(error::infallible)
|
||||||
|
.unwrap_unchecked()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -68,7 +68,11 @@ where
|
|||||||
a.map(move |ai| (ai, b.clone()))
|
a.map(move |ai| (ai, b.clone()))
|
||||||
.filter_map(|(ai, b)| async move {
|
.filter_map(|(ai, b)| async move {
|
||||||
let mut lock = b.lock().await;
|
let mut lock = b.lock().await;
|
||||||
while let Some(bi) = Pin::new(&mut *lock).next_if(|bi| *bi <= ai).await.as_ref() {
|
while let Some(bi) = Pin::new(&mut *lock)
|
||||||
|
.next_if(|bi| *bi <= ai)
|
||||||
|
.await
|
||||||
|
.as_ref()
|
||||||
|
{
|
||||||
if ai == *bi {
|
if ai == *bi {
|
||||||
return Some(ai);
|
return Some(ai);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,11 @@ where
|
|||||||
let h = h.into().unwrap_or_else(runtime::Handle::current);
|
let h = h.into().unwrap_or_else(runtime::Handle::current);
|
||||||
self.broadn_and_then(n, move |val| {
|
self.broadn_and_then(n, move |val| {
|
||||||
let (h, f) = (h.clone(), f.clone());
|
let (h, f) = (h.clone(), f.clone());
|
||||||
async move { h.spawn_blocking(move || f(val)).map_err(E::from).await? }
|
async move {
|
||||||
|
h.spawn_blocking(move || f(val))
|
||||||
|
.map_err(E::from)
|
||||||
|
.await?
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user