diff --git a/src/app.rs b/src/app.rs index 64119aa34..289db1fdc 100644 --- a/src/app.rs +++ b/src/app.rs @@ -61,7 +61,6 @@ pub async fn start(config: &Configuration, app_container: &AppContainer) -> Vec< // Load whitelisted torrents if app_container.tracker.is_listed() { app_container - .tracker .whitelist_manager .load_whitelist_from_database() .await @@ -81,6 +80,7 @@ pub async fn start(config: &Configuration, app_container: &AppContainer) -> Vec< udp_tracker::start_job( udp_tracker_config, app_container.tracker.clone(), + app_container.whitelist_authorization.clone(), app_container.stats_event_sender.clone(), app_container.ban_service.clone(), registar.give_form(), @@ -99,6 +99,7 @@ pub async fn start(config: &Configuration, app_container: &AppContainer) -> Vec< if let Some(job) = http_tracker::start_job( http_tracker_config, app_container.tracker.clone(), + app_container.whitelist_authorization.clone(), app_container.stats_event_sender.clone(), registar.give_form(), servers::http::Version::V1, @@ -117,6 +118,7 @@ pub async fn start(config: &Configuration, app_container: &AppContainer) -> Vec< if let Some(job) = tracker_apis::start_job( http_api_config, app_container.tracker.clone(), + app_container.whitelist_manager.clone(), app_container.ban_service.clone(), app_container.stats_event_sender.clone(), app_container.stats_repository.clone(), diff --git a/src/app_test.rs b/src/app_test.rs index c50f87965..ffd55581e 100644 --- a/src/app_test.rs +++ b/src/app_test.rs @@ -4,15 +4,26 @@ use std::sync::Arc; use torrust_tracker_configuration::Configuration; use crate::core::databases::Database; -use crate::core::services::{initialize_database, initialize_whitelist}; -use crate::core::whitelist::WhiteListManager; +use crate::core::services::initialize_database; +use crate::core::whitelist; +use crate::core::whitelist::repository::in_memory::InMemoryWhitelist; /// Initialize the tracker dependencies. #[allow(clippy::type_complexity)] #[must_use] -pub fn initialize_tracker_dependencies(config: &Configuration) -> (Arc>, Arc) { +pub fn initialize_tracker_dependencies( + config: &Configuration, +) -> ( + Arc>, + Arc, + Arc, +) { let database = initialize_database(config); - let whitelist_manager = initialize_whitelist(database.clone()); + let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); + let whitelist_authorization = Arc::new(whitelist::authorization::Authorization::new( + &config.core, + &in_memory_whitelist.clone(), + )); - (database, whitelist_manager) + (database, in_memory_whitelist, whitelist_authorization) } diff --git a/src/bootstrap/app.rs b/src/bootstrap/app.rs index 53bf44f79..5dbdd15cb 100644 --- a/src/bootstrap/app.rs +++ b/src/bootstrap/app.rs @@ -22,7 +22,9 @@ use tracing::instrument; use super::config::initialize_configuration; use crate::bootstrap; use crate::container::AppContainer; -use crate::core::services::{initialize_database, initialize_tracker, initialize_whitelist, statistics}; +use crate::core::services::{initialize_database, initialize_tracker, initialize_whitelist_manager, statistics}; +use crate::core::whitelist; +use crate::core::whitelist::repository::in_memory::InMemoryWhitelist; use crate::servers::udp::server::banning::BanService; use crate::servers::udp::server::launcher::MAX_CONNECTION_ID_ERRORS_PER_IP; use crate::shared::crypto::ephemeral_instance_keys; @@ -81,11 +83,18 @@ pub fn initialize_app_container(configuration: &Configuration) -> AppContainer { let stats_repository = Arc::new(stats_repository); let ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP))); let database = initialize_database(configuration); - let whitelist_manager = initialize_whitelist(database.clone()); - let tracker = Arc::new(initialize_tracker(configuration, &database, &whitelist_manager)); + let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); + let whitelist_authorization = Arc::new(whitelist::authorization::Authorization::new( + &configuration.core, + &in_memory_whitelist.clone(), + )); + let whitelist_manager = initialize_whitelist_manager(database.clone(), in_memory_whitelist.clone()); + + let tracker = Arc::new(initialize_tracker(configuration, &database, &whitelist_authorization)); AppContainer { tracker, + whitelist_authorization, ban_service, stats_event_sender, stats_repository, diff --git a/src/bootstrap/jobs/http_tracker.rs b/src/bootstrap/jobs/http_tracker.rs index d32e8d4aa..dea866648 100644 --- a/src/bootstrap/jobs/http_tracker.rs +++ b/src/bootstrap/jobs/http_tracker.rs @@ -20,7 +20,7 @@ use tracing::instrument; use super::make_rust_tls; use crate::core::statistics::event::sender::Sender; -use crate::core::{self, statistics}; +use crate::core::{self, statistics, whitelist}; use crate::servers::http::server::{HttpServer, Launcher}; use crate::servers::http::Version; use crate::servers::registar::ServiceRegistrationForm; @@ -34,10 +34,11 @@ use crate::servers::registar::ServiceRegistrationForm; /// /// It would panic if the `config::HttpTracker` struct would contain inappropriate values. /// -#[instrument(skip(config, tracker, stats_event_sender, form))] +#[instrument(skip(config, tracker, whitelist_authorization, stats_event_sender, form))] pub async fn start_job( config: &HttpTracker, tracker: Arc, + whitelist_authorization: Arc, stats_event_sender: Arc>>, form: ServiceRegistrationForm, version: Version, @@ -49,21 +50,32 @@ pub async fn start_job( .map(|tls| tls.expect("it should have a valid http tracker tls configuration")); match version { - Version::V1 => Some(start_v1(socket, tls, tracker.clone(), stats_event_sender.clone(), form).await), + Version::V1 => Some( + start_v1( + socket, + tls, + tracker.clone(), + whitelist_authorization.clone(), + stats_event_sender.clone(), + form, + ) + .await, + ), } } #[allow(clippy::async_yields_async)] -#[instrument(skip(socket, tls, tracker, stats_event_sender, form))] +#[instrument(skip(socket, tls, tracker, whitelist_authorization, stats_event_sender, form))] async fn start_v1( socket: SocketAddr, tls: Option, tracker: Arc, + whitelist_authorization: Arc, stats_event_sender: Arc>>, form: ServiceRegistrationForm, ) -> JoinHandle<()> { let server = HttpServer::new(Launcher::new(socket, tls)) - .start(tracker, stats_event_sender, form) + .start(tracker, whitelist_authorization, stats_event_sender, form) .await .expect("it should be able to start to the http tracker"); @@ -88,7 +100,9 @@ mod tests { use crate::bootstrap::app::initialize_global_services; use crate::bootstrap::jobs::http_tracker::start_job; - use crate::core::services::{initialize_database, initialize_tracker, initialize_whitelist, statistics}; + use crate::core::services::{initialize_database, initialize_tracker, statistics}; + use crate::core::whitelist; + use crate::core::whitelist::repository::in_memory::InMemoryWhitelist; use crate::servers::http::Version; use crate::servers::registar::Registar; @@ -104,13 +118,24 @@ mod tests { initialize_global_services(&cfg); let database = initialize_database(&cfg); - let whitelist_manager = initialize_whitelist(database.clone()); - let tracker = Arc::new(initialize_tracker(&cfg, &database, &whitelist_manager)); + let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); + let whitelist_authorization = Arc::new(whitelist::authorization::Authorization::new( + &cfg.core, + &in_memory_whitelist.clone(), + )); + let tracker = Arc::new(initialize_tracker(&cfg, &database, &whitelist_authorization)); let version = Version::V1; - start_job(config, tracker, stats_event_sender, Registar::default().give_form(), version) - .await - .expect("it should be able to join to the http tracker start-job"); + start_job( + config, + tracker, + whitelist_authorization, + stats_event_sender, + Registar::default().give_form(), + version, + ) + .await + .expect("it should be able to join to the http tracker start-job"); } } diff --git a/src/bootstrap/jobs/tracker_apis.rs b/src/bootstrap/jobs/tracker_apis.rs index 9c284fbfc..7e06829c4 100644 --- a/src/bootstrap/jobs/tracker_apis.rs +++ b/src/bootstrap/jobs/tracker_apis.rs @@ -30,9 +30,10 @@ use torrust_tracker_configuration::{AccessTokens, HttpApi}; use tracing::instrument; use super::make_rust_tls; -use crate::core; use crate::core::statistics::event::sender::Sender; use crate::core::statistics::repository::Repository; +use crate::core::whitelist::manager::WhiteListManager; +use crate::core::{self}; use crate::servers::apis::server::{ApiServer, Launcher}; use crate::servers::apis::Version; use crate::servers::registar::ServiceRegistrationForm; @@ -58,10 +59,12 @@ pub struct ApiServerJobStarted(); /// It would panic if unable to send the `ApiServerJobStarted` notice. /// /// -#[instrument(skip(config, tracker, ban_service, stats_event_sender, stats_repository, form))] +#[allow(clippy::too_many_arguments)] +#[instrument(skip(config, tracker, whitelist_manager, ban_service, stats_event_sender, stats_repository, form))] pub async fn start_job( config: &HttpApi, tracker: Arc, + whitelist_manager: Arc, ban_service: Arc>, stats_event_sender: Arc>>, stats_repository: Arc, @@ -82,6 +85,7 @@ pub async fn start_job( bind_to, tls, tracker.clone(), + whitelist_manager.clone(), ban_service.clone(), stats_event_sender.clone(), stats_repository.clone(), @@ -99,6 +103,7 @@ pub async fn start_job( socket, tls, tracker, + whitelist_manager, ban_service, stats_event_sender, stats_repository, @@ -109,6 +114,7 @@ async fn start_v1( socket: SocketAddr, tls: Option, tracker: Arc, + whitelist_manager: Arc, ban_service: Arc>, stats_event_sender: Arc>>, stats_repository: Arc, @@ -118,6 +124,7 @@ async fn start_v1( let server = ApiServer::new(Launcher::new(socket, tls)) .start( tracker, + whitelist_manager, stats_event_sender, stats_repository, ban_service, @@ -142,7 +149,9 @@ mod tests { use crate::bootstrap::app::initialize_global_services; use crate::bootstrap::jobs::tracker_apis::start_job; - use crate::core::services::{initialize_database, initialize_tracker, initialize_whitelist, statistics}; + use crate::core::services::{initialize_database, initialize_tracker, initialize_whitelist_manager, statistics}; + use crate::core::whitelist; + use crate::core::whitelist::repository::in_memory::InMemoryWhitelist; use crate::servers::apis::Version; use crate::servers::registar::Registar; use crate::servers::udp::server::banning::BanService; @@ -161,14 +170,21 @@ mod tests { initialize_global_services(&cfg); let database = initialize_database(&cfg); - let whitelist_manager = initialize_whitelist(database.clone()); - let tracker = Arc::new(initialize_tracker(&cfg, &database, &whitelist_manager)); + let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); + let whitelist_authorization = Arc::new(whitelist::authorization::Authorization::new( + &cfg.core, + &in_memory_whitelist.clone(), + )); + let whitelist_manager = initialize_whitelist_manager(database.clone(), in_memory_whitelist.clone()); + + let tracker = Arc::new(initialize_tracker(&cfg, &database, &whitelist_authorization)); let version = Version::V1; start_job( config, tracker, + whitelist_manager, ban_service, stats_event_sender, stats_repository, diff --git a/src/bootstrap/jobs/udp_tracker.rs b/src/bootstrap/jobs/udp_tracker.rs index 105c7f723..724e2043e 100644 --- a/src/bootstrap/jobs/udp_tracker.rs +++ b/src/bootstrap/jobs/udp_tracker.rs @@ -13,8 +13,8 @@ use tokio::task::JoinHandle; use torrust_tracker_configuration::UdpTracker; use tracing::instrument; -use crate::core; use crate::core::statistics::event::sender::Sender; +use crate::core::{self, whitelist}; use crate::servers::registar::ServiceRegistrationForm; use crate::servers::udp::server::banning::BanService; use crate::servers::udp::server::spawner::Spawner; @@ -32,10 +32,11 @@ use crate::servers::udp::UDP_TRACKER_LOG_TARGET; /// It will panic if the task did not finish successfully. #[must_use] #[allow(clippy::async_yields_async)] -#[instrument(skip(config, tracker, stats_event_sender, ban_service, form))] +#[instrument(skip(config, tracker, whitelist_authorization, stats_event_sender, ban_service, form))] pub async fn start_job( config: &UdpTracker, tracker: Arc, + whitelist_authorization: Arc, stats_event_sender: Arc>>, ban_service: Arc>, form: ServiceRegistrationForm, @@ -44,7 +45,14 @@ pub async fn start_job( let cookie_lifetime = config.cookie_lifetime; let server = Server::new(Spawner::new(bind_to)) - .start(tracker, stats_event_sender, ban_service, form, cookie_lifetime) + .start( + tracker, + whitelist_authorization, + stats_event_sender, + ban_service, + form, + cookie_lifetime, + ) .await .expect("it should be able to start the udp tracker"); diff --git a/src/container.rs b/src/container.rs index 7a2b86d18..fd75601ae 100644 --- a/src/container.rs +++ b/src/container.rs @@ -4,12 +4,13 @@ use tokio::sync::RwLock; use crate::core::statistics::event::sender::Sender; use crate::core::statistics::repository::Repository; -use crate::core::whitelist::WhiteListManager; -use crate::core::Tracker; +use crate::core::whitelist::manager::WhiteListManager; +use crate::core::{whitelist, Tracker}; use crate::servers::udp::server::banning::BanService; pub struct AppContainer { pub tracker: Arc, + pub whitelist_authorization: Arc, pub ban_service: Arc>, pub stats_event_sender: Arc>>, pub stats_repository: Arc, diff --git a/src/core/mod.rs b/src/core/mod.rs index e802b2c43..480d0e971 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -467,11 +467,8 @@ use torrust_tracker_primitives::torrent_metrics::TorrentsMetrics; use torrust_tracker_primitives::{peer, DurationSinceUnixEpoch}; use torrust_tracker_torrent_repository::entry::EntrySync; use torrust_tracker_torrent_repository::repository::Repository; -use tracing::instrument; -use whitelist::WhiteListManager; use self::auth::Key; -use self::error::Error; use self::torrent::Torrents; use crate::core::databases::Database; use crate::CurrentClock; @@ -496,8 +493,8 @@ pub struct Tracker { /// Tracker users' keys. Only for private trackers. keys: tokio::sync::RwLock>, - /// The list of allowed torrents. Only for listed trackers. - pub whitelist_manager: Arc, + /// The service to check is a torrent is whitelisted. + pub whitelist_authorization: Arc, /// The in-memory torrents repository. torrents: Arc, @@ -568,13 +565,13 @@ impl Tracker { pub fn new( config: &Core, database: &Arc>, - whitelist_manager: &Arc, + whitelist_authorization: &Arc, ) -> Result { Ok(Tracker { config: config.clone(), database: database.clone(), keys: tokio::sync::RwLock::new(std::collections::HashMap::new()), - whitelist_manager: whitelist_manager.clone(), + whitelist_authorization: whitelist_authorization.clone(), torrents: Arc::default(), }) } @@ -663,7 +660,7 @@ impl Tracker { let mut scrape_data = ScrapeData::empty(); for info_hash in info_hashes { - let swarm_metadata = match self.authorize(info_hash).await { + let swarm_metadata = match self.whitelist_authorization.authorize(info_hash).await { Ok(()) => self.get_swarm_metadata(info_hash), Err(_) => SwarmMetadata::zeroed(), }; @@ -1018,31 +1015,6 @@ impl Tracker { Ok(()) } - /// Right now, there is only authorization when the `Tracker` runs in - /// `listed` or `private_listed` modes. - /// - /// # Context: Authorization - /// - /// # Errors - /// - /// Will return an error if the tracker is running in `listed` mode - /// and the infohash is not whitelisted. - #[instrument(skip(self, info_hash), err)] - pub async fn authorize(&self, info_hash: &InfoHash) -> Result<(), Error> { - if !self.is_listed() { - return Ok(()); - } - - if self.whitelist_manager.is_info_hash_whitelisted(info_hash).await { - return Ok(()); - } - - Err(Error::TorrentNotWhitelisted { - info_hash: *info_hash, - location: Location::caller(), - }) - } - /// It drops the database tables. /// /// # Errors @@ -1082,35 +1054,42 @@ mod tests { use crate::app_test::initialize_tracker_dependencies; use crate::core::peer::Peer; - use crate::core::services::initialize_tracker; - use crate::core::whitelist::WhiteListManager; - use crate::core::{TorrentsMetrics, Tracker}; + use crate::core::services::{initialize_tracker, initialize_whitelist_manager}; + use crate::core::whitelist::manager::WhiteListManager; + use crate::core::{whitelist, TorrentsMetrics, Tracker}; fn public_tracker() -> Tracker { let config = configuration::ephemeral_public(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); - initialize_tracker(&config, &database, &whitelist_manager) + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); + + initialize_tracker(&config, &database, &whitelist_authorization) } fn private_tracker() -> Tracker { let config = configuration::ephemeral_private(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); - initialize_tracker(&config, &database, &whitelist_manager) + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); + + initialize_tracker(&config, &database, &whitelist_authorization) } - fn whitelisted_tracker() -> (Tracker, Arc) { + fn whitelisted_tracker() -> (Tracker, Arc, Arc) { let config = configuration::ephemeral_listed(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); - let tracker = initialize_tracker(&config, &database, &whitelist_manager); - (tracker, whitelist_manager) + let (database, in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); + + let whitelist_manager = initialize_whitelist_manager(database.clone(), in_memory_whitelist.clone()); + + let tracker = initialize_tracker(&config, &database, &whitelist_authorization); + + (tracker, whitelist_authorization, whitelist_manager) } pub fn tracker_persisting_torrents_in_database() -> Tracker { let mut config = configuration::ephemeral_listed(); config.core.tracker_policy.persistent_torrent_completed_stat = true; - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); - initialize_tracker(&config, &database, &whitelist_manager) + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); + + initialize_tracker(&config, &database, &whitelist_authorization) } fn sample_info_hash() -> InfoHash { @@ -1637,24 +1616,24 @@ mod tests { #[tokio::test] async fn it_should_authorize_the_announce_and_scrape_actions_on_whitelisted_torrents() { - let (tracker, whitelist_manager) = whitelisted_tracker(); + let (tracker, _whitelist_authorization, whitelist_manager) = whitelisted_tracker(); let info_hash = sample_info_hash(); let result = whitelist_manager.add_torrent_to_whitelist(&info_hash).await; assert!(result.is_ok()); - let result = tracker.authorize(&info_hash).await; + let result = tracker.whitelist_authorization.authorize(&info_hash).await; assert!(result.is_ok()); } #[tokio::test] async fn it_should_not_authorize_the_announce_and_scrape_actions_on_not_whitelisted_torrents() { - let (tracker, _whitelist_manager) = whitelisted_tracker(); + let (tracker, _whitelist_authorization, _whitelist_manager) = whitelisted_tracker(); let info_hash = sample_info_hash(); - let result = tracker.authorize(&info_hash).await; + let result = tracker.whitelist_authorization.authorize(&info_hash).await; assert!(result.is_err()); } } @@ -1669,7 +1648,7 @@ mod tests { #[tokio::test] async fn it_should_add_a_torrent_to_the_whitelist() { - let (_tracker, whitelist_manager) = whitelisted_tracker(); + let (_tracker, _whitelist_authorization, whitelist_manager) = whitelisted_tracker(); let info_hash = sample_info_hash(); @@ -1680,7 +1659,7 @@ mod tests { #[tokio::test] async fn it_should_remove_a_torrent_from_the_whitelist() { - let (_tracker, whitelist_manager) = whitelisted_tracker(); + let (_tracker, _whitelist_authorization, whitelist_manager) = whitelisted_tracker(); let info_hash = sample_info_hash(); @@ -1696,7 +1675,7 @@ mod tests { #[tokio::test] async fn it_should_load_the_whitelist_from_the_database() { - let (_tracker, whitelist_manager) = whitelisted_tracker(); + let (_tracker, _whitelist_authorization, whitelist_manager) = whitelisted_tracker(); let info_hash = sample_info_hash(); @@ -1739,7 +1718,7 @@ mod tests { #[tokio::test] async fn it_should_return_the_zeroed_swarm_metadata_for_the_requested_file_if_it_is_not_whitelisted() { - let (tracker, _whitelist_manager) = whitelisted_tracker(); + let (tracker, _whitelist_authorization, _whitelist_manager) = whitelisted_tracker(); let info_hash = "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap(); diff --git a/src/core/services/mod.rs b/src/core/services/mod.rs index fd301b62d..611ea24d2 100644 --- a/src/core/services/mod.rs +++ b/src/core/services/mod.rs @@ -14,8 +14,10 @@ use torrust_tracker_configuration::v2_0_0::database; use torrust_tracker_configuration::Configuration; use super::databases::{self, Database}; -use super::whitelist::persisted::DatabaseWhitelist; -use super::whitelist::WhiteListManager; +use super::whitelist; +use super::whitelist::manager::WhiteListManager; +use super::whitelist::repository::in_memory::InMemoryWhitelist; +use super::whitelist::repository::persisted::DatabaseWhitelist; use crate::core::Tracker; /// It returns a new tracker building its dependencies. @@ -27,9 +29,9 @@ use crate::core::Tracker; pub fn initialize_tracker( config: &Configuration, database: &Arc>, - whitelist_manager: &Arc, + whitelist_authorization: &Arc, ) -> Tracker { - match Tracker::new(&Arc::new(config).core, database, whitelist_manager) { + match Tracker::new(&Arc::new(config).core, database, whitelist_authorization) { Ok(tracker) => tracker, Err(error) => { panic!("{}", error) @@ -51,7 +53,10 @@ pub fn initialize_database(config: &Configuration) -> Arc> { } #[must_use] -pub fn initialize_whitelist(database: Arc>) -> Arc { +pub fn initialize_whitelist_manager( + database: Arc>, + in_memory_whitelist: Arc, +) -> Arc { let database_whitelist = Arc::new(DatabaseWhitelist::new(database)); - Arc::new(WhiteListManager::new(database_whitelist)) + Arc::new(WhiteListManager::new(database_whitelist, in_memory_whitelist)) } diff --git a/src/core/services/statistics/mod.rs b/src/core/services/statistics/mod.rs index 1e0403c2a..3567de2a9 100644 --- a/src/core/services/statistics/mod.rs +++ b/src/core/services/statistics/mod.rs @@ -118,9 +118,9 @@ mod tests { use torrust_tracker_test_helpers::configuration; use crate::app_test::initialize_tracker_dependencies; - use crate::core; use crate::core::services::initialize_tracker; use crate::core::services::statistics::{self, get_metrics, TrackerMetrics}; + use crate::core::{self}; use crate::servers::udp::server::banning::BanService; use crate::servers::udp::server::launcher::MAX_CONNECTION_ID_ERRORS_PER_IP; @@ -132,11 +132,10 @@ mod tests { async fn the_statistics_service_should_return_the_tracker_metrics() { let config = tracker_configuration(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); let (_stats_event_sender, stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); let stats_repository = Arc::new(stats_repository); - - let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_manager)); + let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_authorization)); let ban_service = Arc::new(RwLock::new(BanService::new(MAX_CONNECTION_ID_ERRORS_PER_IP))); diff --git a/src/core/services/torrent.rs b/src/core/services/torrent.rs index 593d8be8c..457aa54d8 100644 --- a/src/core/services/torrent.rs +++ b/src/core/services/torrent.rs @@ -142,8 +142,8 @@ mod tests { async fn should_return_none_if_the_tracker_does_not_have_the_torrent() { let config = tracker_configuration(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); - let tracker = initialize_tracker(&config, &database, &whitelist_manager); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); + let tracker = initialize_tracker(&config, &database, &whitelist_authorization); let tracker = Arc::new(tracker); @@ -160,8 +160,8 @@ mod tests { async fn should_return_the_torrent_info_if_the_tracker_has_the_torrent() { let config = tracker_configuration(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); - let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_manager)); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); + let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_authorization)); let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash = InfoHash::from_str(&hash).unwrap(); @@ -204,8 +204,8 @@ mod tests { async fn should_return_an_empty_result_if_the_tracker_does_not_have_any_torrent() { let config = tracker_configuration(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); - let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_manager)); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); + let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_authorization)); let torrents = get_torrents_page(tracker.clone(), Some(&Pagination::default())).await; @@ -216,8 +216,8 @@ mod tests { async fn should_return_a_summarized_info_for_all_torrents() { let config = tracker_configuration(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); - let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_manager)); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); + let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_authorization)); let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash = InfoHash::from_str(&hash).unwrap(); @@ -241,8 +241,8 @@ mod tests { async fn should_allow_limiting_the_number_of_torrents_in_the_result() { let config = tracker_configuration(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); - let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_manager)); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); + let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_authorization)); let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash1 = InfoHash::from_str(&hash1).unwrap(); @@ -264,8 +264,8 @@ mod tests { async fn should_allow_using_pagination_in_the_result() { let config = tracker_configuration(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); - let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_manager)); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); + let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_authorization)); let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash1 = InfoHash::from_str(&hash1).unwrap(); @@ -296,8 +296,8 @@ mod tests { async fn should_return_torrents_ordered_by_info_hash() { let config = tracker_configuration(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); - let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_manager)); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); + let tracker = Arc::new(initialize_tracker(&config, &database, &whitelist_authorization)); let hash1 = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash1 = InfoHash::from_str(&hash1).unwrap(); diff --git a/src/core/whitelist/authorization.rs b/src/core/whitelist/authorization.rs new file mode 100644 index 000000000..74029495f --- /dev/null +++ b/src/core/whitelist/authorization.rs @@ -0,0 +1,59 @@ +use std::panic::Location; +use std::sync::Arc; + +use bittorrent_primitives::info_hash::InfoHash; +use torrust_tracker_configuration::Core; +use tracing::instrument; + +use super::repository::in_memory::InMemoryWhitelist; +use crate::core::error::Error; + +pub struct Authorization { + /// Core tracker configuration. + config: Core, + + /// The in-memory list of allowed torrents. + in_memory_whitelist: Arc, +} + +impl Authorization { + /// Creates a new authorization instance. + pub fn new(config: &Core, in_memory_whitelist: &Arc) -> Self { + Self { + config: config.clone(), + in_memory_whitelist: in_memory_whitelist.clone(), + } + } + + /// It returns true if the torrent is authorized. + /// + /// # Errors + /// + /// Will return an error if the tracker is running in `listed` mode + /// and the infohash is not whitelisted. + #[instrument(skip(self, info_hash), err)] + pub async fn authorize(&self, info_hash: &InfoHash) -> Result<(), Error> { + if !self.is_listed() { + return Ok(()); + } + + if self.is_info_hash_whitelisted(info_hash).await { + return Ok(()); + } + + Err(Error::TorrentNotWhitelisted { + info_hash: *info_hash, + location: Location::caller(), + }) + } + + /// Returns `true` is the tracker is in listed mode. + fn is_listed(&self) -> bool { + self.config.listed + } + + /// It checks if a torrent is whitelisted. + async fn is_info_hash_whitelisted(&self, info_hash: &InfoHash) -> bool { + self.in_memory_whitelist.contains(info_hash).await + } +} diff --git a/src/core/whitelist/manager.rs b/src/core/whitelist/manager.rs new file mode 100644 index 000000000..757053f71 --- /dev/null +++ b/src/core/whitelist/manager.rs @@ -0,0 +1,91 @@ +use std::sync::Arc; + +use bittorrent_primitives::info_hash::InfoHash; + +use super::repository::in_memory::InMemoryWhitelist; +use super::repository::persisted::DatabaseWhitelist; +use crate::core::databases; + +/// It handles the list of allowed torrents. Only for listed trackers. +pub struct WhiteListManager { + /// The in-memory list of allowed torrents. + in_memory_whitelist: Arc, + + /// The persisted list of allowed torrents. + database_whitelist: Arc, +} + +impl WhiteListManager { + #[must_use] + pub fn new(database_whitelist: Arc, in_memory_whitelist: Arc) -> Self { + Self { + in_memory_whitelist, + database_whitelist, + } + } + + /// It adds a torrent to the whitelist. + /// Adding torrents is not relevant to public trackers. + /// + /// # Errors + /// + /// Will return a `database::Error` if unable to add the `info_hash` into the whitelist database. + pub async fn add_torrent_to_whitelist(&self, info_hash: &InfoHash) -> Result<(), databases::error::Error> { + self.database_whitelist.add(info_hash)?; + self.in_memory_whitelist.add(info_hash).await; + Ok(()) + } + + /// It removes a torrent from the whitelist. + /// Removing torrents is not relevant to public trackers. + /// + /// # Errors + /// + /// Will return a `database::Error` if unable to remove the `info_hash` from the whitelist database. + pub async fn remove_torrent_from_whitelist(&self, info_hash: &InfoHash) -> Result<(), databases::error::Error> { + self.database_whitelist.remove(info_hash)?; + self.in_memory_whitelist.remove(info_hash).await; + Ok(()) + } + + /// It removes a torrent from the whitelist in the database. + /// + /// # Errors + /// + /// Will return a `database::Error` if unable to remove the `info_hash` from the whitelist database. + pub fn remove_torrent_from_database_whitelist(&self, info_hash: &InfoHash) -> Result<(), databases::error::Error> { + self.database_whitelist.remove(info_hash) + } + + /// It adds a torrent from the whitelist in memory. + pub async fn add_torrent_to_memory_whitelist(&self, info_hash: &InfoHash) -> bool { + self.in_memory_whitelist.add(info_hash).await + } + + /// It removes a torrent from the whitelist in memory. + pub async fn remove_torrent_from_memory_whitelist(&self, info_hash: &InfoHash) -> bool { + self.in_memory_whitelist.remove(info_hash).await + } + + /// It checks if a torrent is whitelisted. + pub async fn is_info_hash_whitelisted(&self, info_hash: &InfoHash) -> bool { + self.in_memory_whitelist.contains(info_hash).await + } + + /// It loads the whitelist from the database. + /// + /// # Errors + /// + /// Will return a `database::Error` if unable to load the list whitelisted `info_hash`s from the database. + pub async fn load_whitelist_from_database(&self) -> Result<(), databases::error::Error> { + let whitelisted_torrents_from_database = self.database_whitelist.load_from_database()?; + + self.in_memory_whitelist.clear().await; + + for info_hash in whitelisted_torrents_from_database { + let _: bool = self.in_memory_whitelist.add(&info_hash).await; + } + + Ok(()) + } +} diff --git a/src/core/whitelist/mod.rs b/src/core/whitelist/mod.rs index 3a88b404c..89c69b761 100644 --- a/src/core/whitelist/mod.rs +++ b/src/core/whitelist/mod.rs @@ -1,94 +1,3 @@ -pub mod in_memory; -pub mod persisted; - -use std::sync::Arc; - -use bittorrent_primitives::info_hash::InfoHash; -use in_memory::InMemoryWhitelist; -use persisted::DatabaseWhitelist; - -use super::databases::{self}; - -/// It handles the list of allowed torrents. Only for listed trackers. -pub struct WhiteListManager { - /// The in-memory list of allowed torrents. - in_memory_whitelist: InMemoryWhitelist, - - /// The persisted list of allowed torrents. - database_whitelist: Arc, -} - -impl WhiteListManager { - #[must_use] - pub fn new(database_whitelist: Arc) -> Self { - Self { - in_memory_whitelist: InMemoryWhitelist::default(), - database_whitelist, - } - } - - /// It adds a torrent to the whitelist. - /// Adding torrents is not relevant to public trackers. - /// - /// # Errors - /// - /// Will return a `database::Error` if unable to add the `info_hash` into the whitelist database. - pub async fn add_torrent_to_whitelist(&self, info_hash: &InfoHash) -> Result<(), databases::error::Error> { - self.database_whitelist.add(info_hash)?; - self.in_memory_whitelist.add(info_hash).await; - Ok(()) - } - - /// It removes a torrent from the whitelist. - /// Removing torrents is not relevant to public trackers. - /// - /// # Errors - /// - /// Will return a `database::Error` if unable to remove the `info_hash` from the whitelist database. - pub async fn remove_torrent_from_whitelist(&self, info_hash: &InfoHash) -> Result<(), databases::error::Error> { - self.database_whitelist.remove(info_hash)?; - self.in_memory_whitelist.remove(info_hash).await; - Ok(()) - } - - /// It removes a torrent from the whitelist in the database. - /// - /// # Errors - /// - /// Will return a `database::Error` if unable to remove the `info_hash` from the whitelist database. - pub fn remove_torrent_from_database_whitelist(&self, info_hash: &InfoHash) -> Result<(), databases::error::Error> { - self.database_whitelist.remove(info_hash) - } - - /// It adds a torrent from the whitelist in memory. - pub async fn add_torrent_to_memory_whitelist(&self, info_hash: &InfoHash) -> bool { - self.in_memory_whitelist.add(info_hash).await - } - - /// It removes a torrent from the whitelist in memory. - pub async fn remove_torrent_from_memory_whitelist(&self, info_hash: &InfoHash) -> bool { - self.in_memory_whitelist.remove(info_hash).await - } - - /// It checks if a torrent is whitelisted. - pub async fn is_info_hash_whitelisted(&self, info_hash: &InfoHash) -> bool { - self.in_memory_whitelist.contains(info_hash).await - } - - /// It loads the whitelist from the database. - /// - /// # Errors - /// - /// Will return a `database::Error` if unable to load the list whitelisted `info_hash`s from the database. - pub async fn load_whitelist_from_database(&self) -> Result<(), databases::error::Error> { - let whitelisted_torrents_from_database = self.database_whitelist.load_from_database()?; - - self.in_memory_whitelist.clear().await; - - for info_hash in whitelisted_torrents_from_database { - let _: bool = self.in_memory_whitelist.add(&info_hash).await; - } - - Ok(()) - } -} +pub mod authorization; +pub mod manager; +pub mod repository; diff --git a/src/core/whitelist/in_memory.rs b/src/core/whitelist/repository/in_memory.rs similarity index 97% rename from src/core/whitelist/in_memory.rs rename to src/core/whitelist/repository/in_memory.rs index 78e0eb11f..8d919f1e4 100644 --- a/src/core/whitelist/in_memory.rs +++ b/src/core/whitelist/repository/in_memory.rs @@ -34,7 +34,7 @@ impl InMemoryWhitelist { mod tests { use bittorrent_primitives::info_hash::InfoHash; - use crate::core::whitelist::in_memory::InMemoryWhitelist; + use crate::core::whitelist::repository::in_memory::InMemoryWhitelist; fn sample_info_hash() -> InfoHash { "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::().unwrap() // # DevSkim: ignore DS173237 diff --git a/src/core/whitelist/repository/mod.rs b/src/core/whitelist/repository/mod.rs new file mode 100644 index 000000000..51723b68d --- /dev/null +++ b/src/core/whitelist/repository/mod.rs @@ -0,0 +1,2 @@ +pub mod in_memory; +pub mod persisted; diff --git a/src/core/whitelist/persisted.rs b/src/core/whitelist/repository/persisted.rs similarity index 97% rename from src/core/whitelist/persisted.rs rename to src/core/whitelist/repository/persisted.rs index 993060139..fd56d56b5 100644 --- a/src/core/whitelist/persisted.rs +++ b/src/core/whitelist/repository/persisted.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use bittorrent_primitives::info_hash::InfoHash; -use super::databases::{self, Database}; +use crate::core::databases::{self, Database}; /// The persisted list of allowed torrents. pub struct DatabaseWhitelist { diff --git a/src/servers/apis/routes.rs b/src/servers/apis/routes.rs index cb3789a06..a5c33d5ee 100644 --- a/src/servers/apis/routes.rs +++ b/src/servers/apis/routes.rs @@ -32,6 +32,7 @@ use super::v1::context::health_check::handlers::health_check_handler; use super::v1::middlewares::auth::State; use crate::core::statistics::event::sender::Sender; use crate::core::statistics::repository::Repository; +use crate::core::whitelist::manager::WhiteListManager; use crate::core::Tracker; use crate::servers::apis::API_LOG_TARGET; use crate::servers::logging::Latency; @@ -39,9 +40,17 @@ use crate::servers::udp::server::banning::BanService; /// Add all API routes to the router. #[allow(clippy::needless_pass_by_value)] -#[instrument(skip(tracker, ban_service, stats_event_sender, stats_repository, access_tokens))] +#[instrument(skip( + tracker, + whitelist_manager, + ban_service, + stats_event_sender, + stats_repository, + access_tokens +))] pub fn router( tracker: Arc, + whitelist_manager: Arc, ban_service: Arc>, stats_event_sender: Arc>>, stats_repository: Arc, @@ -56,6 +65,7 @@ pub fn router( api_url_prefix, router, tracker.clone(), + &whitelist_manager.clone(), ban_service.clone(), stats_event_sender.clone(), stats_repository.clone(), diff --git a/src/servers/apis/server.rs b/src/servers/apis/server.rs index c4fae6ebf..f98770359 100644 --- a/src/servers/apis/server.rs +++ b/src/servers/apis/server.rs @@ -40,6 +40,7 @@ use tracing::{instrument, Level}; use super::routes::router; use crate::bootstrap::jobs::Started; use crate::core::statistics::repository::Repository; +use crate::core::whitelist::manager::WhiteListManager; use crate::core::{statistics, Tracker}; use crate::servers::apis::API_LOG_TARGET; use crate::servers::custom_axum_server::{self, TimeoutAcceptor}; @@ -125,10 +126,12 @@ impl ApiServer { /// # Panics /// /// It would panic if the bound socket address cannot be sent back to this starter. - #[instrument(skip(self, tracker, stats_event_sender, ban_service, stats_repository, form, access_tokens), err, ret(Display, level = Level::INFO))] + #[allow(clippy::too_many_arguments)] + #[instrument(skip(self, tracker, whitelist_manager, stats_event_sender, ban_service, stats_repository, form, access_tokens), err, ret(Display, level = Level::INFO))] pub async fn start( self, tracker: Arc, + whitelist_manager: Arc, stats_event_sender: Arc>>, stats_repository: Arc, ban_service: Arc>, @@ -146,6 +149,7 @@ impl ApiServer { let _task = launcher .start( tracker, + whitelist_manager, ban_service, stats_event_sender, stats_repository, @@ -255,6 +259,7 @@ impl Launcher { #[instrument(skip( self, tracker, + whitelist_manager, ban_service, stats_event_sender, stats_repository, @@ -265,6 +270,7 @@ impl Launcher { pub fn start( &self, tracker: Arc, + whitelist_manager: Arc, ban_service: Arc>, stats_event_sender: Arc>>, stats_repository: Arc, @@ -277,6 +283,7 @@ impl Launcher { let router = router( tracker, + whitelist_manager, ban_service, stats_event_sender, stats_repository, @@ -335,7 +342,9 @@ mod tests { use crate::bootstrap::app::initialize_global_services; use crate::bootstrap::jobs::make_rust_tls; - use crate::core::services::{initialize_database, initialize_tracker, initialize_whitelist, statistics}; + use crate::core::services::{initialize_database, initialize_tracker, initialize_whitelist_manager, statistics}; + use crate::core::whitelist; + use crate::core::whitelist::repository::in_memory::InMemoryWhitelist; use crate::servers::apis::server::{ApiServer, Launcher}; use crate::servers::registar::Registar; use crate::servers::udp::server::banning::BanService; @@ -354,8 +363,13 @@ mod tests { initialize_global_services(&cfg); let database = initialize_database(&cfg); - let whitelist_manager = initialize_whitelist(database.clone()); - let tracker = Arc::new(initialize_tracker(&cfg, &database, &whitelist_manager)); + let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); + let whitelist_authorization = Arc::new(whitelist::authorization::Authorization::new( + &cfg.core, + &in_memory_whitelist.clone(), + )); + let whitelist_manager = initialize_whitelist_manager(database.clone(), in_memory_whitelist.clone()); + let tracker = Arc::new(initialize_tracker(&cfg, &database, &whitelist_authorization)); let bind_to = config.bind_address; @@ -372,6 +386,7 @@ mod tests { let started = stopped .start( tracker, + whitelist_manager, stats_event_sender, stats_repository, ban_service, diff --git a/src/servers/apis/v1/context/whitelist/handlers.rs b/src/servers/apis/v1/context/whitelist/handlers.rs index f548f5dc4..473ed56c5 100644 --- a/src/servers/apis/v1/context/whitelist/handlers.rs +++ b/src/servers/apis/v1/context/whitelist/handlers.rs @@ -10,7 +10,7 @@ use bittorrent_primitives::info_hash::InfoHash; use super::responses::{ failed_to_reload_whitelist_response, failed_to_remove_torrent_from_whitelist_response, failed_to_whitelist_torrent_response, }; -use crate::core::whitelist::WhiteListManager; +use crate::core::whitelist::manager::WhiteListManager; use crate::servers::apis::v1::responses::{invalid_info_hash_param_response, ok_response}; use crate::servers::apis::InfoHashParam; diff --git a/src/servers/apis/v1/context/whitelist/routes.rs b/src/servers/apis/v1/context/whitelist/routes.rs index c58aa7177..34f1393b8 100644 --- a/src/servers/apis/v1/context/whitelist/routes.rs +++ b/src/servers/apis/v1/context/whitelist/routes.rs @@ -11,25 +11,25 @@ use axum::routing::{delete, get, post}; use axum::Router; use super::handlers::{add_torrent_to_whitelist_handler, reload_whitelist_handler, remove_torrent_from_whitelist_handler}; -use crate::core::Tracker; +use crate::core::whitelist::manager::WhiteListManager; /// It adds the routes to the router for the [`whitelist`](crate::servers::apis::v1::context::whitelist) API context. -pub fn add(prefix: &str, router: Router, tracker: &Arc) -> Router { +pub fn add(prefix: &str, router: Router, whitelist_manager: &Arc) -> Router { let prefix = format!("{prefix}/whitelist"); router // Whitelisted torrents .route( &format!("{prefix}/{{info_hash}}"), - post(add_torrent_to_whitelist_handler).with_state(tracker.whitelist_manager.clone()), + post(add_torrent_to_whitelist_handler).with_state(whitelist_manager.clone()), ) .route( &format!("{prefix}/{{info_hash}}"), - delete(remove_torrent_from_whitelist_handler).with_state(tracker.whitelist_manager.clone()), + delete(remove_torrent_from_whitelist_handler).with_state(whitelist_manager.clone()), ) // Whitelist commands .route( &format!("{prefix}/reload"), - get(reload_whitelist_handler).with_state(tracker.whitelist_manager.clone()), + get(reload_whitelist_handler).with_state(whitelist_manager.clone()), ) } diff --git a/src/servers/apis/v1/routes.rs b/src/servers/apis/v1/routes.rs index 9fbd5da0e..1954af2e4 100644 --- a/src/servers/apis/v1/routes.rs +++ b/src/servers/apis/v1/routes.rs @@ -7,6 +7,7 @@ use tokio::sync::RwLock; use super::context::{auth_key, stats, torrent, whitelist}; use crate::core::statistics::event::sender::Sender; use crate::core::statistics::repository::Repository; +use crate::core::whitelist::manager::WhiteListManager; use crate::core::Tracker; use crate::servers::udp::server::banning::BanService; @@ -15,6 +16,7 @@ pub fn add( prefix: &str, router: Router, tracker: Arc, + whitelist_manager: &Arc, ban_service: Arc>, stats_event_sender: Arc>>, stats_repository: Arc, @@ -30,7 +32,7 @@ pub fn add( stats_event_sender, stats_repository, ); - let router = whitelist::routes::add(&v1_prefix, router, &tracker); + let router = whitelist::routes::add(&v1_prefix, router, whitelist_manager); torrent::routes::add(&v1_prefix, router, tracker) } diff --git a/src/servers/http/server.rs b/src/servers/http/server.rs index 82b65c2ff..b053628ce 100644 --- a/src/servers/http/server.rs +++ b/src/servers/http/server.rs @@ -11,7 +11,7 @@ use tracing::instrument; use super::v1::routes::router; use crate::bootstrap::jobs::Started; -use crate::core::{statistics, Tracker}; +use crate::core::{statistics, whitelist, Tracker}; use crate::servers::custom_axum_server::{self, TimeoutAcceptor}; use crate::servers::http::HTTP_TRACKER_LOG_TARGET; use crate::servers::logging::STARTED_ON; @@ -42,10 +42,11 @@ pub struct Launcher { } impl Launcher { - #[instrument(skip(self, tracker, stats_event_sender, tx_start, rx_halt))] + #[instrument(skip(self, tracker, whitelist_authorization, stats_event_sender, tx_start, rx_halt))] fn start( &self, tracker: Arc, + whitelist_authorization: Arc, stats_event_sender: Arc>>, tx_start: Sender, rx_halt: Receiver, @@ -66,7 +67,7 @@ impl Launcher { tracing::info!(target: HTTP_TRACKER_LOG_TARGET, "Starting on: {protocol}://{}", address); - let app = router(tracker, stats_event_sender, address); + let app = router(tracker, whitelist_authorization, stats_event_sender, address); let running = Box::pin(async { match tls { @@ -162,6 +163,7 @@ impl HttpServer { pub async fn start( self, tracker: Arc, + whitelist_authorization: Arc, stats_event_sender: Arc>>, form: ServiceRegistrationForm, ) -> Result, Error> { @@ -171,7 +173,7 @@ impl HttpServer { let launcher = self.state.launcher; let task = tokio::spawn(async move { - let server = launcher.start(tracker, stats_event_sender, tx_start, rx_halt); + let server = launcher.start(tracker, whitelist_authorization, stats_event_sender, tx_start, rx_halt); server.await; @@ -244,7 +246,9 @@ mod tests { use crate::bootstrap::app::initialize_global_services; use crate::bootstrap::jobs::make_rust_tls; - use crate::core::services::{initialize_database, initialize_tracker, initialize_whitelist, statistics}; + use crate::core::services::{initialize_database, initialize_tracker, initialize_whitelist_manager, statistics}; + use crate::core::whitelist; + use crate::core::whitelist::repository::in_memory::InMemoryWhitelist; use crate::servers::http::server::{HttpServer, Launcher}; use crate::servers::registar::Registar; @@ -258,8 +262,13 @@ mod tests { initialize_global_services(&cfg); let database = initialize_database(&cfg); - let whitelist_manager = initialize_whitelist(database.clone()); - let tracker = Arc::new(initialize_tracker(&cfg, &database, &whitelist_manager)); + let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); + let whitelist_authorization = Arc::new(whitelist::authorization::Authorization::new( + &cfg.core, + &in_memory_whitelist.clone(), + )); + let _whitelist_manager = initialize_whitelist_manager(database.clone(), in_memory_whitelist.clone()); + let tracker = Arc::new(initialize_tracker(&cfg, &database, &whitelist_authorization)); let http_trackers = cfg.http_trackers.clone().expect("missing HTTP trackers configuration"); let config = &http_trackers[0]; @@ -274,7 +283,7 @@ mod tests { let stopped = HttpServer::new(Launcher::new(bind_to, tls)); let started = stopped - .start(tracker, stats_event_sender, register.give_form()) + .start(tracker, whitelist_authorization, stats_event_sender, register.give_form()) .await .expect("it should start the server"); let stopped = started.stop().await.expect("it should stop the server"); diff --git a/src/servers/http/v1/handlers/announce.rs b/src/servers/http/v1/handlers/announce.rs index 24beadbc2..61464f1d5 100644 --- a/src/servers/http/v1/handlers/announce.rs +++ b/src/servers/http/v1/handlers/announce.rs @@ -23,7 +23,7 @@ use torrust_tracker_primitives::peer; use crate::core::auth::Key; use crate::core::statistics::event::sender::Sender; -use crate::core::{PeersWanted, Tracker}; +use crate::core::{whitelist, PeersWanted, Tracker}; use crate::servers::http::v1::extractors::announce_request::ExtractRequest; use crate::servers::http::v1::extractors::authentication_key::Extract as ExtractKey; use crate::servers::http::v1::extractors::client_ip_sources::Extract as ExtractClientIpSources; @@ -36,13 +36,17 @@ use crate::CurrentClock; #[allow(clippy::unused_async)] #[allow(clippy::type_complexity)] pub async fn handle_without_key( - State(state): State<(Arc, Arc>>)>, + State(state): State<( + Arc, + Arc, + Arc>>, + )>, ExtractRequest(announce_request): ExtractRequest, ExtractClientIpSources(client_ip_sources): ExtractClientIpSources, ) -> Response { tracing::debug!("http announce request: {:#?}", announce_request); - handle(&state.0, &state.1, &announce_request, &client_ip_sources, None).await + handle(&state.0, &state.1, &state.2, &announce_request, &client_ip_sources, None).await } /// It handles the `announce` request when the HTTP tracker requires @@ -50,14 +54,18 @@ pub async fn handle_without_key( #[allow(clippy::unused_async)] #[allow(clippy::type_complexity)] pub async fn handle_with_key( - State(state): State<(Arc, Arc>>)>, + State(state): State<( + Arc, + Arc, + Arc>>, + )>, ExtractRequest(announce_request): ExtractRequest, ExtractClientIpSources(client_ip_sources): ExtractClientIpSources, ExtractKey(key): ExtractKey, ) -> Response { tracing::debug!("http announce request: {:#?}", announce_request); - handle(&state.0, &state.1, &announce_request, &client_ip_sources, Some(key)).await + handle(&state.0, &state.1, &state.2, &announce_request, &client_ip_sources, Some(key)).await } /// It handles the `announce` request. @@ -66,6 +74,7 @@ pub async fn handle_with_key( /// `unauthenticated` modes. async fn handle( tracker: &Arc, + whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, announce_request: &Announce, client_ip_sources: &ClientIpSources, @@ -73,6 +82,7 @@ async fn handle( ) -> Response { let announce_data = match handle_announce( tracker, + whitelist_authorization, opt_stats_event_sender, announce_request, client_ip_sources, @@ -94,6 +104,7 @@ async fn handle( async fn handle_announce( tracker: &Arc, + whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, announce_request: &Announce, client_ip_sources: &ClientIpSources, @@ -115,7 +126,7 @@ async fn handle_announce( } // Authorization - match tracker.authorize(&announce_request.info_hash).await { + match whitelist_authorization.authorize(&announce_request.info_hash).await { Ok(()) => (), Err(error) => return Err(responses::error::Error::from(error)), } @@ -198,52 +209,51 @@ pub fn map_to_torrust_event(event: &Option) -> AnnounceEvent { #[cfg(test)] mod tests { + use std::sync::Arc; + use aquatic_udp_protocol::PeerId; use bittorrent_http_protocol::v1::requests::announce::Announce; use bittorrent_http_protocol::v1::responses; use bittorrent_http_protocol::v1::services::peer_ip_resolver::ClientIpSources; use bittorrent_primitives::info_hash::InfoHash; + use torrust_tracker_configuration::Configuration; use torrust_tracker_test_helpers::configuration; use crate::app_test::initialize_tracker_dependencies; use crate::core::services::{initialize_tracker, statistics}; use crate::core::statistics::event::sender::Sender; - use crate::core::Tracker; - - fn private_tracker() -> (Tracker, Option>) { - let config = configuration::ephemeral_private(); + use crate::core::{whitelist, Tracker}; - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); - let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); + type TrackerAndDeps = ( + Arc, + Arc>>, + Arc, + ); - (initialize_tracker(&config, &database, &whitelist_manager), stats_event_sender) + fn private_tracker() -> TrackerAndDeps { + initialize_tracker_and_deps(&configuration::ephemeral_private()) } - fn whitelisted_tracker() -> (Tracker, Option>) { - let config = configuration::ephemeral_listed(); - - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); - let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); - - (initialize_tracker(&config, &database, &whitelist_manager), stats_event_sender) + fn whitelisted_tracker() -> TrackerAndDeps { + initialize_tracker_and_deps(&configuration::ephemeral_listed()) } - fn tracker_on_reverse_proxy() -> (Tracker, Option>) { - let config = configuration::ephemeral_with_reverse_proxy(); - - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); - let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); - - (initialize_tracker(&config, &database, &whitelist_manager), stats_event_sender) + fn tracker_on_reverse_proxy() -> TrackerAndDeps { + initialize_tracker_and_deps(&configuration::ephemeral_with_reverse_proxy()) } - fn tracker_not_on_reverse_proxy() -> (Tracker, Option>) { - let config = configuration::ephemeral_without_reverse_proxy(); + fn tracker_not_on_reverse_proxy() -> TrackerAndDeps { + initialize_tracker_and_deps(&configuration::ephemeral_without_reverse_proxy()) + } - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); + /// Initialize tracker's dependencies and tracker. + fn initialize_tracker_and_deps(config: &Configuration) -> TrackerAndDeps { + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); + let stats_event_sender = Arc::new(stats_event_sender); + let tracker = Arc::new(initialize_tracker(config, &database, &whitelist_authorization)); - (initialize_tracker(&config, &database, &whitelist_manager), stats_event_sender) + (tracker, stats_event_sender, whitelist_authorization) } fn sample_announce_request() -> Announce { @@ -286,7 +296,7 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_authentication_key_is_missing() { - let (tracker, stats_event_sender) = private_tracker(); + let (tracker, stats_event_sender, whitelist_authorization) = private_tracker(); let tracker = Arc::new(tracker); let stats_event_sender = Arc::new(stats_event_sender); @@ -295,6 +305,7 @@ mod tests { let response = handle_announce( &tracker, + &whitelist_authorization, &stats_event_sender, &sample_announce_request(), &sample_client_ip_sources(), @@ -311,7 +322,7 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_authentication_key_is_invalid() { - let (tracker, stats_event_sender) = private_tracker(); + let (tracker, stats_event_sender, whitelist_authorization) = private_tracker(); let tracker = Arc::new(tracker); let stats_event_sender = Arc::new(stats_event_sender); @@ -322,6 +333,7 @@ mod tests { let response = handle_announce( &tracker, + &whitelist_authorization, &stats_event_sender, &sample_announce_request(), &sample_client_ip_sources(), @@ -344,7 +356,7 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_announced_torrent_is_not_whitelisted() { - let (tracker, stats_event_sender) = whitelisted_tracker(); + let (tracker, stats_event_sender, whitelist_authorization) = whitelisted_tracker(); let tracker = Arc::new(tracker); let stats_event_sender = Arc::new(stats_event_sender); @@ -353,6 +365,7 @@ mod tests { let response = handle_announce( &tracker, + &whitelist_authorization, &stats_event_sender, &announce_request, &sample_client_ip_sources(), @@ -383,7 +396,7 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_right_most_x_forwarded_for_header_ip_is_not_available() { - let (tracker, stats_event_sender) = tracker_on_reverse_proxy(); + let (tracker, stats_event_sender, whitelist_authorization) = tracker_on_reverse_proxy(); let tracker = Arc::new(tracker); let stats_event_sender = Arc::new(stats_event_sender); @@ -395,6 +408,7 @@ mod tests { let response = handle_announce( &tracker, + &whitelist_authorization, &stats_event_sender, &sample_announce_request(), &client_ip_sources, @@ -422,7 +436,7 @@ mod tests { #[tokio::test] async fn it_should_fail_when_the_client_ip_from_the_connection_info_is_not_available() { - let (tracker, stats_event_sender) = tracker_not_on_reverse_proxy(); + let (tracker, stats_event_sender, whitelist_authorization) = tracker_not_on_reverse_proxy(); let tracker = Arc::new(tracker); let stats_event_sender = Arc::new(stats_event_sender); @@ -434,6 +448,7 @@ mod tests { let response = handle_announce( &tracker, + &whitelist_authorization, &stats_event_sender, &sample_announce_request(), &client_ip_sources, diff --git a/src/servers/http/v1/handlers/scrape.rs b/src/servers/http/v1/handlers/scrape.rs index a5cf58129..9c57eda58 100644 --- a/src/servers/http/v1/handlers/scrape.rs +++ b/src/servers/http/v1/handlers/scrape.rs @@ -133,37 +133,49 @@ mod tests { fn private_tracker() -> (Tracker, Option>) { let config = configuration::ephemeral_private(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); - (initialize_tracker(&config, &database, &whitelist_manager), stats_event_sender) + ( + initialize_tracker(&config, &database, &whitelist_authorization), + stats_event_sender, + ) } fn whitelisted_tracker() -> (Tracker, Option>) { let config = configuration::ephemeral_listed(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); - (initialize_tracker(&config, &database, &whitelist_manager), stats_event_sender) + ( + initialize_tracker(&config, &database, &whitelist_authorization), + stats_event_sender, + ) } fn tracker_on_reverse_proxy() -> (Tracker, Option>) { let config = configuration::ephemeral_with_reverse_proxy(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); - (initialize_tracker(&config, &database, &whitelist_manager), stats_event_sender) + ( + initialize_tracker(&config, &database, &whitelist_authorization), + stats_event_sender, + ) } fn tracker_not_on_reverse_proxy() -> (Tracker, Option>) { let config = configuration::ephemeral_without_reverse_proxy(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); - (initialize_tracker(&config, &database, &whitelist_manager), stats_event_sender) + ( + initialize_tracker(&config, &database, &whitelist_authorization), + stats_event_sender, + ) } fn sample_scrape_request() -> Scrape { diff --git a/src/servers/http/v1/routes.rs b/src/servers/http/v1/routes.rs index 97eb5b95d..d37c55c7a 100644 --- a/src/servers/http/v1/routes.rs +++ b/src/servers/http/v1/routes.rs @@ -23,7 +23,7 @@ use tracing::{instrument, Level, Span}; use super::handlers::{announce, health_check, scrape}; use crate::core::statistics::event::sender::Sender; -use crate::core::Tracker; +use crate::core::{whitelist, Tracker}; use crate::servers::http::HTTP_TRACKER_LOG_TARGET; use crate::servers::logging::Latency; @@ -32,19 +32,32 @@ use crate::servers::logging::Latency; /// > **NOTICE**: it's added a layer to get the client IP from the connection /// > info. The tracker could use the connection info to get the client IP. #[allow(clippy::needless_pass_by_value)] -#[instrument(skip(tracker, stats_event_sender, server_socket_addr))] -pub fn router(tracker: Arc, stats_event_sender: Arc>>, server_socket_addr: SocketAddr) -> Router { +#[instrument(skip(tracker, whitelist_authorization, stats_event_sender, server_socket_addr))] +pub fn router( + tracker: Arc, + whitelist_authorization: Arc, + stats_event_sender: Arc>>, + server_socket_addr: SocketAddr, +) -> Router { Router::new() // Health check .route("/health_check", get(health_check::handler)) // Announce request .route( "/announce", - get(announce::handle_without_key).with_state((tracker.clone(), stats_event_sender.clone())), + get(announce::handle_without_key).with_state(( + tracker.clone(), + whitelist_authorization.clone(), + stats_event_sender.clone(), + )), ) .route( "/announce/{key}", - get(announce::handle_with_key).with_state((tracker.clone(), stats_event_sender.clone())), + get(announce::handle_with_key).with_state(( + tracker.clone(), + whitelist_authorization.clone(), + stats_event_sender.clone(), + )), ) // Scrape request .route( diff --git a/src/servers/http/v1/services/announce.rs b/src/servers/http/v1/services/announce.rs index 63a904182..17598904c 100644 --- a/src/servers/http/v1/services/announce.rs +++ b/src/servers/http/v1/services/announce.rs @@ -73,11 +73,11 @@ mod tests { fn public_tracker() -> (Tracker, Arc>>) { let config = configuration::ephemeral_public(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); let stats_event_sender = Arc::new(stats_event_sender); - let tracker = initialize_tracker(&config, &database, &whitelist_manager); + let tracker = initialize_tracker(&config, &database, &whitelist_authorization); (tracker, stats_event_sender) } @@ -131,9 +131,9 @@ mod tests { fn test_tracker_factory() -> Tracker { let config = configuration::ephemeral(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); - Tracker::new(&config.core, &database, &whitelist_manager).unwrap() + Tracker::new(&config.core, &database, &whitelist_authorization).unwrap() } #[tokio::test] diff --git a/src/servers/http/v1/services/scrape.rs b/src/servers/http/v1/services/scrape.rs index 56c18cbb3..0a25bccaf 100644 --- a/src/servers/http/v1/services/scrape.rs +++ b/src/servers/http/v1/services/scrape.rs @@ -87,9 +87,9 @@ mod tests { fn public_tracker() -> Tracker { let config = configuration::ephemeral_public(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); - initialize_tracker(&config, &database, &whitelist_manager) + initialize_tracker(&config, &database, &whitelist_authorization) } fn sample_info_hashes() -> Vec { @@ -115,9 +115,9 @@ mod tests { fn test_tracker_factory() -> Tracker { let config = configuration::ephemeral(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); - Tracker::new(&config.core, &database, &whitelist_manager).unwrap() + Tracker::new(&config.core, &database, &whitelist_authorization).unwrap() } mod with_real_data { diff --git a/src/servers/udp/handlers.rs b/src/servers/udp/handlers.rs index a7d964391..c01dc2548 100644 --- a/src/servers/udp/handlers.rs +++ b/src/servers/udp/handlers.rs @@ -21,7 +21,7 @@ use super::connection_cookie::{check, make}; use super::server::banning::BanService; use super::RawRequest; use crate::core::statistics::event::sender::Sender; -use crate::core::{statistics, PeersWanted, Tracker}; +use crate::core::{statistics, whitelist, PeersWanted, Tracker}; use crate::servers::udp::error::Error; use crate::servers::udp::{peer_builder, UDP_TRACKER_LOG_TARGET}; use crate::shared::bit_torrent::common::MAX_SCRAPE_TORRENTS; @@ -54,10 +54,11 @@ impl CookieTimeValues { /// - Delegating the request to the correct handler depending on the request type. /// /// It will return an `Error` response if the request is invalid. -#[instrument(fields(request_id), skip(udp_request, tracker, opt_stats_event_sender, cookie_time_values, ban_service), ret(level = Level::TRACE))] +#[instrument(fields(request_id), skip(udp_request, tracker, whitelist_authorization, opt_stats_event_sender, cookie_time_values, ban_service), ret(level = Level::TRACE))] pub(crate) async fn handle_packet( udp_request: RawRequest, tracker: &Tracker, + whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, local_addr: SocketAddr, cookie_time_values: CookieTimeValues, @@ -76,6 +77,7 @@ pub(crate) async fn handle_packet( request, udp_request.from, tracker, + whitelist_authorization, opt_stats_event_sender, cookie_time_values.clone(), ) @@ -131,11 +133,19 @@ pub(crate) async fn handle_packet( /// # Errors /// /// If a error happens in the `handle_request` function, it will just return the `ServerError`. -#[instrument(skip(request, remote_addr, tracker, opt_stats_event_sender, cookie_time_values))] +#[instrument(skip( + request, + remote_addr, + tracker, + whitelist_authorization, + opt_stats_event_sender, + cookie_time_values +))] pub async fn handle_request( request: Request, remote_addr: SocketAddr, tracker: &Tracker, + whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, cookie_time_values: CookieTimeValues, ) -> Result { @@ -154,6 +164,7 @@ pub async fn handle_request( remote_addr, &announce_request, tracker, + whitelist_authorization, opt_stats_event_sender, cookie_time_values.valid_range, ) @@ -216,11 +227,12 @@ pub async fn handle_connect( /// # Errors /// /// If a error happens in the `handle_announce` function, it will just return the `ServerError`. -#[instrument(fields(transaction_id, connection_id, info_hash), skip(tracker, opt_stats_event_sender), ret(level = Level::TRACE))] +#[instrument(fields(transaction_id, connection_id, info_hash), skip(tracker, whitelist_authorization, opt_stats_event_sender), ret(level = Level::TRACE))] pub async fn handle_announce( remote_addr: SocketAddr, request: &AnnounceRequest, tracker: &Tracker, + whitelist_authorization: &Arc, opt_stats_event_sender: &Arc>>, cookie_valid_range: Range, ) -> Result { @@ -242,7 +254,7 @@ pub async fn handle_announce( let remote_client_ip = remote_addr.ip(); // Authorization - tracker + whitelist_authorization .authorize(&info_hash) .await .map_err(|e| Error::TrackerError { @@ -462,6 +474,7 @@ mod tests { use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; use std::ops::Range; + use std::sync::Arc; use aquatic_udp_protocol::{NumberOfBytes, PeerId}; use torrust_tracker_clock::clock::Time; @@ -471,11 +484,21 @@ mod tests { use super::gen_remote_fingerprint; use crate::app_test::initialize_tracker_dependencies; - use crate::core::services::{initialize_tracker, statistics}; + use crate::core::services::{initialize_tracker, initialize_whitelist_manager, statistics}; use crate::core::statistics::event::sender::Sender; - use crate::core::Tracker; + use crate::core::whitelist::manager::WhiteListManager; + use crate::core::whitelist::repository::in_memory::InMemoryWhitelist; + use crate::core::{whitelist, Tracker}; use crate::CurrentClock; + type TrackerAndDeps = ( + Arc, + Arc>>, + Arc, + Arc, + Arc, + ); + fn tracker_configuration() -> Configuration { default_testing_tracker_configuration() } @@ -484,19 +507,29 @@ mod tests { configuration::ephemeral() } - fn public_tracker() -> (Tracker, Option>) { - initialized_tracker(&configuration::ephemeral_public()) + fn public_tracker() -> TrackerAndDeps { + initialize_tracker_and_deps(&configuration::ephemeral_public()) } - fn whitelisted_tracker() -> (Tracker, Option>) { - initialized_tracker(&configuration::ephemeral_listed()) + fn whitelisted_tracker() -> TrackerAndDeps { + initialize_tracker_and_deps(&configuration::ephemeral_listed()) } - fn initialized_tracker(config: &Configuration) -> (Tracker, Option>) { - let (database, whitelist_manager) = initialize_tracker_dependencies(config); + fn initialize_tracker_and_deps(config: &Configuration) -> TrackerAndDeps { + let (database, in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(config); let (stats_event_sender, _stats_repository) = statistics::setup::factory(config.core.tracker_usage_statistics); + let stats_event_sender = Arc::new(stats_event_sender); + let whitelist_manager = initialize_whitelist_manager(database.clone(), in_memory_whitelist.clone()); + + let tracker = Arc::new(initialize_tracker(config, &database, &whitelist_authorization)); - (initialize_tracker(config, &database, &whitelist_manager), stats_event_sender) + ( + tracker, + stats_event_sender, + in_memory_whitelist, + whitelist_manager, + whitelist_authorization, + ) } fn sample_ipv4_remote_addr() -> SocketAddr { @@ -593,12 +626,14 @@ mod tests { } } - fn test_tracker_factory() -> Tracker { + fn test_tracker_factory() -> (Arc, Arc) { let config = tracker_configuration(); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); - Tracker::new(&config.core, &database, &whitelist_manager).unwrap() + let tracker = Arc::new(Tracker::new(&config.core, &database, &whitelist_authorization).unwrap()); + + (tracker, whitelist_authorization) } mod connect_request { @@ -811,7 +846,7 @@ mod tests { }; use mockall::predicate::eq; - use crate::core::{self, statistics}; + use crate::core::{self, statistics, whitelist}; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::tests::announce_request::AnnounceRequestBuilder; use crate::servers::udp::handlers::tests::{ @@ -822,9 +857,8 @@ mod tests { #[tokio::test] async fn an_announced_peer_should_be_added_to_the_tracker() { - let (tracker, stats_event_sender) = public_tracker(); - let tracker = Arc::new(tracker); - let stats_event_sender = Arc::new(stats_event_sender); + let (tracker, stats_event_sender, _in_memory_whitelist, _whitelist_manager, whitelist_authorization) = + public_tracker(); let client_ip = Ipv4Addr::new(126, 0, 0, 1); let client_port = 8080; @@ -845,6 +879,7 @@ mod tests { remote_addr, &request, &tracker, + &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), ) @@ -863,9 +898,8 @@ mod tests { #[tokio::test] async fn the_announced_peer_should_not_be_included_in_the_response() { - let (tracker, stats_event_sender) = public_tracker(); - let tracker = Arc::new(tracker); - let stats_event_sender = Arc::new(stats_event_sender); + let (tracker, stats_event_sender, _in_memory_whitelist, _whitelist_manager, whitelist_authorization) = + public_tracker(); let remote_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080); @@ -877,6 +911,7 @@ mod tests { remote_addr, &request, &tracker, + &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), ) @@ -904,9 +939,8 @@ mod tests { // From the BEP 15 (https://www.bittorrent.org/beps/bep_0015.html): // "Do note that most trackers will only honor the IP address field under limited circumstances." - let (tracker, stats_event_sender) = public_tracker(); - let tracker = Arc::new(tracker); - let stats_event_sender = Arc::new(stats_event_sender); + let (tracker, stats_event_sender, _in_memory_whitelist, _whitelist_manager, whitelist_authorization) = + public_tracker(); let info_hash = AquaticInfoHash([0u8; 20]); let peer_id = AquaticPeerId([255u8; 20]); @@ -930,6 +964,7 @@ mod tests { remote_addr, &request, &tracker, + &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), ) @@ -957,7 +992,10 @@ mod tests { tracker.upsert_peer_and_get_stats(&info_hash.0.into(), &peer_using_ipv6); } - async fn announce_a_new_peer_using_ipv4(tracker: Arc) -> Response { + async fn announce_a_new_peer_using_ipv4( + tracker: Arc, + whitelist_authorization: Arc, + ) -> Response { let (stats_event_sender, _stats_repository) = crate::core::services::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); @@ -970,6 +1008,7 @@ mod tests { remote_addr, &request, &tracker, + &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), ) @@ -979,12 +1018,12 @@ mod tests { #[tokio::test] async fn when_the_announce_request_comes_from_a_client_using_ipv4_the_response_should_not_include_peers_using_ipv6() { - let (tracker, _stats_event_sender) = public_tracker(); - let tracker = Arc::new(tracker); + let (tracker, _stats_event_sender, _in_memory_whitelist, _whitelist_manager, whitelist_authorization) = + public_tracker(); add_a_torrent_peer_using_ipv6(&tracker); - let response = announce_a_new_peer_using_ipv4(tracker.clone()).await; + let response = announce_a_new_peer_using_ipv4(tracker.clone(), whitelist_authorization).await; // The response should not contain the peer using IPV6 let peers: Option>> = match response { @@ -1006,12 +1045,13 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); - let tracker = Arc::new(test_tracker_factory()); + let (tracker, whitelist_authorization) = test_tracker_factory(); handle_announce( sample_ipv4_socket_address(), &AnnounceRequestBuilder::default().into(), &tracker, + &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), ) @@ -1034,9 +1074,8 @@ mod tests { #[tokio::test] async fn the_peer_ip_should_be_changed_to_the_external_ip_in_the_tracker_configuration_if_defined() { - let (tracker, stats_event_sender) = public_tracker(); - let tracker = Arc::new(tracker); - let stats_event_sender = Arc::new(stats_event_sender); + let (tracker, stats_event_sender, _in_memory_whitelist, _whitelist_manager, whitelist_authorization) = + public_tracker(); let client_ip = Ipv4Addr::new(127, 0, 0, 1); let client_port = 8080; @@ -1057,6 +1096,7 @@ mod tests { remote_addr, &request, &tracker, + &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), ) @@ -1089,7 +1129,7 @@ mod tests { }; use mockall::predicate::eq; - use crate::core::{self, statistics}; + use crate::core::{self, statistics, whitelist}; use crate::servers::udp::connection_cookie::make; use crate::servers::udp::handlers::tests::announce_request::AnnounceRequestBuilder; use crate::servers::udp::handlers::tests::{ @@ -1100,9 +1140,8 @@ mod tests { #[tokio::test] async fn an_announced_peer_should_be_added_to_the_tracker() { - let (tracker, stats_event_sender) = public_tracker(); - let tracker = Arc::new(tracker); - let stats_event_sender = Arc::new(stats_event_sender); + let (tracker, stats_event_sender, _in_memory_whitelist, _whitelist_manager, whitelist_authorization) = + public_tracker(); let client_ip_v4 = Ipv4Addr::new(126, 0, 0, 1); let client_ip_v6 = client_ip_v4.to_ipv6_compatible(); @@ -1124,6 +1163,7 @@ mod tests { remote_addr, &request, &tracker, + &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), ) @@ -1142,9 +1182,8 @@ mod tests { #[tokio::test] async fn the_announced_peer_should_not_be_included_in_the_response() { - let (tracker, stats_event_sender) = public_tracker(); - let tracker = Arc::new(tracker); - let stats_event_sender = Arc::new(stats_event_sender); + let (tracker, stats_event_sender, _in_memory_whitelist, _whitelist_manager, whitelist_authorization) = + public_tracker(); let client_ip_v4 = Ipv4Addr::new(126, 0, 0, 1); let client_ip_v6 = client_ip_v4.to_ipv6_compatible(); @@ -1159,6 +1198,7 @@ mod tests { remote_addr, &request, &tracker, + &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), ) @@ -1186,9 +1226,8 @@ mod tests { // From the BEP 15 (https://www.bittorrent.org/beps/bep_0015.html): // "Do note that most trackers will only honor the IP address field under limited circumstances." - let (tracker, stats_event_sender) = public_tracker(); - let tracker = Arc::new(tracker); - let stats_event_sender = Arc::new(stats_event_sender); + let (tracker, stats_event_sender, _in_memory_whitelist, _whitelist_manager, whitelist_authorization) = + public_tracker(); let info_hash = AquaticInfoHash([0u8; 20]); let peer_id = AquaticPeerId([255u8; 20]); @@ -1212,6 +1251,7 @@ mod tests { remote_addr, &request, &tracker, + &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), ) @@ -1239,7 +1279,10 @@ mod tests { tracker.upsert_peer_and_get_stats(&info_hash.0.into(), &peer_using_ipv4); } - async fn announce_a_new_peer_using_ipv6(tracker: Arc) -> Response { + async fn announce_a_new_peer_using_ipv6( + tracker: Arc, + whitelist_authorization: Arc, + ) -> Response { let (stats_event_sender, _stats_repository) = crate::core::services::statistics::setup::factory(false); let stats_event_sender = Arc::new(stats_event_sender); @@ -1255,6 +1298,7 @@ mod tests { remote_addr, &request, &tracker, + &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), ) @@ -1264,12 +1308,12 @@ mod tests { #[tokio::test] async fn when_the_announce_request_comes_from_a_client_using_ipv6_the_response_should_not_include_peers_using_ipv4() { - let (tracker, _stats_event_sender) = public_tracker(); - let tracker = Arc::new(tracker); + let (tracker, _stats_event_sender, _in_memory_whitelist, _whitelist_manager, whitelist_authorization) = + public_tracker(); add_a_torrent_peer_using_ipv4(&tracker); - let response = announce_a_new_peer_using_ipv6(tracker.clone()).await; + let response = announce_a_new_peer_using_ipv6(tracker.clone(), whitelist_authorization).await; // The response should not contain the peer using IPV4 let peers: Option>> = match response { @@ -1291,7 +1335,7 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); - let tracker = Arc::new(test_tracker_factory()); + let (tracker, whitelist_authorization) = test_tracker_factory(); let remote_addr = sample_ipv6_remote_addr(); @@ -1303,6 +1347,7 @@ mod tests { remote_addr, &announce_request, &tracker, + &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), ) @@ -1331,7 +1376,7 @@ mod tests { async fn the_peer_ip_should_be_changed_to_the_external_ip_in_the_tracker_configuration() { let config = Arc::new(TrackerConfigurationBuilder::default().with_external_ip("::126.0.0.1").into()); - let (database, whitelist_manager) = initialize_tracker_dependencies(&config); + let (database, _in_memory_whitelist, whitelist_authorization) = initialize_tracker_dependencies(&config); let mut stats_event_sender_mock = statistics::event::sender::MockSender::new(); stats_event_sender_mock @@ -1342,7 +1387,7 @@ mod tests { let stats_event_sender: Arc>> = Arc::new(Some(Box::new(stats_event_sender_mock))); - let tracker = Arc::new(core::Tracker::new(&config.core, &database, &whitelist_manager).unwrap()); + let tracker = Arc::new(core::Tracker::new(&config.core, &database, &whitelist_authorization).unwrap()); let loopback_ipv4 = Ipv4Addr::new(127, 0, 0, 1); let loopback_ipv6 = Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1); @@ -1368,6 +1413,7 @@ mod tests { remote_addr, &request, &tracker, + &whitelist_authorization, &stats_event_sender, sample_cookie_valid_range(), ) @@ -1419,9 +1465,8 @@ mod tests { #[tokio::test] async fn should_return_no_stats_when_the_tracker_does_not_have_any_torrent() { - let (tracker, stats_event_sender) = public_tracker(); - let tracker = Arc::new(tracker); - let stats_event_sender = Arc::new(stats_event_sender); + let (tracker, stats_event_sender, _in_memory_whitelist, _whitelist_manager, _whitelist_authorization) = + public_tracker(); let remote_addr = sample_ipv4_remote_addr(); @@ -1507,8 +1552,6 @@ mod tests { } mod with_a_public_tracker { - use std::sync::Arc; - use aquatic_udp_protocol::{NumberOfDownloads, NumberOfPeers, TorrentScrapeStatistics}; use crate::servers::udp::handlers::tests::public_tracker; @@ -1516,8 +1559,8 @@ mod tests { #[tokio::test] async fn should_return_torrent_statistics_when_the_tracker_has_the_requested_torrent() { - let (tracker, _stats_event_sender) = public_tracker(); - let tracker = Arc::new(tracker); + let (tracker, _stats_event_sender, _in_memory_whitelist, _whitelist_manager, _whitelist_authorization) = + public_tracker(); let torrent_stats = match_scrape_response(add_a_sample_seeder_and_scrape(tracker.clone()).await); @@ -1532,8 +1575,6 @@ mod tests { } mod with_a_whitelisted_tracker { - use std::sync::Arc; - use aquatic_udp_protocol::{InfoHash, NumberOfDownloads, NumberOfPeers, TorrentScrapeStatistics}; use crate::servers::udp::handlers::handle_scrape; @@ -1544,19 +1585,15 @@ mod tests { #[tokio::test] async fn should_return_the_torrent_statistics_when_the_requested_torrent_is_whitelisted() { - let (tracker, stats_event_sender) = whitelisted_tracker(); - let tracker = Arc::new(tracker); - let stats_event_sender = Arc::new(stats_event_sender); + let (tracker, stats_event_sender, in_memory_whitelist, _whitelist_manager, _whitelist_authorization) = + whitelisted_tracker(); let remote_addr = sample_ipv4_remote_addr(); let info_hash = InfoHash([0u8; 20]); add_a_seeder(tracker.clone(), &remote_addr, &info_hash).await; - tracker - .whitelist_manager - .add_torrent_to_memory_whitelist(&info_hash.0.into()) - .await; + in_memory_whitelist.add(&info_hash.0.into()).await; let request = build_scrape_request(&remote_addr, &info_hash); @@ -1584,9 +1621,8 @@ mod tests { #[tokio::test] async fn should_return_zeroed_statistics_when_the_requested_torrent_is_not_whitelisted() { - let (tracker, stats_event_sender) = whitelisted_tracker(); - let tracker = Arc::new(tracker); - let stats_event_sender = Arc::new(stats_event_sender); + let (tracker, stats_event_sender, _in_memory_whitelist, _whitelist_manager, _whitelist_authorization) = + whitelisted_tracker(); let remote_addr = sample_ipv4_remote_addr(); let info_hash = InfoHash([0u8; 20]); @@ -1650,7 +1686,8 @@ mod tests { Arc::new(Some(Box::new(stats_event_sender_mock))); let remote_addr = sample_ipv4_remote_addr(); - let tracker = Arc::new(test_tracker_factory()); + + let (tracker, _whitelist_authorization) = test_tracker_factory(); handle_scrape( remote_addr, @@ -1689,7 +1726,8 @@ mod tests { Arc::new(Some(Box::new(stats_event_sender_mock))); let remote_addr = sample_ipv6_remote_addr(); - let tracker = Arc::new(test_tracker_factory()); + + let (tracker, _whitelist_authorization) = test_tracker_factory(); handle_scrape( remote_addr, diff --git a/src/servers/udp/server/launcher.rs b/src/servers/udp/server/launcher.rs index d71ffcfd1..bb5c30d44 100644 --- a/src/servers/udp/server/launcher.rs +++ b/src/servers/udp/server/launcher.rs @@ -14,7 +14,7 @@ use super::banning::BanService; use super::request_buffer::ActiveRequests; use crate::bootstrap::jobs::Started; use crate::core::statistics::event::sender::Sender; -use crate::core::{statistics, Tracker}; +use crate::core::{statistics, whitelist, Tracker}; use crate::servers::logging::STARTED_ON; use crate::servers::registar::ServiceHealthCheckJob; use crate::servers::signals::{shutdown_signal_with_message, Halted}; @@ -40,10 +40,19 @@ impl Launcher { /// It panics if unable to bind to udp socket, and get the address from the udp socket. /// It panics if unable to send address of socket. /// It panics if the udp server is loaded when the tracker is private. - /// - #[instrument(skip(tracker, opt_stats_event_sender, ban_service, bind_to, tx_start, rx_halt))] + #[allow(clippy::too_many_arguments)] + #[instrument(skip( + tracker, + whitelist_authorization, + opt_stats_event_sender, + ban_service, + bind_to, + tx_start, + rx_halt + ))] pub async fn run_with_graceful_shutdown( tracker: Arc, + whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, ban_service: Arc>, bind_to: SocketAddr, @@ -86,6 +95,7 @@ impl Launcher { let () = Self::run_udp_server_main( receiver, tracker.clone(), + whitelist_authorization.clone(), opt_stats_event_sender.clone(), ban_service.clone(), cookie_lifetime, @@ -127,10 +137,11 @@ impl Launcher { ServiceHealthCheckJob::new(binding, info, job) } - #[instrument(skip(receiver, tracker, opt_stats_event_sender, ban_service))] + #[instrument(skip(receiver, tracker, whitelist_authorization, opt_stats_event_sender, ban_service))] async fn run_udp_server_main( mut receiver: Receiver, tracker: Arc, + whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, ban_service: Arc>, cookie_lifetime: Duration, @@ -201,6 +212,7 @@ impl Launcher { let processor = Processor::new( receiver.socket.clone(), tracker.clone(), + whitelist_authorization.clone(), opt_stats_event_sender.clone(), cookie_lifetime, ); diff --git a/src/servers/udp/server/mod.rs b/src/servers/udp/server/mod.rs index b5da9d326..f47e0b1db 100644 --- a/src/servers/udp/server/mod.rs +++ b/src/servers/udp/server/mod.rs @@ -64,7 +64,9 @@ mod tests { use super::spawner::Spawner; use super::Server; use crate::bootstrap::app::initialize_global_services; - use crate::core::services::{initialize_database, initialize_tracker, initialize_whitelist, statistics}; + use crate::core::services::{initialize_database, initialize_tracker, initialize_whitelist_manager, statistics}; + use crate::core::whitelist; + use crate::core::whitelist::repository::in_memory::InMemoryWhitelist; use crate::servers::registar::Registar; use crate::servers::udp::server::banning::BanService; use crate::servers::udp::server::launcher::MAX_CONNECTION_ID_ERRORS_PER_IP; @@ -80,8 +82,13 @@ mod tests { initialize_global_services(&cfg); let database = initialize_database(&cfg); - let whitelist_manager = initialize_whitelist(database.clone()); - let tracker = Arc::new(initialize_tracker(&cfg, &database, &whitelist_manager)); + let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); + let whitelist_authorization = Arc::new(whitelist::authorization::Authorization::new( + &cfg.core, + &in_memory_whitelist.clone(), + )); + let _whitelist_manager = initialize_whitelist_manager(database.clone(), in_memory_whitelist.clone()); + let tracker = Arc::new(initialize_tracker(&cfg, &database, &whitelist_authorization)); let udp_trackers = cfg.udp_trackers.clone().expect("missing UDP trackers configuration"); let config = &udp_trackers[0]; @@ -93,6 +100,7 @@ mod tests { let started = stopped .start( tracker, + whitelist_authorization, stats_event_sender, ban_service, register.give_form(), @@ -119,8 +127,13 @@ mod tests { initialize_global_services(&cfg); let database = initialize_database(&cfg); - let whitelist_manager = initialize_whitelist(database.clone()); - let tracker = Arc::new(initialize_tracker(&cfg, &database, &whitelist_manager)); + let in_memory_whitelist = Arc::new(InMemoryWhitelist::default()); + let whitelist_authorization = Arc::new(whitelist::authorization::Authorization::new( + &cfg.core, + &in_memory_whitelist.clone(), + )); + + let tracker = Arc::new(initialize_tracker(&cfg, &database, &whitelist_authorization)); let config = &cfg.udp_trackers.as_ref().unwrap().first().unwrap(); let bind_to = config.bind_address; @@ -131,6 +144,7 @@ mod tests { let started = stopped .start( tracker, + whitelist_authorization, stats_event_sender, ban_service, register.give_form(), diff --git a/src/servers/udp/server/processor.rs b/src/servers/udp/server/processor.rs index 2ef7cc482..fe3666c1d 100644 --- a/src/servers/udp/server/processor.rs +++ b/src/servers/udp/server/processor.rs @@ -12,13 +12,14 @@ use super::banning::BanService; use super::bound_socket::BoundSocket; use crate::core::statistics::event::sender::Sender; use crate::core::statistics::event::UdpResponseKind; -use crate::core::{statistics, Tracker}; +use crate::core::{statistics, whitelist, Tracker}; use crate::servers::udp::handlers::CookieTimeValues; use crate::servers::udp::{handlers, RawRequest}; pub struct Processor { socket: Arc, tracker: Arc, + whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, cookie_lifetime: f64, } @@ -27,12 +28,14 @@ impl Processor { pub fn new( socket: Arc, tracker: Arc, + whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, cookie_lifetime: f64, ) -> Self { Self { socket, tracker, + whitelist_authorization, opt_stats_event_sender, cookie_lifetime, } @@ -47,6 +50,7 @@ impl Processor { let response = handlers::handle_packet( request, &self.tracker, + &self.whitelist_authorization, &self.opt_stats_event_sender, self.socket.address(), CookieTimeValues::new(self.cookie_lifetime), diff --git a/src/servers/udp/server/spawner.rs b/src/servers/udp/server/spawner.rs index 5d7a97877..aecba39ec 100644 --- a/src/servers/udp/server/spawner.rs +++ b/src/servers/udp/server/spawner.rs @@ -12,7 +12,7 @@ use super::banning::BanService; use super::launcher::Launcher; use crate::bootstrap::jobs::Started; use crate::core::statistics::event::sender::Sender; -use crate::core::Tracker; +use crate::core::{whitelist, Tracker}; use crate::servers::signals::Halted; #[derive(Constructor, Copy, Clone, Debug, Display)] @@ -27,9 +27,11 @@ impl Spawner { /// # Panics /// /// It would panic if unable to resolve the `local_addr` from the supplied ´socket´. + #[allow(clippy::too_many_arguments)] pub fn spawn_launcher( &self, tracker: Arc, + whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, ban_service: Arc>, cookie_lifetime: Duration, @@ -41,6 +43,7 @@ impl Spawner { tokio::spawn(async move { Launcher::run_with_graceful_shutdown( tracker, + whitelist_authorization, opt_stats_event_sender, ban_service, spawner.bind_to, diff --git a/src/servers/udp/server/states.rs b/src/servers/udp/server/states.rs index 5cdca5a7d..9a01b5c6d 100644 --- a/src/servers/udp/server/states.rs +++ b/src/servers/udp/server/states.rs @@ -14,7 +14,7 @@ use super::spawner::Spawner; use super::{Server, UdpError}; use crate::bootstrap::jobs::Started; use crate::core::statistics::event::sender::Sender; -use crate::core::Tracker; +use crate::core::{whitelist, Tracker}; use crate::servers::registar::{ServiceRegistration, ServiceRegistrationForm}; use crate::servers::signals::Halted; use crate::servers::udp::server::launcher::Launcher; @@ -65,10 +65,11 @@ impl Server { /// /// It panics if unable to receive the bound socket address from service. /// - #[instrument(skip(self, tracker, opt_stats_event_sender, ban_service, form), err, ret(Display, level = Level::INFO))] + #[instrument(skip(self, tracker, whitelist_authorization, opt_stats_event_sender, ban_service, form), err, ret(Display, level = Level::INFO))] pub async fn start( self, tracker: Arc, + whitelist_authorization: Arc, opt_stats_event_sender: Arc>>, ban_service: Arc>, form: ServiceRegistrationForm, @@ -82,6 +83,7 @@ impl Server { // May need to wrap in a task to about a tokio bug. let task = self.state.spawner.spawn_launcher( tracker, + whitelist_authorization, opt_stats_event_sender, ban_service, cookie_lifetime, diff --git a/tests/servers/api/environment.rs b/tests/servers/api/environment.rs index dcfe526f1..a9628f053 100644 --- a/tests/servers/api/environment.rs +++ b/tests/servers/api/environment.rs @@ -10,7 +10,7 @@ use torrust_tracker_lib::bootstrap::app::{initialize_app_container, initialize_g use torrust_tracker_lib::bootstrap::jobs::make_rust_tls; use torrust_tracker_lib::core::statistics::event::sender::Sender; use torrust_tracker_lib::core::statistics::repository::Repository; -use torrust_tracker_lib::core::whitelist::WhiteListManager; +use torrust_tracker_lib::core::whitelist::manager::WhiteListManager; use torrust_tracker_lib::core::Tracker; use torrust_tracker_lib::servers::apis::server::{ApiServer, Launcher, Running, Stopped}; use torrust_tracker_lib::servers::registar::Registar; @@ -82,6 +82,7 @@ impl Environment { .server .start( self.tracker, + self.whitelist_manager, self.stats_event_sender, self.stats_repository, self.ban_service, diff --git a/tests/servers/http/environment.rs b/tests/servers/http/environment.rs index 131fe4ac1..160cb49f8 100644 --- a/tests/servers/http/environment.rs +++ b/tests/servers/http/environment.rs @@ -7,8 +7,8 @@ use torrust_tracker_lib::bootstrap::app::{initialize_app_container, initialize_g use torrust_tracker_lib::bootstrap::jobs::make_rust_tls; use torrust_tracker_lib::core::statistics::event::sender::Sender; use torrust_tracker_lib::core::statistics::repository::Repository; -use torrust_tracker_lib::core::whitelist::WhiteListManager; -use torrust_tracker_lib::core::Tracker; +use torrust_tracker_lib::core::whitelist::manager::WhiteListManager; +use torrust_tracker_lib::core::{whitelist, Tracker}; use torrust_tracker_lib::servers::http::server::{HttpServer, Launcher, Running, Stopped}; use torrust_tracker_lib::servers::registar::Registar; use torrust_tracker_primitives::peer; @@ -18,6 +18,7 @@ pub struct Environment { pub tracker: Arc, pub stats_event_sender: Arc>>, pub stats_repository: Arc, + pub whitelist_authorization: Arc, pub whitelist_manager: Arc, pub registar: Registar, pub server: HttpServer, @@ -55,6 +56,7 @@ impl Environment { tracker: app_container.tracker.clone(), stats_event_sender: app_container.stats_event_sender.clone(), stats_repository: app_container.stats_repository.clone(), + whitelist_authorization: app_container.whitelist_authorization.clone(), whitelist_manager: app_container.whitelist_manager.clone(), registar: Registar::default(), server, @@ -66,13 +68,19 @@ impl Environment { Environment { config: self.config, tracker: self.tracker.clone(), + whitelist_authorization: self.whitelist_authorization.clone(), stats_event_sender: self.stats_event_sender.clone(), stats_repository: self.stats_repository.clone(), whitelist_manager: self.whitelist_manager.clone(), registar: self.registar.clone(), server: self .server - .start(self.tracker, self.stats_event_sender, self.registar.give_form()) + .start( + self.tracker, + self.whitelist_authorization, + self.stats_event_sender, + self.registar.give_form(), + ) .await .unwrap(), } @@ -88,6 +96,7 @@ impl Environment { Environment { config: self.config, tracker: self.tracker, + whitelist_authorization: self.whitelist_authorization, stats_event_sender: self.stats_event_sender, stats_repository: self.stats_repository, whitelist_manager: self.whitelist_manager, diff --git a/tests/servers/udp/environment.rs b/tests/servers/udp/environment.rs index 81e626e1c..43778ef6e 100644 --- a/tests/servers/udp/environment.rs +++ b/tests/servers/udp/environment.rs @@ -7,7 +7,7 @@ use torrust_tracker_configuration::{Configuration, UdpTracker, DEFAULT_TIMEOUT}; use torrust_tracker_lib::bootstrap::app::{initialize_app_container, initialize_global_services}; use torrust_tracker_lib::core::statistics::event::sender::Sender; use torrust_tracker_lib::core::statistics::repository::Repository; -use torrust_tracker_lib::core::Tracker; +use torrust_tracker_lib::core::{whitelist, Tracker}; use torrust_tracker_lib::servers::registar::Registar; use torrust_tracker_lib::servers::udp::server::banning::BanService; use torrust_tracker_lib::servers::udp::server::spawner::Spawner; @@ -21,6 +21,7 @@ where { pub config: Arc, pub tracker: Arc, + pub whitelist_authorization: Arc, pub stats_event_sender: Arc>>, pub stats_repository: Arc, pub ban_service: Arc>, @@ -57,6 +58,7 @@ impl Environment { Self { config, tracker: app_container.tracker.clone(), + whitelist_authorization: app_container.whitelist_authorization.clone(), stats_event_sender: app_container.stats_event_sender.clone(), stats_repository: app_container.stats_repository.clone(), ban_service: app_container.ban_service.clone(), @@ -71,6 +73,7 @@ impl Environment { Environment { config: self.config, tracker: self.tracker.clone(), + whitelist_authorization: self.whitelist_authorization.clone(), stats_event_sender: self.stats_event_sender.clone(), stats_repository: self.stats_repository.clone(), ban_service: self.ban_service.clone(), @@ -79,6 +82,7 @@ impl Environment { .server .start( self.tracker, + self.whitelist_authorization, self.stats_event_sender, self.ban_service, self.registar.give_form(), @@ -106,6 +110,7 @@ impl Environment { Environment { config: self.config, tracker: self.tracker, + whitelist_authorization: self.whitelist_authorization, stats_event_sender: self.stats_event_sender, stats_repository: self.stats_repository, ban_service: self.ban_service,