Compare commits
18 commits
main
...
clippy-lin
Author | SHA1 | Date | |
---|---|---|---|
![]() |
c46a47d9d9 | ||
![]() |
e6047a279e | ||
![]() |
69cd15d5c7 | ||
![]() |
879eebd56d | ||
![]() |
fdec10a1c2 | ||
![]() |
f54389085c | ||
![]() |
adca80b848 | ||
![]() |
fe8b88c58b | ||
![]() |
8d72dfa829 | ||
![]() |
77f9d72b56 | ||
![]() |
e27657288d | ||
![]() |
248f4bff30 | ||
![]() |
26832f6c66 | ||
![]() |
2bcc25c848 | ||
![]() |
be5a6730e9 | ||
![]() |
61840544b9 | ||
![]() |
e70b6b3f01 | ||
![]() |
75e1b84904 |
30 changed files with 656 additions and 546 deletions
|
@ -116,7 +116,7 @@ docker build debugging:
|
|||
|
||||
cargo check:
|
||||
stage: test
|
||||
image: docker.io/rust:1.74.1-bullseye
|
||||
image: docker.io/rust:1.75.0-bullseye
|
||||
needs: []
|
||||
interruptible: true
|
||||
before_script:
|
||||
|
|
806
Cargo.lock
generated
806
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
80
Cargo.toml
80
Cargo.toml
|
@ -13,7 +13,7 @@ edition = "2021"
|
|||
# `nix flake update`. If you don't have Nix installed or otherwise don't know
|
||||
# how to do this, ping `@charles:computer.surgery` or `@dusk:gaze.systems` in
|
||||
# the matrix room.
|
||||
rust-version = "1.74.1"
|
||||
rust-version = "1.75.0"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
|
@ -26,7 +26,7 @@ tower-http = { version = "0.4.4", features = ["add-extension", "cors", "sensitiv
|
|||
|
||||
# Used for matrix spec type definitions and helpers
|
||||
#ruma = { version = "0.4.0", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
|
||||
ruma = { git = "https://github.com/ruma/ruma", rev = "9a5142052c808275f47613d4b66cb6c9fc286079", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified", "unstable-msc2870", "unstable-msc3061", "unstable-extensible-events"] }
|
||||
ruma = { git = "https://github.com/ruma/ruma", rev = "aa3acd88d21dfbb7595f54e619f52761bcb0259e", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified", "unstable-msc2870", "unstable-msc3061", "unstable-extensible-events"] }
|
||||
#ruma = { git = "https://github.com/timokoesters/ruma", rev = "4ec9c69bb7e09391add2382b3ebac97b6e8f4c64", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] }
|
||||
#ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-msc3575", "unstable-exhaustive-types", "ring-compat", "unstable-unspecified" ] }
|
||||
|
||||
|
@ -36,7 +36,6 @@ hyperlocal = { git = "https://github.com/softprops/hyperlocal", rev = "2ee4d1496
|
|||
] }
|
||||
hyper = { version = "0.14", features = ["server", "http1", "http2"] }
|
||||
tokio = { version = "1.35.1", features = ["fs", "macros", "signal", "sync"] }
|
||||
loole = "0.3"
|
||||
|
||||
# Used for the http request / response body type for Ruma endpoints used with reqwest
|
||||
bytes = "1.5.0"
|
||||
|
@ -57,7 +56,7 @@ reqwest = { version = "0.11.23", default-features = false, features = ["rustls-t
|
|||
# Used for conduit::Error type
|
||||
thiserror = "1.0.56"
|
||||
# Used to generate thumbnails for images
|
||||
image = { version = "0.24.7", default-features = false, features = ["jpeg", "png", "gif", "webp"] }
|
||||
image = { version = "0.24.8", default-features = false, features = ["jpeg", "png", "gif", "webp"] }
|
||||
# Used to encode server public key
|
||||
base64 = "0.21.7"
|
||||
# Used when hashing the state
|
||||
|
@ -79,7 +78,6 @@ tracing-opentelemetry = "0.22.0"
|
|||
lru-cache = "0.1.2"
|
||||
rusqlite = { version = "0.30.0", optional = true, features = ["bundled"] }
|
||||
parking_lot = { version = "0.12.1", optional = true }
|
||||
crossbeam = { version = "0.8.3", optional = true }
|
||||
num_cpus = "1.16.0"
|
||||
threadpool = "1.8.1"
|
||||
# Used for ruma wrapper
|
||||
|
@ -93,7 +91,7 @@ hmac = "0.12.1"
|
|||
sha-1 = "0.10.1"
|
||||
sha2 = { version = "0.10.8" }
|
||||
# used for conduit's CLI and admin room command parsing
|
||||
clap = { version = "4.4.16", default-features = false, features = ["std", "derive", "help", "usage", "error-context"] }
|
||||
clap = { version = "4.4.17", default-features = false, features = ["std", "derive", "help", "usage", "error-context"] }
|
||||
futures-util = { version = "0.3.30", default-features = false }
|
||||
# Used for reading the configuration from conduit.toml & environment variables
|
||||
figment = { version = "0.10.13", features = ["env", "toml"] }
|
||||
|
@ -162,73 +160,85 @@ debug = 0
|
|||
lto = 'off'
|
||||
incremental = true
|
||||
|
||||
# default release profile
|
||||
[profile.release]
|
||||
lto = 'fat'
|
||||
lto = 'thin'
|
||||
incremental = false
|
||||
codegen-units=1
|
||||
opt-level = 3
|
||||
overflow-checks = true
|
||||
strip = "symbols"
|
||||
panic = "abort"
|
||||
debug = 0
|
||||
# If you want to make flamegraphs, enable debug info:
|
||||
# debug = true
|
||||
|
||||
# high performance release profile which uses fat LTO across all crates, 1 codegen unit, max opt-level, and optimises across all crates
|
||||
[profile.release-high-perf]
|
||||
inherits = "release"
|
||||
lto = 'fat'
|
||||
codegen-units = 1
|
||||
|
||||
# For releases also try to max optimizations for dependencies:
|
||||
[profile.release.build-override]
|
||||
[profile.release-high-perf.build-override]
|
||||
debug = 0
|
||||
opt-level = 3
|
||||
codegen-units=1
|
||||
[profile.release.package."*"]
|
||||
codegen-units = 1
|
||||
|
||||
[profile.release-high-perf.package."*"]
|
||||
debug = 0
|
||||
opt-level = 3
|
||||
codegen-units=1
|
||||
codegen-units = 1
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
[workspace.lints.rust]
|
||||
# missing_abi = "warn"
|
||||
missing_abi = "warn"
|
||||
# missing_docs = "warn"
|
||||
# noop_method_call = "warn"
|
||||
# pointer_structural_match = "warn"
|
||||
noop_method_call = "warn"
|
||||
pointer_structural_match = "warn"
|
||||
# unreachable_pub = "warn"
|
||||
# unused_extern_crates = "warn"
|
||||
# unused_import_braces = "warn"
|
||||
unused_extern_crates = "warn"
|
||||
unused_import_braces = "warn"
|
||||
# unused_lifetimes = "warn"
|
||||
unused_qualifications = "warn"
|
||||
# unused_tuple_struct_fields = "warn"
|
||||
dead_code = "warn"
|
||||
|
||||
[workspace.lints.clippy]
|
||||
suspicious = "warn" # assume deny in practice
|
||||
perf = "warn" # assume deny in practice
|
||||
# redundant_clone = "warn"
|
||||
# cloned_instead_of_copied = "warn"
|
||||
redundant_clone = "warn"
|
||||
cloned_instead_of_copied = "warn"
|
||||
expl_impl_clone_on_copy = "warn"
|
||||
# pedantic = "warn"
|
||||
# as_conversions = "warn"
|
||||
unnecessary_cast = "warn"
|
||||
cast_lossless = "warn"
|
||||
ptr_as_ptr = "warn"
|
||||
mut_mut = "warn"
|
||||
char_lit_as_u8 = "warn"
|
||||
dbg_macro = "warn"
|
||||
# empty_structs_with_brackets = "warn"
|
||||
# get_unwrap = "warn"
|
||||
empty_structs_with_brackets = "warn"
|
||||
get_unwrap = "warn"
|
||||
# if_then_some_else_none = "warn"
|
||||
# let_underscore_must_use = "warn"
|
||||
# map_err_ignore = "warn"
|
||||
# missing_docs_in_private_items = "warn"
|
||||
# negative_feature_names = "warn"
|
||||
# pub_without_shorthand = "warn"
|
||||
negative_feature_names = "warn"
|
||||
pub_without_shorthand = "warn"
|
||||
rc_buffer = "warn"
|
||||
rc_mutex = "warn"
|
||||
# redundant_feature_names = "warn"
|
||||
# redundant_type_annotations = "warn"
|
||||
redundant_feature_names = "warn"
|
||||
redundant_type_annotations = "warn"
|
||||
# ref_patterns = "warn"
|
||||
# rest_pat_in_fully_bound_structs = "warn"
|
||||
# str_to_string = "warn"
|
||||
rest_pat_in_fully_bound_structs = "warn"
|
||||
str_to_string = "warn"
|
||||
# string_add = "warn"
|
||||
# string_slice = "warn"
|
||||
# string_to_string = "warn"
|
||||
string_to_string = "warn"
|
||||
tests_outside_test_module = "warn"
|
||||
undocumented_unsafe_blocks = "warn"
|
||||
# unneeded_field_pattern = "warn"
|
||||
# unseparated_literal_suffix = "warn"
|
||||
unneeded_field_pattern = "warn"
|
||||
unseparated_literal_suffix = "warn"
|
||||
# unwrap_used = "warn"
|
||||
# wildcard_dependencies = "warn"
|
||||
# expect_used = "warn"
|
||||
wildcard_dependencies = "warn"
|
||||
# or_fun_call = "warn"
|
||||
unnecessary_lazy_evaluations = "warn"
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
- Safer and cleaner shutdowns on both database side as we run cleanup on shutdown and exits database loop better (no potential hanging issues in database loop), overall cleaner shutdown logic
|
||||
- Basic binary commands like `conduwuit --version` work (interested in expanding it more)
|
||||
- Allow HEAD HTTP requests in CORS for clients (despite not being explicity mentioned in Matrix spec, HTTP spec says all HEAD requests need to behave the same as GET requests, Synapse supports HEAD requests)
|
||||
- Bump MSRV to 1.74.1
|
||||
- Bump MSRV to 1.75.0 for Cargo.toml workspace lints and latest ruma using 1.75.0
|
||||
- Purge unmaintained/irrelevant/broken database backends (heed, sled, persy)
|
||||
- webp support for images
|
||||
- Support for suggesting servers to join at `/_matrix/client/v3/directory/room/{roomAlias}`
|
||||
|
@ -52,3 +52,4 @@
|
|||
- Only follow 6 redirects total in our default reqwest ClientBuilder
|
||||
- Generate passwords with 25 characters instead of 15
|
||||
- Add missing `reason` field to user ban events (`/ban`)
|
||||
- For all [`/report`](https://spec.matrix.org/v1.9/client-server-api/#post_matrixclientv3roomsroomidreporteventid) requests: check if the reported event ID belongs to the reported room ID, raise report reasoning character limit to 750, fix broken formatting, make a small delayed random response per spec suggestion on privacy, and check if the sender user is in the reported room.
|
|
@ -1,5 +1,5 @@
|
|||
# syntax=docker/dockerfile:1
|
||||
FROM docker.io/rust:1.74.1-bullseye AS base
|
||||
FROM docker.io/rust:1.75.0-bullseye AS base
|
||||
|
||||
FROM base AS builder
|
||||
WORKDIR /usr/src/conduit
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
channel = cargoToml.package.rust-version;
|
||||
|
||||
# THE rust-version HASH
|
||||
sha256 = "sha256-PjvuouwTsYfNKW5Vi5Ye7y+lL7SsWGBxCtBOOm2z14c=";
|
||||
sha256 = "sha256-SXRtAuO4IqNOQq+nLbrsDFbVk+3aVA8NNpSZsKlVH/8=";
|
||||
};
|
||||
|
||||
mkToolchain = fenix.packages.${system}.combine;
|
||||
|
|
|
@ -19,7 +19,7 @@ use register::RegistrationKind;
|
|||
|
||||
const RANDOM_USER_ID_LENGTH: usize = 10;
|
||||
|
||||
/// # `GET /_matrix/client/r0/register/available`
|
||||
/// # `GET /_matrix/client/v3/register/available`
|
||||
///
|
||||
/// Checks if a username is valid and available on this server.
|
||||
///
|
||||
|
|
|
@ -13,7 +13,7 @@ use ruma::{
|
|||
OwnedRoomAliasId, OwnedServerName,
|
||||
};
|
||||
|
||||
/// # `PUT /_matrix/client/r0/directory/room/{roomAlias}`
|
||||
/// # `PUT /_matrix/client/v3/directory/room/{roomAlias}`
|
||||
///
|
||||
/// Creates a new room alias on this server.
|
||||
pub async fn create_alias_route(
|
||||
|
@ -35,15 +35,22 @@ pub async fn create_alias_route(
|
|||
return Err(Error::Conflict("Alias already exists."));
|
||||
}
|
||||
|
||||
services()
|
||||
if services()
|
||||
.rooms
|
||||
.alias
|
||||
.set_alias(&body.room_alias, &body.room_id)?;
|
||||
.set_alias(&body.room_alias, &body.room_id)
|
||||
.is_err()
|
||||
{
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Invalid room alias. Alias must be in the form of '#localpart:server_name'",
|
||||
));
|
||||
};
|
||||
|
||||
Ok(create_alias::v3::Response::new())
|
||||
}
|
||||
|
||||
/// # `DELETE /_matrix/client/r0/directory/room/{roomAlias}`
|
||||
/// # `DELETE /_matrix/client/v3/directory/room/{roomAlias}`
|
||||
///
|
||||
/// Deletes a room alias from this server.
|
||||
///
|
||||
|
@ -59,7 +66,29 @@ pub async fn delete_alias_route(
|
|||
));
|
||||
}
|
||||
|
||||
services().rooms.alias.remove_alias(&body.room_alias)?;
|
||||
if services()
|
||||
.rooms
|
||||
.alias
|
||||
.resolve_local_alias(&body.room_alias)?
|
||||
.is_none()
|
||||
{
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::NotFound,
|
||||
"Alias does not exist.",
|
||||
));
|
||||
}
|
||||
|
||||
if services()
|
||||
.rooms
|
||||
.alias
|
||||
.remove_alias(&body.room_alias)
|
||||
.is_err()
|
||||
{
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Invalid room alias. Alias must be in the form of '#localpart:server_name'",
|
||||
));
|
||||
};
|
||||
|
||||
// TODO: update alt_aliases?
|
||||
|
||||
|
|
|
@ -246,7 +246,8 @@ pub(crate) async fn get_public_rooms_filtered_helper(
|
|||
error!("Invalid room topic event in database for room {}", room_id);
|
||||
Error::bad_database("Invalid room topic event in database.")
|
||||
})
|
||||
})?,
|
||||
})
|
||||
.unwrap_or(None),
|
||||
world_readable: services()
|
||||
.rooms
|
||||
.state_accessor
|
||||
|
|
|
@ -9,9 +9,10 @@ use ruma::api::client::{
|
|||
},
|
||||
};
|
||||
|
||||
/// generated MXC ID (`media-id`) length
|
||||
const MXC_LENGTH: usize = 32;
|
||||
|
||||
/// # `GET /_matrix/media/r0/config`
|
||||
/// # `GET /_matrix/media/v3/config`
|
||||
///
|
||||
/// Returns max upload size.
|
||||
pub async fn get_media_config_route(
|
||||
|
@ -22,7 +23,7 @@ pub async fn get_media_config_route(
|
|||
})
|
||||
}
|
||||
|
||||
/// # `POST /_matrix/media/r0/upload`
|
||||
/// # `POST /_matrix/media/v3/upload`
|
||||
///
|
||||
/// Permanently save media in the server.
|
||||
///
|
||||
|
@ -58,6 +59,7 @@ pub async fn create_content_route(
|
|||
})
|
||||
}
|
||||
|
||||
/// helper method to fetch remote media from other servers over federation
|
||||
pub async fn get_remote_content(
|
||||
mxc: &str,
|
||||
server_name: &ruma::ServerName,
|
||||
|
@ -132,9 +134,7 @@ pub async fn get_content_as_filename_route(
|
|||
let mxc = format!("mxc://{}/{}", body.server_name, body.media_id);
|
||||
|
||||
if let Some(FileMeta {
|
||||
content_disposition: _,
|
||||
content_type,
|
||||
file,
|
||||
content_type, file, ..
|
||||
}) = services().media.get(mxc.clone()).await?
|
||||
{
|
||||
Ok(get_content_as_filename::v3::Response {
|
||||
|
|
|
@ -361,7 +361,7 @@ pub async fn unban_user_route(
|
|||
Ok(unban_user::v3::Response::new())
|
||||
}
|
||||
|
||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/forget`
|
||||
/// # `POST /_matrix/client/v3/rooms/{roomId}/forget`
|
||||
///
|
||||
/// Forgets about a room.
|
||||
///
|
||||
|
@ -1221,7 +1221,7 @@ fn validate_and_add_event_id(
|
|||
Ok((event_id, value))
|
||||
}
|
||||
|
||||
pub(crate) async fn invite_helper<'a>(
|
||||
pub(crate) async fn invite_helper(
|
||||
sender_user: &UserId,
|
||||
user_id: &UserId,
|
||||
room_id: &RoomId,
|
||||
|
|
|
@ -68,7 +68,14 @@ pub use unversioned::*;
|
|||
pub use user_directory::*;
|
||||
pub use voip::*;
|
||||
|
||||
/// generated device ID length
|
||||
pub const DEVICE_ID_LENGTH: usize = 10;
|
||||
|
||||
/// generated user access token length
|
||||
pub const TOKEN_LENGTH: usize = 32;
|
||||
|
||||
/// generated user session ID length
|
||||
pub const SESSION_ID_LENGTH: usize = 32;
|
||||
|
||||
/// auto-generated password length
|
||||
pub const AUTO_GEN_PASSWORD_LENGTH: usize = 25;
|
||||
|
|
|
@ -1,29 +1,61 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use crate::{services, utils::HtmlEscape, Error, Result, Ruma};
|
||||
use rand::Rng;
|
||||
use ruma::{
|
||||
api::client::{error::ErrorKind, room::report_content},
|
||||
events::room::message,
|
||||
int,
|
||||
};
|
||||
use tokio::time::sleep;
|
||||
use tracing::{debug, info};
|
||||
|
||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/report/{eventId}`
|
||||
/// # `POST /_matrix/client/v3/rooms/{roomId}/report/{eventId}`
|
||||
///
|
||||
/// Reports an inappropriate event to homeserver admins
|
||||
///
|
||||
pub async fn report_event_route(
|
||||
body: Ruma<report_content::v3::Request>,
|
||||
) -> Result<report_content::v3::Response> {
|
||||
// user authentication
|
||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||
|
||||
info!("Received /report request by user {}", sender_user);
|
||||
|
||||
// check if we know about the reported event ID or if it's invalid
|
||||
let pdu = match services().rooms.timeline.get_pdu(&body.event_id)? {
|
||||
Some(pdu) => pdu,
|
||||
_ => {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Invalid Event ID",
|
||||
ErrorKind::NotFound,
|
||||
"Event ID is not known to us or Event ID is invalid",
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
// check if the room ID from the URI matches the PDU's room ID
|
||||
if body.room_id != pdu.room_id {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::NotFound,
|
||||
"Event ID does not belong to the reported room",
|
||||
));
|
||||
}
|
||||
|
||||
// check if reporting user is in the reporting room
|
||||
if !services()
|
||||
.rooms
|
||||
.state_cache
|
||||
.room_members(&pdu.room_id)
|
||||
.filter_map(|r| r.ok())
|
||||
.any(|user_id| user_id == *sender_user)
|
||||
{
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::NotFound,
|
||||
"You are not in the room you are reporting.",
|
||||
));
|
||||
}
|
||||
|
||||
// check if score is in valid range
|
||||
if let Some(true) = body.score.map(|s| s > int!(0) || s < int!(-100)) {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
|
@ -31,39 +63,56 @@ pub async fn report_event_route(
|
|||
));
|
||||
};
|
||||
|
||||
if let Some(true) = body.reason.clone().map(|s| s.chars().count() > 500) {
|
||||
// check if report reasoning is less than or equal to 750 characters
|
||||
if let Some(true) = body.reason.clone().map(|s| s.chars().count() >= 750) {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Reason too long, should be 500 characters or fewer",
|
||||
"Reason too long, should be 750 characters or fewer",
|
||||
));
|
||||
};
|
||||
|
||||
services().admin
|
||||
// send admin room message that we received the report with an @room ping for urgency
|
||||
services()
|
||||
.admin
|
||||
.send_message(message::RoomMessageEventContent::text_html(
|
||||
format!(
|
||||
"Report received from: {}\n\n\
|
||||
Event ID: {:?}\n\
|
||||
Room ID: {:?}\n\
|
||||
Sent By: {:?}\n\n\
|
||||
Report Score: {:?}\n\
|
||||
Report Reason: {:?}",
|
||||
sender_user, pdu.event_id, pdu.room_id, pdu.sender, body.score, body.reason
|
||||
),
|
||||
format!(
|
||||
"<details><summary>Report received from: <a href=\"https://matrix.to/#/{0:?}\">{0:?}\
|
||||
</a></summary><ul><li>Event Info<ul><li>Event ID: <code>{1:?}</code>\
|
||||
<a href=\"https://matrix.to/#/{2:?}/{1:?}\">🔗</a></li><li>Room ID: <code>{2:?}</code>\
|
||||
</li><li>Sent By: <a href=\"https://matrix.to/#/{3:?}\">{3:?}</a></li></ul></li><li>\
|
||||
Report Info<ul><li>Report Score: {4:?}</li><li>Report Reason: {5}</li></ul></li>\
|
||||
</ul></details>",
|
||||
sender_user,
|
||||
"@room Report received from: {}\n\n\
|
||||
Event ID: {}\n\
|
||||
Room ID: {}\n\
|
||||
Sent By: {}\n\n\
|
||||
Report Score: {}\n\
|
||||
Report Reason: {}",
|
||||
sender_user.to_owned(),
|
||||
pdu.event_id,
|
||||
pdu.room_id,
|
||||
pdu.sender,
|
||||
body.score,
|
||||
HtmlEscape(body.reason.as_deref().unwrap_or(""))
|
||||
pdu.sender.to_owned(),
|
||||
body.score.unwrap_or(ruma::Int::from(0)),
|
||||
body.reason.as_deref().unwrap_or("")
|
||||
),
|
||||
format!(
|
||||
"<details><summary>@room Report received from: <a href=\"https://matrix.to/#/{0}\">{0}\
|
||||
</a></summary><ul><li>Event Info<ul><li>Event ID: <code>{1}</code>\
|
||||
<a href=\"https://matrix.to/#/{2}/{1}\">🔗</a></li><li>Room ID: <code>{2}</code>\
|
||||
</li><li>Sent By: <a href=\"https://matrix.to/#/{3}\">{3}</a></li></ul></li><li>\
|
||||
Report Info<ul><li>Report Score: {4}</li><li>Report Reason: {5}</li></ul></li>\
|
||||
</ul></details>",
|
||||
sender_user.to_owned(),
|
||||
pdu.event_id.to_owned(),
|
||||
pdu.room_id.to_owned(),
|
||||
pdu.sender.to_owned(),
|
||||
body.score.unwrap_or(ruma::Int::from(0)),
|
||||
HtmlEscape(body.reason.as_deref().unwrap_or(""))
|
||||
),
|
||||
));
|
||||
|
||||
// even though this is kinda security by obscurity, let's still make a small random delay sending a successful response
|
||||
// per spec suggestion regarding enumerating for potential events existing in our server.
|
||||
let time_to_wait = rand::thread_rng().gen_range(8..21);
|
||||
debug!(
|
||||
"Got successful /report request, waiting {} seconds before sending successful response.",
|
||||
time_to_wait
|
||||
);
|
||||
sleep(Duration::from_secs(time_to_wait)).await;
|
||||
|
||||
Ok(report_content::v3::Response {})
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ impl FedDest {
|
|||
fn into_uri_string(self) -> String {
|
||||
match self {
|
||||
Self::Literal(addr) => addr.to_string(),
|
||||
Self::Named(host, ref port) => host + port,
|
||||
Self::Named(host, port) => host + &port,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,10 +14,13 @@ mod proxy;
|
|||
|
||||
use self::proxy::ProxyConfig;
|
||||
|
||||
/// all the config options for conduwuit
|
||||
#[derive(Clone, Debug, Deserialize)]
|
||||
pub struct Config {
|
||||
/// [`IpAddr`] conduwuit will listen on (can be IPv4 or IPv6)
|
||||
#[serde(default = "default_address")]
|
||||
pub address: IpAddr,
|
||||
/// default TCP port conduwuit will listen on
|
||||
#[serde(default = "default_port")]
|
||||
pub port: u16,
|
||||
pub tls: Option<TlsConfig>,
|
||||
|
@ -214,14 +217,23 @@ impl fmt::Display for Config {
|
|||
),
|
||||
("Allow encryption", &self.allow_encryption.to_string()),
|
||||
("Allow federation", &self.allow_federation.to_string()),
|
||||
(
|
||||
"Allow incoming federated presence requests (updates)",
|
||||
&self.allow_incoming_presence.to_string(),
|
||||
),
|
||||
(
|
||||
"Allow outgoing federated presence requests (updates)",
|
||||
&self.allow_outgoing_presence.to_string(),
|
||||
),
|
||||
(
|
||||
"Allow local presence requests (updates)",
|
||||
&self.allow_local_presence.to_string(),
|
||||
),
|
||||
(
|
||||
"Allow device name federation",
|
||||
&self.allow_device_name_federation.to_string(),
|
||||
),
|
||||
(
|
||||
"Notification push path",
|
||||
&self.notification_push_path.to_string(),
|
||||
),
|
||||
("Notification push path", &self.notification_push_path),
|
||||
("Allow room creation", &self.allow_room_creation.to_string()),
|
||||
(
|
||||
"Allow public room directory over federation",
|
||||
|
@ -280,10 +292,7 @@ impl fmt::Display for Config {
|
|||
"zstd Response Body Compression",
|
||||
&self.zstd_compression.to_string(),
|
||||
),
|
||||
(
|
||||
"RocksDB database log level",
|
||||
&self.rocksdb_log_level.to_string(),
|
||||
),
|
||||
("RocksDB database log level", &self.rocksdb_log_level),
|
||||
(
|
||||
"RocksDB database log time-to-roll",
|
||||
&self.rocksdb_log_time_to_roll.to_string(),
|
||||
|
@ -393,11 +402,11 @@ fn default_rocksdb_log_time_to_roll() -> usize {
|
|||
}
|
||||
|
||||
// I know, it's a great name
|
||||
pub fn default_default_room_version() -> RoomVersionId {
|
||||
pub(crate) fn default_default_room_version() -> RoomVersionId {
|
||||
RoomVersionId::V10
|
||||
}
|
||||
|
||||
pub fn default_rocksdb_max_log_file_size() -> usize {
|
||||
fn default_rocksdb_max_log_file_size() -> usize {
|
||||
// 4 megabytes
|
||||
4 * 1024 * 1024
|
||||
}
|
||||
|
|
|
@ -95,20 +95,20 @@ impl PartialProxyConfig {
|
|||
|
||||
/// A domain name, that optionally allows a * as its first subdomain.
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum WildCardedDomain {
|
||||
enum WildCardedDomain {
|
||||
WildCard,
|
||||
WildCarded(String),
|
||||
Exact(String),
|
||||
}
|
||||
impl WildCardedDomain {
|
||||
pub fn matches(&self, domain: &str) -> bool {
|
||||
fn matches(&self, domain: &str) -> bool {
|
||||
match self {
|
||||
WildCardedDomain::WildCard => true,
|
||||
WildCardedDomain::WildCarded(d) => domain.ends_with(d),
|
||||
WildCardedDomain::Exact(d) => domain == d,
|
||||
}
|
||||
}
|
||||
pub fn more_specific_than(&self, other: &Self) -> bool {
|
||||
fn more_specific_than(&self, other: &Self) -> bool {
|
||||
match (self, other) {
|
||||
(WildCardedDomain::WildCard, WildCardedDomain::WildCard) => false,
|
||||
(_, WildCardedDomain::WildCard) => true,
|
||||
|
|
|
@ -7,12 +7,12 @@ use std::{future::Future, pin::Pin, sync::Arc};
|
|||
pub mod sqlite;
|
||||
|
||||
#[cfg(feature = "rocksdb")]
|
||||
pub mod rocksdb;
|
||||
pub(crate) mod rocksdb;
|
||||
|
||||
#[cfg(any(feature = "sqlite", feature = "rocksdb"))]
|
||||
pub mod watchers;
|
||||
pub(crate) mod watchers;
|
||||
|
||||
pub trait KeyValueDatabaseEngine: Send + Sync {
|
||||
pub(crate) trait KeyValueDatabaseEngine: Send + Sync {
|
||||
fn open(config: &Config) -> Result<Self>
|
||||
where
|
||||
Self: Sized;
|
||||
|
@ -27,7 +27,7 @@ pub trait KeyValueDatabaseEngine: Send + Sync {
|
|||
fn clear_caches(&self) {}
|
||||
}
|
||||
|
||||
pub trait KvTree: Send + Sync {
|
||||
pub(crate) trait KvTree: Send + Sync {
|
||||
fn get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
|
||||
|
||||
fn insert(&self, key: &[u8], value: &[u8]) -> Result<()>;
|
||||
|
|
|
@ -8,14 +8,14 @@ use std::{
|
|||
|
||||
use rocksdb::LogLevel::{Debug, Error, Fatal, Info, Warn};
|
||||
|
||||
pub struct Engine {
|
||||
pub(crate) struct Engine {
|
||||
rocks: rocksdb::DBWithThreadMode<rocksdb::MultiThreaded>,
|
||||
cache: rocksdb::Cache,
|
||||
old_cfs: Vec<String>,
|
||||
config: Config,
|
||||
}
|
||||
|
||||
pub struct RocksDbEngineTree<'a> {
|
||||
struct RocksDbEngineTree<'a> {
|
||||
db: Arc<Engine>,
|
||||
name: &'a str,
|
||||
watchers: Watchers,
|
||||
|
|
|
@ -11,8 +11,8 @@ use ruma::{
|
|||
|
||||
use crate::{database::KeyValueDatabase, service, services, utils, Error, Result};
|
||||
|
||||
pub const COUNTER: &[u8] = b"c";
|
||||
pub const LAST_CHECK_FOR_UPDATES_COUNT: &[u8] = b"u";
|
||||
const COUNTER: &[u8] = b"c";
|
||||
const LAST_CHECK_FOR_UPDATES_COUNT: &[u8] = b"u";
|
||||
|
||||
#[async_trait]
|
||||
impl service::globals::Data for KeyValueDatabase {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
pub mod abstraction;
|
||||
pub mod key_value;
|
||||
pub(crate) mod abstraction;
|
||||
pub(crate) mod key_value;
|
||||
|
||||
use crate::{
|
||||
service::rooms::{edus::presence::presence_handler, timeline::PduCount},
|
||||
|
@ -1094,7 +1094,7 @@ impl KeyValueDatabase {
|
|||
use tokio::time::Instant;
|
||||
|
||||
let timer_interval =
|
||||
Duration::from_secs(services().globals.config.cleanup_second_interval as u64);
|
||||
Duration::from_secs(u64::from(services().globals.config.cleanup_second_interval));
|
||||
|
||||
fn perform_cleanup() {
|
||||
let start = Instant::now();
|
||||
|
|
|
@ -53,7 +53,7 @@ static GLOBAL: Jemalloc = Jemalloc;
|
|||
|
||||
#[derive(Parser)]
|
||||
#[clap(version, about, long_about = None)]
|
||||
struct Args {}
|
||||
struct Args;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
mod data;
|
||||
|
||||
pub use data::Data;
|
||||
pub(crate) use data::Data;
|
||||
|
||||
use ruma::{
|
||||
events::{AnyEphemeralRoomEvent, RoomAccountDataEventType},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
mod data;
|
||||
|
||||
pub use data::Data;
|
||||
pub(crate) use data::Data;
|
||||
|
||||
use crate::Result;
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ pub struct Service<'a> {
|
|||
pub roomid_mutex_federation: RwLock<HashMap<OwnedRoomId, Arc<TokioMutex<()>>>>, // this lock will be held longer
|
||||
pub roomid_federationhandletime: RwLock<HashMap<OwnedRoomId, (OwnedEventId, Instant)>>,
|
||||
pub stateres_mutex: Arc<Mutex<()>>,
|
||||
pub rotate: RotationHandler,
|
||||
pub(crate) rotate: RotationHandler,
|
||||
|
||||
pub shutdown: AtomicBool,
|
||||
pub argon: Argon2<'a>,
|
||||
|
@ -84,12 +84,12 @@ pub struct Service<'a> {
|
|||
/// Handles "rotation" of long-polling requests. "Rotation" in this context is similar to "rotation" of log files and the like.
|
||||
///
|
||||
/// This is utilized to have sync workers return early and release read locks on the database.
|
||||
pub struct RotationHandler(broadcast::Sender<()>, broadcast::Receiver<()>);
|
||||
pub(crate) struct RotationHandler(broadcast::Sender<()>, ());
|
||||
|
||||
impl RotationHandler {
|
||||
pub fn new() -> Self {
|
||||
let (s, r) = broadcast::channel(1);
|
||||
Self(s, r)
|
||||
let (s, _r) = broadcast::channel(1);
|
||||
Self(s, ())
|
||||
}
|
||||
|
||||
pub fn watch(&self) -> impl Future<Output = ()> {
|
||||
|
@ -113,13 +113,13 @@ impl Default for RotationHandler {
|
|||
|
||||
type DnsOverrides = Box<dyn Fn(&str) -> Option<SocketAddr> + Send + Sync>;
|
||||
|
||||
pub struct Resolver {
|
||||
struct Resolver {
|
||||
inner: GaiResolver,
|
||||
overrides: DnsOverrides,
|
||||
}
|
||||
|
||||
impl Resolver {
|
||||
pub fn new(overrides: DnsOverrides) -> Resolver {
|
||||
fn new(overrides: DnsOverrides) -> Resolver {
|
||||
Resolver {
|
||||
inner: GaiResolver::new(),
|
||||
overrides,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
mod data;
|
||||
pub use data::Data;
|
||||
pub(crate) use data::Data;
|
||||
|
||||
use crate::Result;
|
||||
use ruma::{
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
mod data;
|
||||
use std::io::Cursor;
|
||||
|
||||
pub use data::Data;
|
||||
pub(crate) use data::Data;
|
||||
|
||||
use crate::{services, Result};
|
||||
use image::imageops::FilterType;
|
||||
|
|
|
@ -7,19 +7,19 @@ use lru_cache::LruCache;
|
|||
|
||||
use crate::{Config, Result};
|
||||
|
||||
pub mod account_data;
|
||||
pub mod admin;
|
||||
pub mod appservice;
|
||||
pub mod globals;
|
||||
pub mod key_backups;
|
||||
pub mod media;
|
||||
pub mod pdu;
|
||||
pub mod pusher;
|
||||
pub mod rooms;
|
||||
pub mod sending;
|
||||
pub mod transaction_ids;
|
||||
pub mod uiaa;
|
||||
pub mod users;
|
||||
pub(crate) mod account_data;
|
||||
pub(crate) mod admin;
|
||||
pub(crate) mod appservice;
|
||||
pub(crate) mod globals;
|
||||
pub(crate) mod key_backups;
|
||||
pub(crate) mod media;
|
||||
pub(crate) mod pdu;
|
||||
pub(crate) mod pusher;
|
||||
pub(crate) mod rooms;
|
||||
pub(crate) mod sending;
|
||||
pub(crate) mod transaction_ids;
|
||||
pub(crate) mod uiaa;
|
||||
pub(crate) mod users;
|
||||
|
||||
pub struct Services<'a> {
|
||||
pub appservice: appservice::Service,
|
||||
|
|
|
@ -631,7 +631,7 @@ impl Service {
|
|||
state_res::resolve(room_version_id, &fork_states, auth_chain_sets, |id| {
|
||||
let res = services().rooms.timeline.get_pdu(id);
|
||||
if let Err(e) = &res {
|
||||
error!("LOOK AT ME Failed to fetch event: {}", e);
|
||||
error!("Failed to fetch event: {}", e);
|
||||
}
|
||||
res.ok().flatten()
|
||||
});
|
||||
|
@ -975,13 +975,16 @@ impl Service {
|
|||
debug!("Resolving state");
|
||||
|
||||
let lock = services().globals.stateres_mutex.lock();
|
||||
let state = match state_res::resolve(room_version_id, &fork_states, auth_chain_sets, |id| {
|
||||
let res = services().rooms.timeline.get_pdu(id);
|
||||
if let Err(e) = &res {
|
||||
error!("LOOK AT ME Failed to fetch event: {}", e);
|
||||
}
|
||||
res.ok().flatten()
|
||||
}) {
|
||||
let state_resolve =
|
||||
state_res::resolve(room_version_id, &fork_states, auth_chain_sets, |id| {
|
||||
let res = services().rooms.timeline.get_pdu(id);
|
||||
if let Err(e) = &res {
|
||||
error!("Failed to fetch event: {}", e);
|
||||
}
|
||||
res.ok().flatten()
|
||||
});
|
||||
|
||||
let state = match state_resolve {
|
||||
Ok(new_state) => new_state,
|
||||
Err(e) => {
|
||||
error!("State resolution failed: {}", e);
|
||||
|
|
|
@ -346,7 +346,8 @@ impl Service {
|
|||
error!("Invalid room topic event in database for room {}", room_id);
|
||||
Error::bad_database("Invalid room topic event in database.")
|
||||
})
|
||||
})?,
|
||||
})
|
||||
.unwrap_or(None),
|
||||
world_readable: services()
|
||||
.rooms
|
||||
.state_accessor
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
pub mod error;
|
||||
pub(crate) mod error;
|
||||
|
||||
use crate::{services, Error, Result};
|
||||
use argon2::{password_hash::SaltString, PasswordHasher};
|
||||
|
@ -14,14 +14,14 @@ use std::{
|
|||
time::{SystemTime, UNIX_EPOCH},
|
||||
};
|
||||
|
||||
pub fn millis_since_unix_epoch() -> u64 {
|
||||
pub(crate) fn millis_since_unix_epoch() -> u64 {
|
||||
SystemTime::now()
|
||||
.duration_since(UNIX_EPOCH)
|
||||
.expect("time is valid")
|
||||
.as_millis() as u64
|
||||
}
|
||||
|
||||
pub fn increment(old: Option<&[u8]>) -> Option<Vec<u8>> {
|
||||
pub(crate) fn increment(old: Option<&[u8]>) -> Option<Vec<u8>> {
|
||||
let number = match old.map(|bytes| bytes.try_into()) {
|
||||
Some(Ok(bytes)) => {
|
||||
let number = u64::from_be_bytes(bytes);
|
||||
|
@ -89,7 +89,7 @@ pub fn calculate_hash(keys: &[&[u8]]) -> Vec<u8> {
|
|||
hash.as_ref().to_owned()
|
||||
}
|
||||
|
||||
pub fn common_elements(
|
||||
pub(crate) fn common_elements(
|
||||
mut iterators: impl Iterator<Item = impl Iterator<Item = Vec<u8>>>,
|
||||
check_order: impl Fn(&[u8], &[u8]) -> Ordering,
|
||||
) -> Option<impl Iterator<Item = Vec<u8>>> {
|
||||
|
@ -116,7 +116,7 @@ pub fn common_elements(
|
|||
/// Fallible conversion from any value that implements `Serialize` to a `CanonicalJsonObject`.
|
||||
///
|
||||
/// `value` must serialize to an `serde_json::Value::Object`.
|
||||
pub fn to_canonical_object<T: serde::Serialize>(
|
||||
pub(crate) fn to_canonical_object<T: serde::Serialize>(
|
||||
value: T,
|
||||
) -> Result<CanonicalJsonObject, CanonicalJsonError> {
|
||||
use serde::ser::Error;
|
||||
|
@ -129,7 +129,7 @@ pub fn to_canonical_object<T: serde::Serialize>(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn deserialize_from_str<
|
||||
pub(crate) fn deserialize_from_str<
|
||||
'de,
|
||||
D: serde::de::Deserializer<'de>,
|
||||
T: FromStr<Err = E>,
|
||||
|
@ -160,7 +160,7 @@ pub fn deserialize_from_str<
|
|||
|
||||
/// Wrapper struct which will emit the HTML-escaped version of the contained
|
||||
/// string when passed to a format string.
|
||||
pub struct HtmlEscape<'a>(pub &'a str);
|
||||
pub(crate) struct HtmlEscape<'a>(pub(crate) &'a str);
|
||||
|
||||
impl<'a> fmt::Display for HtmlEscape<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
|
|
Reference in a new issue