1 parent
5b22add1f3
commit
2c98b8f925
38 files changed
+915
-87
No files matched your search
+60
-8
@@ -19,6 +19,7 @@ pub mod quota;
|
||||
pub mod response_templates;
|
||||
pub mod search;
|
||||
pub mod send;
|
||||
pub mod settings;
|
||||
pub mod sieve;
|
||||
pub mod special_folders;
|
||||
pub mod tags;
|
||||
@@ -29,8 +30,10 @@ use std::net::{IpAddr, Ipv4Addr, SocketAddr};
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
|
||||
use axum::body::Body;
|
||||
use axum::extract::{ConnectInfo, DefaultBodyLimit};
|
||||
use axum::http::Request;
|
||||
use axum::http::{HeaderValue, Request};
|
||||
use axum::response::Response;
|
||||
use axum::routing::{delete, get, patch, post, put};
|
||||
use axum::{Extension, Router, middleware};
|
||||
use tower_governor::GovernorError;
|
||||
@@ -101,6 +104,32 @@ impl KeyExtractor for ProxyAwareIpExtractor {
|
||||
}
|
||||
}
|
||||
|
||||
async fn add_security_headers(request: Request<Body>, next: middleware::Next) -> Response {
|
||||
let mut response = next.run(request).await;
|
||||
let headers = response.headers_mut();
|
||||
headers.insert(
|
||||
"x-content-type-options",
|
||||
HeaderValue::from_static("nosniff"),
|
||||
);
|
||||
headers.insert("x-frame-options", HeaderValue::from_static("DENY"));
|
||||
headers.insert("referrer-policy", HeaderValue::from_static("no-referrer"));
|
||||
headers.insert(
|
||||
"permissions-policy",
|
||||
HeaderValue::from_static("camera=(), microphone=(), geolocation=()"),
|
||||
);
|
||||
headers.insert(
|
||||
"cross-origin-opener-policy",
|
||||
HeaderValue::from_static("same-origin"),
|
||||
);
|
||||
headers.insert(
|
||||
"content-security-policy",
|
||||
HeaderValue::from_static(
|
||||
"default-src 'self'; base-uri 'self'; object-src 'none'; frame-ancestors 'none'; form-action 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: http: https:; font-src 'self' data:; connect-src 'self' ws: wss:",
|
||||
),
|
||||
);
|
||||
response
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub fn create_router(
|
||||
config: Arc<AppConfig>,
|
||||
@@ -455,6 +484,9 @@ pub fn create_router_with_storage(config: Arc<AppConfig>, services: RouterServic
|
||||
delete(calendar::delete_meeting_template),
|
||||
)
|
||||
.route("/quota", get(quota::get_quota))
|
||||
.route("/settings/reset", post(settings::reset_all_settings));
|
||||
|
||||
let diagnostics_routes = Router::new()
|
||||
.route("/diagnostics/imap", get(diagnostics::imap_diagnostics))
|
||||
.route("/diagnostics/smtp", get(diagnostics::smtp_diagnostics))
|
||||
.route("/diagnostics/sync", get(diagnostics::sync_diagnostics))
|
||||
@@ -466,7 +498,9 @@ pub fn create_router_with_storage(config: Arc<AppConfig>, services: RouterServic
|
||||
.route(
|
||||
"/diagnostics/search/rebuild",
|
||||
post(diagnostics::rebuild_search_index),
|
||||
)
|
||||
);
|
||||
|
||||
let sieve_routes = Router::new()
|
||||
.route("/sieve/status", get(sieve::status))
|
||||
.route("/sieve/scripts", get(sieve::list_scripts))
|
||||
.route(
|
||||
@@ -481,9 +515,20 @@ pub fn create_router_with_storage(config: Arc<AppConfig>, services: RouterServic
|
||||
)
|
||||
.route("/sieve/scripts/{name}/rename", post(sieve::rename_script))
|
||||
.route("/sieve/deactivate", post(sieve::deactivate_script))
|
||||
.route("/sieve/check", post(sieve::check_script))
|
||||
.layer(middleware::from_fn(auth_guard))
|
||||
.layer(middleware::from_fn(csrf_protection));
|
||||
.route("/sieve/check", post(sieve::check_script));
|
||||
|
||||
let protected_data = if config.diagnostics_enabled {
|
||||
protected_data.merge(diagnostics_routes)
|
||||
} else {
|
||||
protected_data
|
||||
};
|
||||
let protected_data = if config.sieve_enabled {
|
||||
protected_data.merge(sieve_routes)
|
||||
} else {
|
||||
protected_data
|
||||
}
|
||||
.layer(middleware::from_fn(auth_guard))
|
||||
.layer(middleware::from_fn(csrf_protection));
|
||||
|
||||
let ws_route = Router::new().route("/ws", get(crate::realtime::ws::ws_handler));
|
||||
|
||||
@@ -492,7 +537,8 @@ pub fn create_router_with_storage(config: Arc<AppConfig>, services: RouterServic
|
||||
.route("/ready", get(health::readiness_check))
|
||||
.nest("/auth", auth_router)
|
||||
.merge(ws_route)
|
||||
.merge(protected_data);
|
||||
.merge(protected_data)
|
||||
.fallback(|| async { axum::http::StatusCode::NOT_FOUND });
|
||||
|
||||
let inner = Router::new()
|
||||
.nest("/api", api_router)
|
||||
@@ -509,7 +555,7 @@ pub fn create_router_with_storage(config: Arc<AppConfig>, services: RouterServic
|
||||
}
|
||||
};
|
||||
|
||||
router
|
||||
let router = router
|
||||
.layer(Extension(idle_manager))
|
||||
.layer(Extension(event_bus))
|
||||
.layer(Extension(smtp_client))
|
||||
@@ -518,7 +564,13 @@ pub fn create_router_with_storage(config: Arc<AppConfig>, services: RouterServic
|
||||
.layer(Extension(imap_client))
|
||||
.layer(Extension(store))
|
||||
.layer(Extension(config.clone()))
|
||||
.layer(TraceLayer::new_for_http())
|
||||
.layer(TraceLayer::new_for_http());
|
||||
|
||||
if config.security_headers_enabled {
|
||||
router.layer(middleware::from_fn(add_security_headers))
|
||||
} else {
|
||||
router
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in new issue
Block a user