cargo fmt
This commit is contained in:
parent
33a2b2b772
commit
a4637e2ba1
119 changed files with 2787 additions and 1761 deletions
|
@ -1,7 +1,11 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use ruma::{UserId, RoomId, events::{RoomAccountDataEventType, AnyEphemeralRoomEvent}, serde::Raw};
|
||||
use crate::Result;
|
||||
use ruma::{
|
||||
events::{AnyEphemeralRoomEvent, RoomAccountDataEventType},
|
||||
serde::Raw,
|
||||
RoomId, UserId,
|
||||
};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
/// Places one event in the account data of the user and removes the previous entry.
|
||||
|
|
|
@ -3,9 +3,7 @@ mod data;
|
|||
pub use data::Data;
|
||||
|
||||
use ruma::{
|
||||
api::client::{
|
||||
error::ErrorKind,
|
||||
},
|
||||
api::client::error::ErrorKind,
|
||||
events::{AnyEphemeralRoomEvent, RoomAccountDataEventType},
|
||||
serde::Raw,
|
||||
signatures::CanonicalJsonValue,
|
||||
|
|
|
@ -28,7 +28,15 @@ use ruma::{
|
|||
use serde_json::value::to_raw_value;
|
||||
use tokio::sync::{mpsc, MutexGuard, RwLock, RwLockReadGuard};
|
||||
|
||||
use crate::{Result, services, Error, api::{server_server, client_server::{AUTO_GEN_PASSWORD_LENGTH, leave_all_rooms}}, PduEvent, utils::{HtmlEscape, self}};
|
||||
use crate::{
|
||||
api::{
|
||||
client_server::{leave_all_rooms, AUTO_GEN_PASSWORD_LENGTH},
|
||||
server_server,
|
||||
},
|
||||
services,
|
||||
utils::{self, HtmlEscape},
|
||||
Error, PduEvent, Result,
|
||||
};
|
||||
|
||||
use super::pdu::PduBuilder;
|
||||
|
||||
|
@ -153,7 +161,6 @@ enum AdminCommand {
|
|||
EnableRoom { room_id: Box<RoomId> },
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AdminRoomEvent {
|
||||
ProcessMessage(String),
|
||||
|
@ -166,16 +173,14 @@ pub struct Service {
|
|||
}
|
||||
|
||||
impl Service {
|
||||
pub fn start_handler(
|
||||
&self,
|
||||
mut receiver: mpsc::UnboundedReceiver<AdminRoomEvent>,
|
||||
) {
|
||||
pub fn start_handler(&self, mut receiver: mpsc::UnboundedReceiver<AdminRoomEvent>) {
|
||||
tokio::spawn(async move {
|
||||
// TODO: Use futures when we have long admin commands
|
||||
//let mut futures = FuturesUnordered::new();
|
||||
|
||||
let conduit_user = UserId::parse(format!("@conduit:{}", services().globals.server_name()))
|
||||
.expect("@conduit:server_name is valid");
|
||||
let conduit_user =
|
||||
UserId::parse(format!("@conduit:{}", services().globals.server_name()))
|
||||
.expect("@conduit:server_name is valid");
|
||||
|
||||
let conduit_room = services()
|
||||
.rooms
|
||||
|
@ -193,7 +198,8 @@ impl Service {
|
|||
mutex_lock: &MutexGuard<'_, ()>| {
|
||||
services()
|
||||
.rooms
|
||||
.timeline.build_and_append_pdu(
|
||||
.timeline
|
||||
.build_and_append_pdu(
|
||||
PduBuilder {
|
||||
event_type: RoomEventType::RoomMessage,
|
||||
content: to_raw_value(&message)
|
||||
|
@ -316,9 +322,11 @@ impl Service {
|
|||
) -> Result<RoomMessageEventContent> {
|
||||
let reply_message_content = match command {
|
||||
AdminCommand::RegisterAppservice => {
|
||||
if body.len() > 2 && body[0].trim() == "```" && body.last().unwrap().trim() == "```" {
|
||||
if body.len() > 2 && body[0].trim() == "```" && body.last().unwrap().trim() == "```"
|
||||
{
|
||||
let appservice_config = body[1..body.len() - 1].join("\n");
|
||||
let parsed_config = serde_yaml::from_str::<serde_yaml::Value>(&appservice_config);
|
||||
let parsed_config =
|
||||
serde_yaml::from_str::<serde_yaml::Value>(&appservice_config);
|
||||
match parsed_config {
|
||||
Ok(yaml) => match services().appservice.register_appservice(yaml) {
|
||||
Ok(id) => RoomMessageEventContent::text_plain(format!(
|
||||
|
@ -343,7 +351,10 @@ impl Service {
|
|||
}
|
||||
AdminCommand::UnregisterAppservice {
|
||||
appservice_identifier,
|
||||
} => match services().appservice.unregister_appservice(&appservice_identifier) {
|
||||
} => match services()
|
||||
.appservice
|
||||
.unregister_appservice(&appservice_identifier)
|
||||
{
|
||||
Ok(()) => RoomMessageEventContent::text_plain("Appservice unregistered."),
|
||||
Err(e) => RoomMessageEventContent::text_plain(format!(
|
||||
"Failed to unregister appservice: {}",
|
||||
|
@ -351,7 +362,11 @@ impl Service {
|
|||
)),
|
||||
},
|
||||
AdminCommand::ListAppservices => {
|
||||
if let Ok(appservices) = services().appservice.iter_ids().map(|ids| ids.collect::<Vec<_>>()) {
|
||||
if let Ok(appservices) = services()
|
||||
.appservice
|
||||
.iter_ids()
|
||||
.map(|ids| ids.collect::<Vec<_>>())
|
||||
{
|
||||
let count = appservices.len();
|
||||
let output = format!(
|
||||
"Appservices ({}): {}",
|
||||
|
@ -399,7 +414,11 @@ impl Service {
|
|||
Err(e) => RoomMessageEventContent::text_plain(e.to_string()),
|
||||
},
|
||||
AdminCommand::IncomingFederation => {
|
||||
let map = services().globals.roomid_federationhandletime.read().unwrap();
|
||||
let map = services()
|
||||
.globals
|
||||
.roomid_federationhandletime
|
||||
.read()
|
||||
.unwrap();
|
||||
let mut msg: String = format!("Handling {} incoming pdus:\n", map.len());
|
||||
|
||||
for (r, (e, i)) in map.iter() {
|
||||
|
@ -426,7 +445,10 @@ impl Service {
|
|||
Error::bad_database("Invalid room id field in event in database")
|
||||
})?;
|
||||
let start = Instant::now();
|
||||
let count = services().rooms.auth_chain.get_auth_chain(room_id, vec![event_id])
|
||||
let count = services()
|
||||
.rooms
|
||||
.auth_chain
|
||||
.get_auth_chain(room_id, vec![event_id])
|
||||
.await?
|
||||
.count();
|
||||
let elapsed = start.elapsed();
|
||||
|
@ -439,7 +461,8 @@ impl Service {
|
|||
}
|
||||
}
|
||||
AdminCommand::ParsePdu => {
|
||||
if body.len() > 2 && body[0].trim() == "```" && body.last().unwrap().trim() == "```" {
|
||||
if body.len() > 2 && body[0].trim() == "```" && body.last().unwrap().trim() == "```"
|
||||
{
|
||||
let string = body[1..body.len() - 1].join("\n");
|
||||
match serde_json::from_str(&string) {
|
||||
Ok(value) => {
|
||||
|
@ -477,15 +500,18 @@ impl Service {
|
|||
}
|
||||
AdminCommand::GetPdu { event_id } => {
|
||||
let mut outlier = false;
|
||||
let mut pdu_json = services().rooms.timeline.get_non_outlier_pdu_json(&event_id)?;
|
||||
let mut pdu_json = services()
|
||||
.rooms
|
||||
.timeline
|
||||
.get_non_outlier_pdu_json(&event_id)?;
|
||||
if pdu_json.is_none() {
|
||||
outlier = true;
|
||||
pdu_json = services().rooms.timeline.get_pdu_json(&event_id)?;
|
||||
}
|
||||
match pdu_json {
|
||||
Some(json) => {
|
||||
let json_text =
|
||||
serde_json::to_string_pretty(&json).expect("canonical json is valid json");
|
||||
let json_text = serde_json::to_string_pretty(&json)
|
||||
.expect("canonical json is valid json");
|
||||
RoomMessageEventContent::text_html(
|
||||
format!(
|
||||
"{}\n```json\n{}\n```",
|
||||
|
@ -539,8 +565,11 @@ impl Service {
|
|||
if !services().users.exists(&user_id)?
|
||||
|| services().users.is_deactivated(&user_id)?
|
||||
|| user_id
|
||||
== UserId::parse_with_server_name("conduit", services().globals.server_name())
|
||||
.expect("conduit user exists")
|
||||
== UserId::parse_with_server_name(
|
||||
"conduit",
|
||||
services().globals.server_name(),
|
||||
)
|
||||
.expect("conduit user exists")
|
||||
{
|
||||
return Ok(RoomMessageEventContent::text_plain(
|
||||
"The specified user does not exist or is deactivated!",
|
||||
|
@ -549,7 +578,10 @@ impl Service {
|
|||
|
||||
let new_password = utils::random_string(AUTO_GEN_PASSWORD_LENGTH);
|
||||
|
||||
match services().users.set_password(&user_id, Some(new_password.as_str())) {
|
||||
match services()
|
||||
.users
|
||||
.set_password(&user_id, Some(new_password.as_str()))
|
||||
{
|
||||
Ok(()) => RoomMessageEventContent::text_plain(format!(
|
||||
"Successfully reset the password for user {}: {}",
|
||||
user_id, new_password
|
||||
|
@ -590,7 +622,8 @@ impl Service {
|
|||
|
||||
// Default to pretty displayname
|
||||
let displayname = format!("{} ⚡️", user_id.localpart());
|
||||
services().users
|
||||
services()
|
||||
.users
|
||||
.set_displayname(&user_id, Some(displayname.clone()))?;
|
||||
|
||||
// Initial account data
|
||||
|
@ -604,7 +637,8 @@ impl Service {
|
|||
content: ruma::events::push_rules::PushRulesEventContent {
|
||||
global: ruma::push::Ruleset::server_default(&user_id),
|
||||
},
|
||||
}).expect("to json value always works"),
|
||||
})
|
||||
.expect("to json value always works"),
|
||||
)?;
|
||||
|
||||
// we dont add a device since we're not the user, just the creator
|
||||
|
@ -651,7 +685,8 @@ impl Service {
|
|||
}
|
||||
}
|
||||
AdminCommand::DeactivateAll { leave_rooms, force } => {
|
||||
if body.len() > 2 && body[0].trim() == "```" && body.last().unwrap().trim() == "```" {
|
||||
if body.len() > 2 && body[0].trim() == "```" && body.last().unwrap().trim() == "```"
|
||||
{
|
||||
let usernames = body.clone().drain(1..body.len() - 1).collect::<Vec<_>>();
|
||||
|
||||
let mut user_ids: Vec<&UserId> = Vec::new();
|
||||
|
@ -672,17 +707,15 @@ impl Service {
|
|||
let mut admins = Vec::new();
|
||||
|
||||
if !force {
|
||||
user_ids.retain(|&user_id| {
|
||||
match services().users.is_admin(user_id) {
|
||||
Ok(is_admin) => match is_admin {
|
||||
true => {
|
||||
admins.push(user_id.localpart());
|
||||
false
|
||||
}
|
||||
false => true,
|
||||
},
|
||||
Err(_) => false,
|
||||
}
|
||||
user_ids.retain(|&user_id| match services().users.is_admin(user_id) {
|
||||
Ok(is_admin) => match is_admin {
|
||||
true => {
|
||||
admins.push(user_id.localpart());
|
||||
false
|
||||
}
|
||||
false => true,
|
||||
},
|
||||
Err(_) => false,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -783,8 +816,8 @@ impl Service {
|
|||
} else {
|
||||
// Wrap the usage line in a code block, and add a yaml block example
|
||||
// This makes the usage of e.g. `register-appservice` more accurate
|
||||
let re =
|
||||
Regex::new("(?m)^USAGE:\n (.*?)\n\n").expect("Regex compilation should not fail");
|
||||
let re = Regex::new("(?m)^USAGE:\n (.*?)\n\n")
|
||||
.expect("Regex compilation should not fail");
|
||||
re.replace_all(&text, "USAGE:\n<pre>$1[nobr]\n[commandbodyblock]</pre>")
|
||||
.replace("[commandbodyblock]", &command_body)
|
||||
};
|
||||
|
@ -808,7 +841,8 @@ impl Service {
|
|||
services().rooms.short.get_or_create_shortroomid(&room_id)?;
|
||||
|
||||
let mutex_state = Arc::clone(
|
||||
services().globals
|
||||
services()
|
||||
.globals
|
||||
.roomid_mutex_state
|
||||
.write()
|
||||
.unwrap()
|
||||
|
@ -818,8 +852,9 @@ impl Service {
|
|||
let state_lock = mutex_state.lock().await;
|
||||
|
||||
// Create a user for the server
|
||||
let conduit_user = UserId::parse_with_server_name("conduit", services().globals.server_name())
|
||||
.expect("@conduit:server_name is valid");
|
||||
let conduit_user =
|
||||
UserId::parse_with_server_name("conduit", services().globals.server_name())
|
||||
.expect("@conduit:server_name is valid");
|
||||
|
||||
services().users.create(&conduit_user, None)?;
|
||||
|
||||
|
@ -1002,9 +1037,10 @@ impl Service {
|
|||
user_id: &UserId,
|
||||
displayname: String,
|
||||
) -> Result<()> {
|
||||
let admin_room_alias: Box<RoomAliasId> = format!("#admins:{}", services().globals.server_name())
|
||||
.try_into()
|
||||
.expect("#admins:server_name is a valid alias name");
|
||||
let admin_room_alias: Box<RoomAliasId> =
|
||||
format!("#admins:{}", services().globals.server_name())
|
||||
.try_into()
|
||||
.expect("#admins:server_name is a valid alias name");
|
||||
let room_id = services()
|
||||
.rooms
|
||||
.alias
|
||||
|
@ -1012,7 +1048,8 @@ impl Service {
|
|||
.expect("Admin room must exist");
|
||||
|
||||
let mutex_state = Arc::clone(
|
||||
services().globals
|
||||
services()
|
||||
.globals
|
||||
.roomid_mutex_state
|
||||
.write()
|
||||
.unwrap()
|
||||
|
@ -1022,8 +1059,9 @@ impl Service {
|
|||
let state_lock = mutex_state.lock().await;
|
||||
|
||||
// Use the server user to grant the new admin's power level
|
||||
let conduit_user = UserId::parse_with_server_name("conduit", services().globals.server_name())
|
||||
.expect("@conduit:server_name is valid");
|
||||
let conduit_user =
|
||||
UserId::parse_with_server_name("conduit", services().globals.server_name())
|
||||
.expect("@conduit:server_name is valid");
|
||||
|
||||
// Invite and join the real user
|
||||
services().rooms.timeline.build_and_append_pdu(
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use ruma::{signatures::Ed25519KeyPair, DeviceId, UserId, ServerName, api::federation::discovery::{ServerSigningKeys, VerifyKey}, ServerSigningKeyId};
|
||||
use ruma::{
|
||||
api::federation::discovery::{ServerSigningKeys, VerifyKey},
|
||||
signatures::Ed25519KeyPair,
|
||||
DeviceId, ServerName, ServerSigningKeyId, UserId,
|
||||
};
|
||||
|
||||
use crate::Result;
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ pub use data::Data;
|
|||
use crate::api::server_server::FedDest;
|
||||
use crate::service::*;
|
||||
|
||||
use crate::{Config, utils, Error, Result};
|
||||
use crate::{utils, Config, Error, Result};
|
||||
use ruma::{
|
||||
api::{
|
||||
client::sync::sync_events,
|
||||
|
@ -89,12 +89,8 @@ impl Default for RotationHandler {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
impl Service {
|
||||
pub fn load(
|
||||
db: Arc<dyn Data>,
|
||||
config: Config,
|
||||
) -> Result<Self> {
|
||||
pub fn load(db: Arc<dyn Data>, config: Config) -> Result<Self> {
|
||||
let keypair = db.load_keypair();
|
||||
|
||||
let keypair = match keypair {
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
use std::collections::BTreeMap;
|
||||
|
||||
use ruma::{api::client::backup::{BackupAlgorithm, RoomKeyBackup, KeyBackupData}, serde::Raw, UserId, RoomId};
|
||||
use crate::Result;
|
||||
use ruma::{
|
||||
api::client::backup::{BackupAlgorithm, KeyBackupData, RoomKeyBackup},
|
||||
serde::Raw,
|
||||
RoomId, UserId,
|
||||
};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn create_backup(
|
||||
|
@ -21,16 +25,10 @@ pub trait Data: Send + Sync {
|
|||
|
||||
fn get_latest_backup_version(&self, user_id: &UserId) -> Result<Option<String>>;
|
||||
|
||||
fn get_latest_backup(
|
||||
&self,
|
||||
user_id: &UserId,
|
||||
) -> Result<Option<(String, Raw<BackupAlgorithm>)>>;
|
||||
fn get_latest_backup(&self, user_id: &UserId)
|
||||
-> Result<Option<(String, Raw<BackupAlgorithm>)>>;
|
||||
|
||||
fn get_backup(
|
||||
&self,
|
||||
user_id: &UserId,
|
||||
version: &str,
|
||||
) -> Result<Option<Raw<BackupAlgorithm>>>;
|
||||
fn get_backup(&self, user_id: &UserId, version: &str) -> Result<Option<Raw<BackupAlgorithm>>>;
|
||||
|
||||
fn add_key(
|
||||
&self,
|
||||
|
@ -68,12 +66,7 @@ pub trait Data: Send + Sync {
|
|||
|
||||
fn delete_all_keys(&self, user_id: &UserId, version: &str) -> Result<()>;
|
||||
|
||||
fn delete_room_keys(
|
||||
&self,
|
||||
user_id: &UserId,
|
||||
version: &str,
|
||||
room_id: &RoomId,
|
||||
) -> Result<()>;
|
||||
fn delete_room_keys(&self, user_id: &UserId, version: &str, room_id: &RoomId) -> Result<()>;
|
||||
|
||||
fn delete_room_key(
|
||||
&self,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
|
||||
use crate::{utils, Error, Result, services};
|
||||
use crate::{services, utils, Error, Result};
|
||||
use ruma::{
|
||||
api::client::{
|
||||
backup::{BackupAlgorithm, KeyBackupData, RoomKeyBackup},
|
||||
|
@ -65,7 +65,8 @@ impl Service {
|
|||
session_id: &str,
|
||||
key_data: &Raw<KeyBackupData>,
|
||||
) -> Result<()> {
|
||||
self.db.add_key(user_id, version, room_id, session_id, key_data)
|
||||
self.db
|
||||
.add_key(user_id, version, room_id, session_id, key_data)
|
||||
}
|
||||
|
||||
pub fn count_keys(&self, user_id: &UserId, version: &str) -> Result<usize> {
|
||||
|
@ -123,6 +124,7 @@ impl Service {
|
|||
room_id: &RoomId,
|
||||
session_id: &str,
|
||||
) -> Result<()> {
|
||||
self.db.delete_room_key(user_id, version, room_id, session_id)
|
||||
self.db
|
||||
.delete_room_key(user_id, version, room_id, session_id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
use crate::Result;
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn create_file_metadata(&self, mxc: String, width: u32, height: u32, content_disposition: Option<&str>, content_type: Option<&str>) -> Result<Vec<u8>>;
|
||||
fn create_file_metadata(
|
||||
&self,
|
||||
mxc: String,
|
||||
width: u32,
|
||||
height: u32,
|
||||
content_disposition: Option<&str>,
|
||||
content_type: Option<&str>,
|
||||
) -> Result<Vec<u8>>;
|
||||
|
||||
/// Returns content_disposition, content_type and the metadata key.
|
||||
fn search_file_metadata(&self, mxc: String, width: u32, height: u32) -> Result<(Option<String>, Option<String>, Vec<u8>)>;
|
||||
fn search_file_metadata(
|
||||
&self,
|
||||
mxc: String,
|
||||
width: u32,
|
||||
height: u32,
|
||||
) -> Result<(Option<String>, Option<String>, Vec<u8>)>;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
|
||||
use crate::{services, utils, Error, Result};
|
||||
use image::{imageops::FilterType, GenericImageView};
|
||||
use crate::{utils, Error, Result, services};
|
||||
use std::{mem, sync::Arc};
|
||||
use tokio::{
|
||||
fs::File,
|
||||
|
@ -29,7 +29,9 @@ impl Service {
|
|||
file: &[u8],
|
||||
) -> Result<()> {
|
||||
// Width, Height = 0 if it's not a thumbnail
|
||||
let key = self.db.create_file_metadata(mxc, 0, 0, content_disposition, content_type)?;
|
||||
let key = self
|
||||
.db
|
||||
.create_file_metadata(mxc, 0, 0, content_disposition, content_type)?;
|
||||
|
||||
let path = services().globals.get_media_file(&key);
|
||||
let mut f = File::create(path).await?;
|
||||
|
@ -48,7 +50,9 @@ impl Service {
|
|||
height: u32,
|
||||
file: &[u8],
|
||||
) -> Result<()> {
|
||||
let key = self.db.create_file_metadata(mxc, width, height, content_disposition, content_type)?;
|
||||
let key =
|
||||
self.db
|
||||
.create_file_metadata(mxc, width, height, content_disposition, content_type)?;
|
||||
|
||||
let path = services().globals.get_media_file(&key);
|
||||
let mut f = File::create(path).await?;
|
||||
|
@ -59,12 +63,13 @@ impl Service {
|
|||
|
||||
/// Downloads a file.
|
||||
pub async fn get(&self, mxc: String) -> Result<Option<FileMeta>> {
|
||||
if let Ok((content_disposition, content_type, key)) = self.db.search_file_metadata(mxc, 0, 0) {
|
||||
if let Ok((content_disposition, content_type, key)) =
|
||||
self.db.search_file_metadata(mxc, 0, 0)
|
||||
{
|
||||
let path = services().globals.get_media_file(&key);
|
||||
let mut file = Vec::new();
|
||||
File::open(path).await?.read_to_end(&mut file).await?;
|
||||
|
||||
|
||||
Ok(Some(FileMeta {
|
||||
content_disposition,
|
||||
content_type,
|
||||
|
@ -108,7 +113,9 @@ impl Service {
|
|||
.thumbnail_properties(width, height)
|
||||
.unwrap_or((0, 0, false)); // 0, 0 because that's the original file
|
||||
|
||||
if let Ok((content_disposition, content_type, key)) = self.db.search_file_metadata(mxc.clone(), width, height) {
|
||||
if let Ok((content_disposition, content_type, key)) =
|
||||
self.db.search_file_metadata(mxc.clone(), width, height)
|
||||
{
|
||||
// Using saved thumbnail
|
||||
let path = services().globals.get_media_file(&key);
|
||||
let mut file = Vec::new();
|
||||
|
@ -119,7 +126,9 @@ impl Service {
|
|||
content_type,
|
||||
file: file.to_vec(),
|
||||
}))
|
||||
} else if let Ok((content_disposition, content_type, key)) = self.db.search_file_metadata(mxc.clone(), 0, 0) {
|
||||
} else if let Ok((content_disposition, content_type, key)) =
|
||||
self.db.search_file_metadata(mxc.clone(), 0, 0)
|
||||
{
|
||||
// Generate a thumbnail
|
||||
let path = services().globals.get_media_file(&key);
|
||||
let mut file = Vec::new();
|
||||
|
@ -180,7 +189,13 @@ impl Service {
|
|||
thumbnail.write_to(&mut thumbnail_bytes, image::ImageOutputFormat::Png)?;
|
||||
|
||||
// Save thumbnail in database so we don't have to generate it again next time
|
||||
let thumbnail_key = self.db.create_file_metadata(mxc, width, height, content_disposition.as_deref(), content_type.as_deref())?;
|
||||
let thumbnail_key = self.db.create_file_metadata(
|
||||
mxc,
|
||||
width,
|
||||
height,
|
||||
content_disposition.as_deref(),
|
||||
content_type.as_deref(),
|
||||
)?;
|
||||
|
||||
let path = services().globals.get_media_file(&thumbnail_key);
|
||||
let mut f = File::create(path).await?;
|
||||
|
|
|
@ -5,7 +5,7 @@ use std::{
|
|||
|
||||
use lru_cache::LruCache;
|
||||
|
||||
use crate::{Result, Config};
|
||||
use crate::{Config, Result};
|
||||
|
||||
pub mod account_data;
|
||||
pub mod admin;
|
||||
|
@ -49,7 +49,8 @@ impl Services {
|
|||
+ key_backups::Data
|
||||
+ media::Data,
|
||||
>(
|
||||
db: Arc<D>, config: Config
|
||||
db: Arc<D>,
|
||||
config: Config,
|
||||
) -> Result<Self> {
|
||||
Ok(Self {
|
||||
appservice: appservice::Service { db: db.clone() },
|
||||
|
@ -76,30 +77,26 @@ impl Services {
|
|||
state: rooms::state::Service { db: db.clone() },
|
||||
state_accessor: rooms::state_accessor::Service { db: db.clone() },
|
||||
state_cache: rooms::state_cache::Service { db: db.clone() },
|
||||
state_compressor: rooms::state_compressor::Service { db: db.clone(), stateinfo_cache: Mutex::new(LruCache::new((100.0 * config.conduit_cache_capacity_modifier) as usize,)) },
|
||||
timeline: rooms::timeline::Service { db: db.clone(), lasttimelinecount_cache: Mutex::new(HashMap::new()) },
|
||||
state_compressor: rooms::state_compressor::Service {
|
||||
db: db.clone(),
|
||||
stateinfo_cache: Mutex::new(LruCache::new(
|
||||
(100.0 * config.conduit_cache_capacity_modifier) as usize,
|
||||
)),
|
||||
},
|
||||
timeline: rooms::timeline::Service {
|
||||
db: db.clone(),
|
||||
lasttimelinecount_cache: Mutex::new(HashMap::new()),
|
||||
},
|
||||
user: rooms::user::Service { db: db.clone() },
|
||||
},
|
||||
transaction_ids: transaction_ids::Service {
|
||||
db: db.clone()
|
||||
},
|
||||
uiaa: uiaa::Service {
|
||||
db: db.clone()
|
||||
},
|
||||
users: users::Service {
|
||||
db: db.clone()
|
||||
},
|
||||
account_data: account_data::Service {
|
||||
db: db.clone()
|
||||
},
|
||||
transaction_ids: transaction_ids::Service { db: db.clone() },
|
||||
uiaa: uiaa::Service { db: db.clone() },
|
||||
users: users::Service { db: db.clone() },
|
||||
account_data: account_data::Service { db: db.clone() },
|
||||
admin: admin::Service { sender: todo!() },
|
||||
globals: globals::Service::load(db.clone(), config)?,
|
||||
key_backups: key_backups::Service {
|
||||
db: db.clone()
|
||||
},
|
||||
media: media::Service {
|
||||
db: db.clone()
|
||||
},
|
||||
key_backups: key_backups::Service { db: db.clone() },
|
||||
media: media::Service { db: db.clone() },
|
||||
sending: sending::Service {
|
||||
maximum_requests: todo!(),
|
||||
sender: todo!(),
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{Error, services};
|
||||
use crate::{services, Error};
|
||||
use ruma::{
|
||||
events::{
|
||||
room::member::RoomMemberEventContent, AnyEphemeralRoomEvent, AnyRoomEvent, AnyStateEvent,
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
use ruma::{UserId, api::client::push::{set_pusher, get_pushers}};
|
||||
use crate::Result;
|
||||
use ruma::{
|
||||
api::client::push::{get_pushers, set_pusher},
|
||||
UserId,
|
||||
};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn set_pusher(&self, sender: &UserId, pusher: set_pusher::v3::Pusher) -> Result<()>;
|
||||
|
@ -8,8 +11,5 @@ pub trait Data: Send + Sync {
|
|||
|
||||
fn get_pushers(&self, sender: &UserId) -> Result<Vec<get_pushers::v3::Pusher>>;
|
||||
|
||||
fn get_pusher_senderkeys<'a>(
|
||||
&'a self,
|
||||
sender: &UserId,
|
||||
) -> Box<dyn Iterator<Item = Vec<u8>>>;
|
||||
fn get_pusher_senderkeys<'a>(&'a self, sender: &UserId) -> Box<dyn Iterator<Item = Vec<u8>>>;
|
||||
}
|
||||
|
|
|
@ -79,7 +79,11 @@ impl Service {
|
|||
//*reqwest_request.timeout_mut() = Some(Duration::from_secs(5));
|
||||
|
||||
let url = reqwest_request.url().clone();
|
||||
let response = services().globals.default_client().execute(reqwest_request).await;
|
||||
let response = services()
|
||||
.globals
|
||||
.default_client()
|
||||
.execute(reqwest_request)
|
||||
.await;
|
||||
|
||||
match response {
|
||||
Ok(mut response) => {
|
||||
|
@ -196,7 +200,8 @@ impl Service {
|
|||
let ctx = PushConditionRoomCtx {
|
||||
room_id: room_id.to_owned(),
|
||||
member_count: 10_u32.into(), // TODO: get member count efficiently
|
||||
user_display_name: services().users
|
||||
user_display_name: services()
|
||||
.users
|
||||
.displayname(user)?
|
||||
.unwrap_or_else(|| user.localpart().to_owned()),
|
||||
users_power_levels: power_levels.users.clone(),
|
||||
|
@ -276,10 +281,10 @@ impl Service {
|
|||
let user_name = services().users.displayname(&event.sender)?;
|
||||
notifi.sender_display_name = user_name.as_deref();
|
||||
|
||||
let room_name = if let Some(room_name_pdu) =
|
||||
services().rooms
|
||||
let room_name = if let Some(room_name_pdu) = services()
|
||||
.rooms
|
||||
.state_accessor
|
||||
.room_state_get(&event.room_id, &StateEventType::RoomName, "")?
|
||||
.room_state_get(&event.room_id, &StateEventType::RoomName, "")?
|
||||
{
|
||||
serde_json::from_str::<RoomNameEventContent>(room_name_pdu.content.get())
|
||||
.map_err(|_| Error::bad_database("Invalid room name event in database."))?
|
||||
|
@ -290,11 +295,8 @@ impl Service {
|
|||
|
||||
notifi.room_name = room_name.as_deref();
|
||||
|
||||
self.send_request(
|
||||
url,
|
||||
send_event_notification::v1::Request::new(notifi),
|
||||
)
|
||||
.await?;
|
||||
self.send_request(url, send_event_notification::v1::Request::new(notifi))
|
||||
.await?;
|
||||
}
|
||||
|
||||
// TODO: email
|
||||
|
|
|
@ -1,25 +1,15 @@
|
|||
use ruma::{RoomId, RoomAliasId};
|
||||
use crate::Result;
|
||||
use ruma::{RoomAliasId, RoomId};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
/// Creates or updates the alias to the given room id.
|
||||
fn set_alias(
|
||||
&self,
|
||||
alias: &RoomAliasId,
|
||||
room_id: &RoomId
|
||||
) -> Result<()>;
|
||||
fn set_alias(&self, alias: &RoomAliasId, room_id: &RoomId) -> Result<()>;
|
||||
|
||||
/// Forgets about an alias. Returns an error if the alias did not exist.
|
||||
fn remove_alias(
|
||||
&self,
|
||||
alias: &RoomAliasId,
|
||||
) -> Result<()>;
|
||||
fn remove_alias(&self, alias: &RoomAliasId) -> Result<()>;
|
||||
|
||||
/// Looks up the roomid for the given alias.
|
||||
fn resolve_local_alias(
|
||||
&self,
|
||||
alias: &RoomAliasId,
|
||||
) -> Result<Option<Box<RoomId>>>;
|
||||
fn resolve_local_alias(&self, alias: &RoomAliasId) -> Result<Option<Box<RoomId>>>;
|
||||
|
||||
/// Returns all local aliases that point to the given room
|
||||
fn local_aliases_for_room(
|
||||
|
|
|
@ -3,8 +3,8 @@ use std::sync::Arc;
|
|||
|
||||
pub use data::Data;
|
||||
|
||||
use ruma::{RoomAliasId, RoomId};
|
||||
use crate::Result;
|
||||
use ruma::{RoomAliasId, RoomId};
|
||||
|
||||
pub struct Service {
|
||||
db: Arc<dyn Data>,
|
||||
|
@ -12,19 +12,12 @@ pub struct Service {
|
|||
|
||||
impl Service {
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn set_alias(
|
||||
&self,
|
||||
alias: &RoomAliasId,
|
||||
room_id: &RoomId,
|
||||
) -> Result<()> {
|
||||
pub fn set_alias(&self, alias: &RoomAliasId, room_id: &RoomId) -> Result<()> {
|
||||
self.db.set_alias(alias, room_id)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn remove_alias(
|
||||
&self,
|
||||
alias: &RoomAliasId,
|
||||
) -> Result<()> {
|
||||
pub fn remove_alias(&self, alias: &RoomAliasId) -> Result<()> {
|
||||
self.db.remove_alias(alias)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
use std::{collections::HashSet, sync::Arc};
|
||||
use crate::Result;
|
||||
use std::{collections::HashSet, sync::Arc};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn get_cached_eventid_authchain(&self, shorteventid: &[u64]) -> Result<Option<Arc<HashSet<u64>>>>;
|
||||
fn cache_auth_chain(&self, shorteventid: Vec<u64>, auth_chain: Arc<HashSet<u64>>) -> Result<()>;
|
||||
fn get_cached_eventid_authchain(
|
||||
&self,
|
||||
shorteventid: &[u64],
|
||||
) -> Result<Option<Arc<HashSet<u64>>>>;
|
||||
fn cache_auth_chain(&self, shorteventid: Vec<u64>, auth_chain: Arc<HashSet<u64>>)
|
||||
-> Result<()>;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
mod data;
|
||||
use std::{sync::Arc, collections::{HashSet, BTreeSet}};
|
||||
use std::{
|
||||
collections::{BTreeSet, HashSet},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
pub use data::Data;
|
||||
use ruma::{RoomId, EventId, api::client::error::ErrorKind};
|
||||
use ruma::{api::client::error::ErrorKind, EventId, RoomId};
|
||||
use tracing::log::warn;
|
||||
|
||||
use crate::{Result, services, Error};
|
||||
use crate::{services, Error, Result};
|
||||
|
||||
pub struct Service {
|
||||
db: Arc<dyn Data>,
|
||||
|
@ -56,7 +59,11 @@ impl Service {
|
|||
}
|
||||
|
||||
let chunk_key: Vec<u64> = chunk.iter().map(|(short, _)| short).copied().collect();
|
||||
if let Some(cached) = services().rooms.auth_chain.get_cached_eventid_authchain(&chunk_key)? {
|
||||
if let Some(cached) = services()
|
||||
.rooms
|
||||
.auth_chain
|
||||
.get_cached_eventid_authchain(&chunk_key)?
|
||||
{
|
||||
hits += 1;
|
||||
full_auth_chain.extend(cached.iter().copied());
|
||||
continue;
|
||||
|
@ -68,13 +75,18 @@ impl Service {
|
|||
let mut misses2 = 0;
|
||||
let mut i = 0;
|
||||
for (sevent_id, event_id) in chunk {
|
||||
if let Some(cached) = services().rooms.auth_chain.get_cached_eventid_authchain(&[sevent_id])? {
|
||||
if let Some(cached) = services()
|
||||
.rooms
|
||||
.auth_chain
|
||||
.get_cached_eventid_authchain(&[sevent_id])?
|
||||
{
|
||||
hits2 += 1;
|
||||
chunk_cache.extend(cached.iter().copied());
|
||||
} else {
|
||||
misses2 += 1;
|
||||
let auth_chain = Arc::new(self.get_auth_chain_inner(room_id, &event_id)?);
|
||||
services().rooms
|
||||
services()
|
||||
.rooms
|
||||
.auth_chain
|
||||
.cache_auth_chain(vec![sevent_id], Arc::clone(&auth_chain))?;
|
||||
println!(
|
||||
|
@ -97,8 +109,10 @@ impl Service {
|
|||
misses2
|
||||
);
|
||||
let chunk_cache = Arc::new(chunk_cache);
|
||||
services().rooms
|
||||
.auth_chain.cache_auth_chain(chunk_key, Arc::clone(&chunk_cache))?;
|
||||
services()
|
||||
.rooms
|
||||
.auth_chain
|
||||
.cache_auth_chain(chunk_key, Arc::clone(&chunk_cache))?;
|
||||
full_auth_chain.extend(chunk_cache.iter());
|
||||
}
|
||||
|
||||
|
@ -115,11 +129,7 @@ impl Service {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip(self, event_id))]
|
||||
fn get_auth_chain_inner(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
event_id: &EventId,
|
||||
) -> Result<HashSet<u64>> {
|
||||
fn get_auth_chain_inner(&self, room_id: &RoomId, event_id: &EventId) -> Result<HashSet<u64>> {
|
||||
let mut todo = vec![Arc::from(event_id)];
|
||||
let mut found = HashSet::new();
|
||||
|
||||
|
@ -131,7 +141,8 @@ impl Service {
|
|||
}
|
||||
for auth_event in &pdu.auth_events {
|
||||
let sauthevent = services()
|
||||
.rooms.short
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shorteventid(auth_event)?;
|
||||
|
||||
if !found.contains(&sauthevent) {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use ruma::RoomId;
|
||||
use crate::Result;
|
||||
use ruma::RoomId;
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
/// Adds the room to the public room directory
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use ruma::{UserId, RoomId, events::presence::PresenceEvent};
|
||||
use crate::Result;
|
||||
use ruma::{events::presence::PresenceEvent, RoomId, UserId};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
/// Adds a presence event which will be saved until a new event replaces it.
|
||||
|
|
|
@ -2,7 +2,7 @@ mod data;
|
|||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
pub use data::Data;
|
||||
use ruma::{RoomId, UserId, events::presence::PresenceEvent};
|
||||
use ruma::{events::presence::PresenceEvent, RoomId, UserId};
|
||||
|
||||
use crate::Result;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use ruma::{RoomId, events::receipt::ReceiptEvent, UserId, serde::Raw};
|
||||
use crate::Result;
|
||||
use ruma::{events::receipt::ReceiptEvent, serde::Raw, RoomId, UserId};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
/// Replaces the previous read receipt.
|
||||
|
@ -15,13 +15,15 @@ pub trait Data: Send + Sync {
|
|||
&self,
|
||||
room_id: &RoomId,
|
||||
since: u64,
|
||||
) -> Box<dyn Iterator<
|
||||
Item = Result<(
|
||||
Box<UserId>,
|
||||
u64,
|
||||
Raw<ruma::events::AnySyncEphemeralRoomEvent>,
|
||||
)>,
|
||||
>>;
|
||||
) -> Box<
|
||||
dyn Iterator<
|
||||
Item = Result<(
|
||||
Box<UserId>,
|
||||
u64,
|
||||
Raw<ruma::events::AnySyncEphemeralRoomEvent>,
|
||||
)>,
|
||||
>,
|
||||
>;
|
||||
|
||||
/// Sets a private read marker at `count`.
|
||||
fn private_read_set(&self, room_id: &RoomId, user_id: &UserId, count: u64) -> Result<()>;
|
||||
|
|
|
@ -3,8 +3,8 @@ use std::sync::Arc;
|
|||
|
||||
pub use data::Data;
|
||||
|
||||
use ruma::{RoomId, UserId, events::receipt::ReceiptEvent, serde::Raw};
|
||||
use crate::Result;
|
||||
use ruma::{events::receipt::ReceiptEvent, serde::Raw, RoomId, UserId};
|
||||
|
||||
pub struct Service {
|
||||
db: Arc<dyn Data>,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::collections::HashSet;
|
||||
use crate::Result;
|
||||
use ruma::{UserId, RoomId};
|
||||
use ruma::{RoomId, UserId};
|
||||
use std::collections::HashSet;
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
/// Sets a user as typing until the timeout timestamp is reached or roomtyping_remove is
|
||||
|
|
|
@ -2,7 +2,7 @@ mod data;
|
|||
use std::sync::Arc;
|
||||
|
||||
pub use data::Data;
|
||||
use ruma::{UserId, RoomId, events::SyncEphemeralRoomEvent};
|
||||
use ruma::{events::SyncEphemeralRoomEvent, RoomId, UserId};
|
||||
|
||||
use crate::Result;
|
||||
|
||||
|
|
|
@ -1,22 +1,33 @@
|
|||
/// An async function that can recursively call itself.
|
||||
type AsyncRecursiveType<'a, T> = Pin<Box<dyn Future<Output = T> + 'a + Send>>;
|
||||
|
||||
use ruma::{RoomVersionId, signatures::CanonicalJsonObject, api::federation::discovery::{get_server_keys, get_remote_server_keys}};
|
||||
use tokio::sync::Semaphore;
|
||||
use ruma::{
|
||||
api::federation::discovery::{get_remote_server_keys, get_server_keys},
|
||||
signatures::CanonicalJsonObject,
|
||||
RoomVersionId,
|
||||
};
|
||||
use std::{
|
||||
collections::{btree_map, hash_map, BTreeMap, HashMap, HashSet},
|
||||
pin::Pin,
|
||||
sync::{Arc, RwLock, RwLockWriteGuard},
|
||||
time::{Duration, Instant, SystemTime},
|
||||
};
|
||||
use tokio::sync::Semaphore;
|
||||
|
||||
use futures_util::{Future, stream::FuturesUnordered, StreamExt};
|
||||
use futures_util::{stream::FuturesUnordered, Future, StreamExt};
|
||||
use ruma::{
|
||||
api::{
|
||||
client::error::ErrorKind,
|
||||
federation::{event::{get_event, get_room_state_ids}, membership::create_join_event, discovery::get_remote_server_keys_batch::{v2::QueryCriteria, self}},
|
||||
federation::{
|
||||
discovery::get_remote_server_keys_batch::{self, v2::QueryCriteria},
|
||||
event::{get_event, get_room_state_ids},
|
||||
membership::create_join_event,
|
||||
},
|
||||
},
|
||||
events::{
|
||||
room::{create::RoomCreateEventContent, server_acl::RoomServerAclEventContent},
|
||||
StateEventType,
|
||||
},
|
||||
events::{room::{create::RoomCreateEventContent, server_acl::RoomServerAclEventContent}, StateEventType},
|
||||
int,
|
||||
serde::Base64,
|
||||
signatures::CanonicalJsonValue,
|
||||
|
@ -24,9 +35,9 @@ use ruma::{
|
|||
uint, EventId, MilliSecondsSinceUnixEpoch, RoomId, ServerName, ServerSigningKeyId,
|
||||
};
|
||||
use serde_json::value::{to_raw_value, RawValue as RawJsonValue};
|
||||
use tracing::{error, info, trace, warn, debug};
|
||||
use tracing::{debug, error, info, trace, warn};
|
||||
|
||||
use crate::{service::*, services, Result, Error, PduEvent};
|
||||
use crate::{service::*, services, Error, PduEvent, Result};
|
||||
|
||||
pub struct Service;
|
||||
|
||||
|
@ -72,10 +83,7 @@ impl Service {
|
|||
));
|
||||
}
|
||||
|
||||
if services()
|
||||
.rooms
|
||||
.metadata
|
||||
.is_disabled(room_id)? {
|
||||
if services().rooms.metadata.is_disabled(room_id)? {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::Forbidden,
|
||||
"Federation of this room is currently disabled on this server.",
|
||||
|
@ -94,7 +102,8 @@ impl Service {
|
|||
.ok_or_else(|| Error::bad_database("Failed to find create event in db."))?;
|
||||
|
||||
let first_pdu_in_room = services()
|
||||
.rooms.timeline
|
||||
.rooms
|
||||
.timeline
|
||||
.first_pdu_in_room(room_id)?
|
||||
.ok_or_else(|| Error::bad_database("Failed to find first pdu in db."))?;
|
||||
|
||||
|
@ -113,21 +122,20 @@ impl Service {
|
|||
}
|
||||
|
||||
// 9. Fetch any missing prev events doing all checks listed here starting at 1. These are timeline events
|
||||
let (sorted_prev_events, mut eventid_info) = self.fetch_unknown_prev_events(
|
||||
origin,
|
||||
&create_event,
|
||||
room_id,
|
||||
pub_key_map,
|
||||
incoming_pdu.prev_events.clone(),
|
||||
).await?;
|
||||
let (sorted_prev_events, mut eventid_info) = self
|
||||
.fetch_unknown_prev_events(
|
||||
origin,
|
||||
&create_event,
|
||||
room_id,
|
||||
pub_key_map,
|
||||
incoming_pdu.prev_events.clone(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let mut errors = 0;
|
||||
for prev_id in dbg!(sorted_prev_events) {
|
||||
// Check for disabled again because it might have changed
|
||||
if services()
|
||||
.rooms
|
||||
.metadata
|
||||
.is_disabled(room_id)? {
|
||||
if services().rooms.metadata.is_disabled(room_id)? {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::Forbidden,
|
||||
"Federation of this room is currently disabled on this server.",
|
||||
|
@ -224,15 +232,18 @@ impl Service {
|
|||
.write()
|
||||
.unwrap()
|
||||
.insert(room_id.to_owned(), (event_id.to_owned(), start_time));
|
||||
let r = services().rooms.event_handler.upgrade_outlier_to_timeline_pdu(
|
||||
incoming_pdu,
|
||||
val,
|
||||
&create_event,
|
||||
origin,
|
||||
room_id,
|
||||
pub_key_map,
|
||||
)
|
||||
.await;
|
||||
let r = services()
|
||||
.rooms
|
||||
.event_handler
|
||||
.upgrade_outlier_to_timeline_pdu(
|
||||
incoming_pdu,
|
||||
val,
|
||||
&create_event,
|
||||
origin,
|
||||
room_id,
|
||||
pub_key_map,
|
||||
)
|
||||
.await;
|
||||
services()
|
||||
.globals
|
||||
.roomid_federationhandletime
|
||||
|
@ -252,8 +263,7 @@ impl Service {
|
|||
room_id: &'a RoomId,
|
||||
value: BTreeMap<String, CanonicalJsonValue>,
|
||||
pub_key_map: &'a RwLock<BTreeMap<String, BTreeMap<String, Base64>>>,
|
||||
) -> AsyncRecursiveType<'a, Result<(Arc<PduEvent>, BTreeMap<String, CanonicalJsonValue>)>>
|
||||
{
|
||||
) -> AsyncRecursiveType<'a, Result<(Arc<PduEvent>, BTreeMap<String, CanonicalJsonValue>)>> {
|
||||
Box::pin(async move {
|
||||
// TODO: For RoomVersion6 we must check that Raw<..> is canonical do we anywhere?: https://matrix.org/docs/spec/rooms/v6#canonical-json
|
||||
|
||||
|
@ -282,14 +292,22 @@ impl Service {
|
|||
Err(e) => {
|
||||
// Drop
|
||||
warn!("Dropping bad event {}: {}", event_id, e);
|
||||
return Err(Error::BadRequest(ErrorKind::InvalidParam, "Signature verification failed"));
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Signature verification failed",
|
||||
));
|
||||
}
|
||||
Ok(ruma::signatures::Verified::Signatures) => {
|
||||
// Redact
|
||||
warn!("Calculated hash does not match: {}", event_id);
|
||||
match ruma::signatures::redact(&value, room_version_id) {
|
||||
Ok(obj) => obj,
|
||||
Err(_) => return Err(Error::BadRequest(ErrorKind::InvalidParam, "Redaction failed")),
|
||||
Err(_) => {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Redaction failed",
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(ruma::signatures::Verified::All) => value,
|
||||
|
@ -376,7 +394,8 @@ impl Service {
|
|||
&incoming_pdu,
|
||||
None::<PduEvent>, // TODO: third party invite
|
||||
|k, s| auth_events.get(&(k.to_string().into(), s.to_owned())),
|
||||
).map_err(|_e| Error::BadRequest(ErrorKind::InvalidParam, "Auth check failed"))?
|
||||
)
|
||||
.map_err(|_e| Error::BadRequest(ErrorKind::InvalidParam, "Auth check failed"))?
|
||||
{
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
|
@ -415,9 +434,13 @@ impl Service {
|
|||
|
||||
if services()
|
||||
.rooms
|
||||
.pdu_metadata.is_event_soft_failed(&incoming_pdu.event_id)?
|
||||
.pdu_metadata
|
||||
.is_event_soft_failed(&incoming_pdu.event_id)?
|
||||
{
|
||||
return Err(Error::BadRequest(ErrorKind::InvalidParam, "Event has been soft failed"));
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Event has been soft failed",
|
||||
));
|
||||
}
|
||||
|
||||
info!("Upgrading {} to timeline pdu", incoming_pdu.event_id);
|
||||
|
@ -448,7 +471,13 @@ impl Service {
|
|||
.pdu_shortstatehash(prev_event)?;
|
||||
|
||||
let state = if let Some(shortstatehash) = prev_event_sstatehash {
|
||||
Some(services().rooms.state_accessor.state_full_ids(shortstatehash).await)
|
||||
Some(
|
||||
services()
|
||||
.rooms
|
||||
.state_accessor
|
||||
.state_full_ids(shortstatehash)
|
||||
.await,
|
||||
)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -466,10 +495,10 @@ impl Service {
|
|||
})?;
|
||||
|
||||
if let Some(state_key) = &prev_pdu.state_key {
|
||||
let shortstatekey = services()
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shortstatekey(&prev_pdu.kind.to_string().into(), state_key)?;
|
||||
let shortstatekey = services().rooms.short.get_or_create_shortstatekey(
|
||||
&prev_pdu.kind.to_string().into(),
|
||||
state_key,
|
||||
)?;
|
||||
|
||||
state.insert(shortstatekey, Arc::from(prev_event));
|
||||
// Now it's the state after the pdu
|
||||
|
@ -483,21 +512,25 @@ impl Service {
|
|||
|
||||
let mut okay = true;
|
||||
for prev_eventid in &incoming_pdu.prev_events {
|
||||
let prev_event = if let Ok(Some(pdu)) = services().rooms.timeline.get_pdu(prev_eventid) {
|
||||
pdu
|
||||
} else {
|
||||
okay = false;
|
||||
break;
|
||||
};
|
||||
|
||||
let sstatehash =
|
||||
if let Ok(Some(s)) = services().rooms.state_accessor.pdu_shortstatehash(prev_eventid) {
|
||||
s
|
||||
let prev_event =
|
||||
if let Ok(Some(pdu)) = services().rooms.timeline.get_pdu(prev_eventid) {
|
||||
pdu
|
||||
} else {
|
||||
okay = false;
|
||||
break;
|
||||
};
|
||||
|
||||
let sstatehash = if let Ok(Some(s)) = services()
|
||||
.rooms
|
||||
.state_accessor
|
||||
.pdu_shortstatehash(prev_eventid)
|
||||
{
|
||||
s
|
||||
} else {
|
||||
okay = false;
|
||||
break;
|
||||
};
|
||||
|
||||
extremity_sstatehashes.insert(sstatehash, prev_event);
|
||||
}
|
||||
|
||||
|
@ -513,13 +546,10 @@ impl Service {
|
|||
.await?;
|
||||
|
||||
if let Some(state_key) = &prev_event.state_key {
|
||||
let shortstatekey = services()
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shortstatekey(
|
||||
&prev_event.kind.to_string().into(),
|
||||
state_key,
|
||||
)?;
|
||||
let shortstatekey = services().rooms.short.get_or_create_shortstatekey(
|
||||
&prev_event.kind.to_string().into(),
|
||||
state_key,
|
||||
)?;
|
||||
leaf_state.insert(shortstatekey, Arc::from(&*prev_event.event_id));
|
||||
// Now it's the state after the pdu
|
||||
}
|
||||
|
@ -528,7 +558,8 @@ impl Service {
|
|||
let mut starting_events = Vec::with_capacity(leaf_state.len());
|
||||
|
||||
for (k, id) in leaf_state {
|
||||
if let Ok((ty, st_key)) = services().rooms.short.get_statekey_from_short(k) {
|
||||
if let Ok((ty, st_key)) = services().rooms.short.get_statekey_from_short(k)
|
||||
{
|
||||
// FIXME: Undo .to_string().into() when StateMap
|
||||
// is updated to use StateEventType
|
||||
state.insert((ty.to_string().into(), st_key), id.clone());
|
||||
|
@ -567,10 +598,8 @@ impl Service {
|
|||
new_state
|
||||
.into_iter()
|
||||
.map(|((event_type, state_key), event_id)| {
|
||||
let shortstatekey = services()
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shortstatekey(
|
||||
let shortstatekey =
|
||||
services().rooms.short.get_or_create_shortstatekey(
|
||||
&event_type.to_string().into(),
|
||||
&state_key,
|
||||
)?;
|
||||
|
@ -618,15 +647,14 @@ impl Service {
|
|||
|
||||
let mut state: BTreeMap<_, Arc<EventId>> = BTreeMap::new();
|
||||
for (pdu, _) in state_vec {
|
||||
let state_key = pdu
|
||||
.state_key
|
||||
.clone()
|
||||
.ok_or_else(|| Error::bad_database("Found non-state pdu in state events."))?;
|
||||
let state_key = pdu.state_key.clone().ok_or_else(|| {
|
||||
Error::bad_database("Found non-state pdu in state events.")
|
||||
})?;
|
||||
|
||||
let shortstatekey = services()
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shortstatekey(&pdu.kind.to_string().into(), &state_key)?;
|
||||
let shortstatekey = services().rooms.short.get_or_create_shortstatekey(
|
||||
&pdu.kind.to_string().into(),
|
||||
&state_key,
|
||||
)?;
|
||||
|
||||
match state.entry(shortstatekey) {
|
||||
btree_map::Entry::Vacant(v) => {
|
||||
|
@ -648,7 +676,9 @@ impl Service {
|
|||
if state.get(&create_shortstatekey).map(|id| id.as_ref())
|
||||
!= Some(&create_event.event_id)
|
||||
{
|
||||
return Err(Error::bad_database("Incoming event refers to wrong create event."));
|
||||
return Err(Error::bad_database(
|
||||
"Incoming event refers to wrong create event.",
|
||||
));
|
||||
}
|
||||
|
||||
state_at_incoming_event = Some(state);
|
||||
|
@ -683,7 +713,9 @@ impl Service {
|
|||
.map_err(|_e| Error::BadRequest(ErrorKind::InvalidParam, "Auth check failed."))?;
|
||||
|
||||
if !check_result {
|
||||
return Err(Error::bad_database("Event has failed auth check with state at the event."));
|
||||
return Err(Error::bad_database(
|
||||
"Event has failed auth check with state at the event.",
|
||||
));
|
||||
}
|
||||
info!("Auth check succeeded");
|
||||
|
||||
|
@ -703,10 +735,7 @@ impl Service {
|
|||
// Now we calculate the set of extremities this room has after the incoming event has been
|
||||
// applied. We start with the previous extremities (aka leaves)
|
||||
info!("Calculating extremities");
|
||||
let mut extremities = services()
|
||||
.rooms
|
||||
.state
|
||||
.get_forward_extremities(room_id)?;
|
||||
let mut extremities = services().rooms.state.get_forward_extremities(room_id)?;
|
||||
|
||||
// Remove any forward extremities that are referenced by this incoming event's prev_events
|
||||
for prev_event in &incoming_pdu.prev_events {
|
||||
|
@ -716,8 +745,15 @@ impl Service {
|
|||
}
|
||||
|
||||
// Only keep those extremities were not referenced yet
|
||||
extremities
|
||||
.retain(|id| !matches!(services().rooms.pdu_metadata.is_event_referenced(room_id, id), Ok(true)));
|
||||
extremities.retain(|id| {
|
||||
!matches!(
|
||||
services()
|
||||
.rooms
|
||||
.pdu_metadata
|
||||
.is_event_referenced(room_id, id),
|
||||
Ok(true)
|
||||
)
|
||||
});
|
||||
|
||||
info!("Compressing state at event");
|
||||
let state_ids_compressed = state_at_incoming_event
|
||||
|
@ -733,23 +769,21 @@ impl Service {
|
|||
// 13. Check if the event passes auth based on the "current state" of the room, if not "soft fail" it
|
||||
info!("Starting soft fail auth check");
|
||||
|
||||
let auth_events = services()
|
||||
.rooms
|
||||
.state
|
||||
.get_auth_events(
|
||||
room_id,
|
||||
&incoming_pdu.kind,
|
||||
&incoming_pdu.sender,
|
||||
incoming_pdu.state_key.as_deref(),
|
||||
&incoming_pdu.content,
|
||||
)?;
|
||||
let auth_events = services().rooms.state.get_auth_events(
|
||||
room_id,
|
||||
&incoming_pdu.kind,
|
||||
&incoming_pdu.sender,
|
||||
incoming_pdu.state_key.as_deref(),
|
||||
&incoming_pdu.content,
|
||||
)?;
|
||||
|
||||
let soft_fail = !state_res::event_auth::auth_check(
|
||||
&room_version,
|
||||
&incoming_pdu,
|
||||
None::<PduEvent>,
|
||||
|k, s| auth_events.get(&(k.clone(), s.to_owned())),
|
||||
).map_err(|_e| Error::BadRequest(ErrorKind::InvalidParam, "Auth check failed."))?;
|
||||
)
|
||||
.map_err(|_e| Error::BadRequest(ErrorKind::InvalidParam, "Auth check failed."))?;
|
||||
|
||||
if soft_fail {
|
||||
services().rooms.timeline.append_incoming_pdu(
|
||||
|
@ -767,7 +801,10 @@ impl Service {
|
|||
.rooms
|
||||
.pdu_metadata
|
||||
.mark_event_soft_failed(&incoming_pdu.event_id)?;
|
||||
return Err(Error::BadRequest(ErrorKind::InvalidParam, "Event has been soft failed"));
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Event has been soft failed",
|
||||
));
|
||||
}
|
||||
|
||||
if incoming_pdu.state_key.is_some() {
|
||||
|
@ -789,15 +826,12 @@ impl Service {
|
|||
|
||||
info!("Loading extremities");
|
||||
for id in dbg!(&extremities) {
|
||||
match services()
|
||||
.rooms
|
||||
.timeline
|
||||
.get_pdu(id)?
|
||||
{
|
||||
match services().rooms.timeline.get_pdu(id)? {
|
||||
Some(leaf_pdu) => {
|
||||
extremity_sstatehashes.insert(
|
||||
services()
|
||||
.rooms.state_accessor
|
||||
.rooms
|
||||
.state_accessor
|
||||
.pdu_shortstatehash(&leaf_pdu.event_id)?
|
||||
.ok_or_else(|| {
|
||||
error!(
|
||||
|
@ -829,10 +863,10 @@ impl Service {
|
|||
// We also add state after incoming event to the fork states
|
||||
let mut state_after = state_at_incoming_event.clone();
|
||||
if let Some(state_key) = &incoming_pdu.state_key {
|
||||
let shortstatekey = services()
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shortstatekey(&incoming_pdu.kind.to_string().into(), state_key)?;
|
||||
let shortstatekey = services().rooms.short.get_or_create_shortstatekey(
|
||||
&incoming_pdu.kind.to_string().into(),
|
||||
state_key,
|
||||
)?;
|
||||
|
||||
state_after.insert(shortstatekey, Arc::from(&*incoming_pdu.event_id));
|
||||
}
|
||||
|
@ -921,10 +955,10 @@ impl Service {
|
|||
state
|
||||
.into_iter()
|
||||
.map(|((event_type, state_key), event_id)| {
|
||||
let shortstatekey = services()
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shortstatekey(&event_type.to_string().into(), &state_key)?;
|
||||
let shortstatekey = services().rooms.short.get_or_create_shortstatekey(
|
||||
&event_type.to_string().into(),
|
||||
&state_key,
|
||||
)?;
|
||||
services()
|
||||
.rooms
|
||||
.state_compressor
|
||||
|
@ -936,7 +970,10 @@ impl Service {
|
|||
// Set the new room state to the resolved state
|
||||
if update_state {
|
||||
info!("Forcing new room state");
|
||||
let sstatehash = services().rooms.state_compressor.save_state(room_id, new_room_state)?;
|
||||
let sstatehash = services()
|
||||
.rooms
|
||||
.state_compressor
|
||||
.save_state(room_id, new_room_state)?;
|
||||
services()
|
||||
.rooms
|
||||
.state
|
||||
|
@ -951,15 +988,14 @@ impl Service {
|
|||
// We use the `state_at_event` instead of `state_after` so we accurately
|
||||
// represent the state for this event.
|
||||
|
||||
let pdu_id = services().rooms.timeline
|
||||
.append_incoming_pdu(
|
||||
&incoming_pdu,
|
||||
val,
|
||||
extremities.iter().map(|e| (**e).to_owned()).collect(),
|
||||
state_ids_compressed,
|
||||
soft_fail,
|
||||
&state_lock,
|
||||
)?;
|
||||
let pdu_id = services().rooms.timeline.append_incoming_pdu(
|
||||
&incoming_pdu,
|
||||
val,
|
||||
extremities.iter().map(|e| (**e).to_owned()).collect(),
|
||||
state_ids_compressed,
|
||||
soft_fail,
|
||||
&state_lock,
|
||||
)?;
|
||||
|
||||
info!("Appended incoming pdu");
|
||||
|
||||
|
@ -1141,8 +1177,10 @@ impl Service {
|
|||
room_id: &RoomId,
|
||||
pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, Base64>>>,
|
||||
initial_set: Vec<Arc<EventId>>,
|
||||
) -> Result<(Vec<Arc<EventId>>, HashMap<Arc<EventId>,
|
||||
(Arc<PduEvent>, BTreeMap<String, CanonicalJsonValue>)>)> {
|
||||
) -> Result<(
|
||||
Vec<Arc<EventId>>,
|
||||
HashMap<Arc<EventId>, (Arc<PduEvent>, BTreeMap<String, CanonicalJsonValue>)>,
|
||||
)> {
|
||||
let mut graph: HashMap<Arc<EventId>, _> = HashMap::new();
|
||||
let mut eventid_info = HashMap::new();
|
||||
let mut todo_outlier_stack: Vec<Arc<EventId>> = initial_set;
|
||||
|
@ -1223,7 +1261,8 @@ impl Service {
|
|||
.map_or_else(|| uint!(0), |info| info.0.origin_server_ts),
|
||||
),
|
||||
))
|
||||
}).map_err(|_| Error::bad_database("Error sorting prev events"))?;
|
||||
})
|
||||
.map_err(|_| Error::bad_database("Error sorting prev events"))?;
|
||||
|
||||
Ok((sorted, eventid_info))
|
||||
}
|
||||
|
@ -1253,13 +1292,16 @@ impl Service {
|
|||
|
||||
let signature_ids = signature_object.keys().cloned().collect::<Vec<_>>();
|
||||
|
||||
let fetch_res = self.fetch_signing_keys(
|
||||
signature_server.as_str().try_into().map_err(|_| {
|
||||
Error::BadServerResponse("Invalid servername in signatures of server response pdu.")
|
||||
})?,
|
||||
signature_ids,
|
||||
)
|
||||
.await;
|
||||
let fetch_res = self
|
||||
.fetch_signing_keys(
|
||||
signature_server.as_str().try_into().map_err(|_| {
|
||||
Error::BadServerResponse(
|
||||
"Invalid servername in signatures of server response pdu.",
|
||||
)
|
||||
})?,
|
||||
signature_ids,
|
||||
)
|
||||
.await;
|
||||
|
||||
let keys = match fetch_res {
|
||||
Ok(keys) => keys,
|
||||
|
@ -1336,8 +1378,9 @@ impl Service {
|
|||
|
||||
let signature_ids = signature_object.keys().cloned().collect::<Vec<_>>();
|
||||
|
||||
let contains_all_ids =
|
||||
|keys: &BTreeMap<String, Base64>| signature_ids.iter().all(|id| keys.contains_key(id));
|
||||
let contains_all_ids = |keys: &BTreeMap<String, Base64>| {
|
||||
signature_ids.iter().all(|id| keys.contains_key(id))
|
||||
};
|
||||
|
||||
let origin = <&ServerName>::try_from(signature_server.as_str()).map_err(|_| {
|
||||
Error::BadServerResponse("Invalid servername in signatures of server response pdu.")
|
||||
|
@ -1373,8 +1416,10 @@ impl Service {
|
|||
room_version: &RoomVersionId,
|
||||
pub_key_map: &RwLock<BTreeMap<String, BTreeMap<String, Base64>>>,
|
||||
) -> Result<()> {
|
||||
let mut servers: BTreeMap<Box<ServerName>, BTreeMap<Box<ServerSigningKeyId>, QueryCriteria>> =
|
||||
BTreeMap::new();
|
||||
let mut servers: BTreeMap<
|
||||
Box<ServerName>,
|
||||
BTreeMap<Box<ServerSigningKeyId>, QueryCriteria>,
|
||||
> = BTreeMap::new();
|
||||
|
||||
{
|
||||
let mut pkm = pub_key_map
|
||||
|
@ -1440,11 +1485,9 @@ impl Service {
|
|||
.into_iter()
|
||||
.map(|(server, _)| async move {
|
||||
(
|
||||
services().sending
|
||||
.send_federation_request(
|
||||
&server,
|
||||
get_server_keys::v2::Request::new(),
|
||||
)
|
||||
services()
|
||||
.sending
|
||||
.send_federation_request(&server, get_server_keys::v2::Request::new())
|
||||
.await,
|
||||
server,
|
||||
)
|
||||
|
@ -1472,10 +1515,11 @@ impl Service {
|
|||
|
||||
/// Returns Ok if the acl allows the server
|
||||
pub fn acl_check(&self, server_name: &ServerName, room_id: &RoomId) -> Result<()> {
|
||||
let acl_event = match services()
|
||||
.rooms.state_accessor
|
||||
.room_state_get(room_id, &StateEventType::RoomServerAcl, "")?
|
||||
{
|
||||
let acl_event = match services().rooms.state_accessor.room_state_get(
|
||||
room_id,
|
||||
&StateEventType::RoomServerAcl,
|
||||
"",
|
||||
)? {
|
||||
Some(acl) => acl,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
@ -1587,7 +1631,9 @@ impl Service {
|
|||
.ok()
|
||||
.and_then(|resp| resp.server_key.deserialize().ok())
|
||||
{
|
||||
services().globals.add_signing_key(origin, server_key.clone())?;
|
||||
services()
|
||||
.globals
|
||||
.add_signing_key(origin, server_key.clone())?;
|
||||
|
||||
result.extend(
|
||||
server_key
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use ruma::{RoomId, DeviceId, UserId};
|
||||
use crate::Result;
|
||||
use ruma::{DeviceId, RoomId, UserId};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn lazy_load_was_sent_before(
|
||||
|
@ -15,7 +15,7 @@ pub trait Data: Send + Sync {
|
|||
user_id: &UserId,
|
||||
device_id: &DeviceId,
|
||||
room_id: &RoomId,
|
||||
confirmed_user_ids: &mut dyn Iterator<Item=&UserId>,
|
||||
confirmed_user_ids: &mut dyn Iterator<Item = &UserId>,
|
||||
) -> Result<()>;
|
||||
|
||||
fn lazy_load_reset(
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
mod data;
|
||||
use std::{collections::{HashSet, HashMap}, sync::{Mutex, Arc}};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
pub use data::Data;
|
||||
use ruma::{DeviceId, UserId, RoomId};
|
||||
use ruma::{DeviceId, RoomId, UserId};
|
||||
|
||||
use crate::Result;
|
||||
|
||||
pub struct Service {
|
||||
db: Arc<dyn Data>,
|
||||
|
||||
lazy_load_waiting: Mutex<HashMap<(Box<UserId>, Box<DeviceId>, Box<RoomId>, u64), HashSet<Box<UserId>>>>,
|
||||
lazy_load_waiting:
|
||||
Mutex<HashMap<(Box<UserId>, Box<DeviceId>, Box<RoomId>, u64), HashSet<Box<UserId>>>>,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
|
@ -21,7 +25,8 @@ impl Service {
|
|||
room_id: &RoomId,
|
||||
ll_user: &UserId,
|
||||
) -> Result<bool> {
|
||||
self.db.lazy_load_was_sent_before(user_id, device_id, room_id, ll_user)
|
||||
self.db
|
||||
.lazy_load_was_sent_before(user_id, device_id, room_id, ll_user)
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
|
@ -58,7 +63,12 @@ impl Service {
|
|||
room_id.to_owned(),
|
||||
since,
|
||||
)) {
|
||||
self.db.lazy_load_confirm_delivery(user_id, device_id, room_id, &mut user_ids.iter().map(|&u| &*u))?;
|
||||
self.db.lazy_load_confirm_delivery(
|
||||
user_id,
|
||||
device_id,
|
||||
room_id,
|
||||
&mut user_ids.iter().map(|&u| &*u),
|
||||
)?;
|
||||
} else {
|
||||
// Ignore
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use ruma::RoomId;
|
||||
use crate::Result;
|
||||
use ruma::RoomId;
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn exists(&self, room_id: &RoomId) -> Result<bool>;
|
||||
|
|
|
@ -16,7 +16,25 @@ pub mod state_compressor;
|
|||
pub mod timeline;
|
||||
pub mod user;
|
||||
|
||||
pub trait Data: alias::Data + auth_chain::Data + directory::Data + edus::Data + lazy_loading::Data + metadata::Data + outlier::Data + pdu_metadata::Data + search::Data + short::Data + state::Data + state_accessor::Data + state_cache::Data + state_compressor::Data + timeline::Data + user::Data {}
|
||||
pub trait Data:
|
||||
alias::Data
|
||||
+ auth_chain::Data
|
||||
+ directory::Data
|
||||
+ edus::Data
|
||||
+ lazy_loading::Data
|
||||
+ metadata::Data
|
||||
+ outlier::Data
|
||||
+ pdu_metadata::Data
|
||||
+ search::Data
|
||||
+ short::Data
|
||||
+ state::Data
|
||||
+ state_accessor::Data
|
||||
+ state_cache::Data
|
||||
+ state_compressor::Data
|
||||
+ timeline::Data
|
||||
+ user::Data
|
||||
{
|
||||
}
|
||||
|
||||
pub struct Service {
|
||||
pub alias: alias::Service,
|
||||
|
|
|
@ -2,9 +2,9 @@ mod data;
|
|||
use std::sync::Arc;
|
||||
|
||||
pub use data::Data;
|
||||
use ruma::{EventId, signatures::CanonicalJsonObject};
|
||||
use ruma::{signatures::CanonicalJsonObject, EventId};
|
||||
|
||||
use crate::{Result, PduEvent};
|
||||
use crate::{PduEvent, Result};
|
||||
|
||||
pub struct Service {
|
||||
db: Arc<dyn Data>,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use ruma::{EventId, RoomId};
|
||||
use crate::Result;
|
||||
use ruma::{EventId, RoomId};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn mark_as_referenced(&self, room_id: &RoomId, event_ids: &[Arc<EventId>]) -> Result<()>;
|
||||
|
|
|
@ -2,7 +2,7 @@ mod data;
|
|||
use std::sync::Arc;
|
||||
|
||||
pub use data::Data;
|
||||
use ruma::{RoomId, EventId};
|
||||
use ruma::{EventId, RoomId};
|
||||
|
||||
use crate::Result;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use ruma::RoomId;
|
||||
use crate::Result;
|
||||
use ruma::RoomId;
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn index_pdu<'a>(&self, shortroomid: u64, pdu_id: &[u8], message_body: String) -> Result<()>;
|
||||
|
|
|
@ -12,7 +12,12 @@ pub struct Service {
|
|||
|
||||
impl Service {
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn index_pdu<'a>(&self, shortroomid: u64, pdu_id: &[u8], message_body: String) -> Result<()> {
|
||||
pub fn index_pdu<'a>(
|
||||
&self,
|
||||
shortroomid: u64,
|
||||
pdu_id: &[u8],
|
||||
message_body: String,
|
||||
) -> Result<()> {
|
||||
self.db.index_pdu(shortroomid, pdu_id, message_body)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use ruma::{EventId, events::StateEventType, RoomId};
|
||||
use crate::Result;
|
||||
use ruma::{events::StateEventType, EventId, RoomId};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn get_or_create_shorteventid(
|
||||
&self,
|
||||
event_id: &EventId,
|
||||
) -> Result<u64>;
|
||||
fn get_or_create_shorteventid(&self, event_id: &EventId) -> Result<u64>;
|
||||
|
||||
fn get_shortstatekey(
|
||||
&self,
|
||||
|
@ -26,15 +23,9 @@ pub trait Data: Send + Sync {
|
|||
fn get_statekey_from_short(&self, shortstatekey: u64) -> Result<(StateEventType, String)>;
|
||||
|
||||
/// Returns (shortstatehash, already_existed)
|
||||
fn get_or_create_shortstatehash(
|
||||
&self,
|
||||
state_hash: &[u8],
|
||||
) -> Result<(u64, bool)>;
|
||||
fn get_or_create_shortstatehash(&self, state_hash: &[u8]) -> Result<(u64, bool)>;
|
||||
|
||||
fn get_shortroomid(&self, room_id: &RoomId) -> Result<Option<u64>>;
|
||||
|
||||
fn get_or_create_shortroomid(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
) -> Result<u64>;
|
||||
fn get_or_create_shortroomid(&self, room_id: &RoomId) -> Result<u64>;
|
||||
}
|
||||
|
|
|
@ -2,19 +2,16 @@ mod data;
|
|||
use std::sync::Arc;
|
||||
|
||||
pub use data::Data;
|
||||
use ruma::{EventId, events::StateEventType, RoomId};
|
||||
use ruma::{events::StateEventType, EventId, RoomId};
|
||||
|
||||
use crate::{Result, Error, utils, services};
|
||||
use crate::{services, utils, Error, Result};
|
||||
|
||||
pub struct Service {
|
||||
db: Arc<dyn Data>,
|
||||
}
|
||||
|
||||
impl Service {
|
||||
pub fn get_or_create_shorteventid(
|
||||
&self,
|
||||
event_id: &EventId,
|
||||
) -> Result<u64> {
|
||||
pub fn get_or_create_shorteventid(&self, event_id: &EventId) -> Result<u64> {
|
||||
self.db.get_or_create_shorteventid(event_id)
|
||||
}
|
||||
|
||||
|
@ -43,10 +40,7 @@ impl Service {
|
|||
}
|
||||
|
||||
/// Returns (shortstatehash, already_existed)
|
||||
pub fn get_or_create_shortstatehash(
|
||||
&self,
|
||||
state_hash: &[u8],
|
||||
) -> Result<(u64, bool)> {
|
||||
pub fn get_or_create_shortstatehash(&self, state_hash: &[u8]) -> Result<(u64, bool)> {
|
||||
self.db.get_or_create_shortstatehash(state_hash)
|
||||
}
|
||||
|
||||
|
@ -54,10 +48,7 @@ impl Service {
|
|||
self.db.get_shortroomid(room_id)
|
||||
}
|
||||
|
||||
pub fn get_or_create_shortroomid(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
) -> Result<u64> {
|
||||
pub fn get_or_create_shortroomid(&self, room_id: &RoomId) -> Result<u64> {
|
||||
self.db.get_or_create_shortroomid(room_id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use std::sync::Arc;
|
||||
use std::collections::HashSet;
|
||||
use crate::Result;
|
||||
use ruma::{EventId, RoomId};
|
||||
use std::collections::HashSet;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::MutexGuard;
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
|
@ -9,7 +9,10 @@ pub trait Data: Send + Sync {
|
|||
fn get_room_shortstatehash(&self, room_id: &RoomId) -> Result<Option<u64>>;
|
||||
|
||||
/// Update the current state of the room.
|
||||
fn set_room_state(&self, room_id: &RoomId, new_shortstatehash: u64,
|
||||
fn set_room_state(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
new_shortstatehash: u64,
|
||||
_mutex_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room state mutex
|
||||
) -> Result<()>;
|
||||
|
||||
|
@ -20,7 +23,8 @@ pub trait Data: Send + Sync {
|
|||
fn get_forward_extremities(&self, room_id: &RoomId) -> Result<HashSet<Arc<EventId>>>;
|
||||
|
||||
/// Replace the forward extremities of the room.
|
||||
fn set_forward_extremities<'a>(&self,
|
||||
fn set_forward_extremities<'a>(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
event_ids: Vec<Box<EventId>>,
|
||||
_mutex_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room state mutex
|
||||
|
|
|
@ -1,13 +1,24 @@
|
|||
mod data;
|
||||
use std::{collections::{HashSet, HashMap}, sync::Arc};
|
||||
use std::{
|
||||
collections::{HashMap, HashSet},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
pub use data::Data;
|
||||
use ruma::{RoomId, events::{room::{member::MembershipState, create::RoomCreateEventContent}, AnyStrippedStateEvent, StateEventType, RoomEventType}, UserId, EventId, serde::Raw, RoomVersionId, state_res::{StateMap, self}};
|
||||
use ruma::{
|
||||
events::{
|
||||
room::{create::RoomCreateEventContent, member::MembershipState},
|
||||
AnyStrippedStateEvent, RoomEventType, StateEventType,
|
||||
},
|
||||
serde::Raw,
|
||||
state_res::{self, StateMap},
|
||||
EventId, RoomId, RoomVersionId, UserId,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use tokio::sync::MutexGuard;
|
||||
use tracing::warn;
|
||||
|
||||
use crate::{Result, services, PduEvent, Error, utils::calculate_hash};
|
||||
use crate::{services, utils::calculate_hash, Error, PduEvent, Result};
|
||||
|
||||
use super::state_compressor::CompressedStateEvent;
|
||||
|
||||
|
@ -25,7 +36,8 @@ impl Service {
|
|||
statediffremoved: HashSet<CompressedStateEvent>,
|
||||
) -> Result<()> {
|
||||
let mutex_state = Arc::clone(
|
||||
services().globals
|
||||
services()
|
||||
.globals
|
||||
.roomid_mutex_state
|
||||
.write()
|
||||
.unwrap()
|
||||
|
@ -35,7 +47,10 @@ impl Service {
|
|||
let state_lock = mutex_state.lock().await;
|
||||
|
||||
for event_id in statediffnew.into_iter().filter_map(|new| {
|
||||
services().rooms.state_compressor.parse_compressed_state_event(new)
|
||||
services()
|
||||
.rooms
|
||||
.state_compressor
|
||||
.parse_compressed_state_event(new)
|
||||
.ok()
|
||||
.map(|(_, id)| id)
|
||||
}) {
|
||||
|
@ -75,7 +90,14 @@ impl Service {
|
|||
Err(_) => continue,
|
||||
};
|
||||
|
||||
services().rooms.state_cache.update_membership(room_id, &user_id, membership, &pdu.sender, None, false)?;
|
||||
services().rooms.state_cache.update_membership(
|
||||
room_id,
|
||||
&user_id,
|
||||
membership,
|
||||
&pdu.sender,
|
||||
None,
|
||||
false,
|
||||
)?;
|
||||
}
|
||||
|
||||
services().rooms.state_cache.update_joined_count(room_id)?;
|
||||
|
@ -98,7 +120,10 @@ impl Service {
|
|||
room_id: &RoomId,
|
||||
state_ids_compressed: HashSet<CompressedStateEvent>,
|
||||
) -> Result<u64> {
|
||||
let shorteventid = services().rooms.short.get_or_create_shorteventid(event_id)?;
|
||||
let shorteventid = services()
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shorteventid(event_id)?;
|
||||
|
||||
let previous_shortstatehash = self.db.get_room_shortstatehash(room_id)?;
|
||||
|
||||
|
@ -109,12 +134,21 @@ impl Service {
|
|||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
let (shortstatehash, already_existed) =
|
||||
services().rooms.short.get_or_create_shortstatehash(&state_hash)?;
|
||||
let (shortstatehash, already_existed) = services()
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shortstatehash(&state_hash)?;
|
||||
|
||||
if !already_existed {
|
||||
let states_parents = previous_shortstatehash
|
||||
.map_or_else(|| Ok(Vec::new()), |p| services().rooms.state_compressor.load_shortstatehash_info(p))?;
|
||||
let states_parents = previous_shortstatehash.map_or_else(
|
||||
|| Ok(Vec::new()),
|
||||
|p| {
|
||||
services()
|
||||
.rooms
|
||||
.state_compressor
|
||||
.load_shortstatehash_info(p)
|
||||
},
|
||||
)?;
|
||||
|
||||
let (statediffnew, statediffremoved) =
|
||||
if let Some(parent_stateinfo) = states_parents.last() {
|
||||
|
@ -152,11 +186,11 @@ impl Service {
|
|||
/// This adds all current state events (not including the incoming event)
|
||||
/// to `stateid_pduid` and adds the incoming event to `eventid_statehash`.
|
||||
#[tracing::instrument(skip(self, new_pdu))]
|
||||
pub fn append_to_state(
|
||||
&self,
|
||||
new_pdu: &PduEvent,
|
||||
) -> Result<u64> {
|
||||
let shorteventid = services().rooms.short.get_or_create_shorteventid(&new_pdu.event_id)?;
|
||||
pub fn append_to_state(&self, new_pdu: &PduEvent) -> Result<u64> {
|
||||
let shorteventid = services()
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shorteventid(&new_pdu.event_id)?;
|
||||
|
||||
let previous_shortstatehash = self.get_room_shortstatehash(&new_pdu.room_id)?;
|
||||
|
||||
|
@ -165,15 +199,25 @@ impl Service {
|
|||
}
|
||||
|
||||
if let Some(state_key) = &new_pdu.state_key {
|
||||
let states_parents = previous_shortstatehash
|
||||
.map_or_else(|| Ok(Vec::new()), |p| services().rooms.state_compressor.load_shortstatehash_info(p))?;
|
||||
|
||||
let shortstatekey = services().rooms.short.get_or_create_shortstatekey(
|
||||
&new_pdu.kind.to_string().into(),
|
||||
state_key,
|
||||
let states_parents = previous_shortstatehash.map_or_else(
|
||||
|| Ok(Vec::new()),
|
||||
|p| {
|
||||
services()
|
||||
.rooms
|
||||
.state_compressor
|
||||
.load_shortstatehash_info(p)
|
||||
},
|
||||
)?;
|
||||
|
||||
let new = services().rooms.state_compressor.compress_state_event(shortstatekey, &new_pdu.event_id)?;
|
||||
let shortstatekey = services()
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shortstatekey(&new_pdu.kind.to_string().into(), state_key)?;
|
||||
|
||||
let new = services()
|
||||
.rooms
|
||||
.state_compressor
|
||||
.compress_state_event(shortstatekey, &new_pdu.event_id)?;
|
||||
|
||||
let replaces = states_parents
|
||||
.last()
|
||||
|
@ -220,14 +264,18 @@ impl Service {
|
|||
) -> Result<Vec<Raw<AnyStrippedStateEvent>>> {
|
||||
let mut state = Vec::new();
|
||||
// Add recommended events
|
||||
if let Some(e) =
|
||||
services().rooms.state_accessor.room_state_get(&invite_event.room_id, &StateEventType::RoomCreate, "")?
|
||||
{
|
||||
if let Some(e) = services().rooms.state_accessor.room_state_get(
|
||||
&invite_event.room_id,
|
||||
&StateEventType::RoomCreate,
|
||||
"",
|
||||
)? {
|
||||
state.push(e.to_stripped_state_event());
|
||||
}
|
||||
if let Some(e) =
|
||||
services().rooms.state_accessor.room_state_get(&invite_event.room_id, &StateEventType::RoomJoinRules, "")?
|
||||
{
|
||||
if let Some(e) = services().rooms.state_accessor.room_state_get(
|
||||
&invite_event.room_id,
|
||||
&StateEventType::RoomJoinRules,
|
||||
"",
|
||||
)? {
|
||||
state.push(e.to_stripped_state_event());
|
||||
}
|
||||
if let Some(e) = services().rooms.state_accessor.room_state_get(
|
||||
|
@ -237,14 +285,18 @@ impl Service {
|
|||
)? {
|
||||
state.push(e.to_stripped_state_event());
|
||||
}
|
||||
if let Some(e) =
|
||||
services().rooms.state_accessor.room_state_get(&invite_event.room_id, &StateEventType::RoomAvatar, "")?
|
||||
{
|
||||
if let Some(e) = services().rooms.state_accessor.room_state_get(
|
||||
&invite_event.room_id,
|
||||
&StateEventType::RoomAvatar,
|
||||
"",
|
||||
)? {
|
||||
state.push(e.to_stripped_state_event());
|
||||
}
|
||||
if let Some(e) =
|
||||
services().rooms.state_accessor.room_state_get(&invite_event.room_id, &StateEventType::RoomName, "")?
|
||||
{
|
||||
if let Some(e) = services().rooms.state_accessor.room_state_get(
|
||||
&invite_event.room_id,
|
||||
&StateEventType::RoomName,
|
||||
"",
|
||||
)? {
|
||||
state.push(e.to_stripped_state_event());
|
||||
}
|
||||
if let Some(e) = services().rooms.state_accessor.room_state_get(
|
||||
|
@ -260,16 +312,23 @@ impl Service {
|
|||
}
|
||||
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn set_room_state(&self, room_id: &RoomId, shortstatehash: u64,
|
||||
pub fn set_room_state(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
shortstatehash: u64,
|
||||
mutex_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room state mutex
|
||||
) -> Result<()> {
|
||||
) -> Result<()> {
|
||||
self.db.set_room_state(room_id, shortstatehash, mutex_lock)
|
||||
}
|
||||
|
||||
/// Returns the room's version.
|
||||
#[tracing::instrument(skip(self))]
|
||||
pub fn get_room_version(&self, room_id: &RoomId) -> Result<RoomVersionId> {
|
||||
let create_event = services().rooms.state_accessor.room_state_get(room_id, &StateEventType::RoomCreate, "")?;
|
||||
let create_event = services().rooms.state_accessor.room_state_get(
|
||||
room_id,
|
||||
&StateEventType::RoomCreate,
|
||||
"",
|
||||
)?;
|
||||
|
||||
let create_event_content: Option<RoomCreateEventContent> = create_event
|
||||
.as_ref()
|
||||
|
@ -294,12 +353,14 @@ impl Service {
|
|||
self.db.get_forward_extremities(room_id)
|
||||
}
|
||||
|
||||
pub fn set_forward_extremities<'a>(&self,
|
||||
pub fn set_forward_extremities<'a>(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
event_ids: Vec<Box<EventId>>,
|
||||
state_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room state mutex
|
||||
) -> Result<()> {
|
||||
self.db.set_forward_extremities(room_id, event_ids, state_lock)
|
||||
self.db
|
||||
.set_forward_extremities(room_id, event_ids, state_lock)
|
||||
}
|
||||
|
||||
/// This fetches auth events from the current state.
|
||||
|
@ -312,12 +373,13 @@ impl Service {
|
|||
state_key: Option<&str>,
|
||||
content: &serde_json::value::RawValue,
|
||||
) -> Result<StateMap<Arc<PduEvent>>> {
|
||||
let shortstatehash =
|
||||
if let Some(current_shortstatehash) = services().rooms.state.get_room_shortstatehash(room_id)? {
|
||||
current_shortstatehash
|
||||
} else {
|
||||
return Ok(HashMap::new());
|
||||
};
|
||||
let shortstatehash = if let Some(current_shortstatehash) =
|
||||
services().rooms.state.get_room_shortstatehash(room_id)?
|
||||
{
|
||||
current_shortstatehash
|
||||
} else {
|
||||
return Ok(HashMap::new());
|
||||
};
|
||||
|
||||
let auth_events = state_res::auth_types_for_event(kind, sender, state_key, content)
|
||||
.expect("content is a valid JSON object");
|
||||
|
@ -325,14 +387,19 @@ impl Service {
|
|||
let mut sauthevents = auth_events
|
||||
.into_iter()
|
||||
.filter_map(|(event_type, state_key)| {
|
||||
services().rooms.short.get_shortstatekey(&event_type.to_string().into(), &state_key)
|
||||
services()
|
||||
.rooms
|
||||
.short
|
||||
.get_shortstatekey(&event_type.to_string().into(), &state_key)
|
||||
.ok()
|
||||
.flatten()
|
||||
.map(|s| (s, (event_type, state_key)))
|
||||
})
|
||||
.collect::<HashMap<_, _>>();
|
||||
|
||||
let full_state = services().rooms.state_compressor
|
||||
let full_state = services()
|
||||
.rooms
|
||||
.state_compressor
|
||||
.load_shortstatehash_info(shortstatehash)?
|
||||
.pop()
|
||||
.expect("there is always one layer")
|
||||
|
@ -340,11 +407,25 @@ impl Service {
|
|||
|
||||
Ok(full_state
|
||||
.into_iter()
|
||||
.filter_map(|compressed| services().rooms.state_compressor.parse_compressed_state_event(compressed).ok())
|
||||
.filter_map(|compressed| {
|
||||
services()
|
||||
.rooms
|
||||
.state_compressor
|
||||
.parse_compressed_state_event(compressed)
|
||||
.ok()
|
||||
})
|
||||
.filter_map(|(shortstatekey, event_id)| {
|
||||
sauthevents.remove(&shortstatekey).map(|k| (k, event_id))
|
||||
})
|
||||
.filter_map(|(k, event_id)| services().rooms.timeline.get_pdu(&event_id).ok().flatten().map(|pdu| (k, pdu)))
|
||||
.filter_map(|(k, event_id)| {
|
||||
services()
|
||||
.rooms
|
||||
.timeline
|
||||
.get_pdu(&event_id)
|
||||
.ok()
|
||||
.flatten()
|
||||
.map(|pdu| (k, pdu))
|
||||
})
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
use std::{sync::Arc, collections::{HashMap, BTreeMap}};
|
||||
use std::{
|
||||
collections::{BTreeMap, HashMap},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use ruma::{EventId, events::StateEventType, RoomId};
|
||||
use ruma::{events::StateEventType, EventId, RoomId};
|
||||
|
||||
use crate::{Result, PduEvent};
|
||||
use crate::{PduEvent, Result};
|
||||
|
||||
#[async_trait]
|
||||
pub trait Data: Send + Sync {
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
mod data;
|
||||
use std::{sync::Arc, collections::{HashMap, BTreeMap}};
|
||||
use std::{
|
||||
collections::{BTreeMap, HashMap},
|
||||
sync::Arc,
|
||||
};
|
||||
|
||||
pub use data::Data;
|
||||
use ruma::{events::StateEventType, RoomId, EventId};
|
||||
use ruma::{events::StateEventType, EventId, RoomId};
|
||||
|
||||
use crate::{Result, PduEvent};
|
||||
use crate::{PduEvent, Result};
|
||||
|
||||
pub struct Service {
|
||||
db: Arc<dyn Data>,
|
||||
|
|
|
@ -1,12 +1,21 @@
|
|||
use std::{collections::HashSet, sync::Arc};
|
||||
|
||||
use ruma::{UserId, RoomId, serde::Raw, events::{AnyStrippedStateEvent, AnySyncStateEvent}, ServerName};
|
||||
use crate::Result;
|
||||
use ruma::{
|
||||
events::{AnyStrippedStateEvent, AnySyncStateEvent},
|
||||
serde::Raw,
|
||||
RoomId, ServerName, UserId,
|
||||
};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn mark_as_once_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<()>;
|
||||
fn mark_as_joined(&self, user_id: &UserId, room_id: &RoomId) -> Result<()>;
|
||||
fn mark_as_invited(&self, user_id: &UserId, room_id: &RoomId, last_state: Option<Vec<Raw<AnyStrippedStateEvent>>>) -> Result<()>;
|
||||
fn mark_as_invited(
|
||||
&self,
|
||||
user_id: &UserId,
|
||||
room_id: &RoomId,
|
||||
last_state: Option<Vec<Raw<AnyStrippedStateEvent>>>,
|
||||
) -> Result<()>;
|
||||
fn mark_as_left(&self, user_id: &UserId, room_id: &RoomId) -> Result<()>;
|
||||
|
||||
fn update_joined_count(&self, room_id: &RoomId) -> Result<()>;
|
||||
|
|
|
@ -9,8 +9,8 @@ use ruma::{
|
|||
ignored_user_list::IgnoredUserListEvent,
|
||||
room::{create::RoomCreateEventContent, member::MembershipState},
|
||||
tag::{TagEvent, TagEventContent},
|
||||
AnyStrippedStateEvent, AnySyncStateEvent, GlobalAccountDataEventType,
|
||||
RoomAccountDataEventType, StateEventType, RoomAccountDataEvent, RoomAccountDataEventContent,
|
||||
AnyStrippedStateEvent, AnySyncStateEvent, GlobalAccountDataEventType, RoomAccountDataEvent,
|
||||
RoomAccountDataEventContent, RoomAccountDataEventType, StateEventType,
|
||||
},
|
||||
serde::Raw,
|
||||
RoomId, ServerName, UserId,
|
||||
|
@ -97,8 +97,9 @@ impl Service {
|
|||
RoomAccountDataEventType::Tag,
|
||||
)?
|
||||
.map(|event| {
|
||||
serde_json::from_str(event.get())
|
||||
.map_err(|_| Error::bad_database("Invalid account data event in db."))
|
||||
serde_json::from_str(event.get()).map_err(|_| {
|
||||
Error::bad_database("Invalid account data event in db.")
|
||||
})
|
||||
})
|
||||
{
|
||||
services()
|
||||
|
@ -113,16 +114,19 @@ impl Service {
|
|||
};
|
||||
|
||||
// Copy direct chat flag
|
||||
if let Some(mut direct_event) = services().account_data.get(
|
||||
None,
|
||||
user_id,
|
||||
GlobalAccountDataEventType::Direct.to_string().into(),
|
||||
)?
|
||||
if let Some(mut direct_event) = services()
|
||||
.account_data
|
||||
.get(
|
||||
None,
|
||||
user_id,
|
||||
GlobalAccountDataEventType::Direct.to_string().into(),
|
||||
)?
|
||||
.map(|event| {
|
||||
serde_json::from_str::<DirectEvent>(event.get())
|
||||
.map_err(|_| Error::bad_database("Invalid account data event in db."))
|
||||
serde_json::from_str::<DirectEvent>(event.get()).map_err(|_| {
|
||||
Error::bad_database("Invalid account data event in db.")
|
||||
})
|
||||
})
|
||||
{
|
||||
{
|
||||
let direct_event = direct_event?;
|
||||
let mut room_ids_updated = false;
|
||||
|
||||
|
@ -138,7 +142,8 @@ impl Service {
|
|||
None,
|
||||
user_id,
|
||||
GlobalAccountDataEventType::Direct.to_string().into(),
|
||||
&serde_json::to_value(&direct_event).expect("to json always works"),
|
||||
&serde_json::to_value(&direct_event)
|
||||
.expect("to json always works"),
|
||||
)?;
|
||||
}
|
||||
};
|
||||
|
@ -158,10 +163,11 @@ impl Service {
|
|||
.to_string()
|
||||
.into(),
|
||||
)?
|
||||
.map(|event| {
|
||||
serde_json::from_str::<IgnoredUserListEvent>(event.get())
|
||||
.map_err(|_| Error::bad_database("Invalid account data event in db."))
|
||||
}).transpose()?
|
||||
.map(|event| {
|
||||
serde_json::from_str::<IgnoredUserListEvent>(event.get())
|
||||
.map_err(|_| Error::bad_database("Invalid account data event in db."))
|
||||
})
|
||||
.transpose()?
|
||||
.map_or(false, |ignored| {
|
||||
ignored
|
||||
.content
|
||||
|
|
|
@ -1,11 +1,15 @@
|
|||
pub mod data;
|
||||
use std::{mem::size_of, sync::{Arc, Mutex}, collections::HashSet};
|
||||
use std::{
|
||||
collections::HashSet,
|
||||
mem::size_of,
|
||||
sync::{Arc, Mutex},
|
||||
};
|
||||
|
||||
pub use data::Data;
|
||||
use lru_cache::LruCache;
|
||||
use ruma::{EventId, RoomId};
|
||||
|
||||
use crate::{Result, utils, services};
|
||||
use crate::{services, utils, Result};
|
||||
|
||||
use self::data::StateDiff;
|
||||
|
||||
|
@ -23,7 +27,6 @@ pub struct Service {
|
|||
)>,
|
||||
>,
|
||||
>,
|
||||
|
||||
}
|
||||
|
||||
pub type CompressedStateEvent = [u8; 2 * size_of::<u64>()];
|
||||
|
@ -51,7 +54,11 @@ impl Service {
|
|||
return Ok(r.clone());
|
||||
}
|
||||
|
||||
let StateDiff { parent, added, removed } = self.db.get_statediff(shortstatehash)?;
|
||||
let StateDiff {
|
||||
parent,
|
||||
added,
|
||||
removed,
|
||||
} = self.db.get_statediff(shortstatehash)?;
|
||||
|
||||
if let Some(parent) = parent {
|
||||
let mut response = self.load_shortstatehash_info(parent)?;
|
||||
|
@ -81,7 +88,9 @@ impl Service {
|
|||
) -> Result<CompressedStateEvent> {
|
||||
let mut v = shortstatekey.to_be_bytes().to_vec();
|
||||
v.extend_from_slice(
|
||||
&services().rooms.short
|
||||
&services()
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shorteventid(event_id)?
|
||||
.to_be_bytes(),
|
||||
);
|
||||
|
@ -175,7 +184,14 @@ impl Service {
|
|||
|
||||
if parent_states.is_empty() {
|
||||
// There is no parent layer, create a new state
|
||||
self.db.save_statediff(shortstatehash, StateDiff { parent: None, added: statediffnew, removed: statediffremoved })?;
|
||||
self.db.save_statediff(
|
||||
shortstatehash,
|
||||
StateDiff {
|
||||
parent: None,
|
||||
added: statediffnew,
|
||||
removed: statediffremoved,
|
||||
},
|
||||
)?;
|
||||
|
||||
return Ok(());
|
||||
};
|
||||
|
@ -217,7 +233,14 @@ impl Service {
|
|||
)?;
|
||||
} else {
|
||||
// Diff small enough, we add diff as layer on top of parent
|
||||
self.db.save_statediff(shortstatehash, StateDiff { parent: Some(parent.0), added: statediffnew, removed: statediffremoved })?;
|
||||
self.db.save_statediff(
|
||||
shortstatehash,
|
||||
StateDiff {
|
||||
parent: Some(parent.0),
|
||||
added: statediffnew,
|
||||
removed: statediffremoved,
|
||||
},
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -228,8 +251,7 @@ impl Service {
|
|||
&self,
|
||||
room_id: &RoomId,
|
||||
new_state_ids_compressed: HashSet<CompressedStateEvent>,
|
||||
) -> Result<u64>
|
||||
{
|
||||
) -> Result<u64> {
|
||||
let previous_shortstatehash = services().rooms.state.get_room_shortstatehash(room_id)?;
|
||||
|
||||
let state_hash = utils::calculate_hash(
|
||||
|
@ -239,8 +261,10 @@ impl Service {
|
|||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
let (new_shortstatehash, already_existed) =
|
||||
services().rooms.short.get_or_create_shortstatehash(&state_hash)?;
|
||||
let (new_shortstatehash, already_existed) = services()
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shortstatehash(&state_hash)?;
|
||||
|
||||
if Some(new_shortstatehash) == previous_shortstatehash {
|
||||
return Ok(new_shortstatehash);
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use ruma::{signatures::CanonicalJsonObject, EventId, UserId, RoomId};
|
||||
use ruma::{signatures::CanonicalJsonObject, EventId, RoomId, UserId};
|
||||
|
||||
use crate::{Result, PduEvent};
|
||||
use crate::{PduEvent, Result};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn first_pdu_in_room(&self, room_id: &RoomId) -> Result<Option<Arc<PduEvent>>>;
|
||||
|
@ -15,10 +15,7 @@ pub trait Data: Send + Sync {
|
|||
fn get_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>>;
|
||||
|
||||
/// Returns the json of a pdu.
|
||||
fn get_non_outlier_pdu_json(
|
||||
&self,
|
||||
event_id: &EventId,
|
||||
) -> Result<Option<CanonicalJsonObject>>;
|
||||
fn get_non_outlier_pdu_json(&self, event_id: &EventId) -> Result<Option<CanonicalJsonObject>>;
|
||||
|
||||
/// Returns the pdu's id.
|
||||
fn get_pdu_id(&self, event_id: &EventId) -> Result<Option<Vec<u8>>>;
|
||||
|
@ -45,7 +42,13 @@ pub trait Data: Send + Sync {
|
|||
fn pdu_count(&self, pdu_id: &[u8]) -> Result<u64>;
|
||||
|
||||
/// Adds a new pdu to the timeline
|
||||
fn append_pdu(&self, pdu_id: &[u8], pdu: &PduEvent, json: &CanonicalJsonObject, count: u64) -> Result<()>;
|
||||
fn append_pdu(
|
||||
&self,
|
||||
pdu_id: &[u8],
|
||||
pdu: &PduEvent,
|
||||
json: &CanonicalJsonObject,
|
||||
count: u64,
|
||||
) -> Result<()>;
|
||||
|
||||
/// Removes a pdu and creates a new one with the same id.
|
||||
fn replace_pdu(&self, pdu_id: &[u8], pdu: &PduEvent) -> Result<()>;
|
||||
|
@ -75,5 +78,10 @@ pub trait Data: Send + Sync {
|
|||
from: u64,
|
||||
) -> Result<Box<dyn Iterator<Item = Result<(Vec<u8>, PduEvent)>>>>;
|
||||
|
||||
fn increment_notification_counts(&self, room_id: &RoomId, notifies: Vec<Box<UserId>>, highlights: Vec<Box<UserId>>) -> Result<()>;
|
||||
fn increment_notification_counts(
|
||||
&self,
|
||||
room_id: &RoomId,
|
||||
notifies: Vec<Box<UserId>>,
|
||||
highlights: Vec<Box<UserId>>,
|
||||
) -> Result<()>;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
mod data;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::{iter, collections::HashSet};
|
||||
use std::fmt::Debug;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::{collections::HashSet, iter};
|
||||
|
||||
pub use data::Data;
|
||||
use regex::Regex;
|
||||
|
@ -11,13 +11,27 @@ use ruma::events::room::power_levels::RoomPowerLevelsEventContent;
|
|||
use ruma::push::Ruleset;
|
||||
use ruma::signatures::CanonicalJsonValue;
|
||||
use ruma::state_res::RoomVersion;
|
||||
use ruma::{EventId, signatures::CanonicalJsonObject, push::{Action, Tweak}, events::{push_rules::PushRulesEvent, GlobalAccountDataEventType, RoomEventType, room::{member::MembershipState, create::RoomCreateEventContent}, StateEventType}, UserId, RoomAliasId, RoomId, uint, state_res, api::client::error::ErrorKind, serde::to_canonical_value, ServerName};
|
||||
use ruma::{
|
||||
api::client::error::ErrorKind,
|
||||
events::{
|
||||
push_rules::PushRulesEvent,
|
||||
room::{create::RoomCreateEventContent, member::MembershipState},
|
||||
GlobalAccountDataEventType, RoomEventType, StateEventType,
|
||||
},
|
||||
push::{Action, Tweak},
|
||||
serde::to_canonical_value,
|
||||
signatures::CanonicalJsonObject,
|
||||
state_res, uint, EventId, RoomAliasId, RoomId, ServerName, UserId,
|
||||
};
|
||||
use serde::Deserialize;
|
||||
use serde_json::value::to_raw_value;
|
||||
use tokio::sync::MutexGuard;
|
||||
use tracing::{warn, error};
|
||||
use tracing::{error, warn};
|
||||
|
||||
use crate::{services, Result, service::pdu::{PduBuilder, EventHash}, Error, PduEvent, utils};
|
||||
use crate::{
|
||||
service::pdu::{EventHash, PduBuilder},
|
||||
services, utils, Error, PduEvent, Result,
|
||||
};
|
||||
|
||||
use super::state_compressor::CompressedStateEvent;
|
||||
|
||||
|
@ -135,7 +149,11 @@ impl Service {
|
|||
leaves: Vec<Box<EventId>>,
|
||||
state_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room state mutex
|
||||
) -> Result<Vec<u8>> {
|
||||
let shortroomid = services().rooms.short.get_shortroomid(&pdu.room_id)?.expect("room exists");
|
||||
let shortroomid = services()
|
||||
.rooms
|
||||
.short
|
||||
.get_shortroomid(&pdu.room_id)?
|
||||
.expect("room exists");
|
||||
|
||||
// Make unsigned fields correct. This is not properly documented in the spec, but state
|
||||
// events need to have previous content in the unsigned field, so clients can easily
|
||||
|
@ -145,8 +163,15 @@ impl Service {
|
|||
.entry("unsigned".to_owned())
|
||||
.or_insert_with(|| CanonicalJsonValue::Object(Default::default()))
|
||||
{
|
||||
if let Some(shortstatehash) = services().rooms.state_accessor.pdu_shortstatehash(&pdu.event_id).unwrap() {
|
||||
if let Some(prev_state) = services().rooms.state_accessor
|
||||
if let Some(shortstatehash) = services()
|
||||
.rooms
|
||||
.state_accessor
|
||||
.pdu_shortstatehash(&pdu.event_id)
|
||||
.unwrap()
|
||||
{
|
||||
if let Some(prev_state) = services()
|
||||
.rooms
|
||||
.state_accessor
|
||||
.state_get(shortstatehash, &pdu.kind.to_string().into(), state_key)
|
||||
.unwrap()
|
||||
{
|
||||
|
@ -165,11 +190,18 @@ impl Service {
|
|||
}
|
||||
|
||||
// We must keep track of all events that have been referenced.
|
||||
services().rooms.pdu_metadata.mark_as_referenced(&pdu.room_id, &pdu.prev_events)?;
|
||||
services().rooms.state.set_forward_extremities(&pdu.room_id, leaves, state_lock)?;
|
||||
services()
|
||||
.rooms
|
||||
.pdu_metadata
|
||||
.mark_as_referenced(&pdu.room_id, &pdu.prev_events)?;
|
||||
services()
|
||||
.rooms
|
||||
.state
|
||||
.set_forward_extremities(&pdu.room_id, leaves, state_lock)?;
|
||||
|
||||
let mutex_insert = Arc::clone(
|
||||
services().globals
|
||||
services()
|
||||
.globals
|
||||
.roomid_mutex_insert
|
||||
.write()
|
||||
.unwrap()
|
||||
|
@ -181,9 +213,15 @@ impl Service {
|
|||
let count1 = services().globals.next_count()?;
|
||||
// Mark as read first so the sending client doesn't get a notification even if appending
|
||||
// fails
|
||||
services().rooms.edus.read_receipt
|
||||
services()
|
||||
.rooms
|
||||
.edus
|
||||
.read_receipt
|
||||
.private_read_set(&pdu.room_id, &pdu.sender, count1)?;
|
||||
services().rooms.user.reset_notification_counts(&pdu.sender, &pdu.room_id)?;
|
||||
services()
|
||||
.rooms
|
||||
.user
|
||||
.reset_notification_counts(&pdu.sender, &pdu.room_id)?;
|
||||
|
||||
let count2 = services().globals.next_count()?;
|
||||
let mut pdu_id = shortroomid.to_be_bytes().to_vec();
|
||||
|
@ -211,7 +249,12 @@ impl Service {
|
|||
let mut notifies = Vec::new();
|
||||
let mut highlights = Vec::new();
|
||||
|
||||
for user in services().rooms.state_cache.get_our_real_users(&pdu.room_id)?.into_iter() {
|
||||
for user in services()
|
||||
.rooms
|
||||
.state_cache
|
||||
.get_our_real_users(&pdu.room_id)?
|
||||
.into_iter()
|
||||
{
|
||||
// Don't notify the user of their own events
|
||||
if &user == &pdu.sender {
|
||||
continue;
|
||||
|
@ -224,8 +267,11 @@ impl Service {
|
|||
&user,
|
||||
GlobalAccountDataEventType::PushRules.to_string().into(),
|
||||
)?
|
||||
.map(|event| serde_json::from_str::<PushRulesEvent>(event.get())
|
||||
.map_err(|_| Error::bad_database("Invalid push rules event in db."))).transpose()?
|
||||
.map(|event| {
|
||||
serde_json::from_str::<PushRulesEvent>(event.get())
|
||||
.map_err(|_| Error::bad_database("Invalid push rules event in db."))
|
||||
})
|
||||
.transpose()?
|
||||
.map(|ev: PushRulesEvent| ev.content.global)
|
||||
.unwrap_or_else(|| Ruleset::server_default(&user));
|
||||
|
||||
|
@ -263,7 +309,8 @@ impl Service {
|
|||
}
|
||||
}
|
||||
|
||||
self.db.increment_notification_counts(&pdu.room_id, notifies, highlights);
|
||||
self.db
|
||||
.increment_notification_counts(&pdu.room_id, notifies, highlights);
|
||||
|
||||
match pdu.kind {
|
||||
RoomEventType::RoomRedaction => {
|
||||
|
@ -315,7 +362,10 @@ impl Service {
|
|||
.map_err(|_| Error::bad_database("Invalid content in pdu."))?;
|
||||
|
||||
if let Some(body) = content.body {
|
||||
services().rooms.search.index_pdu(shortroomid, &pdu_id, body)?;
|
||||
services()
|
||||
.rooms
|
||||
.search
|
||||
.index_pdu(shortroomid, &pdu_id, body)?;
|
||||
|
||||
let admin_room = services().rooms.alias.resolve_local_alias(
|
||||
<&RoomAliasId>::try_from(
|
||||
|
@ -329,8 +379,8 @@ impl Service {
|
|||
|
||||
// This will evaluate to false if the emergency password is set up so that
|
||||
// the administrator can execute commands as conduit
|
||||
let from_conduit =
|
||||
pdu.sender == server_user && services().globals.emergency_password().is_none();
|
||||
let from_conduit = pdu.sender == server_user
|
||||
&& services().globals.emergency_password().is_none();
|
||||
|
||||
if to_conduit && !from_conduit && admin_room.as_ref() == Some(&pdu.room_id) {
|
||||
services().admin.process_message(body.to_string());
|
||||
|
@ -341,8 +391,14 @@ impl Service {
|
|||
}
|
||||
|
||||
for appservice in services().appservice.all()? {
|
||||
if services().rooms.state_cache.appservice_in_room(&pdu.room_id, &appservice)? {
|
||||
services().sending.send_pdu_appservice(&appservice.0, &pdu_id)?;
|
||||
if services()
|
||||
.rooms
|
||||
.state_cache
|
||||
.appservice_in_room(&pdu.room_id, &appservice)?
|
||||
{
|
||||
services()
|
||||
.sending
|
||||
.send_pdu_appservice(&appservice.0, &pdu_id)?;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -359,11 +415,14 @@ impl Service {
|
|||
.get("sender_localpart")
|
||||
.and_then(|string| string.as_str())
|
||||
.and_then(|string| {
|
||||
UserId::parse_with_server_name(string, services().globals.server_name()).ok()
|
||||
UserId::parse_with_server_name(string, services().globals.server_name())
|
||||
.ok()
|
||||
})
|
||||
{
|
||||
if state_key_uid == &appservice_uid {
|
||||
services().sending.send_pdu_appservice(&appservice.0, &pdu_id)?;
|
||||
services()
|
||||
.sending
|
||||
.send_pdu_appservice(&appservice.0, &pdu_id)?;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -402,7 +461,10 @@ impl Service {
|
|||
.map_or(false, |state_key| users.is_match(state_key))
|
||||
};
|
||||
let matching_aliases = |aliases: &Regex| {
|
||||
services().rooms.alias.local_aliases_for_room(&pdu.room_id)
|
||||
services()
|
||||
.rooms
|
||||
.alias
|
||||
.local_aliases_for_room(&pdu.room_id)
|
||||
.filter_map(|r| r.ok())
|
||||
.any(|room_alias| aliases.is_match(room_alias.as_str()))
|
||||
};
|
||||
|
@ -411,21 +473,22 @@ impl Service {
|
|||
|| rooms.map_or(false, |rooms| rooms.contains(&pdu.room_id.as_str().into()))
|
||||
|| users.iter().any(matching_users)
|
||||
{
|
||||
services().sending.send_pdu_appservice(&appservice.0, &pdu_id)?;
|
||||
services()
|
||||
.sending
|
||||
.send_pdu_appservice(&appservice.0, &pdu_id)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Ok(pdu_id)
|
||||
}
|
||||
|
||||
pub fn create_hash_and_sign_event(
|
||||
&self,
|
||||
pdu_builder: PduBuilder,
|
||||
sender: &UserId,
|
||||
room_id: &RoomId,
|
||||
_mutex_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room state mutex
|
||||
&self,
|
||||
pdu_builder: PduBuilder,
|
||||
sender: &UserId,
|
||||
room_id: &RoomId,
|
||||
_mutex_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room state mutex
|
||||
) -> Result<(PduEvent, CanonicalJsonObject)> {
|
||||
let PduBuilder {
|
||||
event_type,
|
||||
|
@ -443,10 +506,11 @@ impl Service {
|
|||
.take(20)
|
||||
.collect();
|
||||
|
||||
let create_event = services()
|
||||
.rooms
|
||||
.state_accessor
|
||||
.room_state_get(room_id, &StateEventType::RoomCreate, "")?;
|
||||
let create_event = services().rooms.state_accessor.room_state_get(
|
||||
room_id,
|
||||
&StateEventType::RoomCreate,
|
||||
"",
|
||||
)?;
|
||||
|
||||
let create_event_content: Option<RoomCreateEventContent> = create_event
|
||||
.as_ref()
|
||||
|
@ -464,11 +528,15 @@ impl Service {
|
|||
.map_or(services().globals.default_room_version(), |create_event| {
|
||||
create_event.room_version
|
||||
});
|
||||
let room_version =
|
||||
RoomVersion::new(&room_version_id).expect("room version is supported");
|
||||
let room_version = RoomVersion::new(&room_version_id).expect("room version is supported");
|
||||
|
||||
let auth_events =
|
||||
services().rooms.state.get_auth_events(room_id, &event_type, sender, state_key.as_deref(), &content)?;
|
||||
let auth_events = services().rooms.state.get_auth_events(
|
||||
room_id,
|
||||
&event_type,
|
||||
sender,
|
||||
state_key.as_deref(),
|
||||
&content,
|
||||
)?;
|
||||
|
||||
// Our depth is the maximum depth of prev_events + 1
|
||||
let depth = prev_events
|
||||
|
@ -481,9 +549,11 @@ impl Service {
|
|||
let mut unsigned = unsigned.unwrap_or_default();
|
||||
|
||||
if let Some(state_key) = &state_key {
|
||||
if let Some(prev_pdu) =
|
||||
services().rooms.state_accessor.room_state_get(room_id, &event_type.to_string().into(), state_key)?
|
||||
{
|
||||
if let Some(prev_pdu) = services().rooms.state_accessor.room_state_get(
|
||||
room_id,
|
||||
&event_type.to_string().into(),
|
||||
state_key,
|
||||
)? {
|
||||
unsigned.insert(
|
||||
"prev_content".to_owned(),
|
||||
serde_json::from_str(prev_pdu.content.get()).expect("string is valid json"),
|
||||
|
@ -589,7 +659,10 @@ impl Service {
|
|||
);
|
||||
|
||||
// Generate short event id
|
||||
let _shorteventid = services().rooms.short.get_or_create_shorteventid(&pdu.event_id)?;
|
||||
let _shorteventid = services()
|
||||
.rooms
|
||||
.short
|
||||
.get_or_create_shorteventid(&pdu.event_id)?;
|
||||
|
||||
Ok((pdu, pdu_json))
|
||||
}
|
||||
|
@ -604,7 +677,8 @@ impl Service {
|
|||
room_id: &RoomId,
|
||||
state_lock: &MutexGuard<'_, ()>, // Take mutex guard to make sure users get the room state mutex
|
||||
) -> Result<Arc<EventId>> {
|
||||
let (pdu, pdu_json) = self.create_hash_and_sign_event(pdu_builder, sender, room_id, &state_lock)?;
|
||||
let (pdu, pdu_json) =
|
||||
self.create_hash_and_sign_event(pdu_builder, sender, room_id, &state_lock)?;
|
||||
|
||||
// We append to state before appending the pdu, so we don't have a moment in time with the
|
||||
// pdu without it's state. This is okay because append_pdu can't fail.
|
||||
|
@ -621,10 +695,17 @@ impl Service {
|
|||
|
||||
// We set the room state after inserting the pdu, so that we never have a moment in time
|
||||
// where events in the current room state do not exist
|
||||
services().rooms.state.set_room_state(room_id, statehashid, state_lock)?;
|
||||
services()
|
||||
.rooms
|
||||
.state
|
||||
.set_room_state(room_id, statehashid, state_lock)?;
|
||||
|
||||
let mut servers: HashSet<Box<ServerName>> =
|
||||
services().rooms.state_cache.room_servers(room_id).filter_map(|r| r.ok()).collect();
|
||||
let mut servers: HashSet<Box<ServerName>> = services()
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_servers(room_id)
|
||||
.filter_map(|r| r.ok())
|
||||
.collect();
|
||||
|
||||
// In case we are kicking or banning a user, we need to inform their server of the change
|
||||
if pdu.kind == RoomEventType::RoomMember {
|
||||
|
@ -666,13 +747,23 @@ impl Service {
|
|||
)?;
|
||||
|
||||
if soft_fail {
|
||||
services().rooms.pdu_metadata
|
||||
services()
|
||||
.rooms
|
||||
.pdu_metadata
|
||||
.mark_as_referenced(&pdu.room_id, &pdu.prev_events)?;
|
||||
services().rooms.state.set_forward_extremities(&pdu.room_id, new_room_leaves, state_lock)?;
|
||||
services().rooms.state.set_forward_extremities(
|
||||
&pdu.room_id,
|
||||
new_room_leaves,
|
||||
state_lock,
|
||||
)?;
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let pdu_id = services().rooms.timeline.append_pdu(pdu, pdu_json, new_room_leaves, state_lock)?;
|
||||
let pdu_id =
|
||||
services()
|
||||
.rooms
|
||||
.timeline
|
||||
.append_pdu(pdu, pdu_json, new_room_leaves, state_lock)?;
|
||||
|
||||
Ok(Some(pdu_id))
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use ruma::{UserId, RoomId};
|
||||
use crate::Result;
|
||||
use ruma::{RoomId, UserId};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn reset_notification_counts(&self, user_id: &UserId, room_id: &RoomId) -> Result<()>;
|
||||
|
|
|
@ -29,7 +29,8 @@ impl Service {
|
|||
token: u64,
|
||||
shortstatehash: u64,
|
||||
) -> Result<()> {
|
||||
self.db.associate_token_shortstatehash(room_id, token, shortstatehash)
|
||||
self.db
|
||||
.associate_token_shortstatehash(room_id, token, shortstatehash)
|
||||
}
|
||||
|
||||
pub fn get_token_shortstatehash(&self, room_id: &RoomId, token: u64) -> Result<Option<u64>> {
|
||||
|
|
|
@ -6,7 +6,10 @@ use std::{
|
|||
};
|
||||
|
||||
use crate::{
|
||||
utils::{self, calculate_hash}, Error, PduEvent, Result, services, api::{server_server, appservice_server},
|
||||
api::{appservice_server, server_server},
|
||||
services,
|
||||
utils::{self, calculate_hash},
|
||||
Error, PduEvent, Result,
|
||||
};
|
||||
use federation::transactions::send_transaction_message;
|
||||
use futures_util::{stream::FuturesUnordered, StreamExt};
|
||||
|
@ -88,10 +91,7 @@ enum TransactionStatus {
|
|||
}
|
||||
|
||||
impl Service {
|
||||
pub fn start_handler(
|
||||
&self,
|
||||
mut receiver: mpsc::UnboundedReceiver<(Vec<u8>, Vec<u8>)>,
|
||||
) {
|
||||
pub fn start_handler(&self, mut receiver: mpsc::UnboundedReceiver<(Vec<u8>, Vec<u8>)>) {
|
||||
tokio::spawn(async move {
|
||||
let mut futures = FuturesUnordered::new();
|
||||
|
||||
|
@ -119,7 +119,11 @@ impl Service {
|
|||
"Dropping some current events: {:?} {:?} {:?}",
|
||||
key, outgoing_kind, event
|
||||
);
|
||||
services().sending.servercurrentevent_data.remove(&key).unwrap();
|
||||
services()
|
||||
.sending
|
||||
.servercurrentevent_data
|
||||
.remove(&key)
|
||||
.unwrap();
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -129,10 +133,7 @@ impl Service {
|
|||
for (outgoing_kind, events) in initial_transactions {
|
||||
current_transaction_status
|
||||
.insert(outgoing_kind.get_prefix(), TransactionStatus::Running);
|
||||
futures.push(Self::handle_events(
|
||||
outgoing_kind.clone(),
|
||||
events,
|
||||
));
|
||||
futures.push(Self::handle_events(outgoing_kind.clone(), events));
|
||||
}
|
||||
|
||||
loop {
|
||||
|
@ -246,7 +247,11 @@ impl Service {
|
|||
|
||||
if retry {
|
||||
// We retry the previous transaction
|
||||
for (key, value) in services().sending.servercurrentevent_data.scan_prefix(prefix) {
|
||||
for (key, value) in services()
|
||||
.sending
|
||||
.servercurrentevent_data
|
||||
.scan_prefix(prefix)
|
||||
{
|
||||
if let Ok((_, e)) = Self::parse_servercurrentevent(&key, value) {
|
||||
events.push(e);
|
||||
}
|
||||
|
@ -258,7 +263,8 @@ impl Service {
|
|||
} else {
|
||||
&[][..]
|
||||
};
|
||||
services().sending
|
||||
services()
|
||||
.sending
|
||||
.servercurrentevent_data
|
||||
.insert(&full_key, value)?;
|
||||
|
||||
|
@ -273,7 +279,8 @@ impl Service {
|
|||
if let Ok((select_edus, last_count)) = Self::select_edus(server_name) {
|
||||
events.extend(select_edus.into_iter().map(SendingEventType::Edu));
|
||||
|
||||
services().sending
|
||||
services()
|
||||
.sending
|
||||
.servername_educount
|
||||
.insert(server_name.as_bytes(), &last_count.to_be_bytes())?;
|
||||
}
|
||||
|
@ -302,7 +309,8 @@ impl Service {
|
|||
let room_id = room_id?;
|
||||
// Look for device list updates in this room
|
||||
device_list_changes.extend(
|
||||
services().users
|
||||
services()
|
||||
.users
|
||||
.keys_changed(&room_id.to_string(), since, None)
|
||||
.filter_map(|r| r.ok())
|
||||
.filter(|user_id| user_id.server_name() == services().globals.server_name()),
|
||||
|
@ -502,7 +510,8 @@ impl Service {
|
|||
let permit = services().sending.maximum_requests.acquire().await;
|
||||
|
||||
let response = appservice_server::send_request(
|
||||
services().appservice
|
||||
services()
|
||||
.appservice
|
||||
.get_registration(&id)
|
||||
.map_err(|e| (kind.clone(), e))?
|
||||
.ok_or_else(|| {
|
||||
|
@ -621,16 +630,12 @@ impl Service {
|
|||
|
||||
let permit = services().sending.maximum_requests.acquire().await;
|
||||
|
||||
let _response = services().pusher.send_push_notice(
|
||||
&userid,
|
||||
unread,
|
||||
&pusher,
|
||||
rules_for_user,
|
||||
&pdu,
|
||||
)
|
||||
.await
|
||||
.map(|_response| kind.clone())
|
||||
.map_err(|e| (kind.clone(), e));
|
||||
let _response = services()
|
||||
.pusher
|
||||
.send_push_notice(&userid, unread, &pusher, rules_for_user, &pdu)
|
||||
.await
|
||||
.map(|_response| kind.clone())
|
||||
.map_err(|e| (kind.clone(), e));
|
||||
|
||||
drop(permit);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use ruma::{DeviceId, UserId, TransactionId};
|
||||
use crate::Result;
|
||||
use ruma::{DeviceId, TransactionId, UserId};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn add_txnid(
|
||||
|
|
|
@ -3,8 +3,8 @@ use std::sync::Arc;
|
|||
|
||||
pub use data::Data;
|
||||
|
||||
use ruma::{UserId, DeviceId, TransactionId};
|
||||
use crate::Result;
|
||||
use ruma::{DeviceId, TransactionId, UserId};
|
||||
|
||||
pub struct Service {
|
||||
db: Arc<dyn Data>,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use ruma::{api::client::uiaa::UiaaInfo, DeviceId, UserId, signatures::CanonicalJsonValue};
|
||||
use crate::Result;
|
||||
use ruma::{api::client::uiaa::UiaaInfo, signatures::CanonicalJsonValue, DeviceId, UserId};
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
fn set_uiaa_request(
|
||||
|
|
|
@ -3,10 +3,17 @@ use std::sync::Arc;
|
|||
|
||||
pub use data::Data;
|
||||
|
||||
use ruma::{api::client::{uiaa::{UiaaInfo, IncomingAuthData, IncomingPassword, AuthType, IncomingUserIdentifier}, error::ErrorKind}, DeviceId, UserId, signatures::CanonicalJsonValue};
|
||||
use ruma::{
|
||||
api::client::{
|
||||
error::ErrorKind,
|
||||
uiaa::{AuthType, IncomingAuthData, IncomingPassword, IncomingUserIdentifier, UiaaInfo},
|
||||
},
|
||||
signatures::CanonicalJsonValue,
|
||||
DeviceId, UserId,
|
||||
};
|
||||
use tracing::error;
|
||||
|
||||
use crate::{Result, utils, Error, services, api::client_server::SESSION_ID_LENGTH};
|
||||
use crate::{api::client_server::SESSION_ID_LENGTH, services, utils, Error, Result};
|
||||
|
||||
pub struct Service {
|
||||
db: Arc<dyn Data>,
|
||||
|
@ -68,11 +75,11 @@ impl Service {
|
|||
}
|
||||
};
|
||||
|
||||
let user_id =
|
||||
UserId::parse_with_server_name(username.clone(), services().globals.server_name())
|
||||
.map_err(|_| {
|
||||
Error::BadRequest(ErrorKind::InvalidParam, "User ID is invalid.")
|
||||
})?;
|
||||
let user_id = UserId::parse_with_server_name(
|
||||
username.clone(),
|
||||
services().globals.server_name(),
|
||||
)
|
||||
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "User ID is invalid."))?;
|
||||
|
||||
// Check if password is correct
|
||||
if let Some(hash) = services().users.password_hash(&user_id)? {
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
use std::collections::BTreeMap;
|
||||
use crate::Result;
|
||||
use ruma::{UserId, DeviceId, DeviceKeyAlgorithm, DeviceKeyId, serde::Raw, encryption::{OneTimeKey, DeviceKeys, CrossSigningKey}, UInt, events::AnyToDeviceEvent, api::client::{device::Device, filter::IncomingFilterDefinition}, MxcUri};
|
||||
use ruma::{
|
||||
api::client::{device::Device, filter::IncomingFilterDefinition},
|
||||
encryption::{CrossSigningKey, DeviceKeys, OneTimeKey},
|
||||
events::AnyToDeviceEvent,
|
||||
serde::Raw,
|
||||
DeviceId, DeviceKeyAlgorithm, DeviceKeyId, MxcUri, UInt, UserId,
|
||||
};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
pub trait Data: Send + Sync {
|
||||
/// Check if a user has an account on this homeserver.
|
||||
|
@ -127,10 +133,7 @@ pub trait Data: Send + Sync {
|
|||
to: Option<u64>,
|
||||
) -> Box<dyn Iterator<Item = Result<Box<UserId>>>>;
|
||||
|
||||
fn mark_device_key_update(
|
||||
&self,
|
||||
user_id: &UserId,
|
||||
) -> Result<()>;
|
||||
fn mark_device_key_update(&self, user_id: &UserId) -> Result<()>;
|
||||
|
||||
fn get_device_keys(
|
||||
&self,
|
||||
|
@ -182,11 +185,8 @@ pub trait Data: Send + Sync {
|
|||
) -> Result<()>;
|
||||
|
||||
/// Get device metadata.
|
||||
fn get_device_metadata(
|
||||
&self,
|
||||
user_id: &UserId,
|
||||
device_id: &DeviceId,
|
||||
) -> Result<Option<Device>>;
|
||||
fn get_device_metadata(&self, user_id: &UserId, device_id: &DeviceId)
|
||||
-> Result<Option<Device>>;
|
||||
|
||||
fn get_devicelist_version(&self, user_id: &UserId) -> Result<Option<u64>>;
|
||||
|
||||
|
@ -196,11 +196,7 @@ pub trait Data: Send + Sync {
|
|||
) -> Box<dyn Iterator<Item = Result<Device>>>;
|
||||
|
||||
/// Creates a new sync filter. Returns the filter id.
|
||||
fn create_filter(
|
||||
&self,
|
||||
user_id: &UserId,
|
||||
filter: &IncomingFilterDefinition,
|
||||
) -> Result<String>;
|
||||
fn create_filter(&self, user_id: &UserId, filter: &IncomingFilterDefinition) -> Result<String>;
|
||||
|
||||
fn get_filter(
|
||||
&self,
|
||||
|
|
|
@ -2,9 +2,15 @@ mod data;
|
|||
use std::{collections::BTreeMap, mem, sync::Arc};
|
||||
|
||||
pub use data::Data;
|
||||
use ruma::{UserId, MxcUri, DeviceId, DeviceKeyId, serde::Raw, encryption::{OneTimeKey, CrossSigningKey, DeviceKeys}, DeviceKeyAlgorithm, UInt, events::AnyToDeviceEvent, api::client::{device::Device, filter::IncomingFilterDefinition, error::ErrorKind}, RoomAliasId};
|
||||
use ruma::{
|
||||
api::client::{device::Device, error::ErrorKind, filter::IncomingFilterDefinition},
|
||||
encryption::{CrossSigningKey, DeviceKeys, OneTimeKey},
|
||||
events::AnyToDeviceEvent,
|
||||
serde::Raw,
|
||||
DeviceId, DeviceKeyAlgorithm, DeviceKeyId, MxcUri, RoomAliasId, UInt, UserId,
|
||||
};
|
||||
|
||||
use crate::{Result, Error, services};
|
||||
use crate::{services, Error, Result};
|
||||
|
||||
pub struct Service {
|
||||
db: Arc<dyn Data>,
|
||||
|
@ -22,15 +28,20 @@ impl Service {
|
|||
}
|
||||
|
||||
/// Check if a user is an admin
|
||||
pub fn is_admin(
|
||||
&self,
|
||||
user_id: &UserId,
|
||||
) -> Result<bool> {
|
||||
let admin_room_alias_id = RoomAliasId::parse(format!("#admins:{}", services().globals.server_name()))
|
||||
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid alias."))?;
|
||||
let admin_room_id = services().rooms.alias.resolve_local_alias(&admin_room_alias_id)?.unwrap();
|
||||
pub fn is_admin(&self, user_id: &UserId) -> Result<bool> {
|
||||
let admin_room_alias_id =
|
||||
RoomAliasId::parse(format!("#admins:{}", services().globals.server_name()))
|
||||
.map_err(|_| Error::BadRequest(ErrorKind::InvalidParam, "Invalid alias."))?;
|
||||
let admin_room_id = services()
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_local_alias(&admin_room_alias_id)?
|
||||
.unwrap();
|
||||
|
||||
services().rooms.state_cache.is_joined(user_id, &admin_room_id)
|
||||
services()
|
||||
.rooms
|
||||
.state_cache
|
||||
.is_joined(user_id, &admin_room_id)
|
||||
}
|
||||
|
||||
/// Create a new user account on this homeserver.
|
||||
|
@ -39,7 +50,6 @@ impl Service {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
/// Returns the number of users registered on this server.
|
||||
pub fn count(&self) -> Result<usize> {
|
||||
self.db.count()
|
||||
|
@ -118,7 +128,8 @@ impl Service {
|
|||
token: &str,
|
||||
initial_device_display_name: Option<String>,
|
||||
) -> Result<()> {
|
||||
self.db.create_device(user_id, device_id, token, initial_device_display_name)
|
||||
self.db
|
||||
.create_device(user_id, device_id, token, initial_device_display_name)
|
||||
}
|
||||
|
||||
/// Removes a device from a user.
|
||||
|
@ -146,7 +157,8 @@ impl Service {
|
|||
one_time_key_key: &DeviceKeyId,
|
||||
one_time_key_value: &Raw<OneTimeKey>,
|
||||
) -> Result<()> {
|
||||
self.db.add_one_time_key(user_id, device_id, one_time_key_key, one_time_key_value)
|
||||
self.db
|
||||
.add_one_time_key(user_id, device_id, one_time_key_key, one_time_key_value)
|
||||
}
|
||||
|
||||
pub fn last_one_time_keys_update(&self, user_id: &UserId) -> Result<u64> {
|
||||
|
@ -186,7 +198,8 @@ impl Service {
|
|||
self_signing_key: &Option<Raw<CrossSigningKey>>,
|
||||
user_signing_key: &Option<Raw<CrossSigningKey>>,
|
||||
) -> Result<()> {
|
||||
self.db.add_cross_signing_keys(user_id, master_key, self_signing_key, user_signing_key)
|
||||
self.db
|
||||
.add_cross_signing_keys(user_id, master_key, self_signing_key, user_signing_key)
|
||||
}
|
||||
|
||||
pub fn sign_key(
|
||||
|
@ -208,10 +221,7 @@ impl Service {
|
|||
self.db.keys_changed(user_or_room_id, from, to)
|
||||
}
|
||||
|
||||
pub fn mark_device_key_update(
|
||||
&self,
|
||||
user_id: &UserId,
|
||||
) -> Result<()> {
|
||||
pub fn mark_device_key_update(&self, user_id: &UserId) -> Result<()> {
|
||||
self.db.mark_device_key_update(user_id)
|
||||
}
|
||||
|
||||
|
@ -251,7 +261,13 @@ impl Service {
|
|||
event_type: &str,
|
||||
content: serde_json::Value,
|
||||
) -> Result<()> {
|
||||
self.db.add_to_device_event(sender, target_user_id, target_device_id, event_type, content)
|
||||
self.db.add_to_device_event(
|
||||
sender,
|
||||
target_user_id,
|
||||
target_device_id,
|
||||
event_type,
|
||||
content,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn get_to_device_events(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue