Skip to content

Commit b7e009d

Browse files
committed
Merge #1183: Refactor: extract WhitelistManager
57455ca refactor: [#1182] remove whitelist context methods from core tracker (Jose Celano) 882af33 refactor: [#1182] remove duplicate code (Jose Celano) 658d2be refactor: [#1182] inject database and whitelist manager in tracker factory (Jose Celano) 4253d0f refactor: [#1182] use WhitelistManager in API handlers (Jose Celano) 2f1abeb refactor: [#1182] inject database and whitelist in tracker as dep (Jose Celano) cc2bc7b refactor: [#1182] move structs to new mods in whitelist (Jose Celano) 07f53a4 refactor: [#1182] extract strcut DatabaseWhitelist (Jose Celano) ea35ba5 refactor: [#1182] extract struct InMemoryWhitelist (Jose Celano) 39d1620 refactor: [#1182] remove unused methods (Jose Celano) 439493d refactor: [#1182] move extracted service to new mod (Jose Celano) 40eb805 refactor: [1182] extract WhitelistManager (Jose Celano) Pull request description: Refactor: extract `WhitelistManager` ACKs for top commit: josecelano: ACK 57455ca Tree-SHA512: 03fb1b590b8226b96f178b80ce8998955dc70892cba1b9f921138e29cfde5e51df71d3956966338f009b12915b33bbfbb1ff1514c24e8f7868eda402d2918a73
2 parents b403382 + 57455ca commit b7e009d

File tree

21 files changed

+541
-307
lines changed

21 files changed

+541
-307
lines changed

src/app.rs

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ pub async fn start(
6767
// Load whitelisted torrents
6868
if tracker.is_listed() {
6969
tracker
70+
.whitelist_manager
7071
.load_whitelist_from_database()
7172
.await
7273
.expect("Could not load whitelist from database.");

src/bootstrap/app.rs

+14-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ use tracing::instrument;
2121

2222
use super::config::initialize_configuration;
2323
use crate::bootstrap;
24-
use crate::core::services::tracker_factory;
24+
use crate::core::databases::Database;
25+
use crate::core::services::{initialize_database, initialize_whitelist, tracker_factory};
26+
use crate::core::whitelist::WhiteListManager;
2527
use crate::core::Tracker;
2628
use crate::servers::udp::server::banning::BanService;
2729
use crate::servers::udp::server::launcher::MAX_CONNECTION_ID_ERRORS_PER_IP;
@@ -105,7 +107,17 @@ pub fn initialize_static() {
105107
#[must_use]
106108
#[instrument(skip(config))]
107109
pub fn initialize_tracker(config: &Configuration) -> Tracker {
108-
tracker_factory(config)
110+
let (database, whitelist_manager) = initialize_tracker_dependencies(config);
111+
112+
tracker_factory(config, &database, &whitelist_manager)
113+
}
114+
115+
#[must_use]
116+
pub fn initialize_tracker_dependencies(config: &Configuration) -> (Arc<Box<dyn Database>>, Arc<WhiteListManager>) {
117+
let database = initialize_database(config);
118+
let whitelist_manager = initialize_whitelist(database.clone());
119+
120+
(database, whitelist_manager)
109121
}
110122

111123
/// It initializes the log threshold, format and channel.

src/core/mod.rs

+49-136
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ pub mod error;
445445
pub mod services;
446446
pub mod statistics;
447447
pub mod torrent;
448+
pub mod whitelist;
448449

449450
pub mod peer_tests;
450451

@@ -456,11 +457,9 @@ use std::time::Duration;
456457

457458
use auth::PeerKey;
458459
use bittorrent_primitives::info_hash::InfoHash;
459-
use databases::driver::Driver;
460460
use error::PeerKeyError;
461461
use tokio::sync::mpsc::error::SendError;
462462
use torrust_tracker_clock::clock::Time;
463-
use torrust_tracker_configuration::v2_0_0::database;
464463
use torrust_tracker_configuration::{AnnouncePolicy, Core, TORRENT_PEERS_LIMIT};
465464
use torrust_tracker_located_error::Located;
466465
use torrust_tracker_primitives::core::{AnnounceData, ScrapeData};
@@ -470,6 +469,7 @@ use torrust_tracker_primitives::{peer, DurationSinceUnixEpoch};
470469
use torrust_tracker_torrent_repository::entry::EntrySync;
471470
use torrust_tracker_torrent_repository::repository::Repository;
472471
use tracing::instrument;
472+
use whitelist::WhiteListManager;
473473

474474
use self::auth::Key;
475475
use self::error::Error;
@@ -498,7 +498,7 @@ pub struct Tracker {
498498
keys: tokio::sync::RwLock<std::collections::HashMap<Key, auth::PeerKey>>,
499499

500500
/// The list of allowed torrents. Only for listed trackers.
501-
whitelist: tokio::sync::RwLock<std::collections::HashSet<InfoHash>>,
501+
pub whitelist_manager: Arc<WhiteListManager>,
502502

503503
/// The in-memory torrents repository.
504504
torrents: Arc<Torrents>,
@@ -574,24 +574,19 @@ impl Tracker {
574574
/// Will return a `databases::error::Error` if unable to connect to database. The `Tracker` is responsible for the persistence.
575575
pub fn new(
576576
config: &Core,
577+
database: &Arc<Box<dyn Database>>,
578+
whitelist_manager: &Arc<WhiteListManager>,
577579
stats_event_sender: Option<Box<dyn statistics::event::sender::Sender>>,
578580
stats_repository: statistics::repository::Repository,
579581
) -> Result<Tracker, databases::error::Error> {
580-
let driver = match config.database.driver {
581-
database::Driver::Sqlite3 => Driver::Sqlite3,
582-
database::Driver::MySQL => Driver::MySQL,
583-
};
584-
585-
let database = Arc::new(databases::driver::build(&driver, &config.database.path)?);
586-
587582
Ok(Tracker {
588583
config: config.clone(),
584+
database: database.clone(),
589585
keys: tokio::sync::RwLock::new(std::collections::HashMap::new()),
590-
whitelist: tokio::sync::RwLock::new(std::collections::HashSet::new()),
586+
whitelist_manager: whitelist_manager.clone(),
591587
torrents: Arc::default(),
592588
stats_event_sender,
593589
stats_repository,
594-
database,
595590
})
596591
}
597592

@@ -1049,7 +1044,7 @@ impl Tracker {
10491044
return Ok(());
10501045
}
10511046

1052-
if self.is_info_hash_whitelisted(info_hash).await {
1047+
if self.whitelist_manager.is_info_hash_whitelisted(info_hash).await {
10531048
return Ok(());
10541049
}
10551050

@@ -1059,104 +1054,6 @@ impl Tracker {
10591054
})
10601055
}
10611056

1062-
/// It adds a torrent to the whitelist.
1063-
/// Adding torrents is not relevant to public trackers.
1064-
///
1065-
/// # Context: Whitelist
1066-
///
1067-
/// # Errors
1068-
///
1069-
/// Will return a `database::Error` if unable to add the `info_hash` into the whitelist database.
1070-
pub async fn add_torrent_to_whitelist(&self, info_hash: &InfoHash) -> Result<(), databases::error::Error> {
1071-
self.add_torrent_to_database_whitelist(info_hash)?;
1072-
self.add_torrent_to_memory_whitelist(info_hash).await;
1073-
Ok(())
1074-
}
1075-
1076-
/// It adds a torrent to the whitelist if it has not been whitelisted previously
1077-
fn add_torrent_to_database_whitelist(&self, info_hash: &InfoHash) -> Result<(), databases::error::Error> {
1078-
let is_whitelisted = self.database.is_info_hash_whitelisted(*info_hash)?;
1079-
1080-
if is_whitelisted {
1081-
return Ok(());
1082-
}
1083-
1084-
self.database.add_info_hash_to_whitelist(*info_hash)?;
1085-
1086-
Ok(())
1087-
}
1088-
1089-
pub async fn add_torrent_to_memory_whitelist(&self, info_hash: &InfoHash) -> bool {
1090-
self.whitelist.write().await.insert(*info_hash)
1091-
}
1092-
1093-
/// It removes a torrent from the whitelist.
1094-
/// Removing torrents is not relevant to public trackers.
1095-
///
1096-
/// # Context: Whitelist
1097-
///
1098-
/// # Errors
1099-
///
1100-
/// Will return a `database::Error` if unable to remove the `info_hash` from the whitelist database.
1101-
pub async fn remove_torrent_from_whitelist(&self, info_hash: &InfoHash) -> Result<(), databases::error::Error> {
1102-
self.remove_torrent_from_database_whitelist(info_hash)?;
1103-
self.remove_torrent_from_memory_whitelist(info_hash).await;
1104-
Ok(())
1105-
}
1106-
1107-
/// It removes a torrent from the whitelist in the database.
1108-
///
1109-
/// # Context: Whitelist
1110-
///
1111-
/// # Errors
1112-
///
1113-
/// Will return a `database::Error` if unable to remove the `info_hash` from the whitelist database.
1114-
pub fn remove_torrent_from_database_whitelist(&self, info_hash: &InfoHash) -> Result<(), databases::error::Error> {
1115-
let is_whitelisted = self.database.is_info_hash_whitelisted(*info_hash)?;
1116-
1117-
if !is_whitelisted {
1118-
return Ok(());
1119-
}
1120-
1121-
self.database.remove_info_hash_from_whitelist(*info_hash)?;
1122-
1123-
Ok(())
1124-
}
1125-
1126-
/// It removes a torrent from the whitelist in memory.
1127-
///
1128-
/// # Context: Whitelist
1129-
pub async fn remove_torrent_from_memory_whitelist(&self, info_hash: &InfoHash) -> bool {
1130-
self.whitelist.write().await.remove(info_hash)
1131-
}
1132-
1133-
/// It checks if a torrent is whitelisted.
1134-
///
1135-
/// # Context: Whitelist
1136-
pub async fn is_info_hash_whitelisted(&self, info_hash: &InfoHash) -> bool {
1137-
self.whitelist.read().await.contains(info_hash)
1138-
}
1139-
1140-
/// It loads the whitelist from the database.
1141-
///
1142-
/// # Context: Whitelist
1143-
///
1144-
/// # Errors
1145-
///
1146-
/// Will return a `database::Error` if unable to load the list whitelisted `info_hash`s from the database.
1147-
pub async fn load_whitelist_from_database(&self) -> Result<(), databases::error::Error> {
1148-
let whitelisted_torrents_from_database = self.database.load_whitelist()?;
1149-
let mut whitelist = self.whitelist.write().await;
1150-
1151-
whitelist.clear();
1152-
1153-
for info_hash in whitelisted_torrents_from_database {
1154-
let _: bool = whitelist.insert(info_hash);
1155-
}
1156-
1157-
Ok(())
1158-
}
1159-
11601057
/// It return the `Tracker` [`statistics::metrics::Metrics`].
11611058
///
11621059
/// # Context: Statistics
@@ -1214,26 +1111,37 @@ mod tests {
12141111
use torrust_tracker_primitives::DurationSinceUnixEpoch;
12151112
use torrust_tracker_test_helpers::configuration;
12161113

1114+
use crate::bootstrap::app::initialize_tracker_dependencies;
12171115
use crate::core::peer::Peer;
12181116
use crate::core::services::tracker_factory;
1117+
use crate::core::whitelist::WhiteListManager;
12191118
use crate::core::{TorrentsMetrics, Tracker};
12201119

12211120
fn public_tracker() -> Tracker {
1222-
tracker_factory(&configuration::ephemeral_public())
1121+
let config = configuration::ephemeral_public();
1122+
let (database, whitelist_manager) = initialize_tracker_dependencies(&config);
1123+
tracker_factory(&config, &database, &whitelist_manager)
12231124
}
12241125

12251126
fn private_tracker() -> Tracker {
1226-
tracker_factory(&configuration::ephemeral_private())
1127+
let config = configuration::ephemeral_private();
1128+
let (database, whitelist_manager) = initialize_tracker_dependencies(&config);
1129+
tracker_factory(&config, &database, &whitelist_manager)
12271130
}
12281131

1229-
fn whitelisted_tracker() -> Tracker {
1230-
tracker_factory(&configuration::ephemeral_listed())
1132+
fn whitelisted_tracker() -> (Tracker, Arc<WhiteListManager>) {
1133+
let config = configuration::ephemeral_listed();
1134+
let (database, whitelist_manager) = initialize_tracker_dependencies(&config);
1135+
let tracker = tracker_factory(&config, &database, &whitelist_manager);
1136+
1137+
(tracker, whitelist_manager)
12311138
}
12321139

12331140
pub fn tracker_persisting_torrents_in_database() -> Tracker {
1234-
let mut configuration = configuration::ephemeral();
1235-
configuration.core.tracker_policy.persistent_torrent_completed_stat = true;
1236-
tracker_factory(&configuration)
1141+
let mut config = configuration::ephemeral_listed();
1142+
config.core.tracker_policy.persistent_torrent_completed_stat = true;
1143+
let (database, whitelist_manager) = initialize_tracker_dependencies(&config);
1144+
tracker_factory(&config, &database, &whitelist_manager)
12371145
}
12381146

12391147
fn sample_info_hash() -> InfoHash {
@@ -1760,11 +1668,11 @@ mod tests {
17601668

17611669
#[tokio::test]
17621670
async fn it_should_authorize_the_announce_and_scrape_actions_on_whitelisted_torrents() {
1763-
let tracker = whitelisted_tracker();
1671+
let (tracker, whitelist_manager) = whitelisted_tracker();
17641672

17651673
let info_hash = sample_info_hash();
17661674

1767-
let result = tracker.add_torrent_to_whitelist(&info_hash).await;
1675+
let result = whitelist_manager.add_torrent_to_whitelist(&info_hash).await;
17681676
assert!(result.is_ok());
17691677

17701678
let result = tracker.authorize(&info_hash).await;
@@ -1773,7 +1681,7 @@ mod tests {
17731681

17741682
#[tokio::test]
17751683
async fn it_should_not_authorize_the_announce_and_scrape_actions_on_not_whitelisted_torrents() {
1776-
let tracker = whitelisted_tracker();
1684+
let (tracker, _whitelist_manager) = whitelisted_tracker();
17771685

17781686
let info_hash = sample_info_hash();
17791687

@@ -1785,48 +1693,53 @@ mod tests {
17851693
mod handling_the_torrent_whitelist {
17861694
use crate::core::tests::the_tracker::{sample_info_hash, whitelisted_tracker};
17871695

1696+
// todo: after extracting the WhitelistManager from the Tracker,
1697+
// there is no need to use the tracker to test the whitelist.
1698+
// Test not using the `tracker` (`_tracker` variable) should be
1699+
// moved to the whitelist module.
1700+
17881701
#[tokio::test]
17891702
async fn it_should_add_a_torrent_to_the_whitelist() {
1790-
let tracker = whitelisted_tracker();
1703+
let (_tracker, whitelist_manager) = whitelisted_tracker();
17911704

17921705
let info_hash = sample_info_hash();
17931706

1794-
tracker.add_torrent_to_whitelist(&info_hash).await.unwrap();
1707+
whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap();
17951708

1796-
assert!(tracker.is_info_hash_whitelisted(&info_hash).await);
1709+
assert!(whitelist_manager.is_info_hash_whitelisted(&info_hash).await);
17971710
}
17981711

17991712
#[tokio::test]
18001713
async fn it_should_remove_a_torrent_from_the_whitelist() {
1801-
let tracker = whitelisted_tracker();
1714+
let (_tracker, whitelist_manager) = whitelisted_tracker();
18021715

18031716
let info_hash = sample_info_hash();
18041717

1805-
tracker.add_torrent_to_whitelist(&info_hash).await.unwrap();
1718+
whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap();
18061719

1807-
tracker.remove_torrent_from_whitelist(&info_hash).await.unwrap();
1720+
whitelist_manager.remove_torrent_from_whitelist(&info_hash).await.unwrap();
18081721

1809-
assert!(!tracker.is_info_hash_whitelisted(&info_hash).await);
1722+
assert!(!whitelist_manager.is_info_hash_whitelisted(&info_hash).await);
18101723
}
18111724

18121725
mod persistence {
18131726
use crate::core::tests::the_tracker::{sample_info_hash, whitelisted_tracker};
18141727

18151728
#[tokio::test]
18161729
async fn it_should_load_the_whitelist_from_the_database() {
1817-
let tracker = whitelisted_tracker();
1730+
let (_tracker, whitelist_manager) = whitelisted_tracker();
18181731

18191732
let info_hash = sample_info_hash();
18201733

1821-
tracker.add_torrent_to_whitelist(&info_hash).await.unwrap();
1734+
whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap();
1735+
1736+
whitelist_manager.remove_torrent_from_memory_whitelist(&info_hash).await;
18221737

1823-
// Remove torrent from the in-memory whitelist
1824-
tracker.whitelist.write().await.remove(&info_hash);
1825-
assert!(!tracker.is_info_hash_whitelisted(&info_hash).await);
1738+
assert!(!whitelist_manager.is_info_hash_whitelisted(&info_hash).await);
18261739

1827-
tracker.load_whitelist_from_database().await.unwrap();
1740+
whitelist_manager.load_whitelist_from_database().await.unwrap();
18281741

1829-
assert!(tracker.is_info_hash_whitelisted(&info_hash).await);
1742+
assert!(whitelist_manager.is_info_hash_whitelisted(&info_hash).await);
18301743
}
18311744
}
18321745
}
@@ -1857,7 +1770,7 @@ mod tests {
18571770

18581771
#[tokio::test]
18591772
async fn it_should_return_the_zeroed_swarm_metadata_for_the_requested_file_if_it_is_not_whitelisted() {
1860-
let tracker = whitelisted_tracker();
1773+
let (tracker, _whitelist_manager) = whitelisted_tracker();
18611774

18621775
let info_hash = "3b245504cf5f11bbdbe1201cea6a6bf45aee1bc0".parse::<InfoHash>().unwrap();
18631776

0 commit comments

Comments
 (0)