cargo fmt

This commit is contained in:
Timo Kösters 2022-10-05 20:34:31 +02:00 committed by Nyaaori
parent 33a2b2b772
commit a4637e2ba1
No known key found for this signature in database
GPG key ID: E7819C3ED4D1F82E
119 changed files with 2787 additions and 1761 deletions

View file

@ -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.

View file

@ -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,

View file

@ -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(

View file

@ -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;

View file

@ -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 {

View file

@ -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,

View file

@ -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)
}
}

View file

@ -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>)>;
}

View file

@ -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?;

View file

@ -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!(),

View file

@ -1,4 +1,4 @@
use crate::{Error, services};
use crate::{services, Error};
use ruma::{
events::{
room::member::RoomMemberEventContent, AnyEphemeralRoomEvent, AnyRoomEvent, AnyStateEvent,

View file

@ -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>>>;
}

View file

@ -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

View file

@ -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(

View file

@ -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)
}

View file

@ -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<()>;
}

View file

@ -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) {

View file

@ -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

View file

@ -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.

View file

@ -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;

View file

@ -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<()>;

View file

@ -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>,

View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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(

View file

@ -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
}

View file

@ -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>;

View file

@ -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,

View file

@ -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>,

View file

@ -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<()>;

View file

@ -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;

View file

@ -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<()>;

View file

@ -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)
}

View file

@ -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>;
}

View file

@ -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)
}
}

View file

@ -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

View file

@ -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())
}
}

View file

@ -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 {

View file

@ -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>,

View file

@ -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<()>;

View file

@ -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

View file

@ -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);

View file

@ -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<()>;
}

View file

@ -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))
}

View file

@ -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<()>;

View file

@ -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>> {

View file

@ -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);
}

View file

@ -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(

View file

@ -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>,

View file

@ -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(

View file

@ -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)? {

View file

@ -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,

View file

@ -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(