add event_bus_typed
This commit is contained in:
Generated
+133
-3
@@ -189,6 +189,15 @@ dependencies = [
|
|||||||
"derive_arbitrary",
|
"derive_arbitrary",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arc-swap"
|
||||||
|
version = "1.9.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b"
|
||||||
|
dependencies = [
|
||||||
|
"rustversion",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "argon2"
|
name = "argon2"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
@@ -704,6 +713,28 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "axum-server"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1ab4a3ec9ea8a657c72d99a03a824af695bd0fb5ec639ccbd9cd3543b41a5f9"
|
||||||
|
dependencies = [
|
||||||
|
"arc-swap",
|
||||||
|
"bytes",
|
||||||
|
"fs-err",
|
||||||
|
"http 1.5.0",
|
||||||
|
"http-body 1.1.0",
|
||||||
|
"hyper 1.11.0",
|
||||||
|
"hyper-util",
|
||||||
|
"pin-project-lite",
|
||||||
|
"rustls",
|
||||||
|
"rustls-pemfile",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"tokio",
|
||||||
|
"tokio-rustls",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "base16ct"
|
name = "base16ct"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@@ -1753,6 +1784,16 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fs-err"
|
||||||
|
version = "3.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b91aa448ca50d7e79433bdf3ee8d99215430d2ec02ade5aefab2a073a1822e8a"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fs_extra"
|
name = "fs_extra"
|
||||||
version = "1.3.0"
|
version = "1.3.0"
|
||||||
@@ -1992,6 +2033,25 @@ dependencies = [
|
|||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "h2"
|
||||||
|
version = "0.4.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16"
|
||||||
|
dependencies = [
|
||||||
|
"atomic-waker",
|
||||||
|
"bytes",
|
||||||
|
"fnv",
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
"http 1.5.0",
|
||||||
|
"indexmap",
|
||||||
|
"slab",
|
||||||
|
"tokio",
|
||||||
|
"tokio-util",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "half"
|
name = "half"
|
||||||
version = "2.7.1"
|
version = "2.7.1"
|
||||||
@@ -2191,7 +2251,7 @@ dependencies = [
|
|||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"h2",
|
"h2 0.3.27",
|
||||||
"http 0.2.12",
|
"http 0.2.12",
|
||||||
"http-body 0.4.6",
|
"http-body 0.4.6",
|
||||||
"httparse",
|
"httparse",
|
||||||
@@ -2215,6 +2275,7 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
|
"h2 0.4.19",
|
||||||
"http 1.5.0",
|
"http 1.5.0",
|
||||||
"http-body 1.1.0",
|
"http-body 1.1.0",
|
||||||
"httparse",
|
"httparse",
|
||||||
@@ -2957,6 +3018,7 @@ dependencies = [
|
|||||||
"async-trait",
|
"async-trait",
|
||||||
"axum",
|
"axum",
|
||||||
"axum-extra",
|
"axum-extra",
|
||||||
|
"axum-server",
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"chrono",
|
"chrono",
|
||||||
"config",
|
"config",
|
||||||
@@ -2967,6 +3029,7 @@ dependencies = [
|
|||||||
"log",
|
"log",
|
||||||
"migration",
|
"migration",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
|
"rcgen 0.13.2",
|
||||||
"rustrtc",
|
"rustrtc",
|
||||||
"sea-orm",
|
"sea-orm",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -3482,6 +3545,19 @@ dependencies = [
|
|||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rcgen"
|
||||||
|
version = "0.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "75e669e5202259b5314d1ea5397316ad400819437857b90861765f24c4cf80a2"
|
||||||
|
dependencies = [
|
||||||
|
"pem 3.0.6",
|
||||||
|
"ring",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"time",
|
||||||
|
"yasna 0.5.2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rcgen"
|
name = "rcgen"
|
||||||
version = "0.14.10"
|
version = "0.14.10"
|
||||||
@@ -3493,7 +3569,7 @@ dependencies = [
|
|||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"time",
|
"time",
|
||||||
"x509-parser",
|
"x509-parser",
|
||||||
"yasna",
|
"yasna 0.6.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3703,6 +3779,29 @@ dependencies = [
|
|||||||
"windows-sys 0.61.2",
|
"windows-sys 0.61.2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls"
|
||||||
|
version = "0.23.45"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634"
|
||||||
|
dependencies = [
|
||||||
|
"aws-lc-rs",
|
||||||
|
"once_cell",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"rustls-webpki",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-pemfile"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
|
||||||
|
dependencies = [
|
||||||
|
"rustls-pki-types",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-pki-types"
|
name = "rustls-pki-types"
|
||||||
version = "1.15.1"
|
version = "1.15.1"
|
||||||
@@ -3712,6 +3811,18 @@ dependencies = [
|
|||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustls-webpki"
|
||||||
|
version = "0.103.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2"
|
||||||
|
dependencies = [
|
||||||
|
"aws-lc-rs",
|
||||||
|
"ring",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"untrusted 0.9.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustrtc"
|
name = "rustrtc"
|
||||||
version = "0.3.138"
|
version = "0.3.138"
|
||||||
@@ -3735,7 +3846,7 @@ dependencies = [
|
|||||||
"p256",
|
"p256",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"rand 0.10.2",
|
"rand 0.10.2",
|
||||||
"rcgen",
|
"rcgen 0.14.10",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha1 0.11.0",
|
"sha1 0.11.0",
|
||||||
@@ -4635,6 +4746,16 @@ dependencies = [
|
|||||||
"syn 3.0.3",
|
"syn 3.0.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-rustls"
|
||||||
|
version = "0.26.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b0c85f2c3ef0b1cd58b36682f4b17aaa995f0e5db534d85692b4903abce21f67"
|
||||||
|
dependencies = [
|
||||||
|
"rustls",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-stream"
|
name = "tokio-stream"
|
||||||
version = "0.1.19"
|
version = "0.1.19"
|
||||||
@@ -5446,6 +5567,15 @@ version = "1.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
|
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "yasna"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd"
|
||||||
|
dependencies = [
|
||||||
|
"time",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "yasna"
|
name = "yasna"
|
||||||
version = "0.6.0"
|
version = "0.6.0"
|
||||||
|
|||||||
@@ -43,3 +43,5 @@ form_urlencoded = "1.2.2"
|
|||||||
time = "0.3.55"
|
time = "0.3.55"
|
||||||
sha2 = "0.11.0"
|
sha2 = "0.11.0"
|
||||||
rustrtc = "0.3.138"
|
rustrtc = "0.3.138"
|
||||||
|
axum-server = { version = "0.7", features = ["tls-rustls"] }
|
||||||
|
rcgen = "0.13"
|
||||||
|
|||||||
@@ -8,6 +8,12 @@ tcp_port = 8080
|
|||||||
# Voice/Video port
|
# Voice/Video port
|
||||||
udp_port = 8080
|
udp_port = 8080
|
||||||
|
|
||||||
|
# Uncomment for native self-signed HTTPS/WSS. Keep both files between restarts.
|
||||||
|
# [network.tls]
|
||||||
|
# cert_path = "certs/server.pem"
|
||||||
|
# key_path = "certs/server-key.pem"
|
||||||
|
# names = ["localhost", "127.0.0.1"] # include the host clients actually use
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
# DSN for database
|
# DSN for database
|
||||||
# SQLite
|
# SQLite
|
||||||
|
|||||||
@@ -51,6 +51,12 @@ tcp_port = 8080
|
|||||||
# WebRTC ICE/Media UDP multiplexing port
|
# WebRTC ICE/Media UDP multiplexing port
|
||||||
udp_port = 8080
|
udp_port = 8080
|
||||||
|
|
||||||
|
# Optional native HTTPS (omit this section to keep plain HTTP behind a proxy).
|
||||||
|
# [network.tls]
|
||||||
|
# cert_path = "certs/server.pem"
|
||||||
|
# key_path = "certs/server-key.pem"
|
||||||
|
# names = ["localhost", "127.0.0.1"]
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
# DSN for database
|
# DSN for database
|
||||||
# SQLite
|
# SQLite
|
||||||
@@ -103,6 +109,15 @@ pub struct NetworkConfig {
|
|||||||
pub hostv6: Option<Ipv6Addr>,
|
pub hostv6: Option<Ipv6Addr>,
|
||||||
pub tcp_port: u16,
|
pub tcp_port: u16,
|
||||||
pub udp_port: u16,
|
pub udp_port: u16,
|
||||||
|
#[serde(default)]
|
||||||
|
pub tls: Option<TlsConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct TlsConfig {
|
||||||
|
pub cert_path: std::path::PathBuf,
|
||||||
|
pub key_path: std::path::PathBuf,
|
||||||
|
pub names: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Deserialize)]
|
#[derive(Clone, Deserialize)]
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ pub mod metrics;
|
|||||||
pub mod middleware;
|
pub mod middleware;
|
||||||
pub mod permissions;
|
pub mod permissions;
|
||||||
pub mod server;
|
pub mod server;
|
||||||
|
mod tls;
|
||||||
pub mod validation;
|
pub mod validation;
|
||||||
|
|
||||||
pub use permissions::{RequireChannelPermission, RequireServerPermission};
|
pub use permissions::{RequireChannelPermission, RequireServerPermission};
|
||||||
|
|||||||
+20
-1
@@ -15,12 +15,13 @@ use tower_http::catch_panic::CatchPanicLayer;
|
|||||||
use tower_http::cors::CorsLayer;
|
use tower_http::cors::CorsLayer;
|
||||||
use tower_http::trace::TraceLayer;
|
use tower_http::trace::TraceLayer;
|
||||||
|
|
||||||
use crate::config::NetworkConfig;
|
use crate::config::{NetworkConfig, TlsConfig};
|
||||||
use crate::core::AppState;
|
use crate::core::AppState;
|
||||||
use crate::routes;
|
use crate::routes;
|
||||||
|
|
||||||
use super::metrics::HttpMetrics;
|
use super::metrics::HttpMetrics;
|
||||||
use super::middleware;
|
use super::middleware;
|
||||||
|
use super::tls;
|
||||||
|
|
||||||
// ── Erreurs ───────────────────────────────────────────────────────────────────
|
// ── Erreurs ───────────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
@@ -66,6 +67,7 @@ pub enum HttpServerError {
|
|||||||
/// ```
|
/// ```
|
||||||
pub struct HttpServer {
|
pub struct HttpServer {
|
||||||
bind_addr: SocketAddr,
|
bind_addr: SocketAddr,
|
||||||
|
tls: Option<TlsConfig>,
|
||||||
app_state: AppState,
|
app_state: AppState,
|
||||||
metrics: Arc<HttpMetrics>,
|
metrics: Arc<HttpMetrics>,
|
||||||
shutdown_rx: broadcast::Receiver<()>,
|
shutdown_rx: broadcast::Receiver<()>,
|
||||||
@@ -87,6 +89,7 @@ impl HttpServer {
|
|||||||
(
|
(
|
||||||
Self {
|
Self {
|
||||||
bind_addr,
|
bind_addr,
|
||||||
|
tls: network_config.tls.clone(),
|
||||||
app_state,
|
app_state,
|
||||||
metrics,
|
metrics,
|
||||||
shutdown_rx,
|
shutdown_rx,
|
||||||
@@ -149,6 +152,22 @@ impl HttpServer {
|
|||||||
// Outermost : intercepte les panics et retourne une 500 propre
|
// Outermost : intercepte les panics et retourne une 500 propre
|
||||||
.layer(CatchPanicLayer::new());
|
.layer(CatchPanicLayer::new());
|
||||||
|
|
||||||
|
if let Some(tls_config) = &self.tls {
|
||||||
|
let rustls = tls::load_or_create(tls_config).await?;
|
||||||
|
let handle = axum_server::Handle::new();
|
||||||
|
let shutdown = handle.clone();
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let _ = self.shutdown_rx.recv().await;
|
||||||
|
shutdown.graceful_shutdown(Some(std::time::Duration::from_secs(10)));
|
||||||
|
});
|
||||||
|
tracing::info!(addr = %self.bind_addr, "HTTPS server listening");
|
||||||
|
axum_server::bind_rustls(self.bind_addr, rustls)
|
||||||
|
.handle(handle)
|
||||||
|
.serve(app.into_make_service())
|
||||||
|
.await?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let listener =
|
let listener =
|
||||||
TcpListener::bind(self.bind_addr)
|
TcpListener::bind(self.bind_addr)
|
||||||
.await
|
.await
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
use crate::config::TlsConfig;
|
||||||
|
use axum_server::tls_rustls::RustlsConfig;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
pub async fn load_or_create(config: &TlsConfig) -> io::Result<RustlsConfig> {
|
||||||
|
if config.names.is_empty() || config.names.iter().any(|name| name.is_empty()) {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::InvalidInput, "TLS requires at least one non-empty name"));
|
||||||
|
}
|
||||||
|
if config.cert_path == config.key_path {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::InvalidInput, "certificate and key paths must differ"));
|
||||||
|
}
|
||||||
|
|
||||||
|
let cert_exists = config.cert_path.exists();
|
||||||
|
let key_exists = config.key_path.exists();
|
||||||
|
if cert_exists != key_exists {
|
||||||
|
return Err(io::Error::new(io::ErrorKind::InvalidData, "only one TLS file exists; restore the missing file or remove both to regenerate"));
|
||||||
|
}
|
||||||
|
if !cert_exists {
|
||||||
|
let generated = rcgen::generate_simple_self_signed(config.names.clone())
|
||||||
|
.map_err(io::Error::other)?;
|
||||||
|
for path in [&config.cert_path, &config.key_path] {
|
||||||
|
if let Some(parent) = path.parent() {
|
||||||
|
std::fs::create_dir_all(parent)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::fs::write(&config.cert_path, generated.cert.pem())?;
|
||||||
|
let key = generated.key_pair.serialize_pem();
|
||||||
|
#[cfg(unix)]
|
||||||
|
{
|
||||||
|
use std::os::unix::fs::OpenOptionsExt;
|
||||||
|
use std::io::Write;
|
||||||
|
let mut file = std::fs::OpenOptions::new().write(true).create_new(true).mode(0o600).open(&config.key_path)?;
|
||||||
|
file.write_all(key.as_bytes())?;
|
||||||
|
}
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
std::fs::write(&config.key_path, key)?;
|
||||||
|
tracing::info!(cert = %config.cert_path.display(), "Generated self-signed TLS certificate");
|
||||||
|
}
|
||||||
|
RustlsConfig::from_pem_file(&config.cert_path, &config.key_path).await
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn certificate_is_reused_and_partial_pair_is_rejected() {
|
||||||
|
let dir = std::env::temp_dir().join(format!("oxspeak-tls-{}", uuid::Uuid::new_v4()));
|
||||||
|
let config = TlsConfig {
|
||||||
|
cert_path: dir.join("cert.pem"), key_path: dir.join("key.pem"),
|
||||||
|
names: vec!["localhost".into()],
|
||||||
|
};
|
||||||
|
load_or_create(&config).await.unwrap();
|
||||||
|
let cert = std::fs::read(&config.cert_path).unwrap();
|
||||||
|
let key = std::fs::read(&config.key_path).unwrap();
|
||||||
|
load_or_create(&config).await.unwrap();
|
||||||
|
assert_eq!(cert, std::fs::read(&config.cert_path).unwrap());
|
||||||
|
assert_eq!(key, std::fs::read(&config.key_path).unwrap());
|
||||||
|
std::fs::remove_file(&config.key_path).unwrap();
|
||||||
|
assert!(load_or_create(&config).await.is_err());
|
||||||
|
std::fs::remove_dir_all(dir).unwrap();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -341,6 +341,7 @@ mod tests {
|
|||||||
hostv6: None,
|
hostv6: None,
|
||||||
tcp_port: 8080,
|
tcp_port: 8080,
|
||||||
udp_port: 9000,
|
udp_port: 9000,
|
||||||
|
tls: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user