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:
|
cargo check:
|
||||||
stage: test
|
stage: test
|
||||||
image: docker.io/rust:1.74.1-bullseye
|
image: docker.io/rust:1.75.0-bullseye
|
||||||
needs: []
|
needs: []
|
||||||
interruptible: true
|
interruptible: true
|
||||||
before_script:
|
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
|
# `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
|
# how to do this, ping `@charles:computer.surgery` or `@dusk:gaze.systems` in
|
||||||
# the matrix room.
|
# 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
|
# 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
|
# 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 = { 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 = { 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" ] }
|
#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"] }
|
hyper = { version = "0.14", features = ["server", "http1", "http2"] }
|
||||||
tokio = { version = "1.35.1", features = ["fs", "macros", "signal", "sync"] }
|
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
|
# Used for the http request / response body type for Ruma endpoints used with reqwest
|
||||||
bytes = "1.5.0"
|
bytes = "1.5.0"
|
||||||
|
@ -57,7 +56,7 @@ reqwest = { version = "0.11.23", default-features = false, features = ["rustls-t
|
||||||
# Used for conduit::Error type
|
# Used for conduit::Error type
|
||||||
thiserror = "1.0.56"
|
thiserror = "1.0.56"
|
||||||
# Used to generate thumbnails for images
|
# 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
|
# Used to encode server public key
|
||||||
base64 = "0.21.7"
|
base64 = "0.21.7"
|
||||||
# Used when hashing the state
|
# Used when hashing the state
|
||||||
|
@ -79,7 +78,6 @@ tracing-opentelemetry = "0.22.0"
|
||||||
lru-cache = "0.1.2"
|
lru-cache = "0.1.2"
|
||||||
rusqlite = { version = "0.30.0", optional = true, features = ["bundled"] }
|
rusqlite = { version = "0.30.0", optional = true, features = ["bundled"] }
|
||||||
parking_lot = { version = "0.12.1", optional = true }
|
parking_lot = { version = "0.12.1", optional = true }
|
||||||
crossbeam = { version = "0.8.3", optional = true }
|
|
||||||
num_cpus = "1.16.0"
|
num_cpus = "1.16.0"
|
||||||
threadpool = "1.8.1"
|
threadpool = "1.8.1"
|
||||||
# Used for ruma wrapper
|
# Used for ruma wrapper
|
||||||
|
@ -93,7 +91,7 @@ hmac = "0.12.1"
|
||||||
sha-1 = "0.10.1"
|
sha-1 = "0.10.1"
|
||||||
sha2 = { version = "0.10.8" }
|
sha2 = { version = "0.10.8" }
|
||||||
# used for conduit's CLI and admin room command parsing
|
# 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 }
|
futures-util = { version = "0.3.30", default-features = false }
|
||||||
# Used for reading the configuration from conduit.toml & environment variables
|
# Used for reading the configuration from conduit.toml & environment variables
|
||||||
figment = { version = "0.10.13", features = ["env", "toml"] }
|
figment = { version = "0.10.13", features = ["env", "toml"] }
|
||||||
|
@ -162,73 +160,85 @@ debug = 0
|
||||||
lto = 'off'
|
lto = 'off'
|
||||||
incremental = true
|
incremental = true
|
||||||
|
|
||||||
|
# default release profile
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = 'fat'
|
lto = 'thin'
|
||||||
incremental = false
|
incremental = false
|
||||||
codegen-units=1
|
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
overflow-checks = true
|
overflow-checks = true
|
||||||
strip = "symbols"
|
strip = "symbols"
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
debug = 0
|
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:
|
# For releases also try to max optimizations for dependencies:
|
||||||
[profile.release.build-override]
|
[profile.release-high-perf.build-override]
|
||||||
debug = 0
|
debug = 0
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
codegen-units=1
|
codegen-units = 1
|
||||||
[profile.release.package."*"]
|
|
||||||
|
[profile.release-high-perf.package."*"]
|
||||||
debug = 0
|
debug = 0
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
codegen-units=1
|
codegen-units = 1
|
||||||
|
|
||||||
[lints]
|
[lints]
|
||||||
workspace = true
|
workspace = true
|
||||||
|
|
||||||
[workspace.lints.rust]
|
[workspace.lints.rust]
|
||||||
# missing_abi = "warn"
|
missing_abi = "warn"
|
||||||
# missing_docs = "warn"
|
# missing_docs = "warn"
|
||||||
# noop_method_call = "warn"
|
noop_method_call = "warn"
|
||||||
# pointer_structural_match = "warn"
|
pointer_structural_match = "warn"
|
||||||
# unreachable_pub = "warn"
|
# unreachable_pub = "warn"
|
||||||
# unused_extern_crates = "warn"
|
unused_extern_crates = "warn"
|
||||||
# unused_import_braces = "warn"
|
unused_import_braces = "warn"
|
||||||
# unused_lifetimes = "warn"
|
# unused_lifetimes = "warn"
|
||||||
unused_qualifications = "warn"
|
unused_qualifications = "warn"
|
||||||
# unused_tuple_struct_fields = "warn"
|
dead_code = "warn"
|
||||||
|
|
||||||
[workspace.lints.clippy]
|
[workspace.lints.clippy]
|
||||||
suspicious = "warn" # assume deny in practice
|
suspicious = "warn" # assume deny in practice
|
||||||
perf = "warn" # assume deny in practice
|
perf = "warn" # assume deny in practice
|
||||||
# redundant_clone = "warn"
|
redundant_clone = "warn"
|
||||||
# cloned_instead_of_copied = "warn"
|
cloned_instead_of_copied = "warn"
|
||||||
expl_impl_clone_on_copy = "warn"
|
expl_impl_clone_on_copy = "warn"
|
||||||
# pedantic = "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"
|
dbg_macro = "warn"
|
||||||
# empty_structs_with_brackets = "warn"
|
empty_structs_with_brackets = "warn"
|
||||||
# get_unwrap = "warn"
|
get_unwrap = "warn"
|
||||||
# if_then_some_else_none = "warn"
|
# if_then_some_else_none = "warn"
|
||||||
# let_underscore_must_use = "warn"
|
# let_underscore_must_use = "warn"
|
||||||
# map_err_ignore = "warn"
|
# map_err_ignore = "warn"
|
||||||
# missing_docs_in_private_items = "warn"
|
# missing_docs_in_private_items = "warn"
|
||||||
# negative_feature_names = "warn"
|
negative_feature_names = "warn"
|
||||||
# pub_without_shorthand = "warn"
|
pub_without_shorthand = "warn"
|
||||||
rc_buffer = "warn"
|
rc_buffer = "warn"
|
||||||
rc_mutex = "warn"
|
rc_mutex = "warn"
|
||||||
# redundant_feature_names = "warn"
|
redundant_feature_names = "warn"
|
||||||
# redundant_type_annotations = "warn"
|
redundant_type_annotations = "warn"
|
||||||
# ref_patterns = "warn"
|
# ref_patterns = "warn"
|
||||||
# rest_pat_in_fully_bound_structs = "warn"
|
rest_pat_in_fully_bound_structs = "warn"
|
||||||
# str_to_string = "warn"
|
str_to_string = "warn"
|
||||||
# string_add = "warn"
|
# string_add = "warn"
|
||||||
# string_slice = "warn"
|
# string_slice = "warn"
|
||||||
# string_to_string = "warn"
|
string_to_string = "warn"
|
||||||
tests_outside_test_module = "warn"
|
tests_outside_test_module = "warn"
|
||||||
undocumented_unsafe_blocks = "warn"
|
undocumented_unsafe_blocks = "warn"
|
||||||
# unneeded_field_pattern = "warn"
|
unneeded_field_pattern = "warn"
|
||||||
# unseparated_literal_suffix = "warn"
|
unseparated_literal_suffix = "warn"
|
||||||
# unwrap_used = "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
|
- 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)
|
- 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)
|
- 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)
|
- Purge unmaintained/irrelevant/broken database backends (heed, sled, persy)
|
||||||
- webp support for images
|
- webp support for images
|
||||||
- Support for suggesting servers to join at `/_matrix/client/v3/directory/room/{roomAlias}`
|
- 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
|
- Only follow 6 redirects total in our default reqwest ClientBuilder
|
||||||
- Generate passwords with 25 characters instead of 15
|
- Generate passwords with 25 characters instead of 15
|
||||||
- Add missing `reason` field to user ban events (`/ban`)
|
- 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
|
# 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
|
FROM base AS builder
|
||||||
WORKDIR /usr/src/conduit
|
WORKDIR /usr/src/conduit
|
||||||
|
|
|
@ -59,7 +59,7 @@
|
||||||
channel = cargoToml.package.rust-version;
|
channel = cargoToml.package.rust-version;
|
||||||
|
|
||||||
# THE rust-version HASH
|
# THE rust-version HASH
|
||||||
sha256 = "sha256-PjvuouwTsYfNKW5Vi5Ye7y+lL7SsWGBxCtBOOm2z14c=";
|
sha256 = "sha256-SXRtAuO4IqNOQq+nLbrsDFbVk+3aVA8NNpSZsKlVH/8=";
|
||||||
};
|
};
|
||||||
|
|
||||||
mkToolchain = fenix.packages.${system}.combine;
|
mkToolchain = fenix.packages.${system}.combine;
|
||||||
|
|
|
@ -19,7 +19,7 @@ use register::RegistrationKind;
|
||||||
|
|
||||||
const RANDOM_USER_ID_LENGTH: usize = 10;
|
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.
|
/// Checks if a username is valid and available on this server.
|
||||||
///
|
///
|
||||||
|
|
|
@ -13,7 +13,7 @@ use ruma::{
|
||||||
OwnedRoomAliasId, OwnedServerName,
|
OwnedRoomAliasId, OwnedServerName,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/directory/room/{roomAlias}`
|
/// # `PUT /_matrix/client/v3/directory/room/{roomAlias}`
|
||||||
///
|
///
|
||||||
/// Creates a new room alias on this server.
|
/// Creates a new room alias on this server.
|
||||||
pub async fn create_alias_route(
|
pub async fn create_alias_route(
|
||||||
|
@ -35,15 +35,22 @@ pub async fn create_alias_route(
|
||||||
return Err(Error::Conflict("Alias already exists."));
|
return Err(Error::Conflict("Alias already exists."));
|
||||||
}
|
}
|
||||||
|
|
||||||
services()
|
if services()
|
||||||
.rooms
|
.rooms
|
||||||
.alias
|
.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())
|
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.
|
/// 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?
|
// 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!("Invalid room topic event in database for room {}", room_id);
|
||||||
Error::bad_database("Invalid room topic event in database.")
|
Error::bad_database("Invalid room topic event in database.")
|
||||||
})
|
})
|
||||||
})?,
|
})
|
||||||
|
.unwrap_or(None),
|
||||||
world_readable: services()
|
world_readable: services()
|
||||||
.rooms
|
.rooms
|
||||||
.state_accessor
|
.state_accessor
|
||||||
|
|
|
@ -9,9 +9,10 @@ use ruma::api::client::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// generated MXC ID (`media-id`) length
|
||||||
const MXC_LENGTH: usize = 32;
|
const MXC_LENGTH: usize = 32;
|
||||||
|
|
||||||
/// # `GET /_matrix/media/r0/config`
|
/// # `GET /_matrix/media/v3/config`
|
||||||
///
|
///
|
||||||
/// Returns max upload size.
|
/// Returns max upload size.
|
||||||
pub async fn get_media_config_route(
|
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.
|
/// 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(
|
pub async fn get_remote_content(
|
||||||
mxc: &str,
|
mxc: &str,
|
||||||
server_name: &ruma::ServerName,
|
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);
|
let mxc = format!("mxc://{}/{}", body.server_name, body.media_id);
|
||||||
|
|
||||||
if let Some(FileMeta {
|
if let Some(FileMeta {
|
||||||
content_disposition: _,
|
content_type, file, ..
|
||||||
content_type,
|
|
||||||
file,
|
|
||||||
}) = services().media.get(mxc.clone()).await?
|
}) = services().media.get(mxc.clone()).await?
|
||||||
{
|
{
|
||||||
Ok(get_content_as_filename::v3::Response {
|
Ok(get_content_as_filename::v3::Response {
|
||||||
|
|
|
@ -361,7 +361,7 @@ pub async fn unban_user_route(
|
||||||
Ok(unban_user::v3::Response::new())
|
Ok(unban_user::v3::Response::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/forget`
|
/// # `POST /_matrix/client/v3/rooms/{roomId}/forget`
|
||||||
///
|
///
|
||||||
/// Forgets about a room.
|
/// Forgets about a room.
|
||||||
///
|
///
|
||||||
|
@ -1221,7 +1221,7 @@ fn validate_and_add_event_id(
|
||||||
Ok((event_id, value))
|
Ok((event_id, value))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn invite_helper<'a>(
|
pub(crate) async fn invite_helper(
|
||||||
sender_user: &UserId,
|
sender_user: &UserId,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
|
|
|
@ -68,7 +68,14 @@ pub use unversioned::*;
|
||||||
pub use user_directory::*;
|
pub use user_directory::*;
|
||||||
pub use voip::*;
|
pub use voip::*;
|
||||||
|
|
||||||
|
/// generated device ID length
|
||||||
pub const DEVICE_ID_LENGTH: usize = 10;
|
pub const DEVICE_ID_LENGTH: usize = 10;
|
||||||
|
|
||||||
|
/// generated user access token length
|
||||||
pub const TOKEN_LENGTH: usize = 32;
|
pub const TOKEN_LENGTH: usize = 32;
|
||||||
|
|
||||||
|
/// generated user session ID length
|
||||||
pub const SESSION_ID_LENGTH: usize = 32;
|
pub const SESSION_ID_LENGTH: usize = 32;
|
||||||
|
|
||||||
|
/// auto-generated password length
|
||||||
pub const AUTO_GEN_PASSWORD_LENGTH: usize = 25;
|
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 crate::{services, utils::HtmlEscape, Error, Result, Ruma};
|
||||||
|
use rand::Rng;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::{error::ErrorKind, room::report_content},
|
api::client::{error::ErrorKind, room::report_content},
|
||||||
events::room::message,
|
events::room::message,
|
||||||
int,
|
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
|
/// Reports an inappropriate event to homeserver admins
|
||||||
///
|
///
|
||||||
pub async fn report_event_route(
|
pub async fn report_event_route(
|
||||||
body: Ruma<report_content::v3::Request>,
|
body: Ruma<report_content::v3::Request>,
|
||||||
) -> Result<report_content::v3::Response> {
|
) -> Result<report_content::v3::Response> {
|
||||||
|
// user authentication
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
|
info!("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)? {
|
let pdu = match services().rooms.timeline.get_pdu(&body.event_id)? {
|
||||||
Some(pdu) => pdu,
|
Some(pdu) => pdu,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::NotFound,
|
||||||
"Invalid Event ID",
|
"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)) {
|
if let Some(true) = body.score.map(|s| s > int!(0) || s < int!(-100)) {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
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(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
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(
|
.send_message(message::RoomMessageEventContent::text_html(
|
||||||
format!(
|
format!(
|
||||||
"Report received from: {}\n\n\
|
"@room Report received from: {}\n\n\
|
||||||
Event ID: {:?}\n\
|
Event ID: {}\n\
|
||||||
Room ID: {:?}\n\
|
Room ID: {}\n\
|
||||||
Sent By: {:?}\n\n\
|
Sent By: {}\n\n\
|
||||||
Report Score: {:?}\n\
|
Report Score: {}\n\
|
||||||
Report Reason: {:?}",
|
Report Reason: {}",
|
||||||
sender_user, pdu.event_id, pdu.room_id, pdu.sender, body.score, body.reason
|
sender_user.to_owned(),
|
||||||
),
|
|
||||||
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,
|
|
||||||
pdu.event_id,
|
pdu.event_id,
|
||||||
pdu.room_id,
|
pdu.room_id,
|
||||||
pdu.sender,
|
pdu.sender.to_owned(),
|
||||||
body.score,
|
body.score.unwrap_or(ruma::Int::from(0)),
|
||||||
HtmlEscape(body.reason.as_deref().unwrap_or(""))
|
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 {})
|
Ok(report_content::v3::Response {})
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,7 +95,7 @@ impl FedDest {
|
||||||
fn into_uri_string(self) -> String {
|
fn into_uri_string(self) -> String {
|
||||||
match self {
|
match self {
|
||||||
Self::Literal(addr) => addr.to_string(),
|
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;
|
use self::proxy::ProxyConfig;
|
||||||
|
|
||||||
|
/// all the config options for conduwuit
|
||||||
#[derive(Clone, Debug, Deserialize)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
/// [`IpAddr`] conduwuit will listen on (can be IPv4 or IPv6)
|
||||||
#[serde(default = "default_address")]
|
#[serde(default = "default_address")]
|
||||||
pub address: IpAddr,
|
pub address: IpAddr,
|
||||||
|
/// default TCP port conduwuit will listen on
|
||||||
#[serde(default = "default_port")]
|
#[serde(default = "default_port")]
|
||||||
pub port: u16,
|
pub port: u16,
|
||||||
pub tls: Option<TlsConfig>,
|
pub tls: Option<TlsConfig>,
|
||||||
|
@ -214,14 +217,23 @@ impl fmt::Display for Config {
|
||||||
),
|
),
|
||||||
("Allow encryption", &self.allow_encryption.to_string()),
|
("Allow encryption", &self.allow_encryption.to_string()),
|
||||||
("Allow federation", &self.allow_federation.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",
|
"Allow device name federation",
|
||||||
&self.allow_device_name_federation.to_string(),
|
&self.allow_device_name_federation.to_string(),
|
||||||
),
|
),
|
||||||
(
|
("Notification push path", &self.notification_push_path),
|
||||||
"Notification push path",
|
|
||||||
&self.notification_push_path.to_string(),
|
|
||||||
),
|
|
||||||
("Allow room creation", &self.allow_room_creation.to_string()),
|
("Allow room creation", &self.allow_room_creation.to_string()),
|
||||||
(
|
(
|
||||||
"Allow public room directory over federation",
|
"Allow public room directory over federation",
|
||||||
|
@ -280,10 +292,7 @@ impl fmt::Display for Config {
|
||||||
"zstd Response Body Compression",
|
"zstd Response Body Compression",
|
||||||
&self.zstd_compression.to_string(),
|
&self.zstd_compression.to_string(),
|
||||||
),
|
),
|
||||||
(
|
("RocksDB database log level", &self.rocksdb_log_level),
|
||||||
"RocksDB database log level",
|
|
||||||
&self.rocksdb_log_level.to_string(),
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
"RocksDB database log time-to-roll",
|
"RocksDB database log time-to-roll",
|
||||||
&self.rocksdb_log_time_to_roll.to_string(),
|
&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
|
// I know, it's a great name
|
||||||
pub fn default_default_room_version() -> RoomVersionId {
|
pub(crate) fn default_default_room_version() -> RoomVersionId {
|
||||||
RoomVersionId::V10
|
RoomVersionId::V10
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn default_rocksdb_max_log_file_size() -> usize {
|
fn default_rocksdb_max_log_file_size() -> usize {
|
||||||
// 4 megabytes
|
// 4 megabytes
|
||||||
4 * 1024 * 1024
|
4 * 1024 * 1024
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,20 +95,20 @@ impl PartialProxyConfig {
|
||||||
|
|
||||||
/// A domain name, that optionally allows a * as its first subdomain.
|
/// A domain name, that optionally allows a * as its first subdomain.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum WildCardedDomain {
|
enum WildCardedDomain {
|
||||||
WildCard,
|
WildCard,
|
||||||
WildCarded(String),
|
WildCarded(String),
|
||||||
Exact(String),
|
Exact(String),
|
||||||
}
|
}
|
||||||
impl WildCardedDomain {
|
impl WildCardedDomain {
|
||||||
pub fn matches(&self, domain: &str) -> bool {
|
fn matches(&self, domain: &str) -> bool {
|
||||||
match self {
|
match self {
|
||||||
WildCardedDomain::WildCard => true,
|
WildCardedDomain::WildCard => true,
|
||||||
WildCardedDomain::WildCarded(d) => domain.ends_with(d),
|
WildCardedDomain::WildCarded(d) => domain.ends_with(d),
|
||||||
WildCardedDomain::Exact(d) => domain == 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) {
|
match (self, other) {
|
||||||
(WildCardedDomain::WildCard, WildCardedDomain::WildCard) => false,
|
(WildCardedDomain::WildCard, WildCardedDomain::WildCard) => false,
|
||||||
(_, WildCardedDomain::WildCard) => true,
|
(_, WildCardedDomain::WildCard) => true,
|
||||||
|
|
|
@ -7,12 +7,12 @@ use std::{future::Future, pin::Pin, sync::Arc};
|
||||||
pub mod sqlite;
|
pub mod sqlite;
|
||||||
|
|
||||||
#[cfg(feature = "rocksdb")]
|
#[cfg(feature = "rocksdb")]
|
||||||
pub mod rocksdb;
|
pub(crate) mod rocksdb;
|
||||||
|
|
||||||
#[cfg(any(feature = "sqlite", feature = "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>
|
fn open(config: &Config) -> Result<Self>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
|
@ -27,7 +27,7 @@ pub trait KeyValueDatabaseEngine: Send + Sync {
|
||||||
fn clear_caches(&self) {}
|
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 get(&self, key: &[u8]) -> Result<Option<Vec<u8>>>;
|
||||||
|
|
||||||
fn insert(&self, key: &[u8], value: &[u8]) -> Result<()>;
|
fn insert(&self, key: &[u8], value: &[u8]) -> Result<()>;
|
||||||
|
|
|
@ -8,14 +8,14 @@ use std::{
|
||||||
|
|
||||||
use rocksdb::LogLevel::{Debug, Error, Fatal, Info, Warn};
|
use rocksdb::LogLevel::{Debug, Error, Fatal, Info, Warn};
|
||||||
|
|
||||||
pub struct Engine {
|
pub(crate) struct Engine {
|
||||||
rocks: rocksdb::DBWithThreadMode<rocksdb::MultiThreaded>,
|
rocks: rocksdb::DBWithThreadMode<rocksdb::MultiThreaded>,
|
||||||
cache: rocksdb::Cache,
|
cache: rocksdb::Cache,
|
||||||
old_cfs: Vec<String>,
|
old_cfs: Vec<String>,
|
||||||
config: Config,
|
config: Config,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct RocksDbEngineTree<'a> {
|
struct RocksDbEngineTree<'a> {
|
||||||
db: Arc<Engine>,
|
db: Arc<Engine>,
|
||||||
name: &'a str,
|
name: &'a str,
|
||||||
watchers: Watchers,
|
watchers: Watchers,
|
||||||
|
|
|
@ -11,8 +11,8 @@ use ruma::{
|
||||||
|
|
||||||
use crate::{database::KeyValueDatabase, service, services, utils, Error, Result};
|
use crate::{database::KeyValueDatabase, service, services, utils, Error, Result};
|
||||||
|
|
||||||
pub const COUNTER: &[u8] = b"c";
|
const COUNTER: &[u8] = b"c";
|
||||||
pub const LAST_CHECK_FOR_UPDATES_COUNT: &[u8] = b"u";
|
const LAST_CHECK_FOR_UPDATES_COUNT: &[u8] = b"u";
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl service::globals::Data for KeyValueDatabase {
|
impl service::globals::Data for KeyValueDatabase {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
pub mod abstraction;
|
pub(crate) mod abstraction;
|
||||||
pub mod key_value;
|
pub(crate) mod key_value;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
service::rooms::{edus::presence::presence_handler, timeline::PduCount},
|
service::rooms::{edus::presence::presence_handler, timeline::PduCount},
|
||||||
|
@ -1094,7 +1094,7 @@ impl KeyValueDatabase {
|
||||||
use tokio::time::Instant;
|
use tokio::time::Instant;
|
||||||
|
|
||||||
let timer_interval =
|
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() {
|
fn perform_cleanup() {
|
||||||
let start = Instant::now();
|
let start = Instant::now();
|
||||||
|
|
|
@ -53,7 +53,7 @@ static GLOBAL: Jemalloc = Jemalloc;
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[clap(version, about, long_about = None)]
|
#[clap(version, about, long_about = None)]
|
||||||
struct Args {}
|
struct Args;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
mod data;
|
mod data;
|
||||||
|
|
||||||
pub use data::Data;
|
pub(crate) use data::Data;
|
||||||
|
|
||||||
use ruma::{
|
use ruma::{
|
||||||
events::{AnyEphemeralRoomEvent, RoomAccountDataEventType},
|
events::{AnyEphemeralRoomEvent, RoomAccountDataEventType},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
mod data;
|
mod data;
|
||||||
|
|
||||||
pub use data::Data;
|
pub(crate) use data::Data;
|
||||||
|
|
||||||
use crate::Result;
|
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_mutex_federation: RwLock<HashMap<OwnedRoomId, Arc<TokioMutex<()>>>>, // this lock will be held longer
|
||||||
pub roomid_federationhandletime: RwLock<HashMap<OwnedRoomId, (OwnedEventId, Instant)>>,
|
pub roomid_federationhandletime: RwLock<HashMap<OwnedRoomId, (OwnedEventId, Instant)>>,
|
||||||
pub stateres_mutex: Arc<Mutex<()>>,
|
pub stateres_mutex: Arc<Mutex<()>>,
|
||||||
pub rotate: RotationHandler,
|
pub(crate) rotate: RotationHandler,
|
||||||
|
|
||||||
pub shutdown: AtomicBool,
|
pub shutdown: AtomicBool,
|
||||||
pub argon: Argon2<'a>,
|
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.
|
/// 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.
|
/// 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 {
|
impl RotationHandler {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
let (s, r) = broadcast::channel(1);
|
let (s, _r) = broadcast::channel(1);
|
||||||
Self(s, r)
|
Self(s, ())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn watch(&self) -> impl Future<Output = ()> {
|
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>;
|
type DnsOverrides = Box<dyn Fn(&str) -> Option<SocketAddr> + Send + Sync>;
|
||||||
|
|
||||||
pub struct Resolver {
|
struct Resolver {
|
||||||
inner: GaiResolver,
|
inner: GaiResolver,
|
||||||
overrides: DnsOverrides,
|
overrides: DnsOverrides,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resolver {
|
impl Resolver {
|
||||||
pub fn new(overrides: DnsOverrides) -> Resolver {
|
fn new(overrides: DnsOverrides) -> Resolver {
|
||||||
Resolver {
|
Resolver {
|
||||||
inner: GaiResolver::new(),
|
inner: GaiResolver::new(),
|
||||||
overrides,
|
overrides,
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
mod data;
|
mod data;
|
||||||
pub use data::Data;
|
pub(crate) use data::Data;
|
||||||
|
|
||||||
use crate::Result;
|
use crate::Result;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
mod data;
|
mod data;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
pub use data::Data;
|
pub(crate) use data::Data;
|
||||||
|
|
||||||
use crate::{services, Result};
|
use crate::{services, Result};
|
||||||
use image::imageops::FilterType;
|
use image::imageops::FilterType;
|
||||||
|
|
|
@ -7,19 +7,19 @@ use lru_cache::LruCache;
|
||||||
|
|
||||||
use crate::{Config, Result};
|
use crate::{Config, Result};
|
||||||
|
|
||||||
pub mod account_data;
|
pub(crate) mod account_data;
|
||||||
pub mod admin;
|
pub(crate) mod admin;
|
||||||
pub mod appservice;
|
pub(crate) mod appservice;
|
||||||
pub mod globals;
|
pub(crate) mod globals;
|
||||||
pub mod key_backups;
|
pub(crate) mod key_backups;
|
||||||
pub mod media;
|
pub(crate) mod media;
|
||||||
pub mod pdu;
|
pub(crate) mod pdu;
|
||||||
pub mod pusher;
|
pub(crate) mod pusher;
|
||||||
pub mod rooms;
|
pub(crate) mod rooms;
|
||||||
pub mod sending;
|
pub(crate) mod sending;
|
||||||
pub mod transaction_ids;
|
pub(crate) mod transaction_ids;
|
||||||
pub mod uiaa;
|
pub(crate) mod uiaa;
|
||||||
pub mod users;
|
pub(crate) mod users;
|
||||||
|
|
||||||
pub struct Services<'a> {
|
pub struct Services<'a> {
|
||||||
pub appservice: appservice::Service,
|
pub appservice: appservice::Service,
|
||||||
|
|
|
@ -631,7 +631,7 @@ impl Service {
|
||||||
state_res::resolve(room_version_id, &fork_states, auth_chain_sets, |id| {
|
state_res::resolve(room_version_id, &fork_states, auth_chain_sets, |id| {
|
||||||
let res = services().rooms.timeline.get_pdu(id);
|
let res = services().rooms.timeline.get_pdu(id);
|
||||||
if let Err(e) = &res {
|
if let Err(e) = &res {
|
||||||
error!("LOOK AT ME Failed to fetch event: {}", e);
|
error!("Failed to fetch event: {}", e);
|
||||||
}
|
}
|
||||||
res.ok().flatten()
|
res.ok().flatten()
|
||||||
});
|
});
|
||||||
|
@ -975,13 +975,16 @@ impl Service {
|
||||||
debug!("Resolving state");
|
debug!("Resolving state");
|
||||||
|
|
||||||
let lock = services().globals.stateres_mutex.lock();
|
let lock = services().globals.stateres_mutex.lock();
|
||||||
let state = match state_res::resolve(room_version_id, &fork_states, auth_chain_sets, |id| {
|
let state_resolve =
|
||||||
let res = services().rooms.timeline.get_pdu(id);
|
state_res::resolve(room_version_id, &fork_states, auth_chain_sets, |id| {
|
||||||
if let Err(e) = &res {
|
let res = services().rooms.timeline.get_pdu(id);
|
||||||
error!("LOOK AT ME Failed to fetch event: {}", e);
|
if let Err(e) = &res {
|
||||||
}
|
error!("Failed to fetch event: {}", e);
|
||||||
res.ok().flatten()
|
}
|
||||||
}) {
|
res.ok().flatten()
|
||||||
|
});
|
||||||
|
|
||||||
|
let state = match state_resolve {
|
||||||
Ok(new_state) => new_state,
|
Ok(new_state) => new_state,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("State resolution failed: {}", e);
|
error!("State resolution failed: {}", e);
|
||||||
|
|
|
@ -346,7 +346,8 @@ impl Service {
|
||||||
error!("Invalid room topic event in database for room {}", room_id);
|
error!("Invalid room topic event in database for room {}", room_id);
|
||||||
Error::bad_database("Invalid room topic event in database.")
|
Error::bad_database("Invalid room topic event in database.")
|
||||||
})
|
})
|
||||||
})?,
|
})
|
||||||
|
.unwrap_or(None),
|
||||||
world_readable: services()
|
world_readable: services()
|
||||||
.rooms
|
.rooms
|
||||||
.state_accessor
|
.state_accessor
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
pub mod error;
|
pub(crate) mod error;
|
||||||
|
|
||||||
use crate::{services, Error, Result};
|
use crate::{services, Error, Result};
|
||||||
use argon2::{password_hash::SaltString, PasswordHasher};
|
use argon2::{password_hash::SaltString, PasswordHasher};
|
||||||
|
@ -14,14 +14,14 @@ use std::{
|
||||||
time::{SystemTime, UNIX_EPOCH},
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn millis_since_unix_epoch() -> u64 {
|
pub(crate) fn millis_since_unix_epoch() -> u64 {
|
||||||
SystemTime::now()
|
SystemTime::now()
|
||||||
.duration_since(UNIX_EPOCH)
|
.duration_since(UNIX_EPOCH)
|
||||||
.expect("time is valid")
|
.expect("time is valid")
|
||||||
.as_millis() as u64
|
.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()) {
|
let number = match old.map(|bytes| bytes.try_into()) {
|
||||||
Some(Ok(bytes)) => {
|
Some(Ok(bytes)) => {
|
||||||
let number = u64::from_be_bytes(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()
|
hash.as_ref().to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn common_elements(
|
pub(crate) fn common_elements(
|
||||||
mut iterators: impl Iterator<Item = impl Iterator<Item = Vec<u8>>>,
|
mut iterators: impl Iterator<Item = impl Iterator<Item = Vec<u8>>>,
|
||||||
check_order: impl Fn(&[u8], &[u8]) -> Ordering,
|
check_order: impl Fn(&[u8], &[u8]) -> Ordering,
|
||||||
) -> Option<impl Iterator<Item = Vec<u8>>> {
|
) -> 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`.
|
/// Fallible conversion from any value that implements `Serialize` to a `CanonicalJsonObject`.
|
||||||
///
|
///
|
||||||
/// `value` must serialize to an `serde_json::Value::Object`.
|
/// `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,
|
value: T,
|
||||||
) -> Result<CanonicalJsonObject, CanonicalJsonError> {
|
) -> Result<CanonicalJsonObject, CanonicalJsonError> {
|
||||||
use serde::ser::Error;
|
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,
|
'de,
|
||||||
D: serde::de::Deserializer<'de>,
|
D: serde::de::Deserializer<'de>,
|
||||||
T: FromStr<Err = E>,
|
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
|
/// Wrapper struct which will emit the HTML-escaped version of the contained
|
||||||
/// string when passed to a format string.
|
/// 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> {
|
impl<'a> fmt::Display for HtmlEscape<'a> {
|
||||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
|
Reference in a new issue