mirror of
https://gitlab.com/famedly/conduit.git
synced 2024-11-09 06:01:05 +01:00
Merge branch 'axum' into 'next'
Port from rocket to axum See merge request famedly/conduit!263
This commit is contained in:
commit
1d01e2a077
55 changed files with 1499 additions and 2292 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -57,7 +57,6 @@ $RECYCLE.BIN/
|
||||||
*.lnk
|
*.lnk
|
||||||
|
|
||||||
# Conduit
|
# Conduit
|
||||||
Rocket.toml
|
|
||||||
conduit.toml
|
conduit.toml
|
||||||
conduit.db
|
conduit.db
|
||||||
|
|
||||||
|
|
839
Cargo.lock
generated
839
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
24
Cargo.toml
24
Cargo.toml
|
@ -6,26 +6,27 @@ authors = ["timokoesters <timo@koesters.xyz>"]
|
||||||
homepage = "https://conduit.rs"
|
homepage = "https://conduit.rs"
|
||||||
repository = "https://gitlab.com/famedly/conduit"
|
repository = "https://gitlab.com/famedly/conduit"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
version = "0.3.0"
|
version = "0.3.0-next"
|
||||||
rust-version = "1.56"
|
rust-version = "1.56"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
# 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
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Used to handle requests
|
# Web framework
|
||||||
# TODO: This can become optional as soon as proper configs are supported
|
axum = { version = "0.4.4", features = ["headers"], optional = true }
|
||||||
# rocket = { git = "https://github.com/SergioBenitez/Rocket.git", rev = "801e04bd5369eb39e126c75f6d11e1e9597304d8", features = ["tls"] } # Used to handle requests
|
axum-server = { version = "0.3.3", features = ["tls-rustls"] }
|
||||||
rocket = { version = "0.5.0-rc.1", features = ["tls"] } # Used to handle requests
|
tower = { version = "0.4.11", features = ["util"] }
|
||||||
|
tower-http = { version = "0.2.1", features = ["add-extension", "cors", "compression-full", "sensitive-headers", "trace", "util"] }
|
||||||
|
|
||||||
# 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 = "f7a10a7e471b59d3096be2695c2a05d407d80df1", 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 = "f130d09daabf021ad30750eed89483a0f45f820a", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-msc2448", "unstable-pre-spec", "unstable-exhaustive-types"] }
|
||||||
#ruma = { git = "https://github.com/timokoesters/ruma", rev = "50c1db7e0a3a21fc794b0cce3b64285a4c750c71", 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/timokoesters/ruma", rev = "50c1db7e0a3a21fc794b0cce3b64285a4c750c71", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
|
||||||
#ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
|
#ruma = { path = "../ruma/crates/ruma", features = ["compat", "rand", "appservice-api-c", "client-api", "federation-api", "push-gateway-api-c", "state-res", "unstable-pre-spec", "unstable-exhaustive-types"] }
|
||||||
|
|
||||||
# Used for long polling and federation sender, should be the same as rocket::tokio
|
# Async runtime and utilities
|
||||||
tokio = "1.11.0"
|
tokio = { version = "1.11.0", features = ["fs", "macros", "signal", "sync"] }
|
||||||
# Used for storing data permanently
|
# Used for storing data permanently
|
||||||
sled = { version = "0.34.6", features = ["compression", "no_metrics"], optional = true }
|
sled = { version = "0.34.6", features = ["compression", "no_metrics"], optional = true }
|
||||||
#sled = { git = "https://github.com/spacejam/sled.git", rev = "e4640e0773595229f398438886f19bca6f7326a2", features = ["compression"] }
|
#sled = { git = "https://github.com/spacejam/sled.git", rev = "e4640e0773595229f398438886f19bca6f7326a2", features = ["compression"] }
|
||||||
|
@ -33,7 +34,6 @@ persy = { version = "1.2" , optional = true, features=["background_ops"] }
|
||||||
|
|
||||||
# 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.1.0"
|
bytes = "1.1.0"
|
||||||
# Used for rocket<->ruma conversions
|
|
||||||
http = "0.2.4"
|
http = "0.2.4"
|
||||||
# Used to find data directory for default db path
|
# Used to find data directory for default db path
|
||||||
directories = "3.0.2"
|
directories = "3.0.2"
|
||||||
|
@ -84,7 +84,9 @@ hmac = "0.11.0"
|
||||||
sha-1 = "0.9.8"
|
sha-1 = "0.9.8"
|
||||||
# used for conduit's CLI and admin room command parsing
|
# used for conduit's CLI and admin room command parsing
|
||||||
clap = { version = "3.0.10", default-features = false, features = ["std", "derive"] }
|
clap = { version = "3.0.10", default-features = false, features = ["std", "derive"] }
|
||||||
maplit = "1.0.2"
|
futures-util = { version = "0.3.19", default-features = false }
|
||||||
|
# Used for reading the configuration from conduit.toml & environment variables
|
||||||
|
figment = { version = "0.10.6", features = ["env", "toml"] }
|
||||||
|
|
||||||
tikv-jemalloc-ctl = { version = "0.4.2", features = ["use_std"], optional = true }
|
tikv-jemalloc-ctl = { version = "0.4.2", features = ["use_std"], optional = true }
|
||||||
tikv-jemallocator = { version = "0.4.1", features = ["unprefixed_malloc_on_supported_platforms"], optional = true }
|
tikv-jemallocator = { version = "0.4.1", features = ["unprefixed_malloc_on_supported_platforms"], optional = true }
|
||||||
|
@ -98,7 +100,7 @@ backend_heed = ["heed", "crossbeam"]
|
||||||
backend_rocksdb = ["rocksdb"]
|
backend_rocksdb = ["rocksdb"]
|
||||||
jemalloc = ["tikv-jemalloc-ctl", "tikv-jemallocator"]
|
jemalloc = ["tikv-jemalloc-ctl", "tikv-jemallocator"]
|
||||||
sqlite = ["rusqlite", "parking_lot", "tokio/signal"]
|
sqlite = ["rusqlite", "parking_lot", "tokio/signal"]
|
||||||
conduit_bin = [] # TODO: add rocket to this when it is optional
|
conduit_bin = ["axum"]
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "conduit"
|
name = "conduit"
|
||||||
|
|
|
@ -54,7 +54,7 @@ Thanks to Famedly, Prototype Fund (DLR and German BMBF) and all other individual
|
||||||
Thanks to the contributors to Conduit and all libraries we use, for example:
|
Thanks to the contributors to Conduit and all libraries we use, for example:
|
||||||
|
|
||||||
- Ruma: A clean library for the Matrix Spec in Rust
|
- Ruma: A clean library for the Matrix Spec in Rust
|
||||||
- Rocket: A flexible web framework
|
- axum: A modular web framework
|
||||||
|
|
||||||
#### Donate
|
#### Donate
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ allow_registration = true
|
||||||
trusted_servers = ["matrix.org"]
|
trusted_servers = ["matrix.org"]
|
||||||
|
|
||||||
#max_concurrent_requests = 100 # How many requests Conduit sends to other servers at the same time
|
#max_concurrent_requests = 100 # How many requests Conduit sends to other servers at the same time
|
||||||
#log = "info,state_res=warn,rocket=off,_=off,sled=off"
|
#log = "info,state_res=warn,_=off,sled=off"
|
||||||
#workers = 4 # default: cpu core count * 2
|
#workers = 4 # default: cpu core count * 2
|
||||||
|
|
||||||
address = "127.0.0.1" # This makes sure Conduit can only be reached using the reverse proxy
|
address = "127.0.0.1" # This makes sure Conduit can only be reached using the reverse proxy
|
||||||
|
|
2
debian/postinst
vendored
2
debian/postinst
vendored
|
@ -74,7 +74,7 @@ allow_registration = true
|
||||||
#allow_jaeger = false
|
#allow_jaeger = false
|
||||||
|
|
||||||
#max_concurrent_requests = 100 # How many requests Conduit sends to other servers at the same time
|
#max_concurrent_requests = 100 # How many requests Conduit sends to other servers at the same time
|
||||||
#log = "info,state_res=warn,rocket=off,_=off,sled=off"
|
#log = "info,state_res=warn,_=off,sled=off"
|
||||||
#workers = 4 # default: cpu core count * 2
|
#workers = 4 # default: cpu core count * 2
|
||||||
|
|
||||||
# The total amount of memory that the database will use.
|
# The total amount of memory that the database will use.
|
||||||
|
|
|
@ -33,7 +33,7 @@ services:
|
||||||
# CONDUIT_PORT: 6167
|
# CONDUIT_PORT: 6167
|
||||||
# CONDUIT_CONFIG: '/srv/conduit/conduit.toml' # if you want to configure purely by env vars, set this to an empty string ''
|
# CONDUIT_CONFIG: '/srv/conduit/conduit.toml' # if you want to configure purely by env vars, set this to an empty string ''
|
||||||
# Available levels are: error, warn, info, debug, trace - more info at: https://docs.rs/env_logger/*/env_logger/#enabling-logging
|
# Available levels are: error, warn, info, debug, trace - more info at: https://docs.rs/env_logger/*/env_logger/#enabling-logging
|
||||||
# CONDUIT_LOG: info # default is: "info,rocket=off,_=off,sled=off"
|
# CONDUIT_LOG: info # default is: "info,_=off,sled=off"
|
||||||
# CONDUIT_ALLOW_JAEGER: 'false'
|
# CONDUIT_ALLOW_JAEGER: 'false'
|
||||||
# CONDUIT_ALLOW_ENCRYPTION: 'false'
|
# CONDUIT_ALLOW_ENCRYPTION: 'false'
|
||||||
# CONDUIT_ALLOW_FEDERATION: 'false'
|
# CONDUIT_ALLOW_FEDERATION: 'false'
|
||||||
|
|
|
@ -33,7 +33,7 @@ services:
|
||||||
# CONDUIT_PORT: 6167
|
# CONDUIT_PORT: 6167
|
||||||
# CONDUIT_CONFIG: '/srv/conduit/conduit.toml' # if you want to configure purely by env vars, set this to an empty string ''
|
# CONDUIT_CONFIG: '/srv/conduit/conduit.toml' # if you want to configure purely by env vars, set this to an empty string ''
|
||||||
# Available levels are: error, warn, info, debug, trace - more info at: https://docs.rs/env_logger/*/env_logger/#enabling-logging
|
# Available levels are: error, warn, info, debug, trace - more info at: https://docs.rs/env_logger/*/env_logger/#enabling-logging
|
||||||
# CONDUIT_LOG: info # default is: "info,rocket=off,_=off,sled=off"
|
# CONDUIT_LOG: info # default is: "info,_=off,sled=off"
|
||||||
# CONDUIT_ALLOW_JAEGER: 'false'
|
# CONDUIT_ALLOW_JAEGER: 'false'
|
||||||
# CONDUIT_ALLOW_ENCRYPTION: 'false'
|
# CONDUIT_ALLOW_ENCRYPTION: 'false'
|
||||||
# CONDUIT_ALLOW_FEDERATION: 'false'
|
# CONDUIT_ALLOW_FEDERATION: 'false'
|
||||||
|
|
|
@ -4,7 +4,7 @@ use super::{DEVICE_ID_LENGTH, SESSION_ID_LENGTH, TOKEN_LENGTH};
|
||||||
use crate::{
|
use crate::{
|
||||||
database::{admin::make_user_admin, DatabaseGuard},
|
database::{admin::make_user_admin, DatabaseGuard},
|
||||||
pdu::PduBuilder,
|
pdu::PduBuilder,
|
||||||
utils, ConduitResult, Error, Ruma,
|
utils, Error, Result, Ruma,
|
||||||
};
|
};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::{
|
api::client::{
|
||||||
|
@ -27,8 +27,6 @@ use serde_json::value::to_raw_value;
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
use register::RegistrationKind;
|
use register::RegistrationKind;
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{get, post};
|
|
||||||
|
|
||||||
const GUEST_NAME_LENGTH: usize = 10;
|
const GUEST_NAME_LENGTH: usize = 10;
|
||||||
|
|
||||||
|
@ -42,15 +40,11 @@ const GUEST_NAME_LENGTH: usize = 10;
|
||||||
/// - No user or appservice on this server already claimed this username
|
/// - No user or appservice on this server already claimed this username
|
||||||
///
|
///
|
||||||
/// Note: This will not reserve the username, so the username might become invalid when trying to register
|
/// Note: This will not reserve the username, so the username might become invalid when trying to register
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/register/available", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_register_available_route(
|
pub async fn get_register_available_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_username_availability::Request<'_>>,
|
body: Ruma<get_username_availability::Request<'_>>,
|
||||||
) -> ConduitResult<get_username_availability::Response> {
|
) -> Result<get_username_availability::Response> {
|
||||||
// Validate user id
|
// Validate user id
|
||||||
let user_id =
|
let user_id =
|
||||||
UserId::parse_with_server_name(body.username.to_lowercase(), db.globals.server_name())
|
UserId::parse_with_server_name(body.username.to_lowercase(), db.globals.server_name())
|
||||||
|
@ -74,7 +68,7 @@ pub async fn get_register_available_route(
|
||||||
// TODO add check for appservice namespaces
|
// TODO add check for appservice namespaces
|
||||||
|
|
||||||
// If no if check is true we have an username that's available to be used.
|
// If no if check is true we have an username that's available to be used.
|
||||||
Ok(get_username_availability::Response { available: true }.into())
|
Ok(get_username_availability::Response { available: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/register`
|
/// # `POST /_matrix/client/r0/register`
|
||||||
|
@ -90,15 +84,11 @@ pub async fn get_register_available_route(
|
||||||
/// - If type is not guest and no username is given: Always fails after UIAA check
|
/// - If type is not guest and no username is given: Always fails after UIAA check
|
||||||
/// - Creates a new account and populates it with default account data
|
/// - Creates a new account and populates it with default account data
|
||||||
/// - If `inhibit_login` is false: Creates a device and returns device id and access_token
|
/// - If `inhibit_login` is false: Creates a device and returns device id and access_token
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/register", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn register_route(
|
pub async fn register_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<register::Request<'_>>,
|
body: Ruma<register::Request<'_>>,
|
||||||
) -> ConduitResult<register::Response> {
|
) -> Result<register::Response> {
|
||||||
if !db.globals.allow_registration() && !body.from_appservice {
|
if !db.globals.allow_registration() && !body.from_appservice {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::Forbidden,
|
ErrorKind::Forbidden,
|
||||||
|
@ -222,8 +212,7 @@ pub async fn register_route(
|
||||||
access_token: None,
|
access_token: None,
|
||||||
user_id,
|
user_id,
|
||||||
device_id: None,
|
device_id: None,
|
||||||
}
|
});
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate new device id if the user didn't specify one
|
// Generate new device id if the user didn't specify one
|
||||||
|
@ -261,8 +250,7 @@ pub async fn register_route(
|
||||||
access_token: Some(token),
|
access_token: Some(token),
|
||||||
user_id,
|
user_id,
|
||||||
device_id: Some(device_id),
|
device_id: Some(device_id),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/account/password`
|
/// # `POST /_matrix/client/r0/account/password`
|
||||||
|
@ -279,15 +267,11 @@ pub async fn register_route(
|
||||||
/// - Deletes device metadata (device id, device display name, last seen ip, last seen ts)
|
/// - Deletes device metadata (device id, device display name, last seen ip, last seen ts)
|
||||||
/// - Forgets to-device events
|
/// - Forgets to-device events
|
||||||
/// - Triggers device list updates
|
/// - Triggers device list updates
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/account/password", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn change_password_route(
|
pub async fn change_password_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<change_password::Request<'_>>,
|
body: Ruma<change_password::Request<'_>>,
|
||||||
) -> ConduitResult<change_password::Response> {
|
) -> Result<change_password::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
|
@ -340,7 +324,7 @@ pub async fn change_password_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(change_password::Response {}.into())
|
Ok(change_password::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET _matrix/client/r0/account/whoami`
|
/// # `GET _matrix/client/r0/account/whoami`
|
||||||
|
@ -348,17 +332,12 @@ pub async fn change_password_route(
|
||||||
/// Get user_id of the sender user.
|
/// Get user_id of the sender user.
|
||||||
///
|
///
|
||||||
/// Note: Also works for Application Services
|
/// Note: Also works for Application Services
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/account/whoami", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(body))]
|
#[tracing::instrument(skip(body))]
|
||||||
pub async fn whoami_route(body: Ruma<whoami::Request>) -> ConduitResult<whoami::Response> {
|
pub async fn whoami_route(body: Ruma<whoami::Request>) -> Result<whoami::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
Ok(whoami::Response {
|
Ok(whoami::Response {
|
||||||
user_id: sender_user.clone(),
|
user_id: sender_user.clone(),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/account/deactivate`
|
/// # `POST /_matrix/client/r0/account/deactivate`
|
||||||
|
@ -371,15 +350,11 @@ pub async fn whoami_route(body: Ruma<whoami::Request>) -> ConduitResult<whoami::
|
||||||
/// - Forgets all to-device events
|
/// - Forgets all to-device events
|
||||||
/// - Triggers device list updates
|
/// - Triggers device list updates
|
||||||
/// - Removes ability to log in again
|
/// - Removes ability to log in again
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/account/deactivate", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn deactivate_route(
|
pub async fn deactivate_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<deactivate::Request<'_>>,
|
body: Ruma<deactivate::Request<'_>>,
|
||||||
) -> ConduitResult<deactivate::Response> {
|
) -> Result<deactivate::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
|
@ -474,8 +449,7 @@ pub async fn deactivate_route(
|
||||||
|
|
||||||
Ok(deactivate::Response {
|
Ok(deactivate::Response {
|
||||||
id_server_unbind_result: ThirdPartyIdRemovalStatus::NoSupport,
|
id_server_unbind_result: ThirdPartyIdRemovalStatus::NoSupport,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET _matrix/client/r0/account/3pid`
|
/// # `GET _matrix/client/r0/account/3pid`
|
||||||
|
@ -483,14 +457,8 @@ pub async fn deactivate_route(
|
||||||
/// Get a list of third party identifiers associated with this account.
|
/// Get a list of third party identifiers associated with this account.
|
||||||
///
|
///
|
||||||
/// - Currently always returns empty list
|
/// - Currently always returns empty list
|
||||||
#[cfg_attr(
|
pub async fn third_party_route(body: Ruma<get_3pids::Request>) -> Result<get_3pids::Response> {
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/account/3pid", data = "<body>")
|
|
||||||
)]
|
|
||||||
pub async fn third_party_route(
|
|
||||||
body: Ruma<get_3pids::Request>,
|
|
||||||
) -> ConduitResult<get_3pids::Response> {
|
|
||||||
let _sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let _sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
Ok(get_3pids::Response::new(Vec::new()).into())
|
Ok(get_3pids::Response::new(Vec::new()))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{database::DatabaseGuard, ConduitResult, Database, Error, Ruma};
|
use crate::{database::DatabaseGuard, Database, Error, Result, Ruma};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::{
|
api::{
|
||||||
|
@ -12,21 +12,14 @@ use ruma::{
|
||||||
RoomAliasId,
|
RoomAliasId,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{delete, get, put};
|
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/directory/room/{roomAlias}`
|
/// # `PUT /_matrix/client/r0/directory/room/{roomAlias}`
|
||||||
///
|
///
|
||||||
/// Creates a new room alias on this server.
|
/// Creates a new room alias on this server.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/directory/room/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn create_alias_route(
|
pub async fn create_alias_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<create_alias::Request<'_>>,
|
body: Ruma<create_alias::Request<'_>>,
|
||||||
) -> ConduitResult<create_alias::Response> {
|
) -> Result<create_alias::Response> {
|
||||||
if body.room_alias.server_name() != db.globals.server_name() {
|
if body.room_alias.server_name() != db.globals.server_name() {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
|
@ -43,7 +36,7 @@ pub async fn create_alias_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(create_alias::Response::new().into())
|
Ok(create_alias::Response::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `DELETE /_matrix/client/r0/directory/room/{roomAlias}`
|
/// # `DELETE /_matrix/client/r0/directory/room/{roomAlias}`
|
||||||
|
@ -52,15 +45,11 @@ pub async fn create_alias_route(
|
||||||
///
|
///
|
||||||
/// - TODO: additional access control checks
|
/// - TODO: additional access control checks
|
||||||
/// - TODO: Update canonical alias event
|
/// - TODO: Update canonical alias event
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
delete("/_matrix/client/r0/directory/room/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn delete_alias_route(
|
pub async fn delete_alias_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<delete_alias::Request<'_>>,
|
body: Ruma<delete_alias::Request<'_>>,
|
||||||
) -> ConduitResult<delete_alias::Response> {
|
) -> Result<delete_alias::Response> {
|
||||||
if body.room_alias.server_name() != db.globals.server_name() {
|
if body.room_alias.server_name() != db.globals.server_name() {
|
||||||
return Err(Error::BadRequest(
|
return Err(Error::BadRequest(
|
||||||
ErrorKind::InvalidParam,
|
ErrorKind::InvalidParam,
|
||||||
|
@ -74,7 +63,7 @@ pub async fn delete_alias_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(delete_alias::Response::new().into())
|
Ok(delete_alias::Response::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/directory/room/{roomAlias}`
|
/// # `GET /_matrix/client/r0/directory/room/{roomAlias}`
|
||||||
|
@ -82,22 +71,18 @@ pub async fn delete_alias_route(
|
||||||
/// Resolve an alias locally or over federation.
|
/// Resolve an alias locally or over federation.
|
||||||
///
|
///
|
||||||
/// - TODO: Suggest more servers to join via
|
/// - TODO: Suggest more servers to join via
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/directory/room/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_alias_route(
|
pub async fn get_alias_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_alias::Request<'_>>,
|
body: Ruma<get_alias::Request<'_>>,
|
||||||
) -> ConduitResult<get_alias::Response> {
|
) -> Result<get_alias::Response> {
|
||||||
get_alias_helper(&db, &body.room_alias).await
|
get_alias_helper(&db, &body.room_alias).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn get_alias_helper(
|
pub(crate) async fn get_alias_helper(
|
||||||
db: &Database,
|
db: &Database,
|
||||||
room_alias: &RoomAliasId,
|
room_alias: &RoomAliasId,
|
||||||
) -> ConduitResult<get_alias::Response> {
|
) -> Result<get_alias::Response> {
|
||||||
if room_alias.server_name() != db.globals.server_name() {
|
if room_alias.server_name() != db.globals.server_name() {
|
||||||
let response = db
|
let response = db
|
||||||
.sending
|
.sending
|
||||||
|
@ -108,7 +93,7 @@ pub(crate) async fn get_alias_helper(
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
return Ok(get_alias::Response::new(response.room_id, response.servers).into());
|
return Ok(get_alias::Response::new(response.room_id, response.servers));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut room_id = None;
|
let mut room_id = None;
|
||||||
|
@ -159,5 +144,8 @@ pub(crate) async fn get_alias_helper(
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(get_alias::Response::new(room_id, vec![db.globals.server_name().to_owned()]).into())
|
Ok(get_alias::Response::new(
|
||||||
|
room_id,
|
||||||
|
vec![db.globals.server_name().to_owned()],
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{database::DatabaseGuard, ConduitResult, Error, Ruma};
|
use crate::{database::DatabaseGuard, Error, Result, Ruma};
|
||||||
use ruma::api::client::{
|
use ruma::api::client::{
|
||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
r0::backup::{
|
r0::backup::{
|
||||||
|
@ -9,21 +9,14 @@ use ruma::api::client::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{delete, get, post, put};
|
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/room_keys/version`
|
/// # `POST /_matrix/client/r0/room_keys/version`
|
||||||
///
|
///
|
||||||
/// Creates a new backup.
|
/// Creates a new backup.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/unstable/room_keys/version", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn create_backup_route(
|
pub async fn create_backup_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<create_backup::Request>,
|
body: Ruma<create_backup::Request>,
|
||||||
) -> ConduitResult<create_backup::Response> {
|
) -> Result<create_backup::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let version = db
|
let version = db
|
||||||
.key_backups
|
.key_backups
|
||||||
|
@ -31,42 +24,34 @@ pub async fn create_backup_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(create_backup::Response { version }.into())
|
Ok(create_backup::Response { version })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/room_keys/version/{version}`
|
/// # `PUT /_matrix/client/r0/room_keys/version/{version}`
|
||||||
///
|
///
|
||||||
/// Update information about an existing backup. Only `auth_data` can be modified.
|
/// Update information about an existing backup. Only `auth_data` can be modified.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/unstable/room_keys/version/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn update_backup_route(
|
pub async fn update_backup_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<update_backup::Request<'_>>,
|
body: Ruma<update_backup::Request<'_>>,
|
||||||
) -> ConduitResult<update_backup::Response> {
|
) -> Result<update_backup::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
db.key_backups
|
db.key_backups
|
||||||
.update_backup(sender_user, &body.version, &body.algorithm, &db.globals)?;
|
.update_backup(sender_user, &body.version, &body.algorithm, &db.globals)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(update_backup::Response {}.into())
|
Ok(update_backup::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/room_keys/version`
|
/// # `GET /_matrix/client/r0/room_keys/version`
|
||||||
///
|
///
|
||||||
/// Get information about the latest backup version.
|
/// Get information about the latest backup version.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/unstable/room_keys/version", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_latest_backup_route(
|
pub async fn get_latest_backup_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_latest_backup::Request>,
|
body: Ruma<get_latest_backup::Request>,
|
||||||
) -> ConduitResult<get_latest_backup::Response> {
|
) -> Result<get_latest_backup::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let (version, algorithm) =
|
let (version, algorithm) =
|
||||||
|
@ -82,22 +67,17 @@ pub async fn get_latest_backup_route(
|
||||||
count: (db.key_backups.count_keys(sender_user, &version)? as u32).into(),
|
count: (db.key_backups.count_keys(sender_user, &version)? as u32).into(),
|
||||||
etag: db.key_backups.get_etag(sender_user, &version)?,
|
etag: db.key_backups.get_etag(sender_user, &version)?,
|
||||||
version,
|
version,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/room_keys/version`
|
/// # `GET /_matrix/client/r0/room_keys/version`
|
||||||
///
|
///
|
||||||
/// Get information about an existing backup.
|
/// Get information about an existing backup.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/unstable/room_keys/version/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_backup_route(
|
pub async fn get_backup_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_backup::Request<'_>>,
|
body: Ruma<get_backup::Request<'_>>,
|
||||||
) -> ConduitResult<get_backup::Response> {
|
) -> Result<get_backup::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let algorithm = db
|
let algorithm = db
|
||||||
.key_backups
|
.key_backups
|
||||||
|
@ -112,8 +92,7 @@ pub async fn get_backup_route(
|
||||||
count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(),
|
count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(),
|
||||||
etag: db.key_backups.get_etag(sender_user, &body.version)?,
|
etag: db.key_backups.get_etag(sender_user, &body.version)?,
|
||||||
version: body.version.to_owned(),
|
version: body.version.to_owned(),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `DELETE /_matrix/client/r0/room_keys/version/{version}`
|
/// # `DELETE /_matrix/client/r0/room_keys/version/{version}`
|
||||||
|
@ -121,22 +100,18 @@ pub async fn get_backup_route(
|
||||||
/// Delete an existing key backup.
|
/// Delete an existing key backup.
|
||||||
///
|
///
|
||||||
/// - Deletes both information about the backup, as well as all key data related to the backup
|
/// - Deletes both information about the backup, as well as all key data related to the backup
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
delete("/_matrix/client/unstable/room_keys/version/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn delete_backup_route(
|
pub async fn delete_backup_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<delete_backup::Request<'_>>,
|
body: Ruma<delete_backup::Request<'_>>,
|
||||||
) -> ConduitResult<delete_backup::Response> {
|
) -> Result<delete_backup::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
db.key_backups.delete_backup(sender_user, &body.version)?;
|
db.key_backups.delete_backup(sender_user, &body.version)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(delete_backup::Response {}.into())
|
Ok(delete_backup::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/room_keys/keys`
|
/// # `PUT /_matrix/client/r0/room_keys/keys`
|
||||||
|
@ -146,15 +121,11 @@ pub async fn delete_backup_route(
|
||||||
/// - Only manipulating the most recently created version of the backup is allowed
|
/// - Only manipulating the most recently created version of the backup is allowed
|
||||||
/// - Adds the keys to the backup
|
/// - Adds the keys to the backup
|
||||||
/// - Returns the new number of keys in this backup and the etag
|
/// - Returns the new number of keys in this backup and the etag
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/unstable/room_keys/keys", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn add_backup_keys_route(
|
pub async fn add_backup_keys_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<add_backup_keys::Request<'_>>,
|
body: Ruma<add_backup_keys::Request<'_>>,
|
||||||
) -> ConduitResult<add_backup_keys::Response> {
|
) -> Result<add_backup_keys::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
if Some(&body.version)
|
if Some(&body.version)
|
||||||
|
@ -187,8 +158,7 @@ pub async fn add_backup_keys_route(
|
||||||
Ok(add_backup_keys::Response {
|
Ok(add_backup_keys::Response {
|
||||||
count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(),
|
count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(),
|
||||||
etag: db.key_backups.get_etag(sender_user, &body.version)?,
|
etag: db.key_backups.get_etag(sender_user, &body.version)?,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/room_keys/keys/{roomId}`
|
/// # `PUT /_matrix/client/r0/room_keys/keys/{roomId}`
|
||||||
|
@ -198,15 +168,11 @@ pub async fn add_backup_keys_route(
|
||||||
/// - Only manipulating the most recently created version of the backup is allowed
|
/// - Only manipulating the most recently created version of the backup is allowed
|
||||||
/// - Adds the keys to the backup
|
/// - Adds the keys to the backup
|
||||||
/// - Returns the new number of keys in this backup and the etag
|
/// - Returns the new number of keys in this backup and the etag
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/unstable/room_keys/keys/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn add_backup_key_sessions_route(
|
pub async fn add_backup_key_sessions_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<add_backup_key_sessions::Request<'_>>,
|
body: Ruma<add_backup_key_sessions::Request<'_>>,
|
||||||
) -> ConduitResult<add_backup_key_sessions::Response> {
|
) -> Result<add_backup_key_sessions::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
if Some(&body.version)
|
if Some(&body.version)
|
||||||
|
@ -237,8 +203,7 @@ pub async fn add_backup_key_sessions_route(
|
||||||
Ok(add_backup_key_sessions::Response {
|
Ok(add_backup_key_sessions::Response {
|
||||||
count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(),
|
count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(),
|
||||||
etag: db.key_backups.get_etag(sender_user, &body.version)?,
|
etag: db.key_backups.get_etag(sender_user, &body.version)?,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/room_keys/keys/{roomId}/{sessionId}`
|
/// # `PUT /_matrix/client/r0/room_keys/keys/{roomId}/{sessionId}`
|
||||||
|
@ -248,15 +213,11 @@ pub async fn add_backup_key_sessions_route(
|
||||||
/// - Only manipulating the most recently created version of the backup is allowed
|
/// - Only manipulating the most recently created version of the backup is allowed
|
||||||
/// - Adds the keys to the backup
|
/// - Adds the keys to the backup
|
||||||
/// - Returns the new number of keys in this backup and the etag
|
/// - Returns the new number of keys in this backup and the etag
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/unstable/room_keys/keys/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn add_backup_key_session_route(
|
pub async fn add_backup_key_session_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<add_backup_key_session::Request<'_>>,
|
body: Ruma<add_backup_key_session::Request<'_>>,
|
||||||
) -> ConduitResult<add_backup_key_session::Response> {
|
) -> Result<add_backup_key_session::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
if Some(&body.version)
|
if Some(&body.version)
|
||||||
|
@ -285,62 +246,49 @@ pub async fn add_backup_key_session_route(
|
||||||
Ok(add_backup_key_session::Response {
|
Ok(add_backup_key_session::Response {
|
||||||
count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(),
|
count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(),
|
||||||
etag: db.key_backups.get_etag(sender_user, &body.version)?,
|
etag: db.key_backups.get_etag(sender_user, &body.version)?,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/room_keys/keys`
|
/// # `GET /_matrix/client/r0/room_keys/keys`
|
||||||
///
|
///
|
||||||
/// Retrieves all keys from the backup.
|
/// Retrieves all keys from the backup.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/unstable/room_keys/keys", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_backup_keys_route(
|
pub async fn get_backup_keys_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_backup_keys::Request<'_>>,
|
body: Ruma<get_backup_keys::Request<'_>>,
|
||||||
) -> ConduitResult<get_backup_keys::Response> {
|
) -> Result<get_backup_keys::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let rooms = db.key_backups.get_all(sender_user, &body.version)?;
|
let rooms = db.key_backups.get_all(sender_user, &body.version)?;
|
||||||
|
|
||||||
Ok(get_backup_keys::Response { rooms }.into())
|
Ok(get_backup_keys::Response { rooms })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/room_keys/keys/{roomId}`
|
/// # `GET /_matrix/client/r0/room_keys/keys/{roomId}`
|
||||||
///
|
///
|
||||||
/// Retrieves all keys from the backup for a given room.
|
/// Retrieves all keys from the backup for a given room.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/unstable/room_keys/keys/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_backup_key_sessions_route(
|
pub async fn get_backup_key_sessions_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_backup_key_sessions::Request<'_>>,
|
body: Ruma<get_backup_key_sessions::Request<'_>>,
|
||||||
) -> ConduitResult<get_backup_key_sessions::Response> {
|
) -> Result<get_backup_key_sessions::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let sessions = db
|
let sessions = db
|
||||||
.key_backups
|
.key_backups
|
||||||
.get_room(sender_user, &body.version, &body.room_id)?;
|
.get_room(sender_user, &body.version, &body.room_id)?;
|
||||||
|
|
||||||
Ok(get_backup_key_sessions::Response { sessions }.into())
|
Ok(get_backup_key_sessions::Response { sessions })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/room_keys/keys/{roomId}/{sessionId}`
|
/// # `GET /_matrix/client/r0/room_keys/keys/{roomId}/{sessionId}`
|
||||||
///
|
///
|
||||||
/// Retrieves a key from the backup.
|
/// Retrieves a key from the backup.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/unstable/room_keys/keys/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_backup_key_session_route(
|
pub async fn get_backup_key_session_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_backup_key_session::Request<'_>>,
|
body: Ruma<get_backup_key_session::Request<'_>>,
|
||||||
) -> ConduitResult<get_backup_key_session::Response> {
|
) -> Result<get_backup_key_session::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let key_data = db
|
let key_data = db
|
||||||
|
@ -351,21 +299,17 @@ pub async fn get_backup_key_session_route(
|
||||||
"Backup key not found for this user's session.",
|
"Backup key not found for this user's session.",
|
||||||
))?;
|
))?;
|
||||||
|
|
||||||
Ok(get_backup_key_session::Response { key_data }.into())
|
Ok(get_backup_key_session::Response { key_data })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `DELETE /_matrix/client/r0/room_keys/keys`
|
/// # `DELETE /_matrix/client/r0/room_keys/keys`
|
||||||
///
|
///
|
||||||
/// Delete the keys from the backup.
|
/// Delete the keys from the backup.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
delete("/_matrix/client/unstable/room_keys/keys", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn delete_backup_keys_route(
|
pub async fn delete_backup_keys_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<delete_backup_keys::Request<'_>>,
|
body: Ruma<delete_backup_keys::Request<'_>>,
|
||||||
) -> ConduitResult<delete_backup_keys::Response> {
|
) -> Result<delete_backup_keys::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
db.key_backups.delete_all_keys(sender_user, &body.version)?;
|
db.key_backups.delete_all_keys(sender_user, &body.version)?;
|
||||||
|
@ -375,22 +319,17 @@ pub async fn delete_backup_keys_route(
|
||||||
Ok(delete_backup_keys::Response {
|
Ok(delete_backup_keys::Response {
|
||||||
count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(),
|
count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(),
|
||||||
etag: db.key_backups.get_etag(sender_user, &body.version)?,
|
etag: db.key_backups.get_etag(sender_user, &body.version)?,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `DELETE /_matrix/client/r0/room_keys/keys/{roomId}`
|
/// # `DELETE /_matrix/client/r0/room_keys/keys/{roomId}`
|
||||||
///
|
///
|
||||||
/// Delete the keys from the backup for a given room.
|
/// Delete the keys from the backup for a given room.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
delete("/_matrix/client/unstable/room_keys/keys/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn delete_backup_key_sessions_route(
|
pub async fn delete_backup_key_sessions_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<delete_backup_key_sessions::Request<'_>>,
|
body: Ruma<delete_backup_key_sessions::Request<'_>>,
|
||||||
) -> ConduitResult<delete_backup_key_sessions::Response> {
|
) -> Result<delete_backup_key_sessions::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
db.key_backups
|
db.key_backups
|
||||||
|
@ -401,22 +340,17 @@ pub async fn delete_backup_key_sessions_route(
|
||||||
Ok(delete_backup_key_sessions::Response {
|
Ok(delete_backup_key_sessions::Response {
|
||||||
count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(),
|
count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(),
|
||||||
etag: db.key_backups.get_etag(sender_user, &body.version)?,
|
etag: db.key_backups.get_etag(sender_user, &body.version)?,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `DELETE /_matrix/client/r0/room_keys/keys/{roomId}/{sessionId}`
|
/// # `DELETE /_matrix/client/r0/room_keys/keys/{roomId}/{sessionId}`
|
||||||
///
|
///
|
||||||
/// Delete a key from the backup.
|
/// Delete a key from the backup.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
delete("/_matrix/client/unstable/room_keys/keys/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn delete_backup_key_session_route(
|
pub async fn delete_backup_key_session_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<delete_backup_key_session::Request<'_>>,
|
body: Ruma<delete_backup_key_session::Request<'_>>,
|
||||||
) -> ConduitResult<delete_backup_key_session::Response> {
|
) -> Result<delete_backup_key_session::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
db.key_backups
|
db.key_backups
|
||||||
|
@ -427,6 +361,5 @@ pub async fn delete_backup_key_session_route(
|
||||||
Ok(delete_backup_key_session::Response {
|
Ok(delete_backup_key_session::Response {
|
||||||
count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(),
|
count: (db.key_backups.count_keys(sender_user, &body.version)? as u32).into(),
|
||||||
etag: db.key_backups.get_etag(sender_user, &body.version)?,
|
etag: db.key_backups.get_etag(sender_user, &body.version)?,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{ConduitResult, Ruma};
|
use crate::{Result, Ruma};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::r0::capabilities::{
|
api::client::r0::capabilities::{
|
||||||
get_capabilities, Capabilities, RoomVersionStability, RoomVersionsCapability,
|
get_capabilities, Capabilities, RoomVersionStability, RoomVersionsCapability,
|
||||||
|
@ -7,20 +7,13 @@ use ruma::{
|
||||||
};
|
};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::get;
|
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/capabilities`
|
/// # `GET /_matrix/client/r0/capabilities`
|
||||||
///
|
///
|
||||||
/// Get information on the supported feature set and other relevent capabilities of this server.
|
/// Get information on the supported feature set and other relevent capabilities of this server.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/capabilities", data = "<_body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(_body))]
|
#[tracing::instrument(skip(_body))]
|
||||||
pub async fn get_capabilities_route(
|
pub async fn get_capabilities_route(
|
||||||
_body: Ruma<get_capabilities::Request>,
|
_body: Ruma<get_capabilities::Request>,
|
||||||
) -> ConduitResult<get_capabilities::Response> {
|
) -> Result<get_capabilities::Response> {
|
||||||
let mut available = BTreeMap::new();
|
let mut available = BTreeMap::new();
|
||||||
available.insert(RoomVersionId::V5, RoomVersionStability::Stable);
|
available.insert(RoomVersionId::V5, RoomVersionStability::Stable);
|
||||||
available.insert(RoomVersionId::V6, RoomVersionStability::Stable);
|
available.insert(RoomVersionId::V6, RoomVersionStability::Stable);
|
||||||
|
@ -31,5 +24,5 @@ pub async fn get_capabilities_route(
|
||||||
available,
|
available,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(get_capabilities::Response { capabilities }.into())
|
Ok(get_capabilities::Response { capabilities })
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{database::DatabaseGuard, ConduitResult, Error, Ruma};
|
use crate::{database::DatabaseGuard, Error, Result, Ruma};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::{
|
api::client::{
|
||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
|
@ -13,21 +13,14 @@ use ruma::{
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_json::{json, value::RawValue as RawJsonValue};
|
use serde_json::{json, value::RawValue as RawJsonValue};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{get, put};
|
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/user/{userId}/account_data/{type}`
|
/// # `PUT /_matrix/client/r0/user/{userId}/account_data/{type}`
|
||||||
///
|
///
|
||||||
/// Sets some account data for the sender user.
|
/// Sets some account data for the sender user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/user/<_>/account_data/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn set_global_account_data_route(
|
pub async fn set_global_account_data_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<set_global_account_data::Request<'_>>,
|
body: Ruma<set_global_account_data::Request<'_>>,
|
||||||
) -> ConduitResult<set_global_account_data::Response> {
|
) -> Result<set_global_account_data::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let data: serde_json::Value = serde_json::from_str(body.data.get())
|
let data: serde_json::Value = serde_json::from_str(body.data.get())
|
||||||
|
@ -48,24 +41,17 @@ pub async fn set_global_account_data_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(set_global_account_data::Response {}.into())
|
Ok(set_global_account_data::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/user/{userId}/rooms/{roomId}/account_data/{type}`
|
/// # `PUT /_matrix/client/r0/user/{userId}/rooms/{roomId}/account_data/{type}`
|
||||||
///
|
///
|
||||||
/// Sets some room account data for the sender user.
|
/// Sets some room account data for the sender user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put(
|
|
||||||
"/_matrix/client/r0/user/<_>/rooms/<_>/account_data/<_>",
|
|
||||||
data = "<body>"
|
|
||||||
)
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn set_room_account_data_route(
|
pub async fn set_room_account_data_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<set_room_account_data::Request<'_>>,
|
body: Ruma<set_room_account_data::Request<'_>>,
|
||||||
) -> ConduitResult<set_room_account_data::Response> {
|
) -> Result<set_room_account_data::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let data: serde_json::Value = serde_json::from_str(body.data.get())
|
let data: serde_json::Value = serde_json::from_str(body.data.get())
|
||||||
|
@ -86,21 +72,17 @@ pub async fn set_room_account_data_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(set_room_account_data::Response {}.into())
|
Ok(set_room_account_data::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/user/{userId}/account_data/{type}`
|
/// # `GET /_matrix/client/r0/user/{userId}/account_data/{type}`
|
||||||
///
|
///
|
||||||
/// Gets some account data for the sender user.
|
/// Gets some account data for the sender user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/user/<_>/account_data/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_global_account_data_route(
|
pub async fn get_global_account_data_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_global_account_data::Request<'_>>,
|
body: Ruma<get_global_account_data::Request<'_>>,
|
||||||
) -> ConduitResult<get_global_account_data::Response> {
|
) -> Result<get_global_account_data::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let event: Box<RawJsonValue> = db
|
let event: Box<RawJsonValue> = db
|
||||||
|
@ -112,24 +94,17 @@ pub async fn get_global_account_data_route(
|
||||||
.map_err(|_| Error::bad_database("Invalid account data event in db."))?
|
.map_err(|_| Error::bad_database("Invalid account data event in db."))?
|
||||||
.content;
|
.content;
|
||||||
|
|
||||||
Ok(get_global_account_data::Response { account_data }.into())
|
Ok(get_global_account_data::Response { account_data })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/user/{userId}/rooms/{roomId}/account_data/{type}`
|
/// # `GET /_matrix/client/r0/user/{userId}/rooms/{roomId}/account_data/{type}`
|
||||||
///
|
///
|
||||||
/// Gets some room account data for the sender user.
|
/// Gets some room account data for the sender user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get(
|
|
||||||
"/_matrix/client/r0/user/<_>/rooms/<_>/account_data/<_>",
|
|
||||||
data = "<body>"
|
|
||||||
)
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_room_account_data_route(
|
pub async fn get_room_account_data_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_room_account_data::Request<'_>>,
|
body: Ruma<get_room_account_data::Request<'_>>,
|
||||||
) -> ConduitResult<get_room_account_data::Response> {
|
) -> Result<get_room_account_data::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let event: Box<RawJsonValue> = db
|
let event: Box<RawJsonValue> = db
|
||||||
|
@ -145,7 +120,7 @@ pub async fn get_room_account_data_route(
|
||||||
.map_err(|_| Error::bad_database("Invalid account data event in db."))?
|
.map_err(|_| Error::bad_database("Invalid account data event in db."))?
|
||||||
.content;
|
.content;
|
||||||
|
|
||||||
Ok(get_room_account_data::Response { account_data }.into())
|
Ok(get_room_account_data::Response { account_data })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{database::DatabaseGuard, ConduitResult, Error, Ruma};
|
use crate::{database::DatabaseGuard, Error, Result, Ruma};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::{
|
api::client::{
|
||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
|
@ -9,34 +9,24 @@ use ruma::{
|
||||||
use std::{collections::HashSet, convert::TryFrom};
|
use std::{collections::HashSet, convert::TryFrom};
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::get;
|
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/rooms/{roomId}/context`
|
/// # `GET /_matrix/client/r0/rooms/{roomId}/context`
|
||||||
///
|
///
|
||||||
/// Allows loading room history around an event.
|
/// Allows loading room history around an event.
|
||||||
///
|
///
|
||||||
/// - Only works if the user is joined (TODO: always allow, but only show events if the user was
|
/// - Only works if the user is joined (TODO: always allow, but only show events if the user was
|
||||||
/// joined, depending on history_visibility)
|
/// joined, depending on history_visibility)
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/rooms/<_>/context/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_context_route(
|
pub async fn get_context_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_context::Request<'_>>,
|
body: Ruma<get_context::Request<'_>>,
|
||||||
) -> ConduitResult<get_context::Response> {
|
) -> Result<get_context::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
// Load filter
|
let (lazy_load_enabled, lazy_load_send_redundant) = match &body.filter.lazy_load_options {
|
||||||
let filter = body.filter.clone().unwrap_or_default();
|
|
||||||
|
|
||||||
let (lazy_load_enabled, lazy_load_send_redundant) = match filter.lazy_load_options {
|
|
||||||
LazyLoadOptions::Enabled {
|
LazyLoadOptions::Enabled {
|
||||||
include_redundant_members: redundant,
|
include_redundant_members,
|
||||||
} => (true, redundant),
|
} => (true, *include_redundant_members),
|
||||||
_ => (false, false),
|
_ => (false, false),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -198,5 +188,5 @@ pub async fn get_context_route(
|
||||||
state,
|
state,
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(resp.into())
|
Ok(resp)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{database::DatabaseGuard, utils, ConduitResult, Error, Ruma};
|
use crate::{database::DatabaseGuard, utils, Error, Result, Ruma};
|
||||||
use ruma::api::client::{
|
use ruma::api::client::{
|
||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
r0::{
|
r0::{
|
||||||
|
@ -8,21 +8,15 @@ use ruma::api::client::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::SESSION_ID_LENGTH;
|
use super::SESSION_ID_LENGTH;
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{delete, get, post, put};
|
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/devices`
|
/// # `GET /_matrix/client/r0/devices`
|
||||||
///
|
///
|
||||||
/// Get metadata on all devices of the sender user.
|
/// Get metadata on all devices of the sender user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/devices", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_devices_route(
|
pub async fn get_devices_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_devices::Request>,
|
body: Ruma<get_devices::Request>,
|
||||||
) -> ConduitResult<get_devices::Response> {
|
) -> Result<get_devices::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let devices: Vec<device::Device> = db
|
let devices: Vec<device::Device> = db
|
||||||
|
@ -31,21 +25,17 @@ pub async fn get_devices_route(
|
||||||
.filter_map(|r| r.ok()) // Filter out buggy devices
|
.filter_map(|r| r.ok()) // Filter out buggy devices
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(get_devices::Response { devices }.into())
|
Ok(get_devices::Response { devices })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/devices/{deviceId}`
|
/// # `GET /_matrix/client/r0/devices/{deviceId}`
|
||||||
///
|
///
|
||||||
/// Get metadata on a single device of the sender user.
|
/// Get metadata on a single device of the sender user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/devices/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_device_route(
|
pub async fn get_device_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_device::Request<'_>>,
|
body: Ruma<get_device::Request<'_>>,
|
||||||
) -> ConduitResult<get_device::Response> {
|
) -> Result<get_device::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let device = db
|
let device = db
|
||||||
|
@ -53,21 +43,17 @@ pub async fn get_device_route(
|
||||||
.get_device_metadata(sender_user, &body.body.device_id)?
|
.get_device_metadata(sender_user, &body.body.device_id)?
|
||||||
.ok_or(Error::BadRequest(ErrorKind::NotFound, "Device not found."))?;
|
.ok_or(Error::BadRequest(ErrorKind::NotFound, "Device not found."))?;
|
||||||
|
|
||||||
Ok(get_device::Response { device }.into())
|
Ok(get_device::Response { device })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/devices/{deviceId}`
|
/// # `PUT /_matrix/client/r0/devices/{deviceId}`
|
||||||
///
|
///
|
||||||
/// Updates the metadata on a given device of the sender user.
|
/// Updates the metadata on a given device of the sender user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/devices/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn update_device_route(
|
pub async fn update_device_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<update_device::Request<'_>>,
|
body: Ruma<update_device::Request<'_>>,
|
||||||
) -> ConduitResult<update_device::Response> {
|
) -> Result<update_device::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let mut device = db
|
let mut device = db
|
||||||
|
@ -82,7 +68,7 @@ pub async fn update_device_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(update_device::Response {}.into())
|
Ok(update_device::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `DELETE /_matrix/client/r0/devices/{deviceId}`
|
/// # `DELETE /_matrix/client/r0/devices/{deviceId}`
|
||||||
|
@ -94,15 +80,11 @@ pub async fn update_device_route(
|
||||||
/// - Deletes device metadata (device id, device display name, last seen ip, last seen ts)
|
/// - Deletes device metadata (device id, device display name, last seen ip, last seen ts)
|
||||||
/// - Forgets to-device events
|
/// - Forgets to-device events
|
||||||
/// - Triggers device list updates
|
/// - Triggers device list updates
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
delete("/_matrix/client/r0/devices/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn delete_device_route(
|
pub async fn delete_device_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<delete_device::Request<'_>>,
|
body: Ruma<delete_device::Request<'_>>,
|
||||||
) -> ConduitResult<delete_device::Response> {
|
) -> Result<delete_device::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
|
@ -143,7 +125,7 @@ pub async fn delete_device_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(delete_device::Response {}.into())
|
Ok(delete_device::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/devices/{deviceId}`
|
/// # `PUT /_matrix/client/r0/devices/{deviceId}`
|
||||||
|
@ -157,15 +139,11 @@ pub async fn delete_device_route(
|
||||||
/// - Deletes device metadata (device id, device display name, last seen ip, last seen ts)
|
/// - Deletes device metadata (device id, device display name, last seen ip, last seen ts)
|
||||||
/// - Forgets to-device events
|
/// - Forgets to-device events
|
||||||
/// - Triggers device list updates
|
/// - Triggers device list updates
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/delete_devices", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn delete_devices_route(
|
pub async fn delete_devices_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<delete_devices::Request<'_>>,
|
body: Ruma<delete_devices::Request<'_>>,
|
||||||
) -> ConduitResult<delete_devices::Response> {
|
) -> Result<delete_devices::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
|
@ -208,5 +186,5 @@ pub async fn delete_devices_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(delete_devices::Response {}.into())
|
Ok(delete_devices::Response {})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{database::DatabaseGuard, ConduitResult, Database, Error, Result, Ruma};
|
use crate::{database::DatabaseGuard, Database, Error, Result, Ruma};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::{
|
api::{
|
||||||
client::{
|
client::{
|
||||||
|
@ -29,23 +29,16 @@ use ruma::{
|
||||||
};
|
};
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{get, post, put};
|
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/publicRooms`
|
/// # `POST /_matrix/client/r0/publicRooms`
|
||||||
///
|
///
|
||||||
/// Lists the public rooms on this server.
|
/// Lists the public rooms on this server.
|
||||||
///
|
///
|
||||||
/// - Rooms are ordered by the number of joined members
|
/// - Rooms are ordered by the number of joined members
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/publicRooms", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_public_rooms_filtered_route(
|
pub async fn get_public_rooms_filtered_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_public_rooms_filtered::Request<'_>>,
|
body: Ruma<get_public_rooms_filtered::Request<'_>>,
|
||||||
) -> ConduitResult<get_public_rooms_filtered::Response> {
|
) -> Result<get_public_rooms_filtered::Response> {
|
||||||
get_public_rooms_filtered_helper(
|
get_public_rooms_filtered_helper(
|
||||||
&db,
|
&db,
|
||||||
body.server.as_deref(),
|
body.server.as_deref(),
|
||||||
|
@ -62,15 +55,11 @@ pub async fn get_public_rooms_filtered_route(
|
||||||
/// Lists the public rooms on this server.
|
/// Lists the public rooms on this server.
|
||||||
///
|
///
|
||||||
/// - Rooms are ordered by the number of joined members
|
/// - Rooms are ordered by the number of joined members
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/publicRooms", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_public_rooms_route(
|
pub async fn get_public_rooms_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_public_rooms::Request<'_>>,
|
body: Ruma<get_public_rooms::Request<'_>>,
|
||||||
) -> ConduitResult<get_public_rooms::Response> {
|
) -> Result<get_public_rooms::Response> {
|
||||||
let response = get_public_rooms_filtered_helper(
|
let response = get_public_rooms_filtered_helper(
|
||||||
&db,
|
&db,
|
||||||
body.server.as_deref(),
|
body.server.as_deref(),
|
||||||
|
@ -79,16 +68,14 @@ pub async fn get_public_rooms_route(
|
||||||
&IncomingFilter::default(),
|
&IncomingFilter::default(),
|
||||||
&IncomingRoomNetwork::Matrix,
|
&IncomingRoomNetwork::Matrix,
|
||||||
)
|
)
|
||||||
.await?
|
.await?;
|
||||||
.0;
|
|
||||||
|
|
||||||
Ok(get_public_rooms::Response {
|
Ok(get_public_rooms::Response {
|
||||||
chunk: response.chunk,
|
chunk: response.chunk,
|
||||||
prev_batch: response.prev_batch,
|
prev_batch: response.prev_batch,
|
||||||
next_batch: response.next_batch,
|
next_batch: response.next_batch,
|
||||||
total_room_count_estimate: response.total_room_count_estimate,
|
total_room_count_estimate: response.total_room_count_estimate,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/directory/list/room/{roomId}`
|
/// # `PUT /_matrix/client/r0/directory/list/room/{roomId}`
|
||||||
|
@ -96,15 +83,11 @@ pub async fn get_public_rooms_route(
|
||||||
/// Sets the visibility of a given room in the room directory.
|
/// Sets the visibility of a given room in the room directory.
|
||||||
///
|
///
|
||||||
/// - TODO: Access control checks
|
/// - TODO: Access control checks
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/directory/list/room/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn set_room_visibility_route(
|
pub async fn set_room_visibility_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<set_room_visibility::Request<'_>>,
|
body: Ruma<set_room_visibility::Request<'_>>,
|
||||||
) -> ConduitResult<set_room_visibility::Response> {
|
) -> Result<set_room_visibility::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
match &body.visibility {
|
match &body.visibility {
|
||||||
|
@ -123,29 +106,24 @@ pub async fn set_room_visibility_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(set_room_visibility::Response {}.into())
|
Ok(set_room_visibility::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/directory/list/room/{roomId}`
|
/// # `GET /_matrix/client/r0/directory/list/room/{roomId}`
|
||||||
///
|
///
|
||||||
/// Gets the visibility of a given room in the room directory.
|
/// Gets the visibility of a given room in the room directory.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/directory/list/room/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_room_visibility_route(
|
pub async fn get_room_visibility_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_room_visibility::Request<'_>>,
|
body: Ruma<get_room_visibility::Request<'_>>,
|
||||||
) -> ConduitResult<get_room_visibility::Response> {
|
) -> Result<get_room_visibility::Response> {
|
||||||
Ok(get_room_visibility::Response {
|
Ok(get_room_visibility::Response {
|
||||||
visibility: if db.rooms.is_public_room(&body.room_id)? {
|
visibility: if db.rooms.is_public_room(&body.room_id)? {
|
||||||
room::Visibility::Public
|
room::Visibility::Public
|
||||||
} else {
|
} else {
|
||||||
room::Visibility::Private
|
room::Visibility::Private
|
||||||
},
|
},
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn get_public_rooms_filtered_helper(
|
pub(crate) async fn get_public_rooms_filtered_helper(
|
||||||
|
@ -155,7 +133,7 @@ pub(crate) async fn get_public_rooms_filtered_helper(
|
||||||
since: Option<&str>,
|
since: Option<&str>,
|
||||||
filter: &IncomingFilter,
|
filter: &IncomingFilter,
|
||||||
_network: &IncomingRoomNetwork,
|
_network: &IncomingRoomNetwork,
|
||||||
) -> ConduitResult<get_public_rooms_filtered::Response> {
|
) -> Result<get_public_rooms_filtered::Response> {
|
||||||
if let Some(other_server) = server.filter(|server| *server != db.globals.server_name().as_str())
|
if let Some(other_server) = server.filter(|server| *server != db.globals.server_name().as_str())
|
||||||
{
|
{
|
||||||
let response = db
|
let response = db
|
||||||
|
@ -191,8 +169,7 @@ pub(crate) async fn get_public_rooms_filtered_helper(
|
||||||
prev_batch: response.prev_batch,
|
prev_batch: response.prev_batch,
|
||||||
next_batch: response.next_batch,
|
next_batch: response.next_batch,
|
||||||
total_room_count_estimate: response.total_room_count_estimate,
|
total_room_count_estimate: response.total_room_count_estimate,
|
||||||
}
|
});
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let limit = limit.map_or(10, u64::from);
|
let limit = limit.map_or(10, u64::from);
|
||||||
|
@ -372,6 +349,5 @@ pub(crate) async fn get_public_rooms_filtered_helper(
|
||||||
prev_batch,
|
prev_batch,
|
||||||
next_batch,
|
next_batch,
|
||||||
total_room_count_estimate: Some(total_room_count_estimate),
|
total_room_count_estimate: Some(total_room_count_estimate),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,47 +1,38 @@
|
||||||
use crate::{database::DatabaseGuard, ConduitResult, Error, Ruma};
|
use crate::{database::DatabaseGuard, Error, Result, Ruma};
|
||||||
use ruma::api::client::{
|
use ruma::api::client::{
|
||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
r0::filter::{create_filter, get_filter},
|
r0::filter::{create_filter, get_filter},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{get, post};
|
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/user/{userId}/filter/{filterId}`
|
/// # `GET /_matrix/client/r0/user/{userId}/filter/{filterId}`
|
||||||
///
|
///
|
||||||
/// Loads a filter that was previously created.
|
/// Loads a filter that was previously created.
|
||||||
///
|
///
|
||||||
/// - A user can only access their own filters
|
/// - A user can only access their own filters
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/user/<_>/filter/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_filter_route(
|
pub async fn get_filter_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_filter::Request<'_>>,
|
body: Ruma<get_filter::Request<'_>>,
|
||||||
) -> ConduitResult<get_filter::Response> {
|
) -> Result<get_filter::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let filter = match db.users.get_filter(sender_user, &body.filter_id)? {
|
let filter = match db.users.get_filter(sender_user, &body.filter_id)? {
|
||||||
Some(filter) => filter,
|
Some(filter) => filter,
|
||||||
None => return Err(Error::BadRequest(ErrorKind::NotFound, "Filter not found.")),
|
None => return Err(Error::BadRequest(ErrorKind::NotFound, "Filter not found.")),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(get_filter::Response::new(filter).into())
|
Ok(get_filter::Response::new(filter))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/user/{userId}/filter`
|
/// # `PUT /_matrix/client/r0/user/{userId}/filter`
|
||||||
///
|
///
|
||||||
/// Creates a new filter to be used by other endpoints.
|
/// Creates a new filter to be used by other endpoints.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/user/<_>/filter", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn create_filter_route(
|
pub async fn create_filter_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<create_filter::Request<'_>>,
|
body: Ruma<create_filter::Request<'_>>,
|
||||||
) -> ConduitResult<create_filter::Response> {
|
) -> Result<create_filter::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
Ok(create_filter::Response::new(db.users.create_filter(sender_user, &body.filter)?).into())
|
Ok(create_filter::Response::new(
|
||||||
|
db.users.create_filter(sender_user, &body.filter)?,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use super::SESSION_ID_LENGTH;
|
use super::SESSION_ID_LENGTH;
|
||||||
use crate::{database::DatabaseGuard, utils, ConduitResult, Database, Error, Result, Ruma};
|
use crate::{database::DatabaseGuard, utils, Database, Error, Result, Ruma};
|
||||||
use rocket::futures::{prelude::*, stream::FuturesUnordered};
|
use futures_util::{stream::FuturesUnordered, StreamExt};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::{
|
api::{
|
||||||
client::{
|
client::{
|
||||||
|
@ -21,24 +21,17 @@ use ruma::{
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{get, post};
|
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/keys/upload`
|
/// # `POST /_matrix/client/r0/keys/upload`
|
||||||
///
|
///
|
||||||
/// Publish end-to-end encryption keys for the sender device.
|
/// Publish end-to-end encryption keys for the sender device.
|
||||||
///
|
///
|
||||||
/// - Adds one time keys
|
/// - Adds one time keys
|
||||||
/// - If there are no device keys yet: Adds device keys (TODO: merge with existing keys?)
|
/// - If there are no device keys yet: Adds device keys (TODO: merge with existing keys?)
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/keys/upload", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn upload_keys_route(
|
pub async fn upload_keys_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<upload_keys::Request>,
|
body: Ruma<upload_keys::Request>,
|
||||||
) -> ConduitResult<upload_keys::Response> {
|
) -> Result<upload_keys::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
|
@ -69,8 +62,7 @@ pub async fn upload_keys_route(
|
||||||
|
|
||||||
Ok(upload_keys::Response {
|
Ok(upload_keys::Response {
|
||||||
one_time_key_counts: db.users.count_one_time_keys(sender_user, sender_device)?,
|
one_time_key_counts: db.users.count_one_time_keys(sender_user, sender_device)?,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/keys/query`
|
/// # `POST /_matrix/client/r0/keys/query`
|
||||||
|
@ -80,15 +72,11 @@ pub async fn upload_keys_route(
|
||||||
/// - Always fetches users from other servers over federation
|
/// - Always fetches users from other servers over federation
|
||||||
/// - Gets master keys, self-signing keys, user signing keys and device keys.
|
/// - Gets master keys, self-signing keys, user signing keys and device keys.
|
||||||
/// - The master and self-signing keys contain signatures that the user is allowed to see
|
/// - The master and self-signing keys contain signatures that the user is allowed to see
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/keys/query", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_keys_route(
|
pub async fn get_keys_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_keys::Request<'_>>,
|
body: Ruma<get_keys::Request<'_>>,
|
||||||
) -> ConduitResult<get_keys::Response> {
|
) -> Result<get_keys::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let response = get_keys_helper(
|
let response = get_keys_helper(
|
||||||
|
@ -99,26 +87,22 @@ pub async fn get_keys_route(
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(response.into())
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/keys/claim`
|
/// # `POST /_matrix/client/r0/keys/claim`
|
||||||
///
|
///
|
||||||
/// Claims one-time keys
|
/// Claims one-time keys
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/keys/claim", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn claim_keys_route(
|
pub async fn claim_keys_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<claim_keys::Request>,
|
body: Ruma<claim_keys::Request>,
|
||||||
) -> ConduitResult<claim_keys::Response> {
|
) -> Result<claim_keys::Response> {
|
||||||
let response = claim_keys_helper(&body.one_time_keys, &db).await?;
|
let response = claim_keys_helper(&body.one_time_keys, &db).await?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(response.into())
|
Ok(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/keys/device_signing/upload`
|
/// # `POST /_matrix/client/r0/keys/device_signing/upload`
|
||||||
|
@ -126,15 +110,11 @@ pub async fn claim_keys_route(
|
||||||
/// Uploads end-to-end key information for the sender user.
|
/// Uploads end-to-end key information for the sender user.
|
||||||
///
|
///
|
||||||
/// - Requires UIAA to verify password
|
/// - Requires UIAA to verify password
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/unstable/keys/device_signing/upload", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn upload_signing_keys_route(
|
pub async fn upload_signing_keys_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<upload_signing_keys::Request<'_>>,
|
body: Ruma<upload_signing_keys::Request<'_>>,
|
||||||
) -> ConduitResult<upload_signing_keys::Response> {
|
) -> Result<upload_signing_keys::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
|
@ -184,21 +164,17 @@ pub async fn upload_signing_keys_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(upload_signing_keys::Response {}.into())
|
Ok(upload_signing_keys::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/keys/signatures/upload`
|
/// # `POST /_matrix/client/r0/keys/signatures/upload`
|
||||||
///
|
///
|
||||||
/// Uploads end-to-end key signatures from the sender user.
|
/// Uploads end-to-end key signatures from the sender user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/unstable/keys/signatures/upload", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn upload_signatures_route(
|
pub async fn upload_signatures_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<upload_signatures::Request>,
|
body: Ruma<upload_signatures::Request>,
|
||||||
) -> ConduitResult<upload_signatures::Response> {
|
) -> Result<upload_signatures::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
for (user_id, signed_keys) in &body.signed_keys {
|
for (user_id, signed_keys) in &body.signed_keys {
|
||||||
|
@ -248,7 +224,7 @@ pub async fn upload_signatures_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(upload_signatures::Response {}.into())
|
Ok(upload_signatures::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/keys/changes`
|
/// # `POST /_matrix/client/r0/keys/changes`
|
||||||
|
@ -256,15 +232,11 @@ pub async fn upload_signatures_route(
|
||||||
/// Gets a list of users who have updated their device identity keys since the previous sync token.
|
/// Gets a list of users who have updated their device identity keys since the previous sync token.
|
||||||
///
|
///
|
||||||
/// - TODO: left users
|
/// - TODO: left users
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/keys/changes", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_key_changes_route(
|
pub async fn get_key_changes_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_key_changes::Request<'_>>,
|
body: Ruma<get_key_changes::Request<'_>>,
|
||||||
) -> ConduitResult<get_key_changes::Response> {
|
) -> Result<get_key_changes::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let mut device_list_updates = HashSet::new();
|
let mut device_list_updates = HashSet::new();
|
||||||
|
@ -303,8 +275,7 @@ pub async fn get_key_changes_route(
|
||||||
Ok(get_key_changes::Response {
|
Ok(get_key_changes::Response {
|
||||||
changed: device_list_updates.into_iter().collect(),
|
changed: device_list_updates.into_iter().collect(),
|
||||||
left: Vec::new(), // TODO
|
left: Vec::new(), // TODO
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
|
pub(crate) async fn get_keys_helper<F: Fn(&UserId) -> bool>(
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
database::{media::FileMeta, DatabaseGuard},
|
database::{media::FileMeta, DatabaseGuard},
|
||||||
utils, ConduitResult, Error, Ruma,
|
utils, Error, Result, Ruma,
|
||||||
};
|
};
|
||||||
use ruma::api::client::{
|
use ruma::api::client::{
|
||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
|
@ -10,23 +10,19 @@ use ruma::api::client::{
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{get, post};
|
|
||||||
|
|
||||||
const MXC_LENGTH: usize = 32;
|
const MXC_LENGTH: usize = 32;
|
||||||
|
|
||||||
/// # `GET /_matrix/media/r0/config`
|
/// # `GET /_matrix/media/r0/config`
|
||||||
///
|
///
|
||||||
/// Returns max upload size.
|
/// Returns max upload size.
|
||||||
#[cfg_attr(feature = "conduit_bin", get("/_matrix/media/r0/config"))]
|
#[tracing::instrument(skip(db, _body))]
|
||||||
#[tracing::instrument(skip(db))]
|
|
||||||
pub async fn get_media_config_route(
|
pub async fn get_media_config_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
) -> ConduitResult<get_media_config::Response> {
|
_body: Ruma<get_media_config::Request>,
|
||||||
|
) -> Result<get_media_config::Response> {
|
||||||
Ok(get_media_config::Response {
|
Ok(get_media_config::Response {
|
||||||
upload_size: db.globals.max_request_size().into(),
|
upload_size: db.globals.max_request_size().into(),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/media/r0/upload`
|
/// # `POST /_matrix/media/r0/upload`
|
||||||
|
@ -35,15 +31,11 @@ pub async fn get_media_config_route(
|
||||||
///
|
///
|
||||||
/// - Some metadata will be saved in the database
|
/// - Some metadata will be saved in the database
|
||||||
/// - Media will be saved in the media/ directory
|
/// - Media will be saved in the media/ directory
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/media/r0/upload", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn create_content_route(
|
pub async fn create_content_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<create_content::Request<'_>>,
|
body: Ruma<create_content::Request<'_>>,
|
||||||
) -> ConduitResult<create_content::Response> {
|
) -> Result<create_content::Response> {
|
||||||
let mxc = format!(
|
let mxc = format!(
|
||||||
"mxc://{}/{}",
|
"mxc://{}/{}",
|
||||||
db.globals.server_name(),
|
db.globals.server_name(),
|
||||||
|
@ -69,8 +61,7 @@ pub async fn create_content_route(
|
||||||
Ok(create_content::Response {
|
Ok(create_content::Response {
|
||||||
content_uri: mxc.try_into().expect("Invalid mxc:// URI"),
|
content_uri: mxc.try_into().expect("Invalid mxc:// URI"),
|
||||||
blurhash: None,
|
blurhash: None,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_remote_content(
|
pub async fn get_remote_content(
|
||||||
|
@ -110,15 +101,11 @@ pub async fn get_remote_content(
|
||||||
/// Load media from our server or over federation.
|
/// Load media from our server or over federation.
|
||||||
///
|
///
|
||||||
/// - Only allows federation if `allow_remote` is true
|
/// - Only allows federation if `allow_remote` is true
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/media/r0/download/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_content_route(
|
pub async fn get_content_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_content::Request<'_>>,
|
body: Ruma<get_content::Request<'_>>,
|
||||||
) -> ConduitResult<get_content::Response> {
|
) -> Result<get_content::Response> {
|
||||||
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 {
|
||||||
|
@ -131,12 +118,11 @@ pub async fn get_content_route(
|
||||||
file,
|
file,
|
||||||
content_type,
|
content_type,
|
||||||
content_disposition,
|
content_disposition,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
} else if &*body.server_name != db.globals.server_name() && body.allow_remote {
|
} else if &*body.server_name != db.globals.server_name() && body.allow_remote {
|
||||||
let remote_content_response =
|
let remote_content_response =
|
||||||
get_remote_content(&db, &mxc, &body.server_name, &body.media_id).await?;
|
get_remote_content(&db, &mxc, &body.server_name, &body.media_id).await?;
|
||||||
Ok(remote_content_response.into())
|
Ok(remote_content_response)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::BadRequest(ErrorKind::NotFound, "Media not found."))
|
Err(Error::BadRequest(ErrorKind::NotFound, "Media not found."))
|
||||||
}
|
}
|
||||||
|
@ -147,15 +133,11 @@ pub async fn get_content_route(
|
||||||
/// Load media from our server or over federation, permitting desired filename.
|
/// Load media from our server or over federation, permitting desired filename.
|
||||||
///
|
///
|
||||||
/// - Only allows federation if `allow_remote` is true
|
/// - Only allows federation if `allow_remote` is true
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/media/r0/download/<_>/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_content_as_filename_route(
|
pub async fn get_content_as_filename_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_content_as_filename::Request<'_>>,
|
body: Ruma<get_content_as_filename::Request<'_>>,
|
||||||
) -> ConduitResult<get_content_as_filename::Response> {
|
) -> Result<get_content_as_filename::Response> {
|
||||||
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 {
|
||||||
|
@ -168,8 +150,7 @@ pub async fn get_content_as_filename_route(
|
||||||
file,
|
file,
|
||||||
content_type,
|
content_type,
|
||||||
content_disposition: Some(format!("inline; filename={}", body.filename)),
|
content_disposition: Some(format!("inline; filename={}", body.filename)),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
} else if &*body.server_name != db.globals.server_name() && body.allow_remote {
|
} else if &*body.server_name != db.globals.server_name() && body.allow_remote {
|
||||||
let remote_content_response =
|
let remote_content_response =
|
||||||
get_remote_content(&db, &mxc, &body.server_name, &body.media_id).await?;
|
get_remote_content(&db, &mxc, &body.server_name, &body.media_id).await?;
|
||||||
|
@ -178,8 +159,7 @@ pub async fn get_content_as_filename_route(
|
||||||
content_disposition: Some(format!("inline: filename={}", body.filename)),
|
content_disposition: Some(format!("inline: filename={}", body.filename)),
|
||||||
content_type: remote_content_response.content_type,
|
content_type: remote_content_response.content_type,
|
||||||
file: remote_content_response.file,
|
file: remote_content_response.file,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
} else {
|
} else {
|
||||||
Err(Error::BadRequest(ErrorKind::NotFound, "Media not found."))
|
Err(Error::BadRequest(ErrorKind::NotFound, "Media not found."))
|
||||||
}
|
}
|
||||||
|
@ -190,15 +170,11 @@ pub async fn get_content_as_filename_route(
|
||||||
/// Load media thumbnail from our server or over federation.
|
/// Load media thumbnail from our server or over federation.
|
||||||
///
|
///
|
||||||
/// - Only allows federation if `allow_remote` is true
|
/// - Only allows federation if `allow_remote` is true
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/media/r0/thumbnail/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_content_thumbnail_route(
|
pub async fn get_content_thumbnail_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_content_thumbnail::Request<'_>>,
|
body: Ruma<get_content_thumbnail::Request<'_>>,
|
||||||
) -> ConduitResult<get_content_thumbnail::Response> {
|
) -> Result<get_content_thumbnail::Response> {
|
||||||
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 {
|
||||||
|
@ -217,7 +193,7 @@ pub async fn get_content_thumbnail_route(
|
||||||
)
|
)
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
Ok(get_content_thumbnail::Response { file, content_type }.into())
|
Ok(get_content_thumbnail::Response { file, content_type })
|
||||||
} else if &*body.server_name != db.globals.server_name() && body.allow_remote {
|
} else if &*body.server_name != db.globals.server_name() && body.allow_remote {
|
||||||
let get_thumbnail_response = db
|
let get_thumbnail_response = db
|
||||||
.sending
|
.sending
|
||||||
|
@ -247,7 +223,7 @@ pub async fn get_content_thumbnail_route(
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(get_thumbnail_response.into())
|
Ok(get_thumbnail_response)
|
||||||
} else {
|
} else {
|
||||||
Err(Error::BadRequest(ErrorKind::NotFound, "Media not found."))
|
Err(Error::BadRequest(ErrorKind::NotFound, "Media not found."))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
||||||
client_server,
|
client_server,
|
||||||
database::DatabaseGuard,
|
database::DatabaseGuard,
|
||||||
pdu::{EventHash, PduBuilder, PduEvent},
|
pdu::{EventHash, PduBuilder, PduEvent},
|
||||||
server_server, utils, ConduitResult, Database, Error, Result, Ruma,
|
server_server, utils, Database, Error, Result, Ruma,
|
||||||
};
|
};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::{
|
api::{
|
||||||
|
@ -36,24 +36,17 @@ use std::{
|
||||||
};
|
};
|
||||||
use tracing::{debug, error, warn};
|
use tracing::{debug, error, warn};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{get, post};
|
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/join`
|
/// # `POST /_matrix/client/r0/rooms/{roomId}/join`
|
||||||
///
|
///
|
||||||
/// Tries to join the sender user into a room.
|
/// Tries to join the sender user into a room.
|
||||||
///
|
///
|
||||||
/// - If the server knowns about this room: creates the join event and does auth rules locally
|
/// - If the server knowns about this room: creates the join event and does auth rules locally
|
||||||
/// - If the server does not know about the room: asks other servers over federation
|
/// - If the server does not know about the room: asks other servers over federation
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/rooms/<_>/join", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn join_room_by_id_route(
|
pub async fn join_room_by_id_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<join_room_by_id::Request<'_>>,
|
body: Ruma<join_room_by_id::Request<'_>>,
|
||||||
) -> ConduitResult<join_room_by_id::Response> {
|
) -> Result<join_room_by_id::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let mut servers: HashSet<_> = db
|
let mut servers: HashSet<_> = db
|
||||||
|
@ -90,15 +83,11 @@ pub async fn join_room_by_id_route(
|
||||||
///
|
///
|
||||||
/// - If the server knowns about this room: creates the join event and does auth rules locally
|
/// - If the server knowns about this room: creates the join event and does auth rules locally
|
||||||
/// - If the server does not know about the room: asks other servers over federation
|
/// - If the server does not know about the room: asks other servers over federation
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/join/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn join_room_by_id_or_alias_route(
|
pub async fn join_room_by_id_or_alias_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<join_room_by_id_or_alias::Request<'_>>,
|
body: Ruma<join_room_by_id_or_alias::Request<'_>>,
|
||||||
) -> ConduitResult<join_room_by_id_or_alias::Response> {
|
) -> Result<join_room_by_id_or_alias::Response> {
|
||||||
let sender_user = body.sender_user.as_deref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_deref().expect("user is authenticated");
|
||||||
let body = body.body;
|
let body = body.body;
|
||||||
|
|
||||||
|
@ -122,7 +111,7 @@ pub async fn join_room_by_id_or_alias_route(
|
||||||
Err(room_alias) => {
|
Err(room_alias) => {
|
||||||
let response = client_server::get_alias_helper(&db, &room_alias).await?;
|
let response = client_server::get_alias_helper(&db, &room_alias).await?;
|
||||||
|
|
||||||
(response.0.servers.into_iter().collect(), response.0.room_id)
|
(response.servers.into_iter().collect(), response.room_id)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -138,9 +127,8 @@ pub async fn join_room_by_id_or_alias_route(
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(join_room_by_id_or_alias::Response {
|
Ok(join_room_by_id_or_alias::Response {
|
||||||
room_id: join_room_response.0.room_id,
|
room_id: join_room_response.room_id,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/leave`
|
/// # `POST /_matrix/client/r0/rooms/{roomId}/leave`
|
||||||
|
@ -148,42 +136,34 @@ pub async fn join_room_by_id_or_alias_route(
|
||||||
/// Tries to leave the sender user from a room.
|
/// Tries to leave the sender user from a room.
|
||||||
///
|
///
|
||||||
/// - This should always work if the user is currently joined.
|
/// - This should always work if the user is currently joined.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/rooms/<_>/leave", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn leave_room_route(
|
pub async fn leave_room_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<leave_room::Request<'_>>,
|
body: Ruma<leave_room::Request<'_>>,
|
||||||
) -> ConduitResult<leave_room::Response> {
|
) -> Result<leave_room::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
db.rooms.leave_room(sender_user, &body.room_id, &db).await?;
|
db.rooms.leave_room(sender_user, &body.room_id, &db).await?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(leave_room::Response::new().into())
|
Ok(leave_room::Response::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/invite`
|
/// # `POST /_matrix/client/r0/rooms/{roomId}/invite`
|
||||||
///
|
///
|
||||||
/// Tries to send an invite event into the room.
|
/// Tries to send an invite event into the room.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/rooms/<_>/invite", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn invite_user_route(
|
pub async fn invite_user_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<invite_user::Request<'_>>,
|
body: Ruma<invite_user::Request<'_>>,
|
||||||
) -> ConduitResult<invite_user::Response> {
|
) -> Result<invite_user::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
if let invite_user::IncomingInvitationRecipient::UserId { user_id } = &body.recipient {
|
if let invite_user::IncomingInvitationRecipient::UserId { user_id } = &body.recipient {
|
||||||
invite_helper(sender_user, user_id, &body.room_id, &db, false).await?;
|
invite_helper(sender_user, user_id, &body.room_id, &db, false).await?;
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
Ok(invite_user::Response {}.into())
|
Ok(invite_user::Response {})
|
||||||
} else {
|
} else {
|
||||||
Err(Error::BadRequest(ErrorKind::NotFound, "User not found."))
|
Err(Error::BadRequest(ErrorKind::NotFound, "User not found."))
|
||||||
}
|
}
|
||||||
|
@ -192,15 +172,11 @@ pub async fn invite_user_route(
|
||||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/kick`
|
/// # `POST /_matrix/client/r0/rooms/{roomId}/kick`
|
||||||
///
|
///
|
||||||
/// Tries to send a kick event into the room.
|
/// Tries to send a kick event into the room.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/rooms/<_>/kick", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn kick_user_route(
|
pub async fn kick_user_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<kick_user::Request<'_>>,
|
body: Ruma<kick_user::Request<'_>>,
|
||||||
) -> ConduitResult<kick_user::Response> {
|
) -> Result<kick_user::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let mut event: RoomMemberEventContent = serde_json::from_str(
|
let mut event: RoomMemberEventContent = serde_json::from_str(
|
||||||
|
@ -250,21 +226,17 @@ pub async fn kick_user_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(kick_user::Response::new().into())
|
Ok(kick_user::Response::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/ban`
|
/// # `POST /_matrix/client/r0/rooms/{roomId}/ban`
|
||||||
///
|
///
|
||||||
/// Tries to send a ban event into the room.
|
/// Tries to send a ban event into the room.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/rooms/<_>/ban", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn ban_user_route(
|
pub async fn ban_user_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<ban_user::Request<'_>>,
|
body: Ruma<ban_user::Request<'_>>,
|
||||||
) -> ConduitResult<ban_user::Response> {
|
) -> Result<ban_user::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
// TODO: reason
|
// TODO: reason
|
||||||
|
@ -325,21 +297,17 @@ pub async fn ban_user_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(ban_user::Response::new().into())
|
Ok(ban_user::Response::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/unban`
|
/// # `POST /_matrix/client/r0/rooms/{roomId}/unban`
|
||||||
///
|
///
|
||||||
/// Tries to send an unban event into the room.
|
/// Tries to send an unban event into the room.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/rooms/<_>/unban", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn unban_user_route(
|
pub async fn unban_user_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<unban_user::Request<'_>>,
|
body: Ruma<unban_user::Request<'_>>,
|
||||||
) -> ConduitResult<unban_user::Response> {
|
) -> Result<unban_user::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let mut event: RoomMemberEventContent = serde_json::from_str(
|
let mut event: RoomMemberEventContent = serde_json::from_str(
|
||||||
|
@ -388,7 +356,7 @@ pub async fn unban_user_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(unban_user::Response::new().into())
|
Ok(unban_user::Response::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/forget`
|
/// # `POST /_matrix/client/r0/rooms/{roomId}/forget`
|
||||||
|
@ -399,36 +367,28 @@ pub async fn unban_user_route(
|
||||||
///
|
///
|
||||||
/// Note: Other devices of the user have no way of knowing the room was forgotten, so this has to
|
/// Note: Other devices of the user have no way of knowing the room was forgotten, so this has to
|
||||||
/// be called from every device
|
/// be called from every device
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/rooms/<_>/forget", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn forget_room_route(
|
pub async fn forget_room_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<forget_room::Request<'_>>,
|
body: Ruma<forget_room::Request<'_>>,
|
||||||
) -> ConduitResult<forget_room::Response> {
|
) -> Result<forget_room::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
db.rooms.forget(&body.room_id, sender_user)?;
|
db.rooms.forget(&body.room_id, sender_user)?;
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(forget_room::Response::new().into())
|
Ok(forget_room::Response::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/joined_rooms`
|
/// # `POST /_matrix/client/r0/joined_rooms`
|
||||||
///
|
///
|
||||||
/// Lists all rooms the user has joined.
|
/// Lists all rooms the user has joined.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/joined_rooms", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn joined_rooms_route(
|
pub async fn joined_rooms_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<joined_rooms::Request>,
|
body: Ruma<joined_rooms::Request>,
|
||||||
) -> ConduitResult<joined_rooms::Response> {
|
) -> Result<joined_rooms::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
Ok(joined_rooms::Response {
|
Ok(joined_rooms::Response {
|
||||||
|
@ -437,8 +397,7 @@ pub async fn joined_rooms_route(
|
||||||
.rooms_joined(sender_user)
|
.rooms_joined(sender_user)
|
||||||
.filter_map(|r| r.ok())
|
.filter_map(|r| r.ok())
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/members`
|
/// # `POST /_matrix/client/r0/rooms/{roomId}/members`
|
||||||
|
@ -446,15 +405,11 @@ pub async fn joined_rooms_route(
|
||||||
/// Lists all joined users in a room (TODO: at a specific point in time, with a specific membership).
|
/// Lists all joined users in a room (TODO: at a specific point in time, with a specific membership).
|
||||||
///
|
///
|
||||||
/// - Only works if the user is currently joined
|
/// - Only works if the user is currently joined
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/rooms/<_>/members", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_member_events_route(
|
pub async fn get_member_events_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_member_events::Request<'_>>,
|
body: Ruma<get_member_events::Request<'_>>,
|
||||||
) -> ConduitResult<get_member_events::Response> {
|
) -> Result<get_member_events::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
// TODO: check history visibility?
|
// TODO: check history visibility?
|
||||||
|
@ -473,8 +428,7 @@ pub async fn get_member_events_route(
|
||||||
.filter(|(key, _)| key.0 == EventType::RoomMember)
|
.filter(|(key, _)| key.0 == EventType::RoomMember)
|
||||||
.map(|(_, pdu)| pdu.to_member_event())
|
.map(|(_, pdu)| pdu.to_member_event())
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/joined_members`
|
/// # `POST /_matrix/client/r0/rooms/{roomId}/joined_members`
|
||||||
|
@ -483,15 +437,11 @@ pub async fn get_member_events_route(
|
||||||
///
|
///
|
||||||
/// - The sender user must be in the room
|
/// - The sender user must be in the room
|
||||||
/// - TODO: An appservice just needs a puppet joined
|
/// - TODO: An appservice just needs a puppet joined
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/rooms/<_>/joined_members", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn joined_members_route(
|
pub async fn joined_members_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<joined_members::Request<'_>>,
|
body: Ruma<joined_members::Request<'_>>,
|
||||||
) -> ConduitResult<joined_members::Response> {
|
) -> Result<joined_members::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
if !db.rooms.is_joined(sender_user, &body.room_id)? {
|
if !db.rooms.is_joined(sender_user, &body.room_id)? {
|
||||||
|
@ -515,7 +465,7 @@ pub async fn joined_members_route(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(joined_members::Response { joined }.into())
|
Ok(joined_members::Response { joined })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(db))]
|
#[tracing::instrument(skip(db))]
|
||||||
|
@ -525,7 +475,7 @@ async fn join_room_by_id_helper(
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
servers: &HashSet<Box<ServerName>>,
|
servers: &HashSet<Box<ServerName>>,
|
||||||
_third_party_signed: Option<&IncomingThirdPartySigned>,
|
_third_party_signed: Option<&IncomingThirdPartySigned>,
|
||||||
) -> ConduitResult<join_room_by_id::Response> {
|
) -> Result<join_room_by_id::Response> {
|
||||||
let sender_user = sender_user.expect("user is authenticated");
|
let sender_user = sender_user.expect("user is authenticated");
|
||||||
|
|
||||||
let mutex_state = Arc::clone(
|
let mutex_state = Arc::clone(
|
||||||
|
@ -781,7 +731,7 @@ async fn join_room_by_id_helper(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(join_room_by_id::Response::new(room_id.to_owned()).into())
|
Ok(join_room_by_id::Response::new(room_id.to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_and_add_event_id(
|
fn validate_and_add_event_id(
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{database::DatabaseGuard, pdu::PduBuilder, utils, ConduitResult, Error, Ruma};
|
use crate::{database::DatabaseGuard, pdu::PduBuilder, utils, Error, Result, Ruma};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::{
|
api::client::{
|
||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
|
@ -11,9 +11,6 @@ use std::{
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{get, put};
|
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/rooms/{roomId}/send/{eventType}/{txnId}`
|
/// # `PUT /_matrix/client/r0/rooms/{roomId}/send/{eventType}/{txnId}`
|
||||||
///
|
///
|
||||||
/// Send a message event into the room.
|
/// Send a message event into the room.
|
||||||
|
@ -21,15 +18,11 @@ use rocket::{get, put};
|
||||||
/// - Is a NOOP if the txn id was already used before and returns the same event id again
|
/// - Is a NOOP if the txn id was already used before and returns the same event id again
|
||||||
/// - The only requirement for the content is that it has to be valid json
|
/// - The only requirement for the content is that it has to be valid json
|
||||||
/// - Tries to send the event into the room, auth rules will determine if it is allowed
|
/// - Tries to send the event into the room, auth rules will determine if it is allowed
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/rooms/<_>/send/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn send_message_event_route(
|
pub async fn send_message_event_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<send_message_event::Request<'_>>,
|
body: Ruma<send_message_event::Request<'_>>,
|
||||||
) -> ConduitResult<send_message_event::Response> {
|
) -> Result<send_message_event::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let sender_device = body.sender_device.as_deref();
|
let sender_device = body.sender_device.as_deref();
|
||||||
|
|
||||||
|
@ -69,7 +62,7 @@ pub async fn send_message_event_route(
|
||||||
.map_err(|_| Error::bad_database("Invalid txnid bytes in database."))?
|
.map_err(|_| Error::bad_database("Invalid txnid bytes in database."))?
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|_| Error::bad_database("Invalid event id in txnid data."))?;
|
.map_err(|_| Error::bad_database("Invalid event id in txnid data."))?;
|
||||||
return Ok(send_message_event::Response { event_id }.into());
|
return Ok(send_message_event::Response { event_id });
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut unsigned = BTreeMap::new();
|
let mut unsigned = BTreeMap::new();
|
||||||
|
@ -101,7 +94,7 @@ pub async fn send_message_event_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(send_message_event::Response::new((*event_id).to_owned()).into())
|
Ok(send_message_event::Response::new((*event_id).to_owned()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/rooms/{roomId}/messages`
|
/// # `GET /_matrix/client/r0/rooms/{roomId}/messages`
|
||||||
|
@ -110,15 +103,11 @@ pub async fn send_message_event_route(
|
||||||
///
|
///
|
||||||
/// - Only works if the user is joined (TODO: always allow, but only show events where the user was
|
/// - Only works if the user is joined (TODO: always allow, but only show events where the user was
|
||||||
/// joined, depending on history_visibility)
|
/// joined, depending on history_visibility)
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/rooms/<_>/messages", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_message_events_route(
|
pub async fn get_message_events_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_message_events::Request<'_>>,
|
body: Ruma<get_message_events::Request<'_>>,
|
||||||
) -> ConduitResult<get_message_events::Response> {
|
) -> Result<get_message_events::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
|
@ -246,5 +235,5 @@ pub async fn get_message_events_route(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(resp.into())
|
Ok(resp)
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,23 +62,6 @@ pub use unversioned::*;
|
||||||
pub use user_directory::*;
|
pub use user_directory::*;
|
||||||
pub use voip::*;
|
pub use voip::*;
|
||||||
|
|
||||||
#[cfg(not(feature = "conduit_bin"))]
|
|
||||||
use super::State;
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use {
|
|
||||||
crate::ConduitResult, rocket::options, ruma::api::client::r0::to_device::send_event_to_device,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const DEVICE_ID_LENGTH: usize = 10;
|
pub const DEVICE_ID_LENGTH: usize = 10;
|
||||||
pub const TOKEN_LENGTH: usize = 256;
|
pub const TOKEN_LENGTH: usize = 256;
|
||||||
pub const SESSION_ID_LENGTH: usize = 256;
|
pub const SESSION_ID_LENGTH: usize = 256;
|
||||||
|
|
||||||
/// # `OPTIONS`
|
|
||||||
///
|
|
||||||
/// Web clients use this to get CORS headers.
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
#[options("/<_..>")]
|
|
||||||
#[tracing::instrument]
|
|
||||||
pub async fn options_route() -> ConduitResult<send_event_to_device::Response> {
|
|
||||||
Ok(send_event_to_device::Response {}.into())
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,22 +1,15 @@
|
||||||
use crate::{database::DatabaseGuard, utils, ConduitResult, Ruma};
|
use crate::{database::DatabaseGuard, utils, Result, Ruma};
|
||||||
use ruma::api::client::r0::presence::{get_presence, set_presence};
|
use ruma::api::client::r0::presence::{get_presence, set_presence};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{get, put};
|
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/presence/{userId}/status`
|
/// # `PUT /_matrix/client/r0/presence/{userId}/status`
|
||||||
///
|
///
|
||||||
/// Sets the presence state of the sender user.
|
/// Sets the presence state of the sender user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/presence/<_>/status", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn set_presence_route(
|
pub async fn set_presence_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<set_presence::Request<'_>>,
|
body: Ruma<set_presence::Request<'_>>,
|
||||||
) -> ConduitResult<set_presence::Response> {
|
) -> Result<set_presence::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
for room_id in db.rooms.rooms_joined(sender_user) {
|
for room_id in db.rooms.rooms_joined(sender_user) {
|
||||||
|
@ -46,7 +39,7 @@ pub async fn set_presence_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(set_presence::Response {}.into())
|
Ok(set_presence::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/presence/{userId}/status`
|
/// # `GET /_matrix/client/r0/presence/{userId}/status`
|
||||||
|
@ -54,15 +47,11 @@ pub async fn set_presence_route(
|
||||||
/// Gets the presence state of the given user.
|
/// Gets the presence state of the given user.
|
||||||
///
|
///
|
||||||
/// - Only works if you share a room with the user
|
/// - Only works if you share a room with the user
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/presence/<_>/status", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_presence_route(
|
pub async fn get_presence_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_presence::Request<'_>>,
|
body: Ruma<get_presence::Request<'_>>,
|
||||||
) -> ConduitResult<get_presence::Response> {
|
) -> Result<get_presence::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let mut presence_event = None;
|
let mut presence_event = None;
|
||||||
|
@ -93,8 +82,7 @@ pub async fn get_presence_route(
|
||||||
.last_active_ago
|
.last_active_ago
|
||||||
.map(|millis| Duration::from_millis(millis.into())),
|
.map(|millis| Duration::from_millis(millis.into())),
|
||||||
presence: presence.content.presence,
|
presence: presence.content.presence,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
} else {
|
} else {
|
||||||
todo!();
|
todo!();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{database::DatabaseGuard, pdu::PduBuilder, utils, ConduitResult, Error, Ruma};
|
use crate::{database::DatabaseGuard, pdu::PduBuilder, utils, Error, Result, Ruma};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::{
|
api::{
|
||||||
client::{
|
client::{
|
||||||
|
@ -14,23 +14,16 @@ use ruma::{
|
||||||
use serde_json::value::to_raw_value;
|
use serde_json::value::to_raw_value;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{get, put};
|
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/profile/{userId}/displayname`
|
/// # `PUT /_matrix/client/r0/profile/{userId}/displayname`
|
||||||
///
|
///
|
||||||
/// Updates the displayname.
|
/// Updates the displayname.
|
||||||
///
|
///
|
||||||
/// - Also makes sure other users receive the update using presence EDUs
|
/// - Also makes sure other users receive the update using presence EDUs
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/profile/<_>/displayname", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn set_displayname_route(
|
pub async fn set_displayname_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<set_display_name::Request<'_>>,
|
body: Ruma<set_display_name::Request<'_>>,
|
||||||
) -> ConduitResult<set_display_name::Response> {
|
) -> Result<set_display_name::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
db.users
|
db.users
|
||||||
|
@ -116,7 +109,7 @@ pub async fn set_displayname_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(set_display_name::Response {}.into())
|
Ok(set_display_name::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/profile/{userId}/displayname`
|
/// # `GET /_matrix/client/r0/profile/{userId}/displayname`
|
||||||
|
@ -124,15 +117,11 @@ pub async fn set_displayname_route(
|
||||||
/// Returns the displayname of the user.
|
/// Returns the displayname of the user.
|
||||||
///
|
///
|
||||||
/// - If user is on another server: Fetches displayname over federation
|
/// - If user is on another server: Fetches displayname over federation
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/profile/<_>/displayname", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_displayname_route(
|
pub async fn get_displayname_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_display_name::Request<'_>>,
|
body: Ruma<get_display_name::Request<'_>>,
|
||||||
) -> ConduitResult<get_display_name::Response> {
|
) -> Result<get_display_name::Response> {
|
||||||
if body.user_id.server_name() != db.globals.server_name() {
|
if body.user_id.server_name() != db.globals.server_name() {
|
||||||
let response = db
|
let response = db
|
||||||
.sending
|
.sending
|
||||||
|
@ -148,14 +137,12 @@ pub async fn get_displayname_route(
|
||||||
|
|
||||||
return Ok(get_display_name::Response {
|
return Ok(get_display_name::Response {
|
||||||
displayname: response.displayname,
|
displayname: response.displayname,
|
||||||
}
|
});
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(get_display_name::Response {
|
Ok(get_display_name::Response {
|
||||||
displayname: db.users.displayname(&body.user_id)?,
|
displayname: db.users.displayname(&body.user_id)?,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/profile/{userId}/avatar_url`
|
/// # `PUT /_matrix/client/r0/profile/{userId}/avatar_url`
|
||||||
|
@ -163,15 +150,11 @@ pub async fn get_displayname_route(
|
||||||
/// Updates the avatar_url and blurhash.
|
/// Updates the avatar_url and blurhash.
|
||||||
///
|
///
|
||||||
/// - Also makes sure other users receive the update using presence EDUs
|
/// - Also makes sure other users receive the update using presence EDUs
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/profile/<_>/avatar_url", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn set_avatar_url_route(
|
pub async fn set_avatar_url_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<set_avatar_url::Request<'_>>,
|
body: Ruma<set_avatar_url::Request<'_>>,
|
||||||
) -> ConduitResult<set_avatar_url::Response> {
|
) -> Result<set_avatar_url::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
db.users
|
db.users
|
||||||
|
@ -259,7 +242,7 @@ pub async fn set_avatar_url_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(set_avatar_url::Response {}.into())
|
Ok(set_avatar_url::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/profile/{userId}/avatar_url`
|
/// # `GET /_matrix/client/r0/profile/{userId}/avatar_url`
|
||||||
|
@ -267,15 +250,11 @@ pub async fn set_avatar_url_route(
|
||||||
/// Returns the avatar_url and blurhash of the user.
|
/// Returns the avatar_url and blurhash of the user.
|
||||||
///
|
///
|
||||||
/// - If user is on another server: Fetches avatar_url and blurhash over federation
|
/// - If user is on another server: Fetches avatar_url and blurhash over federation
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/profile/<_>/avatar_url", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_avatar_url_route(
|
pub async fn get_avatar_url_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_avatar_url::Request<'_>>,
|
body: Ruma<get_avatar_url::Request<'_>>,
|
||||||
) -> ConduitResult<get_avatar_url::Response> {
|
) -> Result<get_avatar_url::Response> {
|
||||||
if body.user_id.server_name() != db.globals.server_name() {
|
if body.user_id.server_name() != db.globals.server_name() {
|
||||||
let response = db
|
let response = db
|
||||||
.sending
|
.sending
|
||||||
|
@ -292,15 +271,13 @@ pub async fn get_avatar_url_route(
|
||||||
return Ok(get_avatar_url::Response {
|
return Ok(get_avatar_url::Response {
|
||||||
avatar_url: response.avatar_url,
|
avatar_url: response.avatar_url,
|
||||||
blurhash: response.blurhash,
|
blurhash: response.blurhash,
|
||||||
}
|
});
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(get_avatar_url::Response {
|
Ok(get_avatar_url::Response {
|
||||||
avatar_url: db.users.avatar_url(&body.user_id)?,
|
avatar_url: db.users.avatar_url(&body.user_id)?,
|
||||||
blurhash: db.users.blurhash(&body.user_id)?,
|
blurhash: db.users.blurhash(&body.user_id)?,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/profile/{userId}`
|
/// # `GET /_matrix/client/r0/profile/{userId}`
|
||||||
|
@ -308,15 +285,11 @@ pub async fn get_avatar_url_route(
|
||||||
/// Returns the displayname, avatar_url and blurhash of the user.
|
/// Returns the displayname, avatar_url and blurhash of the user.
|
||||||
///
|
///
|
||||||
/// - If user is on another server: Fetches profile over federation
|
/// - If user is on another server: Fetches profile over federation
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/profile/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_profile_route(
|
pub async fn get_profile_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_profile::Request<'_>>,
|
body: Ruma<get_profile::Request<'_>>,
|
||||||
) -> ConduitResult<get_profile::Response> {
|
) -> Result<get_profile::Response> {
|
||||||
if body.user_id.server_name() != db.globals.server_name() {
|
if body.user_id.server_name() != db.globals.server_name() {
|
||||||
let response = db
|
let response = db
|
||||||
.sending
|
.sending
|
||||||
|
@ -334,8 +307,7 @@ pub async fn get_profile_route(
|
||||||
displayname: response.displayname,
|
displayname: response.displayname,
|
||||||
avatar_url: response.avatar_url,
|
avatar_url: response.avatar_url,
|
||||||
blurhash: response.blurhash,
|
blurhash: response.blurhash,
|
||||||
}
|
});
|
||||||
.into());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !db.users.exists(&body.user_id)? {
|
if !db.users.exists(&body.user_id)? {
|
||||||
|
@ -350,6 +322,5 @@ pub async fn get_profile_route(
|
||||||
avatar_url: db.users.avatar_url(&body.user_id)?,
|
avatar_url: db.users.avatar_url(&body.user_id)?,
|
||||||
blurhash: db.users.blurhash(&body.user_id)?,
|
blurhash: db.users.blurhash(&body.user_id)?,
|
||||||
displayname: db.users.displayname(&body.user_id)?,
|
displayname: db.users.displayname(&body.user_id)?,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{database::DatabaseGuard, ConduitResult, Error, Ruma};
|
use crate::{database::DatabaseGuard, Error, Result, Ruma};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::{
|
api::client::{
|
||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
|
@ -12,21 +12,14 @@ use ruma::{
|
||||||
push::{ConditionalPushRuleInit, PatternedPushRuleInit, SimplePushRuleInit},
|
push::{ConditionalPushRuleInit, PatternedPushRuleInit, SimplePushRuleInit},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{delete, get, post, put};
|
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/pushrules`
|
/// # `GET /_matrix/client/r0/pushrules`
|
||||||
///
|
///
|
||||||
/// Retrieves the push rules event for this user.
|
/// Retrieves the push rules event for this user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/pushrules", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_pushrules_all_route(
|
pub async fn get_pushrules_all_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_pushrules_all::Request>,
|
body: Ruma<get_pushrules_all::Request>,
|
||||||
) -> ConduitResult<get_pushrules_all::Response> {
|
) -> Result<get_pushrules_all::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let event: PushRulesEvent = db
|
let event: PushRulesEvent = db
|
||||||
|
@ -39,22 +32,17 @@ pub async fn get_pushrules_all_route(
|
||||||
|
|
||||||
Ok(get_pushrules_all::Response {
|
Ok(get_pushrules_all::Response {
|
||||||
global: event.content.global,
|
global: event.content.global,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}`
|
/// # `GET /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}`
|
||||||
///
|
///
|
||||||
/// Retrieves a single specified push rule for this user.
|
/// Retrieves a single specified push rule for this user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/pushrules/<_>/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_pushrule_route(
|
pub async fn get_pushrule_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_pushrule::Request<'_>>,
|
body: Ruma<get_pushrule::Request<'_>>,
|
||||||
) -> ConduitResult<get_pushrule::Response> {
|
) -> Result<get_pushrule::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let event: PushRulesEvent = db
|
let event: PushRulesEvent = db
|
||||||
|
@ -91,7 +79,7 @@ pub async fn get_pushrule_route(
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(rule) = rule {
|
if let Some(rule) = rule {
|
||||||
Ok(get_pushrule::Response { rule }.into())
|
Ok(get_pushrule::Response { rule })
|
||||||
} else {
|
} else {
|
||||||
Err(Error::BadRequest(
|
Err(Error::BadRequest(
|
||||||
ErrorKind::NotFound,
|
ErrorKind::NotFound,
|
||||||
|
@ -103,15 +91,11 @@ pub async fn get_pushrule_route(
|
||||||
/// # `PUT /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}`
|
/// # `PUT /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}`
|
||||||
///
|
///
|
||||||
/// Creates a single specified push rule for this user.
|
/// Creates a single specified push rule for this user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/pushrules/<_>/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn set_pushrule_route(
|
pub async fn set_pushrule_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<set_pushrule::Request<'_>>,
|
body: Ruma<set_pushrule::Request<'_>>,
|
||||||
) -> ConduitResult<set_pushrule::Response> {
|
) -> Result<set_pushrule::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let body = body.body;
|
let body = body.body;
|
||||||
|
|
||||||
|
@ -198,21 +182,17 @@ pub async fn set_pushrule_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(set_pushrule::Response {}.into())
|
Ok(set_pushrule::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/actions`
|
/// # `GET /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/actions`
|
||||||
///
|
///
|
||||||
/// Gets the actions of a single specified push rule for this user.
|
/// Gets the actions of a single specified push rule for this user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/pushrules/<_>/<_>/<_>/actions", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_pushrule_actions_route(
|
pub async fn get_pushrule_actions_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_pushrule_actions::Request<'_>>,
|
body: Ruma<get_pushrule_actions::Request<'_>>,
|
||||||
) -> ConduitResult<get_pushrule_actions::Response> {
|
) -> Result<get_pushrule_actions::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
if body.scope != "global" {
|
if body.scope != "global" {
|
||||||
|
@ -259,22 +239,17 @@ pub async fn get_pushrule_actions_route(
|
||||||
|
|
||||||
Ok(get_pushrule_actions::Response {
|
Ok(get_pushrule_actions::Response {
|
||||||
actions: actions.unwrap_or_default(),
|
actions: actions.unwrap_or_default(),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/actions`
|
/// # `PUT /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/actions`
|
||||||
///
|
///
|
||||||
/// Sets the actions of a single specified push rule for this user.
|
/// Sets the actions of a single specified push rule for this user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/pushrules/<_>/<_>/<_>/actions", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn set_pushrule_actions_route(
|
pub async fn set_pushrule_actions_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<set_pushrule_actions::Request<'_>>,
|
body: Ruma<set_pushrule_actions::Request<'_>>,
|
||||||
) -> ConduitResult<set_pushrule_actions::Response> {
|
) -> Result<set_pushrule_actions::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
if body.scope != "global" {
|
if body.scope != "global" {
|
||||||
|
@ -332,21 +307,17 @@ pub async fn set_pushrule_actions_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(set_pushrule_actions::Response {}.into())
|
Ok(set_pushrule_actions::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/enabled`
|
/// # `GET /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/enabled`
|
||||||
///
|
///
|
||||||
/// Gets the enabled status of a single specified push rule for this user.
|
/// Gets the enabled status of a single specified push rule for this user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/pushrules/<_>/<_>/<_>/enabled", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_pushrule_enabled_route(
|
pub async fn get_pushrule_enabled_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_pushrule_enabled::Request<'_>>,
|
body: Ruma<get_pushrule_enabled::Request<'_>>,
|
||||||
) -> ConduitResult<get_pushrule_enabled::Response> {
|
) -> Result<get_pushrule_enabled::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
if body.scope != "global" {
|
if body.scope != "global" {
|
||||||
|
@ -396,21 +367,17 @@ pub async fn get_pushrule_enabled_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(get_pushrule_enabled::Response { enabled }.into())
|
Ok(get_pushrule_enabled::Response { enabled })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/enabled`
|
/// # `PUT /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/enabled`
|
||||||
///
|
///
|
||||||
/// Sets the enabled status of a single specified push rule for this user.
|
/// Sets the enabled status of a single specified push rule for this user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/pushrules/<_>/<_>/<_>/enabled", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn set_pushrule_enabled_route(
|
pub async fn set_pushrule_enabled_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<set_pushrule_enabled::Request<'_>>,
|
body: Ruma<set_pushrule_enabled::Request<'_>>,
|
||||||
) -> ConduitResult<set_pushrule_enabled::Response> {
|
) -> Result<set_pushrule_enabled::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
if body.scope != "global" {
|
if body.scope != "global" {
|
||||||
|
@ -473,21 +440,17 @@ pub async fn set_pushrule_enabled_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(set_pushrule_enabled::Response {}.into())
|
Ok(set_pushrule_enabled::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `DELETE /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}`
|
/// # `DELETE /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}`
|
||||||
///
|
///
|
||||||
/// Deletes a single specified push rule for this user.
|
/// Deletes a single specified push rule for this user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
delete("/_matrix/client/r0/pushrules/<_>/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn delete_pushrule_route(
|
pub async fn delete_pushrule_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<delete_pushrule::Request<'_>>,
|
body: Ruma<delete_pushrule::Request<'_>>,
|
||||||
) -> ConduitResult<delete_pushrule::Response> {
|
) -> Result<delete_pushrule::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
if body.scope != "global" {
|
if body.scope != "global" {
|
||||||
|
@ -540,27 +503,22 @@ pub async fn delete_pushrule_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(delete_pushrule::Response {}.into())
|
Ok(delete_pushrule::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/pushers`
|
/// # `GET /_matrix/client/r0/pushers`
|
||||||
///
|
///
|
||||||
/// Gets all currently active pushers for the sender user.
|
/// Gets all currently active pushers for the sender user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/pushers", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_pushers_route(
|
pub async fn get_pushers_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_pushers::Request>,
|
body: Ruma<get_pushers::Request>,
|
||||||
) -> ConduitResult<get_pushers::Response> {
|
) -> Result<get_pushers::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
Ok(get_pushers::Response {
|
Ok(get_pushers::Response {
|
||||||
pushers: db.pusher.get_pushers(sender_user)?,
|
pushers: db.pusher.get_pushers(sender_user)?,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/pushers/set`
|
/// # `POST /_matrix/client/r0/pushers/set`
|
||||||
|
@ -568,15 +526,11 @@ pub async fn get_pushers_route(
|
||||||
/// Adds a pusher for the sender user.
|
/// Adds a pusher for the sender user.
|
||||||
///
|
///
|
||||||
/// - TODO: Handle `append`
|
/// - TODO: Handle `append`
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/pushers/set", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn set_pushers_route(
|
pub async fn set_pushers_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<set_pusher::Request>,
|
body: Ruma<set_pusher::Request>,
|
||||||
) -> ConduitResult<set_pusher::Response> {
|
) -> Result<set_pusher::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let pusher = body.pusher.clone();
|
let pusher = body.pusher.clone();
|
||||||
|
|
||||||
|
@ -584,5 +538,5 @@ pub async fn set_pushers_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(set_pusher::Response::default().into())
|
Ok(set_pusher::Response::default())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{database::DatabaseGuard, ConduitResult, Error, Ruma};
|
use crate::{database::DatabaseGuard, Error, Result, Ruma};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::{
|
api::client::{
|
||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
|
@ -10,24 +10,17 @@ use ruma::{
|
||||||
};
|
};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::post;
|
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/read_markers`
|
/// # `POST /_matrix/client/r0/rooms/{roomId}/read_markers`
|
||||||
///
|
///
|
||||||
/// Sets different types of read markers.
|
/// Sets different types of read markers.
|
||||||
///
|
///
|
||||||
/// - Updates fully-read account data event to `fully_read`
|
/// - Updates fully-read account data event to `fully_read`
|
||||||
/// - If `read_receipt` is set: Update private marker and public read receipt EDU
|
/// - If `read_receipt` is set: Update private marker and public read receipt EDU
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/rooms/<_>/read_markers", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn set_read_marker_route(
|
pub async fn set_read_marker_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<set_read_marker::Request<'_>>,
|
body: Ruma<set_read_marker::Request<'_>>,
|
||||||
) -> ConduitResult<set_read_marker::Response> {
|
) -> Result<set_read_marker::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let fully_read_event = ruma::events::fully_read::FullyReadEvent {
|
let fully_read_event = ruma::events::fully_read::FullyReadEvent {
|
||||||
|
@ -83,21 +76,17 @@ pub async fn set_read_marker_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(set_read_marker::Response {}.into())
|
Ok(set_read_marker::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/receipt/{receiptType}/{eventId}`
|
/// # `POST /_matrix/client/r0/rooms/{roomId}/receipt/{receiptType}/{eventId}`
|
||||||
///
|
///
|
||||||
/// Sets private read marker and public read receipt EDU.
|
/// Sets private read marker and public read receipt EDU.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/rooms/<_>/receipt/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn create_receipt_route(
|
pub async fn create_receipt_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<create_receipt::Request<'_>>,
|
body: Ruma<create_receipt::Request<'_>>,
|
||||||
) -> ConduitResult<create_receipt::Response> {
|
) -> Result<create_receipt::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
db.rooms.edus.private_read_set(
|
db.rooms.edus.private_read_set(
|
||||||
|
@ -139,5 +128,5 @@ pub async fn create_receipt_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(create_receipt::Response {}.into())
|
Ok(create_receipt::Response {})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::{database::DatabaseGuard, pdu::PduBuilder, ConduitResult, Ruma};
|
use crate::{database::DatabaseGuard, pdu::PduBuilder, Result, Ruma};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::r0::redact::redact_event,
|
api::client::r0::redact::redact_event,
|
||||||
events::{room::redaction::RoomRedactionEventContent, EventType},
|
events::{room::redaction::RoomRedactionEventContent, EventType},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::put;
|
|
||||||
use serde_json::value::to_raw_value;
|
use serde_json::value::to_raw_value;
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/rooms/{roomId}/redact/{eventId}/{txnId}`
|
/// # `PUT /_matrix/client/r0/rooms/{roomId}/redact/{eventId}/{txnId}`
|
||||||
|
@ -15,15 +13,11 @@ use serde_json::value::to_raw_value;
|
||||||
/// Tries to send a redaction event into the room.
|
/// Tries to send a redaction event into the room.
|
||||||
///
|
///
|
||||||
/// - TODO: Handle txn id
|
/// - TODO: Handle txn id
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/rooms/<_>/redact/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn redact_event_route(
|
pub async fn redact_event_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<redact_event::Request<'_>>,
|
body: Ruma<redact_event::Request<'_>>,
|
||||||
) -> ConduitResult<redact_event::Response> {
|
) -> Result<redact_event::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let body = body.body;
|
let body = body.body;
|
||||||
|
|
||||||
|
@ -59,5 +53,5 @@ pub async fn redact_event_route(
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
let event_id = (*event_id).to_owned();
|
let event_id = (*event_id).to_owned();
|
||||||
Ok(redact_event::Response { event_id }.into())
|
Ok(redact_event::Response { event_id })
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +1,19 @@
|
||||||
use crate::{database::DatabaseGuard, ConduitResult, Error, Ruma};
|
use crate::{database::DatabaseGuard, utils::HtmlEscape, Error, Result, Ruma};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::{error::ErrorKind, r0::room::report_content},
|
api::client::{error::ErrorKind, r0::room::report_content},
|
||||||
events::room::message,
|
events::room::message,
|
||||||
int,
|
int,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{http::RawStr, post};
|
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/report/{eventId}`
|
/// # `POST /_matrix/client/r0/rooms/{roomId}/report/{eventId}`
|
||||||
///
|
///
|
||||||
/// Reports an inappropriate event to homeserver admins
|
/// Reports an inappropriate event to homeserver admins
|
||||||
///
|
///
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/rooms/<_>/report/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn report_event_route(
|
pub async fn report_event_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<report_content::Request<'_>>,
|
body: Ruma<report_content::Request<'_>>,
|
||||||
) -> ConduitResult<report_content::Response> {
|
) -> Result<report_content::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let pdu = match db.rooms.get_pdu(&body.event_id)? {
|
let pdu = match db.rooms.get_pdu(&body.event_id)? {
|
||||||
|
@ -70,11 +63,11 @@ pub async fn report_event_route(
|
||||||
pdu.room_id,
|
pdu.room_id,
|
||||||
pdu.sender,
|
pdu.sender,
|
||||||
body.score,
|
body.score,
|
||||||
RawStr::new(&body.reason).html_escape()
|
HtmlEscape(&body.reason)
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(report_content::Response {}.into())
|
Ok(report_content::Response {})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
client_server::invite_helper, database::DatabaseGuard, pdu::PduBuilder, ConduitResult, Error,
|
client_server::invite_helper, database::DatabaseGuard, pdu::PduBuilder, Error, Result, Ruma,
|
||||||
Ruma,
|
|
||||||
};
|
};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::{
|
api::client::{
|
||||||
|
@ -30,9 +29,6 @@ use serde_json::{json, value::to_raw_value};
|
||||||
use std::{cmp::max, collections::BTreeMap, sync::Arc};
|
use std::{cmp::max, collections::BTreeMap, sync::Arc};
|
||||||
use tracing::{info, warn};
|
use tracing::{info, warn};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{get, post};
|
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/createRoom`
|
/// # `POST /_matrix/client/r0/createRoom`
|
||||||
///
|
///
|
||||||
/// Creates a new room.
|
/// Creates a new room.
|
||||||
|
@ -49,15 +45,11 @@ use rocket::{get, post};
|
||||||
/// - Send events listed in initial state
|
/// - Send events listed in initial state
|
||||||
/// - Send events implied by `name` and `topic`
|
/// - Send events implied by `name` and `topic`
|
||||||
/// - Send invite events
|
/// - Send invite events
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/createRoom", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn create_room_route(
|
pub async fn create_room_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<create_room::Request<'_>>,
|
body: Ruma<create_room::Request<'_>>,
|
||||||
) -> ConduitResult<create_room::Response> {
|
) -> Result<create_room::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let room_id = RoomId::new(db.globals.server_name());
|
let room_id = RoomId::new(db.globals.server_name());
|
||||||
|
@ -417,7 +409,7 @@ pub async fn create_room_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(create_room::Response::new(room_id).into())
|
Ok(create_room::Response::new(room_id))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/rooms/{roomId}/event/{eventId}`
|
/// # `GET /_matrix/client/r0/rooms/{roomId}/event/{eventId}`
|
||||||
|
@ -425,15 +417,11 @@ pub async fn create_room_route(
|
||||||
/// Gets a single event.
|
/// Gets a single event.
|
||||||
///
|
///
|
||||||
/// - You have to currently be joined to the room (TODO: Respect history visibility)
|
/// - You have to currently be joined to the room (TODO: Respect history visibility)
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/rooms/<_>/event/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_room_event_route(
|
pub async fn get_room_event_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_room_event::Request<'_>>,
|
body: Ruma<get_room_event::Request<'_>>,
|
||||||
) -> ConduitResult<get_room_event::Response> {
|
) -> Result<get_room_event::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
if !db.rooms.is_joined(sender_user, &body.room_id)? {
|
if !db.rooms.is_joined(sender_user, &body.room_id)? {
|
||||||
|
@ -449,8 +437,7 @@ pub async fn get_room_event_route(
|
||||||
.get_pdu(&body.event_id)?
|
.get_pdu(&body.event_id)?
|
||||||
.ok_or(Error::BadRequest(ErrorKind::NotFound, "Event not found."))?
|
.ok_or(Error::BadRequest(ErrorKind::NotFound, "Event not found."))?
|
||||||
.to_room_event(),
|
.to_room_event(),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/rooms/{roomId}/aliases`
|
/// # `GET /_matrix/client/r0/rooms/{roomId}/aliases`
|
||||||
|
@ -458,15 +445,11 @@ pub async fn get_room_event_route(
|
||||||
/// Lists all aliases of the room.
|
/// Lists all aliases of the room.
|
||||||
///
|
///
|
||||||
/// - Only users joined to the room are allowed to call this TODO: Allow any user to call it if history_visibility is world readable
|
/// - Only users joined to the room are allowed to call this TODO: Allow any user to call it if history_visibility is world readable
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/rooms/<_>/aliases", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_room_aliases_route(
|
pub async fn get_room_aliases_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<aliases::Request<'_>>,
|
body: Ruma<aliases::Request<'_>>,
|
||||||
) -> ConduitResult<aliases::Response> {
|
) -> Result<aliases::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
if !db.rooms.is_joined(sender_user, &body.room_id)? {
|
if !db.rooms.is_joined(sender_user, &body.room_id)? {
|
||||||
|
@ -482,8 +465,7 @@ pub async fn get_room_aliases_route(
|
||||||
.room_aliases(&body.room_id)
|
.room_aliases(&body.room_id)
|
||||||
.filter_map(|a| a.ok())
|
.filter_map(|a| a.ok())
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/rooms/{roomId}/upgrade`
|
/// # `POST /_matrix/client/r0/rooms/{roomId}/upgrade`
|
||||||
|
@ -496,15 +478,11 @@ pub async fn get_room_aliases_route(
|
||||||
/// - Transfers some state events
|
/// - Transfers some state events
|
||||||
/// - Moves local aliases
|
/// - Moves local aliases
|
||||||
/// - Modifies old room power levels to prevent users from speaking
|
/// - Modifies old room power levels to prevent users from speaking
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/rooms/<_>/upgrade", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn upgrade_room_route(
|
pub async fn upgrade_room_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<upgrade_room::Request<'_>>,
|
body: Ruma<upgrade_room::Request<'_>>,
|
||||||
) -> ConduitResult<upgrade_room::Response> {
|
) -> Result<upgrade_room::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
if !matches!(body.new_version, RoomVersionId::V5 | RoomVersionId::V6) {
|
if !matches!(body.new_version, RoomVersionId::V5 | RoomVersionId::V6) {
|
||||||
|
@ -728,5 +706,5 @@ pub async fn upgrade_room_route(
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
// Return the replacement room id
|
// Return the replacement room id
|
||||||
Ok(upgrade_room::Response { replacement_room }.into())
|
Ok(upgrade_room::Response { replacement_room })
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
use crate::{database::DatabaseGuard, ConduitResult, Error, Ruma};
|
use crate::{database::DatabaseGuard, Error, Result, Ruma};
|
||||||
use ruma::api::client::{error::ErrorKind, r0::search::search_events};
|
use ruma::api::client::{error::ErrorKind, r0::search::search_events};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::post;
|
|
||||||
use search_events::{EventContextResult, ResultCategories, ResultRoomEvents, SearchResult};
|
use search_events::{EventContextResult, ResultCategories, ResultRoomEvents, SearchResult};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
|
@ -11,19 +9,15 @@ use std::collections::BTreeMap;
|
||||||
/// Searches rooms for messages.
|
/// Searches rooms for messages.
|
||||||
///
|
///
|
||||||
/// - Only works if the user is currently joined to the room (TODO: Respect history visibility)
|
/// - Only works if the user is currently joined to the room (TODO: Respect history visibility)
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/search", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn search_events_route(
|
pub async fn search_events_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<search_events::Request<'_>>,
|
body: Ruma<search_events::Request<'_>>,
|
||||||
) -> ConduitResult<search_events::Response> {
|
) -> Result<search_events::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let search_criteria = body.search_categories.room_events.as_ref().unwrap();
|
let search_criteria = body.search_categories.room_events.as_ref().unwrap();
|
||||||
let filter = search_criteria.filter.clone().unwrap_or_default();
|
let filter = &search_criteria.filter;
|
||||||
|
|
||||||
let room_ids = filter.rooms.clone().unwrap_or_else(|| {
|
let room_ids = filter.rooms.clone().unwrap_or_else(|| {
|
||||||
db.rooms
|
db.rooms
|
||||||
|
@ -117,6 +111,5 @@ pub async fn search_events_route(
|
||||||
.map(str::to_lowercase)
|
.map(str::to_lowercase)
|
||||||
.collect(),
|
.collect(),
|
||||||
},
|
},
|
||||||
})
|
}))
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::{DEVICE_ID_LENGTH, TOKEN_LENGTH};
|
use super::{DEVICE_ID_LENGTH, TOKEN_LENGTH};
|
||||||
use crate::{database::DatabaseGuard, utils, ConduitResult, Error, Ruma};
|
use crate::{database::DatabaseGuard, utils, Error, Result, Ruma};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::{
|
api::client::{
|
||||||
error::ErrorKind,
|
error::ErrorKind,
|
||||||
|
@ -19,22 +19,17 @@ struct Claims {
|
||||||
exp: usize,
|
exp: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{get, post};
|
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/login`
|
/// # `GET /_matrix/client/r0/login`
|
||||||
///
|
///
|
||||||
/// Get the supported login types of this server. One of these should be used as the `type` field
|
/// Get the supported login types of this server. One of these should be used as the `type` field
|
||||||
/// when logging in.
|
/// when logging in.
|
||||||
#[cfg_attr(feature = "conduit_bin", get("/_matrix/client/r0/login"))]
|
#[tracing::instrument(skip(_body))]
|
||||||
#[tracing::instrument]
|
pub async fn get_login_types_route(
|
||||||
pub async fn get_login_types_route() -> ConduitResult<get_login_types::Response> {
|
_body: Ruma<get_login_types::Request>,
|
||||||
Ok(
|
) -> Result<get_login_types::Response> {
|
||||||
get_login_types::Response::new(vec![get_login_types::LoginType::Password(
|
Ok(get_login_types::Response::new(vec![
|
||||||
Default::default(),
|
get_login_types::LoginType::Password(Default::default()),
|
||||||
)])
|
]))
|
||||||
.into(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/login`
|
/// # `POST /_matrix/client/r0/login`
|
||||||
|
@ -48,15 +43,11 @@ pub async fn get_login_types_route() -> ConduitResult<get_login_types::Response>
|
||||||
///
|
///
|
||||||
/// Note: You can use [`GET /_matrix/client/r0/login`](fn.get_supported_versions_route.html) to see
|
/// Note: You can use [`GET /_matrix/client/r0/login`](fn.get_supported_versions_route.html) to see
|
||||||
/// supported login types.
|
/// supported login types.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/login", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn login_route(
|
pub async fn login_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<login::Request<'_>>,
|
body: Ruma<login::Request<'_>>,
|
||||||
) -> ConduitResult<login::Response> {
|
) -> Result<login::Response> {
|
||||||
// Validate login method
|
// Validate login method
|
||||||
// TODO: Other login methods
|
// TODO: Other login methods
|
||||||
let user_id = match &body.login_info {
|
let user_id = match &body.login_info {
|
||||||
|
@ -161,8 +152,7 @@ pub async fn login_route(
|
||||||
home_server: Some(db.globals.server_name().to_owned()),
|
home_server: Some(db.globals.server_name().to_owned()),
|
||||||
device_id,
|
device_id,
|
||||||
well_known: None,
|
well_known: None,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/logout`
|
/// # `POST /_matrix/client/r0/logout`
|
||||||
|
@ -173,15 +163,11 @@ pub async fn login_route(
|
||||||
/// - Deletes device metadata (device id, device display name, last seen ip, last seen ts)
|
/// - Deletes device metadata (device id, device display name, last seen ip, last seen ts)
|
||||||
/// - Forgets to-device events
|
/// - Forgets to-device events
|
||||||
/// - Triggers device list updates
|
/// - Triggers device list updates
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/logout", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn logout_route(
|
pub async fn logout_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<logout::Request>,
|
body: Ruma<logout::Request>,
|
||||||
) -> ConduitResult<logout::Response> {
|
) -> Result<logout::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
let sender_device = body.sender_device.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
|
@ -189,7 +175,7 @@ pub async fn logout_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(logout::Response::new().into())
|
Ok(logout::Response::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/logout/all`
|
/// # `POST /_matrix/client/r0/logout/all`
|
||||||
|
@ -203,15 +189,11 @@ pub async fn logout_route(
|
||||||
///
|
///
|
||||||
/// Note: This is equivalent to calling [`GET /_matrix/client/r0/logout`](fn.logout_route.html)
|
/// Note: This is equivalent to calling [`GET /_matrix/client/r0/logout`](fn.logout_route.html)
|
||||||
/// from each device of this user.
|
/// from each device of this user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/logout/all", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn logout_all_route(
|
pub async fn logout_all_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<logout_all::Request>,
|
body: Ruma<logout_all::Request>,
|
||||||
) -> ConduitResult<logout_all::Response> {
|
) -> Result<logout_all::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
for device_id in db.users.all_device_ids(sender_user).flatten() {
|
for device_id in db.users.all_device_ids(sender_user).flatten() {
|
||||||
|
@ -220,5 +202,5 @@ pub async fn logout_all_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(logout_all::Response::new().into())
|
Ok(logout_all::Response::new())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
database::DatabaseGuard, pdu::PduBuilder, ConduitResult, Database, Error, Result, Ruma,
|
database::DatabaseGuard, pdu::PduBuilder, Database, Error, Result, Ruma, RumaResponse,
|
||||||
};
|
};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::{
|
api::client::{
|
||||||
|
@ -19,9 +19,6 @@ use ruma::{
|
||||||
EventId, RoomId, UserId,
|
EventId, RoomId, UserId,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{get, put};
|
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/rooms/{roomId}/state/{eventType}/{stateKey}`
|
/// # `PUT /_matrix/client/r0/rooms/{roomId}/state/{eventType}/{stateKey}`
|
||||||
///
|
///
|
||||||
/// Sends a state event into the room.
|
/// Sends a state event into the room.
|
||||||
|
@ -29,15 +26,11 @@ use rocket::{get, put};
|
||||||
/// - The only requirement for the content is that it has to be valid json
|
/// - The only requirement for the content is that it has to be valid json
|
||||||
/// - Tries to send the event into the room, auth rules will determine if it is allowed
|
/// - Tries to send the event into the room, auth rules will determine if it is allowed
|
||||||
/// - If event is new canonical_alias: Rejects if alias is incorrect
|
/// - If event is new canonical_alias: Rejects if alias is incorrect
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/rooms/<_>/state/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn send_state_event_for_key_route(
|
pub async fn send_state_event_for_key_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<send_state_event::Request<'_>>,
|
body: Ruma<send_state_event::Request<'_>>,
|
||||||
) -> ConduitResult<send_state_event::Response> {
|
) -> Result<send_state_event::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let event_id = send_state_event_for_key_helper(
|
let event_id = send_state_event_for_key_helper(
|
||||||
|
@ -53,7 +46,7 @@ pub async fn send_state_event_for_key_route(
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
let event_id = (*event_id).to_owned();
|
let event_id = (*event_id).to_owned();
|
||||||
Ok(send_state_event::Response { event_id }.into())
|
Ok(send_state_event::Response { event_id })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/rooms/{roomId}/state/{eventType}`
|
/// # `PUT /_matrix/client/r0/rooms/{roomId}/state/{eventType}`
|
||||||
|
@ -63,15 +56,11 @@ pub async fn send_state_event_for_key_route(
|
||||||
/// - The only requirement for the content is that it has to be valid json
|
/// - The only requirement for the content is that it has to be valid json
|
||||||
/// - Tries to send the event into the room, auth rules will determine if it is allowed
|
/// - Tries to send the event into the room, auth rules will determine if it is allowed
|
||||||
/// - If event is new canonical_alias: Rejects if alias is incorrect
|
/// - If event is new canonical_alias: Rejects if alias is incorrect
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/rooms/<_>/state/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn send_state_event_for_empty_key_route(
|
pub async fn send_state_event_for_empty_key_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<send_state_event::Request<'_>>,
|
body: Ruma<send_state_event::Request<'_>>,
|
||||||
) -> ConduitResult<send_state_event::Response> {
|
) -> Result<RumaResponse<send_state_event::Response>> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
// Forbid m.room.encryption if encryption is disabled
|
// Forbid m.room.encryption if encryption is disabled
|
||||||
|
@ -103,15 +92,11 @@ pub async fn send_state_event_for_empty_key_route(
|
||||||
/// Get all state events for a room.
|
/// Get all state events for a room.
|
||||||
///
|
///
|
||||||
/// - If not joined: Only works if current room history visibility is world readable
|
/// - If not joined: Only works if current room history visibility is world readable
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/rooms/<_>/state", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_state_events_route(
|
pub async fn get_state_events_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_state_events::Request<'_>>,
|
body: Ruma<get_state_events::Request<'_>>,
|
||||||
) -> ConduitResult<get_state_events::Response> {
|
) -> Result<get_state_events::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
#[allow(clippy::blocks_in_if_conditions)]
|
#[allow(clippy::blocks_in_if_conditions)]
|
||||||
|
@ -146,8 +131,7 @@ pub async fn get_state_events_route(
|
||||||
.values()
|
.values()
|
||||||
.map(|pdu| pdu.to_state_event())
|
.map(|pdu| pdu.to_state_event())
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/rooms/{roomid}/state/{eventType}/{stateKey}`
|
/// # `GET /_matrix/client/r0/rooms/{roomid}/state/{eventType}/{stateKey}`
|
||||||
|
@ -155,15 +139,11 @@ pub async fn get_state_events_route(
|
||||||
/// Get single state event of a room.
|
/// Get single state event of a room.
|
||||||
///
|
///
|
||||||
/// - If not joined: Only works if current room history visibility is world readable
|
/// - If not joined: Only works if current room history visibility is world readable
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/rooms/<_>/state/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_state_events_for_key_route(
|
pub async fn get_state_events_for_key_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_state_events_for_key::Request<'_>>,
|
body: Ruma<get_state_events_for_key::Request<'_>>,
|
||||||
) -> ConduitResult<get_state_events_for_key::Response> {
|
) -> Result<get_state_events_for_key::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
#[allow(clippy::blocks_in_if_conditions)]
|
#[allow(clippy::blocks_in_if_conditions)]
|
||||||
|
@ -202,8 +182,7 @@ pub async fn get_state_events_for_key_route(
|
||||||
Ok(get_state_events_for_key::Response {
|
Ok(get_state_events_for_key::Response {
|
||||||
content: serde_json::from_str(event.content.get())
|
content: serde_json::from_str(event.content.get())
|
||||||
.map_err(|_| Error::bad_database("Invalid event content in database"))?,
|
.map_err(|_| Error::bad_database("Invalid event content in database"))?,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/rooms/{roomid}/state/{eventType}`
|
/// # `GET /_matrix/client/r0/rooms/{roomid}/state/{eventType}`
|
||||||
|
@ -211,15 +190,11 @@ pub async fn get_state_events_for_key_route(
|
||||||
/// Get single state event of a room.
|
/// Get single state event of a room.
|
||||||
///
|
///
|
||||||
/// - If not joined: Only works if current room history visibility is world readable
|
/// - If not joined: Only works if current room history visibility is world readable
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/rooms/<_>/state/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_state_events_for_empty_key_route(
|
pub async fn get_state_events_for_empty_key_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_state_events_for_key::Request<'_>>,
|
body: Ruma<get_state_events_for_key::Request<'_>>,
|
||||||
) -> ConduitResult<get_state_events_for_key::Response> {
|
) -> Result<RumaResponse<get_state_events_for_key::Response>> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
#[allow(clippy::blocks_in_if_conditions)]
|
#[allow(clippy::blocks_in_if_conditions)]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{database::DatabaseGuard, ConduitResult, Database, Error, Result, Ruma, RumaResponse};
|
use crate::{database::DatabaseGuard, Database, Error, Result, Ruma, RumaResponse};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::r0::{
|
api::client::r0::{
|
||||||
filter::{IncomingFilterDefinition, LazyLoadOptions},
|
filter::{IncomingFilterDefinition, LazyLoadOptions},
|
||||||
|
@ -20,9 +20,6 @@ use std::{
|
||||||
use tokio::sync::watch::Sender;
|
use tokio::sync::watch::Sender;
|
||||||
use tracing::error;
|
use tracing::error;
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{get, tokio};
|
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/sync`
|
/// # `GET /_matrix/client/r0/sync`
|
||||||
///
|
///
|
||||||
/// Synchronize the client's state with the latest state on the server.
|
/// Synchronize the client's state with the latest state on the server.
|
||||||
|
@ -57,15 +54,11 @@ use rocket::{get, tokio};
|
||||||
///
|
///
|
||||||
/// - Sync is handled in an async task, multiple requests from the same device with the same
|
/// - Sync is handled in an async task, multiple requests from the same device with the same
|
||||||
/// `since` will be cached
|
/// `since` will be cached
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/sync", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn sync_events_route(
|
pub async fn sync_events_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<sync_events::Request<'_>>,
|
body: Ruma<sync_events::Request<'_>>,
|
||||||
) -> Result<RumaResponse<sync_events::Response>, RumaResponse<UiaaResponse>> {
|
) -> Result<sync_events::Response, RumaResponse<UiaaResponse>> {
|
||||||
let sender_user = body.sender_user.expect("user is authenticated");
|
let sender_user = body.sender_user.expect("user is authenticated");
|
||||||
let sender_device = body.sender_device.expect("user is authenticated");
|
let sender_device = body.sender_device.expect("user is authenticated");
|
||||||
let body = body.body;
|
let body = body.body;
|
||||||
|
@ -139,7 +132,7 @@ async fn sync_helper_wrapper(
|
||||||
sender_user: Box<UserId>,
|
sender_user: Box<UserId>,
|
||||||
sender_device: Box<DeviceId>,
|
sender_device: Box<DeviceId>,
|
||||||
body: sync_events::IncomingRequest,
|
body: sync_events::IncomingRequest,
|
||||||
tx: Sender<Option<ConduitResult<sync_events::Response>>>,
|
tx: Sender<Option<Result<sync_events::Response>>>,
|
||||||
) {
|
) {
|
||||||
let since = body.since.clone();
|
let since = body.since.clone();
|
||||||
|
|
||||||
|
@ -173,7 +166,7 @@ async fn sync_helper_wrapper(
|
||||||
|
|
||||||
drop(db);
|
drop(db);
|
||||||
|
|
||||||
let _ = tx.send(Some(r.map(|(r, _)| r.into())));
|
let _ = tx.send(Some(r.map(|(r, _)| r)));
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn sync_helper(
|
async fn sync_helper(
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{database::DatabaseGuard, ConduitResult, Ruma};
|
use crate::{database::DatabaseGuard, Result, Ruma};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::r0::tag::{create_tag, delete_tag, get_tags},
|
api::client::r0::tag::{create_tag, delete_tag, get_tags},
|
||||||
events::{
|
events::{
|
||||||
|
@ -8,23 +8,16 @@ use ruma::{
|
||||||
};
|
};
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{delete, get, put};
|
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/user/{userId}/rooms/{roomId}/tags/{tag}`
|
/// # `PUT /_matrix/client/r0/user/{userId}/rooms/{roomId}/tags/{tag}`
|
||||||
///
|
///
|
||||||
/// Adds a tag to the room.
|
/// Adds a tag to the room.
|
||||||
///
|
///
|
||||||
/// - Inserts the tag into the tag event of the room account data.
|
/// - Inserts the tag into the tag event of the room account data.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/user/<_>/rooms/<_>/tags/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn update_tag_route(
|
pub async fn update_tag_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<create_tag::Request<'_>>,
|
body: Ruma<create_tag::Request<'_>>,
|
||||||
) -> ConduitResult<create_tag::Response> {
|
) -> Result<create_tag::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let mut tags_event = db
|
let mut tags_event = db
|
||||||
|
@ -50,7 +43,7 @@ pub async fn update_tag_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(create_tag::Response {}.into())
|
Ok(create_tag::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `DELETE /_matrix/client/r0/user/{userId}/rooms/{roomId}/tags/{tag}`
|
/// # `DELETE /_matrix/client/r0/user/{userId}/rooms/{roomId}/tags/{tag}`
|
||||||
|
@ -58,15 +51,11 @@ pub async fn update_tag_route(
|
||||||
/// Deletes a tag from the room.
|
/// Deletes a tag from the room.
|
||||||
///
|
///
|
||||||
/// - Removes the tag from the tag event of the room account data.
|
/// - Removes the tag from the tag event of the room account data.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
delete("/_matrix/client/r0/user/<_>/rooms/<_>/tags/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn delete_tag_route(
|
pub async fn delete_tag_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<delete_tag::Request<'_>>,
|
body: Ruma<delete_tag::Request<'_>>,
|
||||||
) -> ConduitResult<delete_tag::Response> {
|
) -> Result<delete_tag::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let mut tags_event = db
|
let mut tags_event = db
|
||||||
|
@ -89,7 +78,7 @@ pub async fn delete_tag_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(delete_tag::Response {}.into())
|
Ok(delete_tag::Response {})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/user/{userId}/rooms/{roomId}/tags`
|
/// # `GET /_matrix/client/r0/user/{userId}/rooms/{roomId}/tags`
|
||||||
|
@ -97,15 +86,11 @@ pub async fn delete_tag_route(
|
||||||
/// Returns tags on the room.
|
/// Returns tags on the room.
|
||||||
///
|
///
|
||||||
/// - Gets the tag event of the room account data.
|
/// - Gets the tag event of the room account data.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/user/<_>/rooms/<_>/tags", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_tags_route(
|
pub async fn get_tags_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_tags::Request<'_>>,
|
body: Ruma<get_tags::Request<'_>>,
|
||||||
) -> ConduitResult<get_tags::Response> {
|
) -> Result<get_tags::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
Ok(get_tags::Response {
|
Ok(get_tags::Response {
|
||||||
|
@ -119,6 +104,5 @@ pub async fn get_tags_route(
|
||||||
})
|
})
|
||||||
.content
|
.content
|
||||||
.tags,
|
.tags,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,17 @@
|
||||||
use crate::ConduitResult;
|
use crate::{Result, Ruma};
|
||||||
use ruma::api::client::r0::thirdparty::get_protocols;
|
use ruma::api::client::r0::thirdparty::get_protocols;
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::get;
|
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/thirdparty/protocols`
|
/// # `GET /_matrix/client/r0/thirdparty/protocols`
|
||||||
///
|
///
|
||||||
/// TODO: Fetches all metadata about protocols supported by the homeserver.
|
/// TODO: Fetches all metadata about protocols supported by the homeserver.
|
||||||
#[cfg_attr(
|
#[tracing::instrument(skip(_body))]
|
||||||
feature = "conduit_bin",
|
pub async fn get_protocols_route(
|
||||||
get("/_matrix/client/r0/thirdparty/protocols")
|
_body: Ruma<get_protocols::Request>,
|
||||||
)]
|
) -> Result<get_protocols::Response> {
|
||||||
#[tracing::instrument]
|
|
||||||
pub async fn get_protocols_route() -> ConduitResult<get_protocols::Response> {
|
|
||||||
// TODO
|
// TODO
|
||||||
Ok(get_protocols::Response {
|
Ok(get_protocols::Response {
|
||||||
protocols: BTreeMap::new(),
|
protocols: BTreeMap::new(),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use crate::{database::DatabaseGuard, ConduitResult, Error, Ruma};
|
use crate::{database::DatabaseGuard, Error, Result, Ruma};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::{
|
api::{
|
||||||
client::{error::ErrorKind, r0::to_device::send_event_to_device},
|
client::{error::ErrorKind, r0::to_device::send_event_to_device},
|
||||||
|
@ -10,21 +10,14 @@ use ruma::{
|
||||||
to_device::DeviceIdOrAllDevices,
|
to_device::DeviceIdOrAllDevices,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::put;
|
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/sendToDevice/{eventType}/{txnId}`
|
/// # `PUT /_matrix/client/r0/sendToDevice/{eventType}/{txnId}`
|
||||||
///
|
///
|
||||||
/// Send a to-device event to a set of client devices.
|
/// Send a to-device event to a set of client devices.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/sendToDevice/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn send_event_to_device_route(
|
pub async fn send_event_to_device_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<send_event_to_device::Request<'_>>,
|
body: Ruma<send_event_to_device::Request<'_>>,
|
||||||
) -> ConduitResult<send_event_to_device::Response> {
|
) -> Result<send_event_to_device::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
let sender_device = body.sender_device.as_deref();
|
let sender_device = body.sender_device.as_deref();
|
||||||
|
|
||||||
|
@ -101,5 +94,5 @@ pub async fn send_event_to_device_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(send_event_to_device::Response {}.into())
|
Ok(send_event_to_device::Response {})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +1,15 @@
|
||||||
use crate::{database::DatabaseGuard, utils, ConduitResult, Ruma};
|
use crate::{database::DatabaseGuard, utils, Result, Ruma};
|
||||||
use create_typing_event::Typing;
|
use create_typing_event::Typing;
|
||||||
use ruma::api::client::r0::typing::create_typing_event;
|
use ruma::api::client::r0::typing::create_typing_event;
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::put;
|
|
||||||
|
|
||||||
/// # `PUT /_matrix/client/r0/rooms/{roomId}/typing/{userId}`
|
/// # `PUT /_matrix/client/r0/rooms/{roomId}/typing/{userId}`
|
||||||
///
|
///
|
||||||
/// Sets the typing state of the sender user.
|
/// Sets the typing state of the sender user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/client/r0/rooms/<_>/typing/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub fn create_typing_event_route(
|
pub async fn create_typing_event_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<create_typing_event::Request<'_>>,
|
body: Ruma<create_typing_event::Request<'_>>,
|
||||||
) -> ConduitResult<create_typing_event::Response> {
|
) -> Result<create_typing_event::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
if let Typing::Yes(duration) = body.state {
|
if let Typing::Yes(duration) = body.state {
|
||||||
|
@ -32,5 +25,5 @@ pub fn create_typing_event_route(
|
||||||
.typing_remove(sender_user, &body.room_id, &db.globals)?;
|
.typing_remove(sender_user, &body.room_id, &db.globals)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(create_typing_event::Response {}.into())
|
Ok(create_typing_event::Response {})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
use std::{collections::BTreeMap, iter::FromIterator};
|
use std::{collections::BTreeMap, iter::FromIterator};
|
||||||
|
|
||||||
use crate::ConduitResult;
|
use crate::{Result, Ruma};
|
||||||
use ruma::api::client::unversioned::get_supported_versions;
|
use ruma::api::client::unversioned::get_supported_versions;
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::get;
|
|
||||||
|
|
||||||
/// # `GET /_matrix/client/versions`
|
/// # `GET /_matrix/client/versions`
|
||||||
///
|
///
|
||||||
/// Get the versions of the specification and unstable features supported by this server.
|
/// Get the versions of the specification and unstable features supported by this server.
|
||||||
|
@ -16,13 +13,14 @@ use rocket::get;
|
||||||
///
|
///
|
||||||
/// Note: Unstable features are used while developing new features. Clients should avoid using
|
/// Note: Unstable features are used while developing new features. Clients should avoid using
|
||||||
/// unstable features in their stable releases
|
/// unstable features in their stable releases
|
||||||
#[cfg_attr(feature = "conduit_bin", get("/_matrix/client/versions"))]
|
#[tracing::instrument(skip(_body))]
|
||||||
#[tracing::instrument]
|
pub async fn get_supported_versions_route(
|
||||||
pub async fn get_supported_versions_route() -> ConduitResult<get_supported_versions::Response> {
|
_body: Ruma<get_supported_versions::Request>,
|
||||||
|
) -> Result<get_supported_versions::Response> {
|
||||||
let resp = get_supported_versions::Response {
|
let resp = get_supported_versions::Response {
|
||||||
versions: vec!["r0.5.0".to_owned(), "r0.6.0".to_owned()],
|
versions: vec!["r0.5.0".to_owned(), "r0.6.0".to_owned()],
|
||||||
unstable_features: BTreeMap::from_iter([("org.matrix.e2e_cross_signing".to_owned(), true)]),
|
unstable_features: BTreeMap::from_iter([("org.matrix.e2e_cross_signing".to_owned(), true)]),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(resp.into())
|
Ok(resp)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,16 @@
|
||||||
use crate::{database::DatabaseGuard, ConduitResult, Ruma};
|
use crate::{database::DatabaseGuard, Result, Ruma};
|
||||||
use ruma::api::client::r0::user_directory::search_users;
|
use ruma::api::client::r0::user_directory::search_users;
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::post;
|
|
||||||
|
|
||||||
/// # `POST /_matrix/client/r0/user_directory/search`
|
/// # `POST /_matrix/client/r0/user_directory/search`
|
||||||
///
|
///
|
||||||
/// Searches all known users for a match.
|
/// Searches all known users for a match.
|
||||||
///
|
///
|
||||||
/// - TODO: Hide users that are not in any public rooms?
|
/// - TODO: Hide users that are not in any public rooms?
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/client/r0/user_directory/search", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn search_users_route(
|
pub async fn search_users_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<search_users::Request<'_>>,
|
body: Ruma<search_users::Request<'_>>,
|
||||||
) -> ConduitResult<search_users::Response> {
|
) -> Result<search_users::Response> {
|
||||||
let limit = u64::from(body.limit) as usize;
|
let limit = u64::from(body.limit) as usize;
|
||||||
|
|
||||||
let mut users = db.users.iter().filter_map(|user_id| {
|
let mut users = db.users.iter().filter_map(|user_id| {
|
||||||
|
@ -55,5 +48,5 @@ pub async fn search_users_route(
|
||||||
let results = users.by_ref().take(limit).collect();
|
let results = users.by_ref().take(limit).collect();
|
||||||
let limited = users.next().is_some();
|
let limited = users.next().is_some();
|
||||||
|
|
||||||
Ok(search_users::Response { results, limited }.into())
|
Ok(search_users::Response { results, limited })
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,27 +1,19 @@
|
||||||
use crate::{database::DatabaseGuard, ConduitResult, Ruma};
|
use crate::{database::DatabaseGuard, Result, Ruma};
|
||||||
use hmac::{Hmac, Mac, NewMac};
|
use hmac::{Hmac, Mac, NewMac};
|
||||||
use ruma::api::client::r0::voip::get_turn_server_info;
|
use ruma::{api::client::r0::voip::get_turn_server_info, SecondsSinceUnixEpoch};
|
||||||
use ruma::SecondsSinceUnixEpoch;
|
|
||||||
use sha1::Sha1;
|
use sha1::Sha1;
|
||||||
use std::time::{Duration, SystemTime};
|
use std::time::{Duration, SystemTime};
|
||||||
|
|
||||||
type HmacSha1 = Hmac<Sha1>;
|
type HmacSha1 = Hmac<Sha1>;
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::get;
|
|
||||||
|
|
||||||
/// # `GET /_matrix/client/r0/voip/turnServer`
|
/// # `GET /_matrix/client/r0/voip/turnServer`
|
||||||
///
|
///
|
||||||
/// TODO: Returns information about the recommended turn server.
|
/// TODO: Returns information about the recommended turn server.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/client/r0/voip/turnServer", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(body, db))]
|
#[tracing::instrument(skip(body, db))]
|
||||||
pub async fn turn_server_route(
|
pub async fn turn_server_route(
|
||||||
body: Ruma<get_turn_server_info::Request>,
|
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
) -> ConduitResult<get_turn_server_info::Response> {
|
body: Ruma<get_turn_server_info::Request>,
|
||||||
|
) -> Result<get_turn_server_info::Response> {
|
||||||
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
let sender_user = body.sender_user.as_ref().expect("user is authenticated");
|
||||||
|
|
||||||
let turn_secret = db.globals.turn_secret();
|
let turn_secret = db.globals.turn_secret();
|
||||||
|
@ -53,6 +45,5 @@ pub async fn turn_server_route(
|
||||||
password,
|
password,
|
||||||
uris: db.globals.turn_uris().to_vec(),
|
uris: db.globals.turn_uris().to_vec(),
|
||||||
ttl: Duration::from_secs(db.globals.turn_ttl()),
|
ttl: Duration::from_secs(db.globals.turn_ttl()),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use std::collections::BTreeMap;
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
net::{IpAddr, Ipv4Addr},
|
||||||
|
};
|
||||||
|
|
||||||
use ruma::ServerName;
|
use ruma::ServerName;
|
||||||
use serde::{de::IgnoredAny, Deserialize};
|
use serde::{de::IgnoredAny, Deserialize};
|
||||||
|
@ -10,6 +13,12 @@ use self::proxy::ProxyConfig;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
|
#[serde(default = "default_address")]
|
||||||
|
pub address: IpAddr,
|
||||||
|
#[serde(default = "default_port")]
|
||||||
|
pub port: u16,
|
||||||
|
pub tls: Option<TlsConfig>,
|
||||||
|
|
||||||
pub server_name: Box<ServerName>,
|
pub server_name: Box<ServerName>,
|
||||||
#[serde(default = "default_database_backend")]
|
#[serde(default = "default_database_backend")]
|
||||||
pub database_backend: String,
|
pub database_backend: String,
|
||||||
|
@ -62,6 +71,12 @@ pub struct Config {
|
||||||
pub catchall: BTreeMap<String, IgnoredAny>,
|
pub catchall: BTreeMap<String, IgnoredAny>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
|
pub struct TlsConfig {
|
||||||
|
pub certs: String,
|
||||||
|
pub key: String,
|
||||||
|
}
|
||||||
|
|
||||||
const DEPRECATED_KEYS: &[&str] = &["cache_capacity"];
|
const DEPRECATED_KEYS: &[&str] = &["cache_capacity"];
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
|
@ -90,6 +105,14 @@ fn true_fn() -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn default_address() -> IpAddr {
|
||||||
|
Ipv4Addr::LOCALHOST.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn default_port() -> u16 {
|
||||||
|
8000
|
||||||
|
}
|
||||||
|
|
||||||
fn default_database_backend() -> String {
|
fn default_database_backend() -> String {
|
||||||
"sqlite".to_owned()
|
"sqlite".to_owned()
|
||||||
}
|
}
|
||||||
|
@ -123,7 +146,7 @@ fn default_max_concurrent_requests() -> u16 {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_log() -> String {
|
fn default_log() -> String {
|
||||||
"info,state_res=warn,rocket=off,_=off,sled=off".to_owned()
|
"info,state_res=warn,_=off,sled=off".to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_turn_ttl() -> u64 {
|
fn default_turn_ttl() -> u64 {
|
||||||
|
|
|
@ -13,16 +13,12 @@ pub mod transaction_ids;
|
||||||
pub mod uiaa;
|
pub mod uiaa;
|
||||||
pub mod users;
|
pub mod users;
|
||||||
|
|
||||||
|
use self::admin::create_admin_room;
|
||||||
use crate::{utils, Config, Error, Result};
|
use crate::{utils, Config, Error, Result};
|
||||||
use abstraction::DatabaseEngine;
|
use abstraction::DatabaseEngine;
|
||||||
use directories::ProjectDirs;
|
use directories::ProjectDirs;
|
||||||
|
use futures_util::{stream::FuturesUnordered, StreamExt};
|
||||||
use lru_cache::LruCache;
|
use lru_cache::LruCache;
|
||||||
use rocket::{
|
|
||||||
futures::{channel::mpsc, stream::FuturesUnordered, StreamExt},
|
|
||||||
outcome::{try_outcome, IntoOutcome},
|
|
||||||
request::{FromRequest, Request},
|
|
||||||
Shutdown, State,
|
|
||||||
};
|
|
||||||
use ruma::{DeviceId, EventId, RoomId, UserId};
|
use ruma::{DeviceId, EventId, RoomId, UserId};
|
||||||
use std::{
|
use std::{
|
||||||
collections::{BTreeMap, HashMap, HashSet},
|
collections::{BTreeMap, HashMap, HashSet},
|
||||||
|
@ -33,11 +29,9 @@ use std::{
|
||||||
path::Path,
|
path::Path,
|
||||||
sync::{Arc, Mutex, RwLock},
|
sync::{Arc, Mutex, RwLock},
|
||||||
};
|
};
|
||||||
use tokio::sync::{OwnedRwLockReadGuard, RwLock as TokioRwLock, Semaphore};
|
use tokio::sync::{mpsc, OwnedRwLockReadGuard, RwLock as TokioRwLock, Semaphore};
|
||||||
use tracing::{debug, error, info, warn};
|
use tracing::{debug, error, info, warn};
|
||||||
|
|
||||||
use self::admin::create_admin_room;
|
|
||||||
|
|
||||||
pub struct Database {
|
pub struct Database {
|
||||||
_db: Arc<dyn DatabaseEngine>,
|
_db: Arc<dyn DatabaseEngine>,
|
||||||
pub globals: globals::Globals,
|
pub globals: globals::Globals,
|
||||||
|
@ -151,8 +145,8 @@ impl Database {
|
||||||
eprintln!("ERROR: Max request size is less than 1KB. Please increase it.");
|
eprintln!("ERROR: Max request size is less than 1KB. Please increase it.");
|
||||||
}
|
}
|
||||||
|
|
||||||
let (admin_sender, admin_receiver) = mpsc::unbounded();
|
let (admin_sender, admin_receiver) = mpsc::unbounded_channel();
|
||||||
let (sending_sender, sending_receiver) = mpsc::unbounded();
|
let (sending_sender, sending_receiver) = mpsc::unbounded_channel();
|
||||||
|
|
||||||
let db = Arc::new(TokioRwLock::from(Self {
|
let db = Arc::new(TokioRwLock::from(Self {
|
||||||
_db: builder.clone(),
|
_db: builder.clone(),
|
||||||
|
@ -764,14 +758,9 @@ impl Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
#[cfg(feature = "conduit_bin")]
|
||||||
pub async fn start_on_shutdown_tasks(db: Arc<TokioRwLock<Self>>, shutdown: Shutdown) {
|
pub async fn on_shutdown(db: Arc<TokioRwLock<Self>>) {
|
||||||
tokio::spawn(async move {
|
|
||||||
shutdown.await;
|
|
||||||
|
|
||||||
info!(target: "shutdown-sync", "Received shutdown notification, notifying sync helpers...");
|
info!(target: "shutdown-sync", "Received shutdown notification, notifying sync helpers...");
|
||||||
|
|
||||||
db.read().await.globals.rotate.fire();
|
db.read().await.globals.rotate.fire();
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn watch(&self, user_id: &UserId, device_id: &DeviceId) {
|
pub async fn watch(&self, user_id: &UserId, device_id: &DeviceId) {
|
||||||
|
@ -948,14 +937,23 @@ impl Deref for DatabaseGuard {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[rocket::async_trait]
|
#[cfg(feature = "conduit_bin")]
|
||||||
impl<'r> FromRequest<'r> for DatabaseGuard {
|
#[axum::async_trait]
|
||||||
type Error = ();
|
impl<B> axum::extract::FromRequest<B> for DatabaseGuard
|
||||||
|
where
|
||||||
|
B: Send,
|
||||||
|
{
|
||||||
|
type Rejection = axum::extract::rejection::ExtensionRejection;
|
||||||
|
|
||||||
async fn from_request(req: &'r Request<'_>) -> rocket::request::Outcome<Self, ()> {
|
async fn from_request(
|
||||||
let db = try_outcome!(req.guard::<&State<Arc<TokioRwLock<Database>>>>().await);
|
req: &mut axum::extract::RequestParts<B>,
|
||||||
|
) -> Result<Self, Self::Rejection> {
|
||||||
|
use axum::extract::Extension;
|
||||||
|
|
||||||
Ok(DatabaseGuard(Arc::clone(db).read_owned().await)).or_forward(())
|
let Extension(db): Extension<Arc<TokioRwLock<Database>>> =
|
||||||
|
Extension::from_request(req).await?;
|
||||||
|
|
||||||
|
Ok(DatabaseGuard(db.read_owned().await))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
use super::{super::Config, watchers::Watchers, DatabaseEngine, Tree};
|
use super::{super::Config, watchers::Watchers, DatabaseEngine, Tree};
|
||||||
use crate::{utils, Result};
|
use crate::{utils, Result};
|
||||||
use std::{future::Future, pin::Pin, sync::Arc, sync::RwLock};
|
use std::{
|
||||||
|
future::Future,
|
||||||
|
pin::Pin,
|
||||||
|
sync::{Arc, RwLock},
|
||||||
|
};
|
||||||
|
|
||||||
pub struct Engine {
|
pub struct Engine {
|
||||||
rocks: rocksdb::DBWithThreadMode<rocksdb::MultiThreaded>,
|
rocks: rocksdb::DBWithThreadMode<rocksdb::MultiThreaded>,
|
||||||
|
|
|
@ -1,34 +1,41 @@
|
||||||
use std::{collections::BTreeMap, convert::TryFrom, convert::TryInto, sync::Arc, time::Instant};
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
convert::{TryFrom, TryInto},
|
||||||
|
sync::Arc,
|
||||||
|
time::Instant,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{Error, Result},
|
error::{Error, Result},
|
||||||
pdu::PduBuilder,
|
pdu::PduBuilder,
|
||||||
server_server, Database, PduEvent,
|
server_server,
|
||||||
|
utils::HtmlEscape,
|
||||||
|
Database, PduEvent,
|
||||||
};
|
};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use rocket::{
|
|
||||||
futures::{channel::mpsc, stream::StreamExt},
|
|
||||||
http::RawStr,
|
|
||||||
};
|
|
||||||
use ruma::{
|
use ruma::{
|
||||||
events::room::{
|
events::{
|
||||||
|
room::{
|
||||||
canonical_alias::RoomCanonicalAliasEventContent,
|
canonical_alias::RoomCanonicalAliasEventContent,
|
||||||
create::RoomCreateEventContent,
|
create::RoomCreateEventContent,
|
||||||
guest_access::{GuestAccess, RoomGuestAccessEventContent},
|
guest_access::{GuestAccess, RoomGuestAccessEventContent},
|
||||||
history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent},
|
history_visibility::{HistoryVisibility, RoomHistoryVisibilityEventContent},
|
||||||
join_rules::{JoinRule, RoomJoinRulesEventContent},
|
join_rules::{JoinRule, RoomJoinRulesEventContent},
|
||||||
member::{MembershipState, RoomMemberEventContent},
|
member::{MembershipState, RoomMemberEventContent},
|
||||||
|
message::RoomMessageEventContent,
|
||||||
name::RoomNameEventContent,
|
name::RoomNameEventContent,
|
||||||
power_levels::RoomPowerLevelsEventContent,
|
power_levels::RoomPowerLevelsEventContent,
|
||||||
topic::RoomTopicEventContent,
|
topic::RoomTopicEventContent,
|
||||||
},
|
},
|
||||||
events::{room::message::RoomMessageEventContent, EventType},
|
EventType,
|
||||||
|
},
|
||||||
identifiers::{EventId, RoomAliasId, RoomId, RoomName, RoomVersionId, ServerName, UserId},
|
identifiers::{EventId, RoomAliasId, RoomId, RoomName, RoomVersionId, ServerName, UserId},
|
||||||
};
|
};
|
||||||
use serde_json::value::to_raw_value;
|
use serde_json::value::to_raw_value;
|
||||||
use tokio::sync::{MutexGuard, RwLock, RwLockReadGuard};
|
use tokio::sync::{mpsc, MutexGuard, RwLock, RwLockReadGuard};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub enum AdminRoomEvent {
|
pub enum AdminRoomEvent {
|
||||||
ProcessMessage(String),
|
ProcessMessage(String),
|
||||||
SendMessage(RoomMessageEventContent),
|
SendMessage(RoomMessageEventContent),
|
||||||
|
@ -91,7 +98,7 @@ impl Admin {
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
Some(event) = receiver.next() => {
|
Some(event) = receiver.recv() => {
|
||||||
let guard = db.read().await;
|
let guard = db.read().await;
|
||||||
let mutex_state = Arc::clone(
|
let mutex_state = Arc::clone(
|
||||||
guard.globals
|
guard.globals
|
||||||
|
@ -123,13 +130,13 @@ impl Admin {
|
||||||
|
|
||||||
pub fn process_message(&self, room_message: String) {
|
pub fn process_message(&self, room_message: String) {
|
||||||
self.sender
|
self.sender
|
||||||
.unbounded_send(AdminRoomEvent::ProcessMessage(room_message))
|
.send(AdminRoomEvent::ProcessMessage(room_message))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_message(&self, message_content: RoomMessageEventContent) {
|
pub fn send_message(&self, message_content: RoomMessageEventContent) {
|
||||||
self.sender
|
self.sender
|
||||||
.unbounded_send(AdminRoomEvent::SendMessage(message_content))
|
.send(AdminRoomEvent::SendMessage(message_content))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -405,7 +412,7 @@ fn process_admin_command(
|
||||||
} else {
|
} else {
|
||||||
"PDU was accepted"
|
"PDU was accepted"
|
||||||
},
|
},
|
||||||
RawStr::new(&json_text).html_escape()
|
HtmlEscape(&json_text)
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{database::Config, server_server::FedDest, utils, ConduitResult, Error, Result};
|
use crate::{database::Config, server_server::FedDest, utils, Error, Result};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::{
|
api::{
|
||||||
client::r0::sync::sync_events,
|
client::r0::sync::sync_events,
|
||||||
|
@ -28,7 +28,7 @@ type TlsNameMap = HashMap<String, (Vec<IpAddr>, u16)>;
|
||||||
type RateLimitState = (Instant, u32); // Time if last failed try, number of failed tries
|
type RateLimitState = (Instant, u32); // Time if last failed try, number of failed tries
|
||||||
type SyncHandle = (
|
type SyncHandle = (
|
||||||
Option<String>, // since
|
Option<String>, // since
|
||||||
Receiver<Option<ConduitResult<sync_events::Response>>>, // rx
|
Receiver<Option<Result<sync_events::Response>>>, // rx
|
||||||
);
|
);
|
||||||
|
|
||||||
pub struct Globals {
|
pub struct Globals {
|
||||||
|
|
|
@ -9,11 +9,8 @@ use crate::{
|
||||||
appservice_server, database::pusher, server_server, utils, Database, Error, PduEvent, Result,
|
appservice_server, database::pusher, server_server, utils, Database, Error, PduEvent, Result,
|
||||||
};
|
};
|
||||||
use federation::transactions::send_transaction_message;
|
use federation::transactions::send_transaction_message;
|
||||||
|
use futures_util::{stream::FuturesUnordered, StreamExt};
|
||||||
use ring::digest;
|
use ring::digest;
|
||||||
use rocket::futures::{
|
|
||||||
channel::mpsc,
|
|
||||||
stream::{FuturesUnordered, StreamExt},
|
|
||||||
};
|
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::{
|
api::{
|
||||||
appservice,
|
appservice,
|
||||||
|
@ -33,7 +30,7 @@ use ruma::{
|
||||||
};
|
};
|
||||||
use tokio::{
|
use tokio::{
|
||||||
select,
|
select,
|
||||||
sync::{RwLock, Semaphore},
|
sync::{mpsc, RwLock, Semaphore},
|
||||||
};
|
};
|
||||||
use tracing::{error, warn};
|
use tracing::{error, warn};
|
||||||
|
|
||||||
|
@ -170,7 +167,7 @@ impl Sending {
|
||||||
Self::parse_servercurrentevent(&k, v).ok().map(|ev| (ev, k))
|
Self::parse_servercurrentevent(&k, v).ok().map(|ev| (ev, k))
|
||||||
})
|
})
|
||||||
.take(30)
|
.take(30)
|
||||||
.collect::<>();
|
.collect();
|
||||||
|
|
||||||
// TODO: find edus
|
// TODO: find edus
|
||||||
|
|
||||||
|
@ -207,7 +204,7 @@ impl Sending {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
Some((key, value)) = receiver.next() => {
|
Some((key, value)) = receiver.recv() => {
|
||||||
if let Ok((outgoing_kind, event)) = Self::parse_servercurrentevent(&key, value) {
|
if let Ok((outgoing_kind, event)) = Self::parse_servercurrentevent(&key, value) {
|
||||||
let guard = db.read().await;
|
let guard = db.read().await;
|
||||||
|
|
||||||
|
@ -417,7 +414,7 @@ impl Sending {
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(pdu_id);
|
key.extend_from_slice(pdu_id);
|
||||||
self.servernameevent_data.insert(&key, &[])?;
|
self.servernameevent_data.insert(&key, &[])?;
|
||||||
self.sender.unbounded_send((key, vec![])).unwrap();
|
self.sender.send((key, vec![])).unwrap();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -433,7 +430,7 @@ impl Sending {
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(pdu_id);
|
key.extend_from_slice(pdu_id);
|
||||||
|
|
||||||
self.sender.unbounded_send((key.clone(), vec![])).unwrap();
|
self.sender.send((key.clone(), vec![])).unwrap();
|
||||||
|
|
||||||
(key, Vec::new())
|
(key, Vec::new())
|
||||||
});
|
});
|
||||||
|
@ -454,7 +451,7 @@ impl Sending {
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(&id.to_be_bytes());
|
key.extend_from_slice(&id.to_be_bytes());
|
||||||
self.servernameevent_data.insert(&key, &serialized)?;
|
self.servernameevent_data.insert(&key, &serialized)?;
|
||||||
self.sender.unbounded_send((key, serialized)).unwrap();
|
self.sender.send((key, serialized)).unwrap();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -466,7 +463,7 @@ impl Sending {
|
||||||
key.push(0xff);
|
key.push(0xff);
|
||||||
key.extend_from_slice(pdu_id);
|
key.extend_from_slice(pdu_id);
|
||||||
self.servernameevent_data.insert(&key, &[])?;
|
self.servernameevent_data.insert(&key, &[])?;
|
||||||
self.sender.unbounded_send((key, vec![])).unwrap();
|
self.sender.send((key, vec![])).unwrap();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use std::collections::BTreeMap;
|
use std::{
|
||||||
use std::sync::Arc;
|
collections::BTreeMap,
|
||||||
use std::sync::RwLock;
|
sync::{Arc, RwLock},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{client_server::SESSION_ID_LENGTH, utils, Error, Result};
|
use crate::{client_server::SESSION_ID_LENGTH, utils, Error, Result};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
|
|
48
src/error.rs
48
src/error.rs
|
@ -1,27 +1,20 @@
|
||||||
|
use std::convert::Infallible;
|
||||||
|
|
||||||
|
use http::StatusCode;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::client::{
|
api::client::{
|
||||||
error::{Error as RumaError, ErrorKind},
|
error::{Error as RumaError, ErrorKind},
|
||||||
r0::uiaa::UiaaInfo,
|
r0::uiaa::{UiaaInfo, UiaaResponse},
|
||||||
},
|
},
|
||||||
ServerName,
|
ServerName,
|
||||||
};
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use tracing::warn;
|
use tracing::{error, warn};
|
||||||
|
|
||||||
#[cfg(feature = "persy")]
|
#[cfg(feature = "persy")]
|
||||||
use persy::PersyError;
|
use persy::PersyError;
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
use crate::RumaResponse;
|
||||||
use {
|
|
||||||
crate::RumaResponse,
|
|
||||||
http::StatusCode,
|
|
||||||
rocket::{
|
|
||||||
response::{self, Responder},
|
|
||||||
Request,
|
|
||||||
},
|
|
||||||
ruma::api::client::r0::uiaa::UiaaResponse,
|
|
||||||
tracing::error,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
pub type Result<T, E = Error> = std::result::Result<T, E>;
|
||||||
|
|
||||||
|
@ -81,6 +74,12 @@ pub enum Error {
|
||||||
BadRequest(ErrorKind, &'static str),
|
BadRequest(ErrorKind, &'static str),
|
||||||
#[error("{0}")]
|
#[error("{0}")]
|
||||||
Conflict(&'static str), // This is only needed for when a room alias already exists
|
Conflict(&'static str), // This is only needed for when a room alias already exists
|
||||||
|
#[cfg(feature = "conduit_bin")]
|
||||||
|
#[error("{0}")]
|
||||||
|
ExtensionError(#[from] axum::extract::rejection::ExtensionRejection),
|
||||||
|
#[cfg(feature = "conduit_bin")]
|
||||||
|
#[error("{0}")]
|
||||||
|
PathError(#[from] axum::extract::rejection::PathRejection),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Error {
|
impl Error {
|
||||||
|
@ -139,16 +138,6 @@ impl Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
impl<'r, 'o> Responder<'r, 'o> for Error
|
|
||||||
where
|
|
||||||
'o: 'r,
|
|
||||||
{
|
|
||||||
fn respond_to(self, r: &'r Request<'_>) -> response::Result<'o> {
|
|
||||||
self.to_response().respond_to(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "persy")]
|
#[cfg(feature = "persy")]
|
||||||
impl<T: Into<PersyError>> From<persy::PE<T>> for Error {
|
impl<T: Into<PersyError>> From<persy::PE<T>> for Error {
|
||||||
fn from(err: persy::PE<T>) -> Self {
|
fn from(err: persy::PE<T>) -> Self {
|
||||||
|
@ -157,3 +146,16 @@ impl<T: Into<PersyError>> From<persy::PE<T>> for Error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Infallible> for Error {
|
||||||
|
fn from(i: Infallible) -> Self {
|
||||||
|
match i {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "conduit_bin")]
|
||||||
|
impl axum::response::IntoResponse for Error {
|
||||||
|
fn into_response(self) -> axum::response::Response {
|
||||||
|
self.to_response().into_response()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
16
src/lib.rs
16
src/lib.rs
|
@ -7,8 +7,6 @@
|
||||||
#![allow(clippy::suspicious_else_formatting)]
|
#![allow(clippy::suspicious_else_formatting)]
|
||||||
#![deny(clippy::dbg_macro)]
|
#![deny(clippy::dbg_macro)]
|
||||||
|
|
||||||
use std::ops::Deref;
|
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
mod database;
|
mod database;
|
||||||
mod error;
|
mod error;
|
||||||
|
@ -24,16 +22,4 @@ pub use config::Config;
|
||||||
pub use database::Database;
|
pub use database::Database;
|
||||||
pub use error::{Error, Result};
|
pub use error::{Error, Result};
|
||||||
pub use pdu::PduEvent;
|
pub use pdu::PduEvent;
|
||||||
pub use rocket::Config as RocketConfig;
|
pub use ruma_wrapper::{Ruma, RumaResponse};
|
||||||
pub use ruma_wrapper::{ConduitResult, Ruma, RumaResponse};
|
|
||||||
|
|
||||||
pub struct State<'r, T: Send + Sync + 'static>(pub &'r T);
|
|
||||||
|
|
||||||
impl<'r, T: Send + Sync + 'static> Deref for State<'r, T> {
|
|
||||||
type Target = T;
|
|
||||||
|
|
||||||
#[inline(always)]
|
|
||||||
fn deref(&self) -> &T {
|
|
||||||
self.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
535
src/main.rs
535
src/main.rs
|
@ -7,24 +7,35 @@
|
||||||
#![allow(clippy::suspicious_else_formatting)]
|
#![allow(clippy::suspicious_else_formatting)]
|
||||||
#![deny(clippy::dbg_macro)]
|
#![deny(clippy::dbg_macro)]
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::{future::Future, io, net::SocketAddr, sync::Arc, time::Duration};
|
||||||
|
|
||||||
use maplit::hashset;
|
use axum::{
|
||||||
use opentelemetry::trace::{FutureExt, Tracer};
|
extract::{FromRequest, MatchedPath},
|
||||||
use rocket::{
|
response::IntoResponse,
|
||||||
catch, catchers,
|
routing::{get, on, MethodFilter},
|
||||||
figment::{
|
Router,
|
||||||
|
};
|
||||||
|
use axum_server::{bind, bind_rustls, tls_rustls::RustlsConfig, Handle as ServerHandle};
|
||||||
|
use figment::{
|
||||||
providers::{Env, Format, Toml},
|
providers::{Env, Format, Toml},
|
||||||
Figment,
|
Figment,
|
||||||
},
|
|
||||||
routes, Request,
|
|
||||||
};
|
};
|
||||||
use ruma::api::client::error::ErrorKind;
|
use http::{
|
||||||
use tokio::sync::RwLock;
|
header::{self, HeaderName},
|
||||||
|
Method,
|
||||||
|
};
|
||||||
|
use opentelemetry::trace::{FutureExt, Tracer};
|
||||||
|
use ruma::{api::IncomingRequest, Outgoing};
|
||||||
|
use tokio::{signal, sync::RwLock};
|
||||||
|
use tower::ServiceBuilder;
|
||||||
|
use tower_http::{
|
||||||
|
cors::{self, CorsLayer},
|
||||||
|
trace::TraceLayer,
|
||||||
|
ServiceBuilderExt as _,
|
||||||
|
};
|
||||||
use tracing_subscriber::{prelude::*, EnvFilter};
|
use tracing_subscriber::{prelude::*, EnvFilter};
|
||||||
|
|
||||||
pub use conduit::*; // Re-export everything from the library crate
|
pub use conduit::*; // Re-export everything from the library crate
|
||||||
pub use rocket::State;
|
|
||||||
|
|
||||||
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
|
#[cfg(all(not(target_env = "msvc"), feature = "jemalloc"))]
|
||||||
use tikv_jemallocator::Jemalloc;
|
use tikv_jemallocator::Jemalloc;
|
||||||
|
@ -33,160 +44,10 @@ use tikv_jemallocator::Jemalloc;
|
||||||
#[global_allocator]
|
#[global_allocator]
|
||||||
static GLOBAL: Jemalloc = Jemalloc;
|
static GLOBAL: Jemalloc = Jemalloc;
|
||||||
|
|
||||||
fn setup_rocket(config: Figment, data: Arc<RwLock<Database>>) -> rocket::Rocket<rocket::Build> {
|
#[tokio::main]
|
||||||
rocket::custom(config)
|
|
||||||
.manage(data)
|
|
||||||
.mount(
|
|
||||||
"/",
|
|
||||||
routes![
|
|
||||||
client_server::get_supported_versions_route,
|
|
||||||
client_server::get_register_available_route,
|
|
||||||
client_server::register_route,
|
|
||||||
client_server::get_login_types_route,
|
|
||||||
client_server::login_route,
|
|
||||||
client_server::whoami_route,
|
|
||||||
client_server::logout_route,
|
|
||||||
client_server::logout_all_route,
|
|
||||||
client_server::change_password_route,
|
|
||||||
client_server::deactivate_route,
|
|
||||||
client_server::third_party_route,
|
|
||||||
client_server::get_capabilities_route,
|
|
||||||
client_server::get_pushrules_all_route,
|
|
||||||
client_server::set_pushrule_route,
|
|
||||||
client_server::get_pushrule_route,
|
|
||||||
client_server::set_pushrule_enabled_route,
|
|
||||||
client_server::get_pushrule_enabled_route,
|
|
||||||
client_server::get_pushrule_actions_route,
|
|
||||||
client_server::set_pushrule_actions_route,
|
|
||||||
client_server::delete_pushrule_route,
|
|
||||||
client_server::get_room_event_route,
|
|
||||||
client_server::get_room_aliases_route,
|
|
||||||
client_server::get_filter_route,
|
|
||||||
client_server::create_filter_route,
|
|
||||||
client_server::set_global_account_data_route,
|
|
||||||
client_server::set_room_account_data_route,
|
|
||||||
client_server::get_global_account_data_route,
|
|
||||||
client_server::get_room_account_data_route,
|
|
||||||
client_server::set_displayname_route,
|
|
||||||
client_server::get_displayname_route,
|
|
||||||
client_server::set_avatar_url_route,
|
|
||||||
client_server::get_avatar_url_route,
|
|
||||||
client_server::get_profile_route,
|
|
||||||
client_server::set_presence_route,
|
|
||||||
client_server::get_presence_route,
|
|
||||||
client_server::upload_keys_route,
|
|
||||||
client_server::get_keys_route,
|
|
||||||
client_server::claim_keys_route,
|
|
||||||
client_server::create_backup_route,
|
|
||||||
client_server::update_backup_route,
|
|
||||||
client_server::delete_backup_route,
|
|
||||||
client_server::get_latest_backup_route,
|
|
||||||
client_server::get_backup_route,
|
|
||||||
client_server::add_backup_key_sessions_route,
|
|
||||||
client_server::add_backup_keys_route,
|
|
||||||
client_server::delete_backup_key_session_route,
|
|
||||||
client_server::delete_backup_key_sessions_route,
|
|
||||||
client_server::delete_backup_keys_route,
|
|
||||||
client_server::get_backup_key_session_route,
|
|
||||||
client_server::get_backup_key_sessions_route,
|
|
||||||
client_server::get_backup_keys_route,
|
|
||||||
client_server::set_read_marker_route,
|
|
||||||
client_server::create_receipt_route,
|
|
||||||
client_server::create_typing_event_route,
|
|
||||||
client_server::create_room_route,
|
|
||||||
client_server::redact_event_route,
|
|
||||||
client_server::report_event_route,
|
|
||||||
client_server::create_alias_route,
|
|
||||||
client_server::delete_alias_route,
|
|
||||||
client_server::get_alias_route,
|
|
||||||
client_server::join_room_by_id_route,
|
|
||||||
client_server::join_room_by_id_or_alias_route,
|
|
||||||
client_server::joined_members_route,
|
|
||||||
client_server::leave_room_route,
|
|
||||||
client_server::forget_room_route,
|
|
||||||
client_server::joined_rooms_route,
|
|
||||||
client_server::kick_user_route,
|
|
||||||
client_server::ban_user_route,
|
|
||||||
client_server::unban_user_route,
|
|
||||||
client_server::invite_user_route,
|
|
||||||
client_server::set_room_visibility_route,
|
|
||||||
client_server::get_room_visibility_route,
|
|
||||||
client_server::get_public_rooms_route,
|
|
||||||
client_server::get_public_rooms_filtered_route,
|
|
||||||
client_server::search_users_route,
|
|
||||||
client_server::get_member_events_route,
|
|
||||||
client_server::get_protocols_route,
|
|
||||||
client_server::send_message_event_route,
|
|
||||||
client_server::send_state_event_for_key_route,
|
|
||||||
client_server::send_state_event_for_empty_key_route,
|
|
||||||
client_server::get_state_events_route,
|
|
||||||
client_server::get_state_events_for_key_route,
|
|
||||||
client_server::get_state_events_for_empty_key_route,
|
|
||||||
client_server::sync_events_route,
|
|
||||||
client_server::get_context_route,
|
|
||||||
client_server::get_message_events_route,
|
|
||||||
client_server::search_events_route,
|
|
||||||
client_server::turn_server_route,
|
|
||||||
client_server::send_event_to_device_route,
|
|
||||||
client_server::get_media_config_route,
|
|
||||||
client_server::create_content_route,
|
|
||||||
client_server::get_content_as_filename_route,
|
|
||||||
client_server::get_content_route,
|
|
||||||
client_server::get_content_thumbnail_route,
|
|
||||||
client_server::get_devices_route,
|
|
||||||
client_server::get_device_route,
|
|
||||||
client_server::update_device_route,
|
|
||||||
client_server::delete_device_route,
|
|
||||||
client_server::delete_devices_route,
|
|
||||||
client_server::get_tags_route,
|
|
||||||
client_server::update_tag_route,
|
|
||||||
client_server::delete_tag_route,
|
|
||||||
client_server::options_route,
|
|
||||||
client_server::upload_signing_keys_route,
|
|
||||||
client_server::upload_signatures_route,
|
|
||||||
client_server::get_key_changes_route,
|
|
||||||
client_server::get_pushers_route,
|
|
||||||
client_server::set_pushers_route,
|
|
||||||
// client_server::third_party_route,
|
|
||||||
client_server::upgrade_room_route,
|
|
||||||
server_server::get_server_version_route,
|
|
||||||
server_server::get_server_keys_route,
|
|
||||||
server_server::get_server_keys_deprecated_route,
|
|
||||||
server_server::get_public_rooms_route,
|
|
||||||
server_server::get_public_rooms_filtered_route,
|
|
||||||
server_server::send_transaction_message_route,
|
|
||||||
server_server::get_event_route,
|
|
||||||
server_server::get_missing_events_route,
|
|
||||||
server_server::get_event_authorization_route,
|
|
||||||
server_server::get_room_state_route,
|
|
||||||
server_server::get_room_state_ids_route,
|
|
||||||
server_server::create_join_event_template_route,
|
|
||||||
server_server::create_join_event_v1_route,
|
|
||||||
server_server::create_join_event_v2_route,
|
|
||||||
server_server::create_invite_route,
|
|
||||||
server_server::get_devices_route,
|
|
||||||
server_server::get_room_information_route,
|
|
||||||
server_server::get_profile_information_route,
|
|
||||||
server_server::get_keys_route,
|
|
||||||
server_server::claim_keys_route,
|
|
||||||
],
|
|
||||||
)
|
|
||||||
.register(
|
|
||||||
"/",
|
|
||||||
catchers![
|
|
||||||
not_found_catcher,
|
|
||||||
forbidden_catcher,
|
|
||||||
unknown_token_catcher,
|
|
||||||
missing_token_catcher,
|
|
||||||
bad_json_catcher
|
|
||||||
],
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rocket::main]
|
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let raw_config =
|
let raw_config =
|
||||||
Figment::from(default_config())
|
Figment::new()
|
||||||
.merge(
|
.merge(
|
||||||
Toml::file(Env::var("CONDUIT_CONFIG").expect(
|
Toml::file(Env::var("CONDUIT_CONFIG").expect(
|
||||||
"The CONDUIT_CONFIG env var needs to be set. Example: /etc/conduit.toml",
|
"The CONDUIT_CONFIG env var needs to be set. Example: /etc/conduit.toml",
|
||||||
|
@ -217,14 +78,7 @@ async fn main() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let rocket = setup_rocket(raw_config, Arc::clone(&db))
|
run_server(&config, db).await.unwrap();
|
||||||
.ignite()
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
Database::start_on_shutdown_tasks(db, rocket.shutdown()).await;
|
|
||||||
|
|
||||||
rocket.launch().await.unwrap();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if config.allow_jaeger {
|
if config.allow_jaeger {
|
||||||
|
@ -264,55 +118,308 @@ async fn main() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[catch(404)]
|
async fn run_server(config: &Config, db: Arc<RwLock<Database>>) -> io::Result<()> {
|
||||||
fn not_found_catcher(_: &Request<'_>) -> String {
|
let addr = SocketAddr::from((config.address, config.port));
|
||||||
"404 Not Found".to_owned()
|
|
||||||
|
let x_requested_with = HeaderName::from_static("x-requested-with");
|
||||||
|
|
||||||
|
let middlewares = ServiceBuilder::new()
|
||||||
|
.sensitive_headers([header::AUTHORIZATION])
|
||||||
|
.layer(
|
||||||
|
TraceLayer::new_for_http().make_span_with(|request: &http::Request<_>| {
|
||||||
|
let path = if let Some(path) = request.extensions().get::<MatchedPath>() {
|
||||||
|
path.as_str()
|
||||||
|
} else {
|
||||||
|
request.uri().path()
|
||||||
|
};
|
||||||
|
|
||||||
|
tracing::info_span!("http_request", %path)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.compression()
|
||||||
|
.layer(
|
||||||
|
CorsLayer::new()
|
||||||
|
.allow_origin(cors::any())
|
||||||
|
.allow_methods([
|
||||||
|
Method::GET,
|
||||||
|
Method::POST,
|
||||||
|
Method::PUT,
|
||||||
|
Method::DELETE,
|
||||||
|
Method::OPTIONS,
|
||||||
|
])
|
||||||
|
.allow_headers([
|
||||||
|
header::ORIGIN,
|
||||||
|
x_requested_with,
|
||||||
|
header::CONTENT_TYPE,
|
||||||
|
header::ACCEPT,
|
||||||
|
header::AUTHORIZATION,
|
||||||
|
])
|
||||||
|
.max_age(Duration::from_secs(86400)),
|
||||||
|
)
|
||||||
|
.add_extension(db.clone());
|
||||||
|
|
||||||
|
let app = routes().layer(middlewares).into_make_service();
|
||||||
|
let handle = ServerHandle::new();
|
||||||
|
|
||||||
|
tokio::spawn(shutdown_signal(handle.clone()));
|
||||||
|
|
||||||
|
match &config.tls {
|
||||||
|
Some(tls) => {
|
||||||
|
let conf = RustlsConfig::from_pem_file(&tls.certs, &tls.key).await?;
|
||||||
|
bind_rustls(addr, conf).handle(handle).serve(app).await?;
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
bind(addr).handle(handle).serve(app).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// After serve exits and before exiting, shutdown the DB
|
||||||
|
Database::on_shutdown(db).await;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[catch(580)]
|
fn routes() -> Router {
|
||||||
fn forbidden_catcher() -> Result<()> {
|
Router::new()
|
||||||
Err(Error::BadRequest(ErrorKind::Forbidden, "Forbidden."))
|
.ruma_route(client_server::get_supported_versions_route)
|
||||||
|
.ruma_route(client_server::get_register_available_route)
|
||||||
|
.ruma_route(client_server::register_route)
|
||||||
|
.ruma_route(client_server::get_login_types_route)
|
||||||
|
.ruma_route(client_server::login_route)
|
||||||
|
.ruma_route(client_server::whoami_route)
|
||||||
|
.ruma_route(client_server::logout_route)
|
||||||
|
.ruma_route(client_server::logout_all_route)
|
||||||
|
.ruma_route(client_server::change_password_route)
|
||||||
|
.ruma_route(client_server::deactivate_route)
|
||||||
|
.ruma_route(client_server::third_party_route)
|
||||||
|
.ruma_route(client_server::get_capabilities_route)
|
||||||
|
.ruma_route(client_server::get_pushrules_all_route)
|
||||||
|
.ruma_route(client_server::set_pushrule_route)
|
||||||
|
.ruma_route(client_server::get_pushrule_route)
|
||||||
|
.ruma_route(client_server::set_pushrule_enabled_route)
|
||||||
|
.ruma_route(client_server::get_pushrule_enabled_route)
|
||||||
|
.ruma_route(client_server::get_pushrule_actions_route)
|
||||||
|
.ruma_route(client_server::set_pushrule_actions_route)
|
||||||
|
.ruma_route(client_server::delete_pushrule_route)
|
||||||
|
.ruma_route(client_server::get_room_event_route)
|
||||||
|
.ruma_route(client_server::get_room_aliases_route)
|
||||||
|
.ruma_route(client_server::get_filter_route)
|
||||||
|
.ruma_route(client_server::create_filter_route)
|
||||||
|
.ruma_route(client_server::set_global_account_data_route)
|
||||||
|
.ruma_route(client_server::set_room_account_data_route)
|
||||||
|
.ruma_route(client_server::get_global_account_data_route)
|
||||||
|
.ruma_route(client_server::get_room_account_data_route)
|
||||||
|
.ruma_route(client_server::set_displayname_route)
|
||||||
|
.ruma_route(client_server::get_displayname_route)
|
||||||
|
.ruma_route(client_server::set_avatar_url_route)
|
||||||
|
.ruma_route(client_server::get_avatar_url_route)
|
||||||
|
.ruma_route(client_server::get_profile_route)
|
||||||
|
.ruma_route(client_server::set_presence_route)
|
||||||
|
.ruma_route(client_server::get_presence_route)
|
||||||
|
.ruma_route(client_server::upload_keys_route)
|
||||||
|
.ruma_route(client_server::get_keys_route)
|
||||||
|
.ruma_route(client_server::claim_keys_route)
|
||||||
|
.ruma_route(client_server::create_backup_route)
|
||||||
|
.ruma_route(client_server::update_backup_route)
|
||||||
|
.ruma_route(client_server::delete_backup_route)
|
||||||
|
.ruma_route(client_server::get_latest_backup_route)
|
||||||
|
.ruma_route(client_server::get_backup_route)
|
||||||
|
.ruma_route(client_server::add_backup_key_sessions_route)
|
||||||
|
.ruma_route(client_server::add_backup_keys_route)
|
||||||
|
.ruma_route(client_server::delete_backup_key_session_route)
|
||||||
|
.ruma_route(client_server::delete_backup_key_sessions_route)
|
||||||
|
.ruma_route(client_server::delete_backup_keys_route)
|
||||||
|
.ruma_route(client_server::get_backup_key_session_route)
|
||||||
|
.ruma_route(client_server::get_backup_key_sessions_route)
|
||||||
|
.ruma_route(client_server::get_backup_keys_route)
|
||||||
|
.ruma_route(client_server::set_read_marker_route)
|
||||||
|
.ruma_route(client_server::create_receipt_route)
|
||||||
|
.ruma_route(client_server::create_typing_event_route)
|
||||||
|
.ruma_route(client_server::create_room_route)
|
||||||
|
.ruma_route(client_server::redact_event_route)
|
||||||
|
.ruma_route(client_server::report_event_route)
|
||||||
|
.ruma_route(client_server::create_alias_route)
|
||||||
|
.ruma_route(client_server::delete_alias_route)
|
||||||
|
.ruma_route(client_server::get_alias_route)
|
||||||
|
.ruma_route(client_server::join_room_by_id_route)
|
||||||
|
.ruma_route(client_server::join_room_by_id_or_alias_route)
|
||||||
|
.ruma_route(client_server::joined_members_route)
|
||||||
|
.ruma_route(client_server::leave_room_route)
|
||||||
|
.ruma_route(client_server::forget_room_route)
|
||||||
|
.ruma_route(client_server::joined_rooms_route)
|
||||||
|
.ruma_route(client_server::kick_user_route)
|
||||||
|
.ruma_route(client_server::ban_user_route)
|
||||||
|
.ruma_route(client_server::unban_user_route)
|
||||||
|
.ruma_route(client_server::invite_user_route)
|
||||||
|
.ruma_route(client_server::set_room_visibility_route)
|
||||||
|
.ruma_route(client_server::get_room_visibility_route)
|
||||||
|
.ruma_route(client_server::get_public_rooms_route)
|
||||||
|
.ruma_route(client_server::get_public_rooms_filtered_route)
|
||||||
|
.ruma_route(client_server::search_users_route)
|
||||||
|
.ruma_route(client_server::get_member_events_route)
|
||||||
|
.ruma_route(client_server::get_protocols_route)
|
||||||
|
.ruma_route(client_server::send_message_event_route)
|
||||||
|
.ruma_route(client_server::send_state_event_for_key_route)
|
||||||
|
.ruma_route(client_server::get_state_events_route)
|
||||||
|
.ruma_route(client_server::get_state_events_for_key_route)
|
||||||
|
// Ruma doesn't have support for multiple paths for a single endpoint yet, and these routes
|
||||||
|
// share one Ruma request / response type pair with {get,send}_state_event_for_key_route
|
||||||
|
.route(
|
||||||
|
"/_matrix/client/r0/rooms/:room_id/state/:event_type",
|
||||||
|
get(client_server::get_state_events_for_empty_key_route)
|
||||||
|
.put(client_server::send_state_event_for_empty_key_route),
|
||||||
|
)
|
||||||
|
.ruma_route(client_server::sync_events_route)
|
||||||
|
.ruma_route(client_server::get_context_route)
|
||||||
|
.ruma_route(client_server::get_message_events_route)
|
||||||
|
.ruma_route(client_server::search_events_route)
|
||||||
|
.ruma_route(client_server::turn_server_route)
|
||||||
|
.ruma_route(client_server::send_event_to_device_route)
|
||||||
|
.ruma_route(client_server::get_media_config_route)
|
||||||
|
.ruma_route(client_server::create_content_route)
|
||||||
|
.ruma_route(client_server::get_content_route)
|
||||||
|
.ruma_route(client_server::get_content_as_filename_route)
|
||||||
|
.ruma_route(client_server::get_content_thumbnail_route)
|
||||||
|
.ruma_route(client_server::get_devices_route)
|
||||||
|
.ruma_route(client_server::get_device_route)
|
||||||
|
.ruma_route(client_server::update_device_route)
|
||||||
|
.ruma_route(client_server::delete_device_route)
|
||||||
|
.ruma_route(client_server::delete_devices_route)
|
||||||
|
.ruma_route(client_server::get_tags_route)
|
||||||
|
.ruma_route(client_server::update_tag_route)
|
||||||
|
.ruma_route(client_server::delete_tag_route)
|
||||||
|
.ruma_route(client_server::upload_signing_keys_route)
|
||||||
|
.ruma_route(client_server::upload_signatures_route)
|
||||||
|
.ruma_route(client_server::get_key_changes_route)
|
||||||
|
.ruma_route(client_server::get_pushers_route)
|
||||||
|
.ruma_route(client_server::set_pushers_route)
|
||||||
|
// .ruma_route(client_server::third_party_route)
|
||||||
|
.ruma_route(client_server::upgrade_room_route)
|
||||||
|
.ruma_route(server_server::get_server_version_route)
|
||||||
|
.route(
|
||||||
|
"/_matrix/key/v2/server",
|
||||||
|
get(server_server::get_server_keys_route),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
"/_matrix/key/v2/server/:key_id",
|
||||||
|
get(server_server::get_server_keys_deprecated_route),
|
||||||
|
)
|
||||||
|
.ruma_route(server_server::get_public_rooms_route)
|
||||||
|
.ruma_route(server_server::get_public_rooms_filtered_route)
|
||||||
|
.ruma_route(server_server::send_transaction_message_route)
|
||||||
|
.ruma_route(server_server::get_event_route)
|
||||||
|
.ruma_route(server_server::get_missing_events_route)
|
||||||
|
.ruma_route(server_server::get_event_authorization_route)
|
||||||
|
.ruma_route(server_server::get_room_state_route)
|
||||||
|
.ruma_route(server_server::get_room_state_ids_route)
|
||||||
|
.ruma_route(server_server::create_join_event_template_route)
|
||||||
|
.ruma_route(server_server::create_join_event_v1_route)
|
||||||
|
.ruma_route(server_server::create_join_event_v2_route)
|
||||||
|
.ruma_route(server_server::create_invite_route)
|
||||||
|
.ruma_route(server_server::get_devices_route)
|
||||||
|
.ruma_route(server_server::get_room_information_route)
|
||||||
|
.ruma_route(server_server::get_profile_information_route)
|
||||||
|
.ruma_route(server_server::get_keys_route)
|
||||||
|
.ruma_route(server_server::claim_keys_route)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[catch(581)]
|
async fn shutdown_signal(handle: ServerHandle) {
|
||||||
fn unknown_token_catcher() -> Result<()> {
|
let ctrl_c = async {
|
||||||
Err(Error::BadRequest(
|
signal::ctrl_c()
|
||||||
ErrorKind::UnknownToken { soft_logout: false },
|
.await
|
||||||
"Unknown token.",
|
.expect("failed to install Ctrl+C handler");
|
||||||
))
|
};
|
||||||
}
|
|
||||||
|
|
||||||
#[catch(582)]
|
|
||||||
fn missing_token_catcher() -> Result<()> {
|
|
||||||
Err(Error::BadRequest(ErrorKind::MissingToken, "Missing token."))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[catch(583)]
|
|
||||||
fn bad_json_catcher() -> Result<()> {
|
|
||||||
Err(Error::BadRequest(ErrorKind::BadJson, "Bad json."))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn default_config() -> rocket::Config {
|
|
||||||
use rocket::config::{LogLevel, Shutdown, Sig};
|
|
||||||
|
|
||||||
rocket::Config {
|
|
||||||
// Disable rocket's logging to get only tracing-subscriber's log output
|
|
||||||
log_level: LogLevel::Off,
|
|
||||||
shutdown: Shutdown {
|
|
||||||
// Once shutdown is triggered, this is the amount of seconds before rocket
|
|
||||||
// will forcefully start shutting down connections, this gives enough time to /sync
|
|
||||||
// requests and the like (which havent gotten the memo, somehow) to still complete gracefully.
|
|
||||||
grace: 35,
|
|
||||||
|
|
||||||
// After the grace period, rocket starts shutting down connections, and waits at least this
|
|
||||||
// many seconds before forcefully shutting all of them down.
|
|
||||||
mercy: 10,
|
|
||||||
|
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
signals: hashset![Sig::Term, Sig::Int],
|
let terminate = async {
|
||||||
|
signal::unix::signal(signal::unix::SignalKind::terminate())
|
||||||
|
.expect("failed to install signal handler")
|
||||||
|
.recv()
|
||||||
|
.await;
|
||||||
|
};
|
||||||
|
|
||||||
..Shutdown::default()
|
#[cfg(not(unix))]
|
||||||
},
|
let terminate = std::future::pending::<()>();
|
||||||
..rocket::Config::release_default()
|
|
||||||
|
tokio::select! {
|
||||||
|
_ = ctrl_c => {},
|
||||||
|
_ = terminate => {},
|
||||||
|
}
|
||||||
|
|
||||||
|
handle.graceful_shutdown(Some(Duration::from_secs(30)));
|
||||||
|
}
|
||||||
|
|
||||||
|
trait RouterExt {
|
||||||
|
fn ruma_route<H, T>(self, handler: H) -> Self
|
||||||
|
where
|
||||||
|
H: RumaHandler<T>,
|
||||||
|
T: 'static;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RouterExt for Router {
|
||||||
|
fn ruma_route<H, T>(self, handler: H) -> Self
|
||||||
|
where
|
||||||
|
H: RumaHandler<T>,
|
||||||
|
T: 'static,
|
||||||
|
{
|
||||||
|
handler.add_to_router(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait RumaHandler<T> {
|
||||||
|
// Can't transform to a handler without boxing or relying on the nightly-only
|
||||||
|
// impl-trait-in-traits feature. Moving a small amount of extra logic into the trait
|
||||||
|
// allows bypassing both.
|
||||||
|
fn add_to_router(self, router: Router) -> Router;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_ruma_handler {
|
||||||
|
( $($ty:ident),* $(,)? ) => {
|
||||||
|
#[axum::async_trait]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
impl<Req, E, F, Fut, $($ty,)*> RumaHandler<($($ty,)* Ruma<Req>,)> for F
|
||||||
|
where
|
||||||
|
Req: Outgoing + 'static,
|
||||||
|
Req::Incoming: IncomingRequest + Send,
|
||||||
|
F: FnOnce($($ty,)* Ruma<Req>) -> Fut + Clone + Send + 'static,
|
||||||
|
Fut: Future<Output = Result<<Req::Incoming as IncomingRequest>::OutgoingResponse, E>>
|
||||||
|
+ Send,
|
||||||
|
E: IntoResponse,
|
||||||
|
$( $ty: FromRequest<axum::body::Body> + Send + 'static, )*
|
||||||
|
{
|
||||||
|
fn add_to_router(self, router: Router) -> Router {
|
||||||
|
let meta = Req::Incoming::METADATA;
|
||||||
|
let method_filter = method_to_filter(meta.method);
|
||||||
|
|
||||||
|
router.route(meta.path, on(method_filter, |$( $ty: $ty, )* req| async move {
|
||||||
|
self($($ty,)* req).await.map(RumaResponse)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_ruma_handler!();
|
||||||
|
impl_ruma_handler!(T1);
|
||||||
|
impl_ruma_handler!(T1, T2);
|
||||||
|
impl_ruma_handler!(T1, T2, T3);
|
||||||
|
impl_ruma_handler!(T1, T2, T3, T4);
|
||||||
|
impl_ruma_handler!(T1, T2, T3, T4, T5);
|
||||||
|
impl_ruma_handler!(T1, T2, T3, T4, T5, T6);
|
||||||
|
impl_ruma_handler!(T1, T2, T3, T4, T5, T6, T7);
|
||||||
|
impl_ruma_handler!(T1, T2, T3, T4, T5, T6, T7, T8);
|
||||||
|
|
||||||
|
fn method_to_filter(method: Method) -> MethodFilter {
|
||||||
|
let method_filter = match method {
|
||||||
|
Method::DELETE => MethodFilter::DELETE,
|
||||||
|
Method::GET => MethodFilter::GET,
|
||||||
|
Method::HEAD => MethodFilter::HEAD,
|
||||||
|
Method::OPTIONS => MethodFilter::OPTIONS,
|
||||||
|
Method::PATCH => MethodFilter::PATCH,
|
||||||
|
Method::POST => MethodFilter::POST,
|
||||||
|
Method::PUT => MethodFilter::PUT,
|
||||||
|
Method::TRACE => MethodFilter::TRACE,
|
||||||
|
m => panic!("Unsupported HTTP method: {:?}", m),
|
||||||
|
};
|
||||||
|
method_filter
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{database::DatabaseGuard, Error};
|
use crate::Error;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::{client::r0::uiaa::UiaaResponse, OutgoingResponse},
|
api::client::r0::uiaa::UiaaResponse,
|
||||||
identifiers::{DeviceId, UserId},
|
identifiers::{DeviceId, UserId},
|
||||||
signatures::CanonicalJsonValue,
|
signatures::CanonicalJsonValue,
|
||||||
Outgoing, ServerName,
|
Outgoing, ServerName,
|
||||||
|
@ -8,24 +8,9 @@ use ruma::{
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
#[cfg(feature = "conduit_bin")]
|
||||||
use {
|
mod axum;
|
||||||
crate::server_server,
|
|
||||||
rocket::{
|
|
||||||
data::{self, ByteUnit, Data, FromData},
|
|
||||||
http::Status,
|
|
||||||
outcome::Outcome::*,
|
|
||||||
response::{self, Responder},
|
|
||||||
tokio::io::AsyncReadExt,
|
|
||||||
Request,
|
|
||||||
},
|
|
||||||
ruma::api::{AuthScheme, IncomingRequest},
|
|
||||||
std::collections::BTreeMap,
|
|
||||||
std::io::Cursor,
|
|
||||||
tracing::{debug, warn},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// This struct converts rocket requests into ruma structs by converting them into http requests
|
/// Extractor for Ruma request structs
|
||||||
/// first.
|
|
||||||
pub struct Ruma<T: Outgoing> {
|
pub struct Ruma<T: Outgoing> {
|
||||||
pub body: T::Incoming,
|
pub body: T::Incoming,
|
||||||
pub sender_user: Option<Box<UserId>>,
|
pub sender_user: Option<Box<UserId>>,
|
||||||
|
@ -36,300 +21,6 @@ pub struct Ruma<T: Outgoing> {
|
||||||
pub from_appservice: bool,
|
pub from_appservice: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
#[rocket::async_trait]
|
|
||||||
impl<'a, T: Outgoing> FromData<'a> for Ruma<T>
|
|
||||||
where
|
|
||||||
T::Incoming: IncomingRequest,
|
|
||||||
{
|
|
||||||
type Error = ();
|
|
||||||
|
|
||||||
#[tracing::instrument(skip(request, data))]
|
|
||||||
async fn from_data(
|
|
||||||
request: &'a Request<'_>,
|
|
||||||
data: Data<'a>,
|
|
||||||
) -> data::Outcome<'a, Self, Self::Error> {
|
|
||||||
let metadata = T::Incoming::METADATA;
|
|
||||||
let db = request
|
|
||||||
.guard::<DatabaseGuard>()
|
|
||||||
.await
|
|
||||||
.expect("database was loaded");
|
|
||||||
|
|
||||||
// Get token from header or query value
|
|
||||||
let token = request
|
|
||||||
.headers()
|
|
||||||
.get_one("Authorization")
|
|
||||||
.and_then(|s| s.get(7..)) // Split off "Bearer "
|
|
||||||
.or_else(|| request.query_value("access_token").and_then(|r| r.ok()));
|
|
||||||
|
|
||||||
let limit = db.globals.max_request_size();
|
|
||||||
let mut handle = data.open(ByteUnit::Byte(limit.into()));
|
|
||||||
let mut body = Vec::new();
|
|
||||||
if handle.read_to_end(&mut body).await.is_err() {
|
|
||||||
// Client disconnected
|
|
||||||
// Missing Token
|
|
||||||
return Failure((Status::new(582), ()));
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut json_body = serde_json::from_slice::<CanonicalJsonValue>(&body).ok();
|
|
||||||
|
|
||||||
let (sender_user, sender_device, sender_servername, from_appservice) = if let Some((
|
|
||||||
_id,
|
|
||||||
registration,
|
|
||||||
)) = db
|
|
||||||
.appservice
|
|
||||||
.all()
|
|
||||||
.unwrap()
|
|
||||||
.iter()
|
|
||||||
.find(|(_id, registration)| {
|
|
||||||
registration
|
|
||||||
.get("as_token")
|
|
||||||
.and_then(|as_token| as_token.as_str())
|
|
||||||
.map_or(false, |as_token| token == Some(as_token))
|
|
||||||
}) {
|
|
||||||
match metadata.authentication {
|
|
||||||
AuthScheme::AccessToken | AuthScheme::QueryOnlyAccessToken => {
|
|
||||||
let user_id = request.query_value::<String>("user_id").map_or_else(
|
|
||||||
|| {
|
|
||||||
UserId::parse_with_server_name(
|
|
||||||
registration
|
|
||||||
.get("sender_localpart")
|
|
||||||
.unwrap()
|
|
||||||
.as_str()
|
|
||||||
.unwrap(),
|
|
||||||
db.globals.server_name(),
|
|
||||||
)
|
|
||||||
.unwrap()
|
|
||||||
},
|
|
||||||
|string| {
|
|
||||||
UserId::parse(string.expect("parsing to string always works")).unwrap()
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if !db.users.exists(&user_id).unwrap() {
|
|
||||||
// Forbidden
|
|
||||||
return Failure((Status::new(580), ()));
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Check if appservice is allowed to be that user
|
|
||||||
(Some(user_id), None, None, true)
|
|
||||||
}
|
|
||||||
AuthScheme::ServerSignatures => (None, None, None, true),
|
|
||||||
AuthScheme::None => (None, None, None, true),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
match metadata.authentication {
|
|
||||||
AuthScheme::AccessToken | AuthScheme::QueryOnlyAccessToken => {
|
|
||||||
if let Some(token) = token {
|
|
||||||
match db.users.find_from_token(token).unwrap() {
|
|
||||||
// Unknown Token
|
|
||||||
None => return Failure((Status::new(581), ())),
|
|
||||||
Some((user_id, device_id)) => (
|
|
||||||
Some(user_id),
|
|
||||||
Some(Box::<DeviceId>::from(device_id)),
|
|
||||||
None,
|
|
||||||
false,
|
|
||||||
),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Missing Token
|
|
||||||
return Failure((Status::new(582), ()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AuthScheme::ServerSignatures => {
|
|
||||||
// Get origin from header
|
|
||||||
let x_matrix = match request
|
|
||||||
.headers()
|
|
||||||
.get_one("Authorization")
|
|
||||||
.and_then(|s| s.get(9..)) // Split off "X-Matrix " and parse the rest
|
|
||||||
.map(|s| {
|
|
||||||
s.split_terminator(',')
|
|
||||||
.map(|field| {
|
|
||||||
let mut splits = field.splitn(2, '=');
|
|
||||||
(splits.next(), splits.next().map(|s| s.trim_matches('"')))
|
|
||||||
})
|
|
||||||
.collect::<BTreeMap<_, _>>()
|
|
||||||
}) {
|
|
||||||
Some(t) => t,
|
|
||||||
None => {
|
|
||||||
warn!("No Authorization header");
|
|
||||||
|
|
||||||
// Forbidden
|
|
||||||
return Failure((Status::new(580), ()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let origin_str = match x_matrix.get(&Some("origin")) {
|
|
||||||
Some(Some(o)) => *o,
|
|
||||||
_ => {
|
|
||||||
warn!("Invalid X-Matrix header origin field: {:?}", x_matrix);
|
|
||||||
|
|
||||||
// Forbidden
|
|
||||||
return Failure((Status::new(580), ()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let origin = match ServerName::parse(origin_str) {
|
|
||||||
Ok(s) => s,
|
|
||||||
_ => {
|
|
||||||
warn!(
|
|
||||||
"Invalid server name in X-Matrix header origin field: {:?}",
|
|
||||||
x_matrix
|
|
||||||
);
|
|
||||||
|
|
||||||
// Forbidden
|
|
||||||
return Failure((Status::new(580), ()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let key = match x_matrix.get(&Some("key")) {
|
|
||||||
Some(Some(k)) => *k,
|
|
||||||
_ => {
|
|
||||||
warn!("Invalid X-Matrix header key field: {:?}", x_matrix);
|
|
||||||
|
|
||||||
// Forbidden
|
|
||||||
return Failure((Status::new(580), ()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let sig = match x_matrix.get(&Some("sig")) {
|
|
||||||
Some(Some(s)) => *s,
|
|
||||||
_ => {
|
|
||||||
warn!("Invalid X-Matrix header sig field: {:?}", x_matrix);
|
|
||||||
|
|
||||||
// Forbidden
|
|
||||||
return Failure((Status::new(580), ()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut request_map = BTreeMap::<String, CanonicalJsonValue>::new();
|
|
||||||
|
|
||||||
if let Some(json_body) = &json_body {
|
|
||||||
request_map.insert("content".to_owned(), json_body.clone());
|
|
||||||
};
|
|
||||||
|
|
||||||
request_map.insert(
|
|
||||||
"method".to_owned(),
|
|
||||||
CanonicalJsonValue::String(request.method().to_string()),
|
|
||||||
);
|
|
||||||
request_map.insert(
|
|
||||||
"uri".to_owned(),
|
|
||||||
CanonicalJsonValue::String(request.uri().to_string()),
|
|
||||||
);
|
|
||||||
request_map.insert(
|
|
||||||
"origin".to_owned(),
|
|
||||||
CanonicalJsonValue::String(origin.as_str().to_owned()),
|
|
||||||
);
|
|
||||||
request_map.insert(
|
|
||||||
"destination".to_owned(),
|
|
||||||
CanonicalJsonValue::String(db.globals.server_name().as_str().to_owned()),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut origin_signatures = BTreeMap::new();
|
|
||||||
origin_signatures
|
|
||||||
.insert(key.to_owned(), CanonicalJsonValue::String(sig.to_owned()));
|
|
||||||
|
|
||||||
let mut signatures = BTreeMap::new();
|
|
||||||
signatures.insert(
|
|
||||||
origin.as_str().to_owned(),
|
|
||||||
CanonicalJsonValue::Object(origin_signatures),
|
|
||||||
);
|
|
||||||
|
|
||||||
request_map.insert(
|
|
||||||
"signatures".to_owned(),
|
|
||||||
CanonicalJsonValue::Object(signatures),
|
|
||||||
);
|
|
||||||
|
|
||||||
let keys =
|
|
||||||
match server_server::fetch_signing_keys(&db, &origin, vec![key.to_owned()])
|
|
||||||
.await
|
|
||||||
{
|
|
||||||
Ok(b) => b,
|
|
||||||
Err(e) => {
|
|
||||||
warn!("Failed to fetch signing keys: {}", e);
|
|
||||||
|
|
||||||
// Forbidden
|
|
||||||
return Failure((Status::new(580), ()));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut pub_key_map = BTreeMap::new();
|
|
||||||
pub_key_map.insert(origin.as_str().to_owned(), keys);
|
|
||||||
|
|
||||||
match ruma::signatures::verify_json(&pub_key_map, &request_map) {
|
|
||||||
Ok(()) => (None, None, Some(origin), false),
|
|
||||||
Err(e) => {
|
|
||||||
warn!(
|
|
||||||
"Failed to verify json request from {}: {}\n{:?}",
|
|
||||||
origin, e, request_map
|
|
||||||
);
|
|
||||||
|
|
||||||
if request.uri().to_string().contains('@') {
|
|
||||||
warn!("Request uri contained '@' character. Make sure your reverse proxy gives Conduit the raw uri (apache: use nocanon)");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forbidden
|
|
||||||
return Failure((Status::new(580), ()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AuthScheme::None => (None, None, None, false),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut http_request = http::Request::builder()
|
|
||||||
.uri(request.uri().to_string())
|
|
||||||
.method(&*request.method().to_string());
|
|
||||||
for header in request.headers().iter() {
|
|
||||||
http_request = http_request.header(header.name.as_str(), &*header.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(json_body) = json_body.as_mut().and_then(|val| val.as_object_mut()) {
|
|
||||||
let user_id = sender_user.clone().unwrap_or_else(|| {
|
|
||||||
UserId::parse_with_server_name("", db.globals.server_name())
|
|
||||||
.expect("we know this is valid")
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(CanonicalJsonValue::Object(initial_request)) = json_body
|
|
||||||
.get("auth")
|
|
||||||
.and_then(|auth| auth.as_object())
|
|
||||||
.and_then(|auth| auth.get("session"))
|
|
||||||
.and_then(|session| session.as_str())
|
|
||||||
.and_then(|session| {
|
|
||||||
db.uiaa.get_uiaa_request(
|
|
||||||
&user_id,
|
|
||||||
&sender_device.clone().unwrap_or_else(|| "".into()),
|
|
||||||
session,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
{
|
|
||||||
for (key, value) in initial_request {
|
|
||||||
json_body.entry(key).or_insert(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
body = serde_json::to_vec(json_body).expect("value to bytes can't fail");
|
|
||||||
}
|
|
||||||
|
|
||||||
let http_request = http_request.body(&*body).unwrap();
|
|
||||||
debug!("{:?}", http_request);
|
|
||||||
match <T::Incoming as IncomingRequest>::try_from_http_request(http_request) {
|
|
||||||
Ok(t) => Success(Ruma {
|
|
||||||
body: t,
|
|
||||||
sender_user,
|
|
||||||
sender_device,
|
|
||||||
sender_servername,
|
|
||||||
from_appservice,
|
|
||||||
json_body,
|
|
||||||
}),
|
|
||||||
Err(e) => {
|
|
||||||
warn!("{:?}", e);
|
|
||||||
// Bad Json
|
|
||||||
Failure((Status::new(583), ()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: Outgoing> Deref for Ruma<T> {
|
impl<T: Outgoing> Deref for Ruma<T> {
|
||||||
type Target = T::Incoming;
|
type Target = T::Incoming;
|
||||||
|
|
||||||
|
@ -338,41 +29,6 @@ impl<T: Outgoing> Deref for Ruma<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This struct converts ruma responses into rocket http responses.
|
|
||||||
pub type ConduitResult<T> = Result<RumaResponse<T>, Error>;
|
|
||||||
|
|
||||||
pub fn response<T: OutgoingResponse>(response: RumaResponse<T>) -> response::Result<'static> {
|
|
||||||
let http_response = response
|
|
||||||
.0
|
|
||||||
.try_into_http_response::<Vec<u8>>()
|
|
||||||
.map_err(|_| Status::InternalServerError)?;
|
|
||||||
|
|
||||||
let mut response = rocket::response::Response::build();
|
|
||||||
|
|
||||||
let status = http_response.status();
|
|
||||||
response.status(Status::new(status.as_u16()));
|
|
||||||
|
|
||||||
for header in http_response.headers() {
|
|
||||||
response.raw_header(header.0.to_string(), header.1.to_str().unwrap().to_owned());
|
|
||||||
}
|
|
||||||
|
|
||||||
let http_body = http_response.into_body();
|
|
||||||
|
|
||||||
response.sized_body(http_body.len(), Cursor::new(http_body));
|
|
||||||
|
|
||||||
response.raw_header("Access-Control-Allow-Origin", "*");
|
|
||||||
response.raw_header(
|
|
||||||
"Access-Control-Allow-Methods",
|
|
||||||
"GET, POST, PUT, DELETE, OPTIONS",
|
|
||||||
);
|
|
||||||
response.raw_header(
|
|
||||||
"Access-Control-Allow-Headers",
|
|
||||||
"Origin, X-Requested-With, Content-Type, Accept, Authorization",
|
|
||||||
);
|
|
||||||
response.raw_header("Access-Control-Max-Age", "86400");
|
|
||||||
response.ok()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct RumaResponse<T>(pub T);
|
pub struct RumaResponse<T>(pub T);
|
||||||
|
|
||||||
|
@ -387,14 +43,3 @@ impl From<Error> for RumaResponse<UiaaResponse> {
|
||||||
t.to_response()
|
t.to_response()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
impl<'r, 'o, T> Responder<'r, 'o> for RumaResponse<T>
|
|
||||||
where
|
|
||||||
'o: 'r,
|
|
||||||
T: OutgoingResponse,
|
|
||||||
{
|
|
||||||
fn respond_to(self, _: &'r Request<'_>) -> response::Result<'o> {
|
|
||||||
response(self)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
371
src/ruma_wrapper/axum.rs
Normal file
371
src/ruma_wrapper/axum.rs
Normal file
|
@ -0,0 +1,371 @@
|
||||||
|
use std::{collections::BTreeMap, iter::FromIterator, str};
|
||||||
|
|
||||||
|
use axum::{
|
||||||
|
async_trait,
|
||||||
|
body::{Full, HttpBody},
|
||||||
|
extract::{
|
||||||
|
rejection::TypedHeaderRejectionReason, FromRequest, Path, RequestParts, TypedHeader,
|
||||||
|
},
|
||||||
|
headers::{
|
||||||
|
authorization::{Bearer, Credentials},
|
||||||
|
Authorization,
|
||||||
|
},
|
||||||
|
response::{IntoResponse, Response},
|
||||||
|
BoxError,
|
||||||
|
};
|
||||||
|
use bytes::{BufMut, Bytes, BytesMut};
|
||||||
|
use http::StatusCode;
|
||||||
|
use ruma::{
|
||||||
|
api::{client::error::ErrorKind, AuthScheme, IncomingRequest, OutgoingResponse},
|
||||||
|
signatures::CanonicalJsonValue,
|
||||||
|
DeviceId, Outgoing, ServerName, UserId,
|
||||||
|
};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use tracing::{debug, error, warn};
|
||||||
|
|
||||||
|
use super::{Ruma, RumaResponse};
|
||||||
|
use crate::{database::DatabaseGuard, server_server, Error, Result};
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl<T, B> FromRequest<B> for Ruma<T>
|
||||||
|
where
|
||||||
|
T: Outgoing,
|
||||||
|
T::Incoming: IncomingRequest,
|
||||||
|
B: HttpBody + Send,
|
||||||
|
B::Data: Send,
|
||||||
|
B::Error: Into<BoxError>,
|
||||||
|
{
|
||||||
|
type Rejection = Error;
|
||||||
|
|
||||||
|
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct QueryParams {
|
||||||
|
access_token: Option<String>,
|
||||||
|
user_id: Option<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let metadata = T::Incoming::METADATA;
|
||||||
|
let db = DatabaseGuard::from_request(req).await?;
|
||||||
|
let auth_header = Option::<TypedHeader<Authorization<Bearer>>>::from_request(req).await?;
|
||||||
|
let path_params = Path::<Vec<String>>::from_request(req).await?;
|
||||||
|
|
||||||
|
let query = req.uri().query().unwrap_or_default();
|
||||||
|
let query_params: QueryParams = match ruma::serde::urlencoded::from_str(query) {
|
||||||
|
Ok(params) => params,
|
||||||
|
Err(e) => {
|
||||||
|
error!(%query, "Failed to deserialize query parameters: {}", e);
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::Unknown,
|
||||||
|
"Failed to read query parameters",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let token = match &auth_header {
|
||||||
|
Some(TypedHeader(Authorization(bearer))) => Some(bearer.token()),
|
||||||
|
None => query_params.access_token.as_deref(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut body = Bytes::from_request(req)
|
||||||
|
.await
|
||||||
|
.map_err(|_| Error::BadRequest(ErrorKind::MissingToken, "Missing token."))?;
|
||||||
|
|
||||||
|
let mut json_body = serde_json::from_slice::<CanonicalJsonValue>(&body).ok();
|
||||||
|
|
||||||
|
let appservices = db.appservice.all().unwrap();
|
||||||
|
let appservice_registration = appservices.iter().find(|(_id, registration)| {
|
||||||
|
registration
|
||||||
|
.get("as_token")
|
||||||
|
.and_then(|as_token| as_token.as_str())
|
||||||
|
.map_or(false, |as_token| token == Some(as_token))
|
||||||
|
});
|
||||||
|
|
||||||
|
let (sender_user, sender_device, sender_servername, from_appservice) =
|
||||||
|
if let Some((_id, registration)) = appservice_registration {
|
||||||
|
match metadata.authentication {
|
||||||
|
AuthScheme::AccessToken | AuthScheme::QueryOnlyAccessToken => {
|
||||||
|
let user_id = query_params.user_id.map_or_else(
|
||||||
|
|| {
|
||||||
|
UserId::parse_with_server_name(
|
||||||
|
registration
|
||||||
|
.get("sender_localpart")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap(),
|
||||||
|
db.globals.server_name(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
},
|
||||||
|
|s| UserId::parse(s).unwrap(),
|
||||||
|
);
|
||||||
|
|
||||||
|
if !db.users.exists(&user_id).unwrap() {
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::Forbidden,
|
||||||
|
"User does not exist.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Check if appservice is allowed to be that user
|
||||||
|
(Some(user_id), None, None, true)
|
||||||
|
}
|
||||||
|
AuthScheme::ServerSignatures => (None, None, None, true),
|
||||||
|
AuthScheme::None => (None, None, None, true),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match metadata.authentication {
|
||||||
|
AuthScheme::AccessToken | AuthScheme::QueryOnlyAccessToken => {
|
||||||
|
let token = match token {
|
||||||
|
Some(token) => token,
|
||||||
|
_ => {
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::MissingToken,
|
||||||
|
"Missing access token.",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match db.users.find_from_token(token).unwrap() {
|
||||||
|
None => {
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::UnknownToken { soft_logout: false },
|
||||||
|
"Unknown access token.",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
Some((user_id, device_id)) => (
|
||||||
|
Some(user_id),
|
||||||
|
Some(Box::<DeviceId>::from(device_id)),
|
||||||
|
None,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AuthScheme::ServerSignatures => {
|
||||||
|
let TypedHeader(Authorization(x_matrix)) =
|
||||||
|
TypedHeader::<Authorization<XMatrix>>::from_request(req)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
warn!("Missing or invalid Authorization header: {}", e);
|
||||||
|
|
||||||
|
let msg = match e.reason() {
|
||||||
|
TypedHeaderRejectionReason::Missing => {
|
||||||
|
"Missing Authorization header."
|
||||||
|
}
|
||||||
|
TypedHeaderRejectionReason::Error(_) => {
|
||||||
|
"Invalid X-Matrix signatures."
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Error::BadRequest(ErrorKind::Forbidden, msg)
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let origin_signatures = BTreeMap::from_iter([(
|
||||||
|
x_matrix.key.clone(),
|
||||||
|
CanonicalJsonValue::String(x_matrix.sig),
|
||||||
|
)]);
|
||||||
|
|
||||||
|
let signatures = BTreeMap::from_iter([(
|
||||||
|
x_matrix.origin.as_str().to_owned(),
|
||||||
|
CanonicalJsonValue::Object(origin_signatures),
|
||||||
|
)]);
|
||||||
|
|
||||||
|
let mut request_map = BTreeMap::from_iter([
|
||||||
|
(
|
||||||
|
"method".to_owned(),
|
||||||
|
CanonicalJsonValue::String(req.method().to_string()),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"uri".to_owned(),
|
||||||
|
CanonicalJsonValue::String(req.uri().to_string()),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"origin".to_owned(),
|
||||||
|
CanonicalJsonValue::String(x_matrix.origin.as_str().to_owned()),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"destination".to_owned(),
|
||||||
|
CanonicalJsonValue::String(
|
||||||
|
db.globals.server_name().as_str().to_owned(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
"signatures".to_owned(),
|
||||||
|
CanonicalJsonValue::Object(signatures),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
|
if let Some(json_body) = &json_body {
|
||||||
|
request_map.insert("content".to_owned(), json_body.clone());
|
||||||
|
};
|
||||||
|
|
||||||
|
let keys_result = server_server::fetch_signing_keys(
|
||||||
|
&db,
|
||||||
|
&x_matrix.origin,
|
||||||
|
vec![x_matrix.key.to_owned()],
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
let keys = match keys_result {
|
||||||
|
Ok(b) => b,
|
||||||
|
Err(e) => {
|
||||||
|
warn!("Failed to fetch signing keys: {}", e);
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::Forbidden,
|
||||||
|
"Failed to fetch signing keys.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let pub_key_map =
|
||||||
|
BTreeMap::from_iter([(x_matrix.origin.as_str().to_owned(), keys)]);
|
||||||
|
|
||||||
|
match ruma::signatures::verify_json(&pub_key_map, &request_map) {
|
||||||
|
Ok(()) => (None, None, Some(x_matrix.origin), false),
|
||||||
|
Err(e) => {
|
||||||
|
warn!(
|
||||||
|
"Failed to verify json request from {}: {}\n{:?}",
|
||||||
|
x_matrix.origin, e, request_map
|
||||||
|
);
|
||||||
|
|
||||||
|
if req.uri().to_string().contains('@') {
|
||||||
|
warn!(
|
||||||
|
"Request uri contained '@' character. Make sure your \
|
||||||
|
reverse proxy gives Conduit the raw uri (apache: use \
|
||||||
|
nocanon)"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Err(Error::BadRequest(
|
||||||
|
ErrorKind::Forbidden,
|
||||||
|
"Failed to verify X-Matrix signatures.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AuthScheme::None => (None, None, None, false),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut http_request = http::Request::builder().uri(req.uri()).method(req.method());
|
||||||
|
*http_request.headers_mut().unwrap() =
|
||||||
|
req.headers().expect("Headers already extracted").clone();
|
||||||
|
|
||||||
|
if let Some(CanonicalJsonValue::Object(json_body)) = &mut json_body {
|
||||||
|
let user_id = sender_user.clone().unwrap_or_else(|| {
|
||||||
|
UserId::parse_with_server_name("", db.globals.server_name())
|
||||||
|
.expect("we know this is valid")
|
||||||
|
});
|
||||||
|
|
||||||
|
let uiaa_request = json_body
|
||||||
|
.get("auth")
|
||||||
|
.and_then(|auth| auth.as_object())
|
||||||
|
.and_then(|auth| auth.get("session"))
|
||||||
|
.and_then(|session| session.as_str())
|
||||||
|
.and_then(|session| {
|
||||||
|
db.uiaa.get_uiaa_request(
|
||||||
|
&user_id,
|
||||||
|
&sender_device.clone().unwrap_or_else(|| "".into()),
|
||||||
|
session,
|
||||||
|
)
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(CanonicalJsonValue::Object(initial_request)) = uiaa_request {
|
||||||
|
for (key, value) in initial_request {
|
||||||
|
json_body.entry(key).or_insert(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut buf = BytesMut::new().writer();
|
||||||
|
serde_json::to_writer(&mut buf, json_body).expect("value serialization can't fail");
|
||||||
|
body = buf.into_inner().freeze();
|
||||||
|
}
|
||||||
|
|
||||||
|
let http_request = http_request.body(&*body).unwrap();
|
||||||
|
|
||||||
|
debug!("{:?}", http_request);
|
||||||
|
|
||||||
|
let body = T::Incoming::try_from_http_request(http_request, &path_params).map_err(|e| {
|
||||||
|
warn!("{:?}", e);
|
||||||
|
Error::BadRequest(ErrorKind::BadJson, "Failed to deserialize request.")
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(Ruma {
|
||||||
|
body,
|
||||||
|
sender_user,
|
||||||
|
sender_device,
|
||||||
|
sender_servername,
|
||||||
|
from_appservice,
|
||||||
|
json_body,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct XMatrix {
|
||||||
|
origin: Box<ServerName>,
|
||||||
|
key: String, // KeyName?
|
||||||
|
sig: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Credentials for XMatrix {
|
||||||
|
const SCHEME: &'static str = "X-Matrix";
|
||||||
|
|
||||||
|
fn decode(value: &http::HeaderValue) -> Option<Self> {
|
||||||
|
debug_assert!(
|
||||||
|
value.as_bytes().starts_with(b"X-Matrix "),
|
||||||
|
"HeaderValue to decode should start with \"X-Matrix ..\", received = {:?}",
|
||||||
|
value,
|
||||||
|
);
|
||||||
|
|
||||||
|
let parameters = str::from_utf8(&value.as_bytes()["X-Matrix ".len()..])
|
||||||
|
.ok()?
|
||||||
|
.trim_start();
|
||||||
|
|
||||||
|
let mut origin = None;
|
||||||
|
let mut key = None;
|
||||||
|
let mut sig = None;
|
||||||
|
|
||||||
|
for entry in parameters.split_terminator(',') {
|
||||||
|
let (name, value) = entry.split_once('=')?;
|
||||||
|
|
||||||
|
// It's not at all clear why some fields are quoted and others not in the spec,
|
||||||
|
// let's simply accept either form for every field.
|
||||||
|
let value = value
|
||||||
|
.strip_prefix('"')
|
||||||
|
.and_then(|rest| rest.strip_suffix('"'))
|
||||||
|
.unwrap_or(value);
|
||||||
|
|
||||||
|
// FIXME: Catch multiple fields of the same name
|
||||||
|
match name {
|
||||||
|
"origin" => origin = Some(value.try_into().ok()?),
|
||||||
|
"key" => key = Some(value.to_owned()),
|
||||||
|
"sig" => sig = Some(value.to_owned()),
|
||||||
|
_ => warn!(
|
||||||
|
"Unexpected field `{}` in X-Matrix Authorization header",
|
||||||
|
name
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(Self {
|
||||||
|
origin: origin?,
|
||||||
|
key: key?,
|
||||||
|
sig: sig?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode(&self) -> http::HeaderValue {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> IntoResponse for RumaResponse<T>
|
||||||
|
where
|
||||||
|
T: OutgoingResponse,
|
||||||
|
{
|
||||||
|
fn into_response(self) -> Response {
|
||||||
|
match self.0.try_into_http_response::<BytesMut>() {
|
||||||
|
Ok(res) => res.map(BytesMut::freeze).map(Full::new).into_response(),
|
||||||
|
Err(_) => StatusCode::INTERNAL_SERVER_ERROR.into_response(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,15 +2,13 @@ use crate::{
|
||||||
client_server::{self, claim_keys_helper, get_keys_helper},
|
client_server::{self, claim_keys_helper, get_keys_helper},
|
||||||
database::{rooms::CompressedStateEvent, DatabaseGuard},
|
database::{rooms::CompressedStateEvent, DatabaseGuard},
|
||||||
pdu::EventHash,
|
pdu::EventHash,
|
||||||
utils, ConduitResult, Database, Error, PduEvent, Result, Ruma,
|
utils, Database, Error, PduEvent, Result, Ruma,
|
||||||
};
|
};
|
||||||
|
use axum::{response::IntoResponse, Json};
|
||||||
|
use futures_util::{stream::FuturesUnordered, StreamExt};
|
||||||
use get_profile_information::v1::ProfileField;
|
use get_profile_information::v1::ProfileField;
|
||||||
use http::header::{HeaderValue, AUTHORIZATION};
|
use http::header::{HeaderValue, AUTHORIZATION};
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use rocket::{
|
|
||||||
futures::{prelude::*, stream::FuturesUnordered},
|
|
||||||
response::content::Json,
|
|
||||||
};
|
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::{
|
api::{
|
||||||
client::error::{Error as RumaError, ErrorKind},
|
client::error::{Error as RumaError, ErrorKind},
|
||||||
|
@ -72,9 +70,6 @@ use std::{
|
||||||
use tokio::sync::{MutexGuard, Semaphore};
|
use tokio::sync::{MutexGuard, Semaphore};
|
||||||
use tracing::{debug, error, info, trace, warn};
|
use tracing::{debug, error, info, trace, warn};
|
||||||
|
|
||||||
#[cfg(feature = "conduit_bin")]
|
|
||||||
use rocket::{get, post, put};
|
|
||||||
|
|
||||||
/// Wraps either an literal IP address plus port, or a hostname plus complement
|
/// Wraps either an literal IP address plus port, or a hostname plus complement
|
||||||
/// (colon-plus-port if it was specified).
|
/// (colon-plus-port if it was specified).
|
||||||
///
|
///
|
||||||
|
@ -495,11 +490,11 @@ async fn request_well_known(
|
||||||
/// # `GET /_matrix/federation/v1/version`
|
/// # `GET /_matrix/federation/v1/version`
|
||||||
///
|
///
|
||||||
/// Get version information on this server.
|
/// Get version information on this server.
|
||||||
#[cfg_attr(feature = "conduit_bin", get("/_matrix/federation/v1/version"))]
|
#[tracing::instrument(skip(db, _body))]
|
||||||
#[tracing::instrument(skip(db))]
|
pub async fn get_server_version_route(
|
||||||
pub fn get_server_version_route(
|
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
) -> ConduitResult<get_server_version::v1::Response> {
|
_body: Ruma<get_server_version::v1::Request>,
|
||||||
|
) -> Result<get_server_version::v1::Response> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
@ -509,8 +504,7 @@ pub fn get_server_version_route(
|
||||||
name: Some("Conduit".to_owned()),
|
name: Some("Conduit".to_owned()),
|
||||||
version: Some(env!("CARGO_PKG_VERSION").to_owned()),
|
version: Some(env!("CARGO_PKG_VERSION").to_owned()),
|
||||||
}),
|
}),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/key/v2/server`
|
/// # `GET /_matrix/key/v2/server`
|
||||||
|
@ -520,12 +514,10 @@ pub fn get_server_version_route(
|
||||||
/// - Matrix does not support invalidating public keys, so the key returned by this will be valid
|
/// - Matrix does not support invalidating public keys, so the key returned by this will be valid
|
||||||
/// forever.
|
/// forever.
|
||||||
// Response type for this endpoint is Json because we need to calculate a signature for the response
|
// Response type for this endpoint is Json because we need to calculate a signature for the response
|
||||||
#[cfg_attr(feature = "conduit_bin", get("/_matrix/key/v2/server"))]
|
|
||||||
#[tracing::instrument(skip(db))]
|
#[tracing::instrument(skip(db))]
|
||||||
pub fn get_server_keys_route(db: DatabaseGuard) -> Json<String> {
|
pub async fn get_server_keys_route(db: DatabaseGuard) -> Result<impl IntoResponse> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
// TODO: Use proper types
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
return Json("Federation is disabled.".to_owned());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut verify_keys: BTreeMap<Box<ServerSigningKeyId>, VerifyKey> = BTreeMap::new();
|
let mut verify_keys: BTreeMap<Box<ServerSigningKeyId>, VerifyKey> = BTreeMap::new();
|
||||||
|
@ -563,7 +555,7 @@ pub fn get_server_keys_route(db: DatabaseGuard) -> Json<String> {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
Json(serde_json::to_string(&response).expect("JSON is canonical"))
|
Ok(Json(response))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/key/v2/server/{keyId}`
|
/// # `GET /_matrix/key/v2/server/{keyId}`
|
||||||
|
@ -572,24 +564,19 @@ pub fn get_server_keys_route(db: DatabaseGuard) -> Json<String> {
|
||||||
///
|
///
|
||||||
/// - Matrix does not support invalidating public keys, so the key returned by this will be valid
|
/// - Matrix does not support invalidating public keys, so the key returned by this will be valid
|
||||||
/// forever.
|
/// forever.
|
||||||
#[cfg_attr(feature = "conduit_bin", get("/_matrix/key/v2/server/<_>"))]
|
|
||||||
#[tracing::instrument(skip(db))]
|
#[tracing::instrument(skip(db))]
|
||||||
pub fn get_server_keys_deprecated_route(db: DatabaseGuard) -> Json<String> {
|
pub async fn get_server_keys_deprecated_route(db: DatabaseGuard) -> impl IntoResponse {
|
||||||
get_server_keys_route(db)
|
get_server_keys_route(db).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/federation/v1/publicRooms`
|
/// # `POST /_matrix/federation/v1/publicRooms`
|
||||||
///
|
///
|
||||||
/// Lists the public rooms on this server.
|
/// Lists the public rooms on this server.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/federation/v1/publicRooms", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_public_rooms_filtered_route(
|
pub async fn get_public_rooms_filtered_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_public_rooms_filtered::v1::Request<'_>>,
|
body: Ruma<get_public_rooms_filtered::v1::Request<'_>>,
|
||||||
) -> ConduitResult<get_public_rooms_filtered::v1::Response> {
|
) -> Result<get_public_rooms_filtered::v1::Response> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
@ -602,8 +589,7 @@ pub async fn get_public_rooms_filtered_route(
|
||||||
&body.filter,
|
&body.filter,
|
||||||
&body.room_network,
|
&body.room_network,
|
||||||
)
|
)
|
||||||
.await?
|
.await?;
|
||||||
.0;
|
|
||||||
|
|
||||||
Ok(get_public_rooms_filtered::v1::Response {
|
Ok(get_public_rooms_filtered::v1::Response {
|
||||||
chunk: response
|
chunk: response
|
||||||
|
@ -621,22 +607,17 @@ pub async fn get_public_rooms_filtered_route(
|
||||||
prev_batch: response.prev_batch,
|
prev_batch: response.prev_batch,
|
||||||
next_batch: response.next_batch,
|
next_batch: response.next_batch,
|
||||||
total_room_count_estimate: response.total_room_count_estimate,
|
total_room_count_estimate: response.total_room_count_estimate,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/federation/v1/publicRooms`
|
/// # `GET /_matrix/federation/v1/publicRooms`
|
||||||
///
|
///
|
||||||
/// Lists the public rooms on this server.
|
/// Lists the public rooms on this server.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/federation/v1/publicRooms", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_public_rooms_route(
|
pub async fn get_public_rooms_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_public_rooms::v1::Request<'_>>,
|
body: Ruma<get_public_rooms::v1::Request<'_>>,
|
||||||
) -> ConduitResult<get_public_rooms::v1::Response> {
|
) -> Result<get_public_rooms::v1::Response> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
@ -649,8 +630,7 @@ pub async fn get_public_rooms_route(
|
||||||
&IncomingFilter::default(),
|
&IncomingFilter::default(),
|
||||||
&IncomingRoomNetwork::Matrix,
|
&IncomingRoomNetwork::Matrix,
|
||||||
)
|
)
|
||||||
.await?
|
.await?;
|
||||||
.0;
|
|
||||||
|
|
||||||
Ok(get_public_rooms::v1::Response {
|
Ok(get_public_rooms::v1::Response {
|
||||||
chunk: response
|
chunk: response
|
||||||
|
@ -668,22 +648,17 @@ pub async fn get_public_rooms_route(
|
||||||
prev_batch: response.prev_batch,
|
prev_batch: response.prev_batch,
|
||||||
next_batch: response.next_batch,
|
next_batch: response.next_batch,
|
||||||
total_room_count_estimate: response.total_room_count_estimate,
|
total_room_count_estimate: response.total_room_count_estimate,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `PUT /_matrix/federation/v1/send/{txnId}`
|
/// # `PUT /_matrix/federation/v1/send/{txnId}`
|
||||||
///
|
///
|
||||||
/// Push EDUs and PDUs to this server.
|
/// Push EDUs and PDUs to this server.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/federation/v1/send/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn send_transaction_message_route(
|
pub async fn send_transaction_message_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<send_transaction_message::v1::Request<'_>>,
|
body: Ruma<send_transaction_message::v1::Request<'_>>,
|
||||||
) -> ConduitResult<send_transaction_message::v1::Response> {
|
) -> Result<send_transaction_message::v1::Response> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
@ -895,7 +870,7 @@ pub async fn send_transaction_message_route(
|
||||||
|
|
||||||
db.flush()?;
|
db.flush()?;
|
||||||
|
|
||||||
Ok(send_transaction_message::v1::Response { pdus: resolved_map }.into())
|
Ok(send_transaction_message::v1::Response { pdus: resolved_map })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An async function that can recursively call itself.
|
/// An async function that can recursively call itself.
|
||||||
|
@ -2309,15 +2284,11 @@ fn get_auth_chain_inner(
|
||||||
/// Retrieves a single event from the server.
|
/// Retrieves a single event from the server.
|
||||||
///
|
///
|
||||||
/// - Only works if a user of this server is currently invited or joined the room
|
/// - Only works if a user of this server is currently invited or joined the room
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/federation/v1/event/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub fn get_event_route(
|
pub async fn get_event_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_event::v1::Request<'_>>,
|
body: Ruma<get_event::v1::Request<'_>>,
|
||||||
) -> ConduitResult<get_event::v1::Response> {
|
) -> Result<get_event::v1::Response> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
@ -2351,22 +2322,17 @@ pub fn get_event_route(
|
||||||
origin: db.globals.server_name().to_owned(),
|
origin: db.globals.server_name().to_owned(),
|
||||||
origin_server_ts: MilliSecondsSinceUnixEpoch::now(),
|
origin_server_ts: MilliSecondsSinceUnixEpoch::now(),
|
||||||
pdu: PduEvent::convert_to_outgoing_federation_event(event),
|
pdu: PduEvent::convert_to_outgoing_federation_event(event),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/federation/v1/get_missing_events/{roomId}`
|
/// # `POST /_matrix/federation/v1/get_missing_events/{roomId}`
|
||||||
///
|
///
|
||||||
/// Retrieves events that the sender is missing.
|
/// Retrieves events that the sender is missing.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/federation/v1/get_missing_events/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub fn get_missing_events_route(
|
pub async fn get_missing_events_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_missing_events::v1::Request<'_>>,
|
body: Ruma<get_missing_events::v1::Request<'_>>,
|
||||||
) -> ConduitResult<get_missing_events::v1::Response> {
|
) -> Result<get_missing_events::v1::Response> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
@ -2428,7 +2394,7 @@ pub fn get_missing_events_route(
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(get_missing_events::v1::Response { events }.into())
|
Ok(get_missing_events::v1::Response { events })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/federation/v1/event_auth/{roomId}/{eventId}`
|
/// # `GET /_matrix/federation/v1/event_auth/{roomId}/{eventId}`
|
||||||
|
@ -2436,15 +2402,11 @@ pub fn get_missing_events_route(
|
||||||
/// Retrieves the auth chain for a given event.
|
/// Retrieves the auth chain for a given event.
|
||||||
///
|
///
|
||||||
/// - This does not include the event itself
|
/// - This does not include the event itself
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/federation/v1/event_auth/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub fn get_event_authorization_route(
|
pub async fn get_event_authorization_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_event_authorization::v1::Request<'_>>,
|
body: Ruma<get_event_authorization::v1::Request<'_>>,
|
||||||
) -> ConduitResult<get_event_authorization::v1::Response> {
|
) -> Result<get_event_authorization::v1::Response> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
@ -2483,22 +2445,17 @@ pub fn get_event_authorization_route(
|
||||||
.filter_map(|id| db.rooms.get_pdu_json(&id).ok()?)
|
.filter_map(|id| db.rooms.get_pdu_json(&id).ok()?)
|
||||||
.map(PduEvent::convert_to_outgoing_federation_event)
|
.map(PduEvent::convert_to_outgoing_federation_event)
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/federation/v1/state/{roomId}`
|
/// # `GET /_matrix/federation/v1/state/{roomId}`
|
||||||
///
|
///
|
||||||
/// Retrieves the current state of the room.
|
/// Retrieves the current state of the room.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/federation/v1/state/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub fn get_room_state_route(
|
pub async fn get_room_state_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_room_state::v1::Request<'_>>,
|
body: Ruma<get_room_state::v1::Request<'_>>,
|
||||||
) -> ConduitResult<get_room_state::v1::Response> {
|
) -> Result<get_room_state::v1::Response> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
@ -2548,22 +2505,17 @@ pub fn get_room_state_route(
|
||||||
.filter_map(|r| r.ok())
|
.filter_map(|r| r.ok())
|
||||||
.collect(),
|
.collect(),
|
||||||
pdus,
|
pdus,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/federation/v1/state_ids/{roomId}`
|
/// # `GET /_matrix/federation/v1/state_ids/{roomId}`
|
||||||
///
|
///
|
||||||
/// Retrieves the current state of the room.
|
/// Retrieves the current state of the room.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/federation/v1/state_ids/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub fn get_room_state_ids_route(
|
pub async fn get_room_state_ids_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_room_state_ids::v1::Request<'_>>,
|
body: Ruma<get_room_state_ids::v1::Request<'_>>,
|
||||||
) -> ConduitResult<get_room_state_ids::v1::Response> {
|
) -> Result<get_room_state_ids::v1::Response> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
@ -2602,22 +2554,17 @@ pub fn get_room_state_ids_route(
|
||||||
Ok(get_room_state_ids::v1::Response {
|
Ok(get_room_state_ids::v1::Response {
|
||||||
auth_chain_ids: auth_chain_ids.map(|id| (*id).to_owned()).collect(),
|
auth_chain_ids: auth_chain_ids.map(|id| (*id).to_owned()).collect(),
|
||||||
pdu_ids,
|
pdu_ids,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/federation/v1/make_join/{roomId}/{userId}`
|
/// # `GET /_matrix/federation/v1/make_join/{roomId}/{userId}`
|
||||||
///
|
///
|
||||||
/// Creates a join template.
|
/// Creates a join template.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/federation/v1/make_join/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub fn create_join_event_template_route(
|
pub async fn create_join_event_template_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<create_join_event_template::v1::Request<'_>>,
|
body: Ruma<create_join_event_template::v1::Request<'_>>,
|
||||||
) -> ConduitResult<create_join_event_template::v1::Response> {
|
) -> Result<create_join_event_template::v1::Response> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
@ -2782,8 +2729,7 @@ pub fn create_join_event_template_route(
|
||||||
Ok(create_join_event_template::v1::Response {
|
Ok(create_join_event_template::v1::Response {
|
||||||
room_version: Some(room_version_id),
|
room_version: Some(room_version_id),
|
||||||
event: to_raw_value(&pdu_json).expect("CanonicalJson can be serialized to JSON"),
|
event: to_raw_value(&pdu_json).expect("CanonicalJson can be serialized to JSON"),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_join_event(
|
async fn create_join_event(
|
||||||
|
@ -2895,15 +2841,11 @@ async fn create_join_event(
|
||||||
/// # `PUT /_matrix/federation/v1/send_join/{roomId}/{eventId}`
|
/// # `PUT /_matrix/federation/v1/send_join/{roomId}/{eventId}`
|
||||||
///
|
///
|
||||||
/// Submits a signed join event.
|
/// Submits a signed join event.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/federation/v1/send_join/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn create_join_event_v1_route(
|
pub async fn create_join_event_v1_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<create_join_event::v1::Request<'_>>,
|
body: Ruma<create_join_event::v1::Request<'_>>,
|
||||||
) -> ConduitResult<create_join_event::v1::Response> {
|
) -> Result<create_join_event::v1::Response> {
|
||||||
let sender_servername = body
|
let sender_servername = body
|
||||||
.sender_servername
|
.sender_servername
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -2911,21 +2853,17 @@ pub async fn create_join_event_v1_route(
|
||||||
|
|
||||||
let room_state = create_join_event(&db, sender_servername, &body.room_id, &body.pdu).await?;
|
let room_state = create_join_event(&db, sender_servername, &body.room_id, &body.pdu).await?;
|
||||||
|
|
||||||
Ok(create_join_event::v1::Response { room_state }.into())
|
Ok(create_join_event::v1::Response { room_state })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `PUT /_matrix/federation/v2/send_join/{roomId}/{eventId}`
|
/// # `PUT /_matrix/federation/v2/send_join/{roomId}/{eventId}`
|
||||||
///
|
///
|
||||||
/// Submits a signed join event.
|
/// Submits a signed join event.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/federation/v2/send_join/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn create_join_event_v2_route(
|
pub async fn create_join_event_v2_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<create_join_event::v2::Request<'_>>,
|
body: Ruma<create_join_event::v2::Request<'_>>,
|
||||||
) -> ConduitResult<create_join_event::v2::Response> {
|
) -> Result<create_join_event::v2::Response> {
|
||||||
let sender_servername = body
|
let sender_servername = body
|
||||||
.sender_servername
|
.sender_servername
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -2933,21 +2871,17 @@ pub async fn create_join_event_v2_route(
|
||||||
|
|
||||||
let room_state = create_join_event(&db, sender_servername, &body.room_id, &body.pdu).await?;
|
let room_state = create_join_event(&db, sender_servername, &body.room_id, &body.pdu).await?;
|
||||||
|
|
||||||
Ok(create_join_event::v2::Response { room_state }.into())
|
Ok(create_join_event::v2::Response { room_state })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `PUT /_matrix/federation/v2/invite/{roomId}/{eventId}`
|
/// # `PUT /_matrix/federation/v2/invite/{roomId}/{eventId}`
|
||||||
///
|
///
|
||||||
/// Invites a remote user to a room.
|
/// Invites a remote user to a room.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
put("/_matrix/federation/v2/invite/<_>/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn create_invite_route(
|
pub async fn create_invite_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<create_invite::v2::Request<'_>>,
|
body: Ruma<create_invite::v2::Request<'_>>,
|
||||||
) -> ConduitResult<create_invite::v2::Response> {
|
) -> Result<create_invite::v2::Response> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
@ -3048,22 +2982,17 @@ pub async fn create_invite_route(
|
||||||
|
|
||||||
Ok(create_invite::v2::Response {
|
Ok(create_invite::v2::Response {
|
||||||
event: PduEvent::convert_to_outgoing_federation_event(signed_event),
|
event: PduEvent::convert_to_outgoing_federation_event(signed_event),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/federation/v1/user/devices/{userId}`
|
/// # `GET /_matrix/federation/v1/user/devices/{userId}`
|
||||||
///
|
///
|
||||||
/// Gets information on all devices of the user.
|
/// Gets information on all devices of the user.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/federation/v1/user/devices/<_>", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub fn get_devices_route(
|
pub async fn get_devices_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_devices::v1::Request<'_>>,
|
body: Ruma<get_devices::v1::Request<'_>>,
|
||||||
) -> ConduitResult<get_devices::v1::Response> {
|
) -> Result<get_devices::v1::Response> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
@ -3091,22 +3020,17 @@ pub fn get_devices_route(
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/federation/v1/query/directory`
|
/// # `GET /_matrix/federation/v1/query/directory`
|
||||||
///
|
///
|
||||||
/// Resolve a room alias to a room id.
|
/// Resolve a room alias to a room id.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/federation/v1/query/directory", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub fn get_room_information_route(
|
pub async fn get_room_information_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_room_information::v1::Request<'_>>,
|
body: Ruma<get_room_information::v1::Request<'_>>,
|
||||||
) -> ConduitResult<get_room_information::v1::Response> {
|
) -> Result<get_room_information::v1::Response> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
@ -3122,22 +3046,17 @@ pub fn get_room_information_route(
|
||||||
Ok(get_room_information::v1::Response {
|
Ok(get_room_information::v1::Response {
|
||||||
room_id,
|
room_id,
|
||||||
servers: vec![db.globals.server_name().to_owned()],
|
servers: vec![db.globals.server_name().to_owned()],
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/federation/v1/query/profile`
|
/// # `GET /_matrix/federation/v1/query/profile`
|
||||||
///
|
///
|
||||||
/// Gets information on a profile.
|
/// Gets information on a profile.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
get("/_matrix/federation/v1/query/profile", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub fn get_profile_information_route(
|
pub async fn get_profile_information_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_profile_information::v1::Request<'_>>,
|
body: Ruma<get_profile_information::v1::Request<'_>>,
|
||||||
) -> ConduitResult<get_profile_information::v1::Response> {
|
) -> Result<get_profile_information::v1::Response> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
@ -3165,22 +3084,17 @@ pub fn get_profile_information_route(
|
||||||
blurhash,
|
blurhash,
|
||||||
displayname,
|
displayname,
|
||||||
avatar_url,
|
avatar_url,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/federation/v1/user/keys/query`
|
/// # `POST /_matrix/federation/v1/user/keys/query`
|
||||||
///
|
///
|
||||||
/// Gets devices and identity keys for the given users.
|
/// Gets devices and identity keys for the given users.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/federation/v1/user/keys/query", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn get_keys_route(
|
pub async fn get_keys_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<get_keys::v1::Request>,
|
body: Ruma<get_keys::v1::Request>,
|
||||||
) -> ConduitResult<get_keys::v1::Response> {
|
) -> Result<get_keys::v1::Response> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
@ -3199,22 +3113,17 @@ pub async fn get_keys_route(
|
||||||
device_keys: result.device_keys,
|
device_keys: result.device_keys,
|
||||||
master_keys: result.master_keys,
|
master_keys: result.master_keys,
|
||||||
self_signing_keys: result.self_signing_keys,
|
self_signing_keys: result.self_signing_keys,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # `POST /_matrix/federation/v1/user/keys/claim`
|
/// # `POST /_matrix/federation/v1/user/keys/claim`
|
||||||
///
|
///
|
||||||
/// Claims one-time keys.
|
/// Claims one-time keys.
|
||||||
#[cfg_attr(
|
|
||||||
feature = "conduit_bin",
|
|
||||||
post("/_matrix/federation/v1/user/keys/claim", data = "<body>")
|
|
||||||
)]
|
|
||||||
#[tracing::instrument(skip(db, body))]
|
#[tracing::instrument(skip(db, body))]
|
||||||
pub async fn claim_keys_route(
|
pub async fn claim_keys_route(
|
||||||
db: DatabaseGuard,
|
db: DatabaseGuard,
|
||||||
body: Ruma<claim_keys::v1::Request>,
|
body: Ruma<claim_keys::v1::Request>,
|
||||||
) -> ConduitResult<claim_keys::v1::Response> {
|
) -> Result<claim_keys::v1::Response> {
|
||||||
if !db.globals.allow_federation() {
|
if !db.globals.allow_federation() {
|
||||||
return Err(Error::bad_config("Federation is disabled."));
|
return Err(Error::bad_config("Federation is disabled."));
|
||||||
}
|
}
|
||||||
|
@ -3225,8 +3134,7 @@ pub async fn claim_keys_route(
|
||||||
|
|
||||||
Ok(claim_keys::v1::Response {
|
Ok(claim_keys::v1::Response {
|
||||||
one_time_keys: result.one_time_keys,
|
one_time_keys: result.one_time_keys,
|
||||||
}
|
})
|
||||||
.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(event, pub_key_map, db))]
|
#[tracing::instrument(skip(event, pub_key_map, db))]
|
||||||
|
|
39
src/utils.rs
39
src/utils.rs
|
@ -3,7 +3,7 @@ use cmp::Ordering;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use ruma::serde::{try_from_json_map, CanonicalJsonError, CanonicalJsonObject};
|
use ruma::serde::{try_from_json_map, CanonicalJsonError, CanonicalJsonObject};
|
||||||
use std::{
|
use std::{
|
||||||
cmp,
|
cmp, fmt,
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
time::{SystemTime, UNIX_EPOCH},
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
};
|
};
|
||||||
|
@ -140,3 +140,40 @@ pub fn deserialize_from_str<
|
||||||
}
|
}
|
||||||
deserializer.deserialize_str(Visitor(std::marker::PhantomData))
|
deserializer.deserialize_str(Visitor(std::marker::PhantomData))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copied from librustdoc:
|
||||||
|
// https://github.com/rust-lang/rust/blob/cbaeec14f90b59a91a6b0f17fc046c66fa811892/src/librustdoc/html/escape.rs
|
||||||
|
|
||||||
|
/// 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);
|
||||||
|
|
||||||
|
impl<'a> fmt::Display for HtmlEscape<'a> {
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
// Because the internet is always right, turns out there's not that many
|
||||||
|
// characters to escape: http://stackoverflow.com/questions/7381974
|
||||||
|
let HtmlEscape(s) = *self;
|
||||||
|
let pile_o_bits = s;
|
||||||
|
let mut last = 0;
|
||||||
|
for (i, ch) in s.char_indices() {
|
||||||
|
let s = match ch {
|
||||||
|
'>' => ">",
|
||||||
|
'<' => "<",
|
||||||
|
'&' => "&",
|
||||||
|
'\'' => "'",
|
||||||
|
'"' => """,
|
||||||
|
_ => continue,
|
||||||
|
};
|
||||||
|
fmt.write_str(&pile_o_bits[last..i])?;
|
||||||
|
fmt.write_str(s)?;
|
||||||
|
// NOTE: we only expect single byte characters here - which is fine as long as we
|
||||||
|
// only match single byte characters
|
||||||
|
last = i + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if last < s.len() {
|
||||||
|
fmt.write_str(&pile_o_bits[last..])?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -27,14 +27,13 @@ RUN chmod +x /workdir/caddy
|
||||||
COPY conduit-example.toml conduit.toml
|
COPY conduit-example.toml conduit.toml
|
||||||
|
|
||||||
ENV SERVER_NAME=localhost
|
ENV SERVER_NAME=localhost
|
||||||
ENV ROCKET_LOG=normal
|
|
||||||
ENV CONDUIT_CONFIG=/workdir/conduit.toml
|
ENV CONDUIT_CONFIG=/workdir/conduit.toml
|
||||||
|
|
||||||
RUN sed -i "s/port = 6167/port = 8008/g" conduit.toml
|
RUN sed -i "s/port = 6167/port = 8008/g" conduit.toml
|
||||||
RUN echo "allow_federation = true" >> conduit.toml
|
RUN echo "allow_federation = true" >> conduit.toml
|
||||||
RUN echo "allow_encryption = true" >> conduit.toml
|
RUN echo "allow_encryption = true" >> conduit.toml
|
||||||
RUN echo "allow_registration = true" >> conduit.toml
|
RUN echo "allow_registration = true" >> conduit.toml
|
||||||
RUN echo "log = \"info,rocket=info,_=off,sled=off\"" >> conduit.toml
|
RUN echo "log = \"info,_=off,sled=off\"" >> conduit.toml
|
||||||
RUN sed -i "s/address = \"127.0.0.1\"/address = \"0.0.0.0\"/g" conduit.toml
|
RUN sed -i "s/address = \"127.0.0.1\"/address = \"0.0.0.0\"/g" conduit.toml
|
||||||
|
|
||||||
# Enabled Caddy auto cert generation for complement provided CA.
|
# Enabled Caddy auto cert generation for complement provided CA.
|
||||||
|
|
Loading…
Reference in a new issue