Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions packages/tracker-core/src/core_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ use std::sync::Arc;
use aquatic_udp_protocol::{AnnounceEvent, NumberOfBytes, PeerId};
use bittorrent_primitives::info_hash::InfoHash;
use torrust_tracker_configuration::Configuration;
#[cfg(test)]
use torrust_tracker_configuration::Core;
use torrust_tracker_primitives::peer::Peer;
use torrust_tracker_primitives::DurationSinceUnixEpoch;
#[cfg(test)]
use torrust_tracker_test_helpers::configuration::ephemeral_sqlite_database;

use super::announce_handler::AnnounceHandler;
use super::databases::setup::initialize_database;
Expand Down Expand Up @@ -103,3 +107,20 @@ pub fn initialize_handlers(config: &Configuration) -> (Arc<AnnounceHandler>, Arc

(announce_handler, scrape_handler)
}

/// # Panics
///
/// Will panic if the temporary file path is not a valid UFT string.
#[cfg(test)]
#[must_use]
pub fn ephemeral_configuration_for_listed_tracker() -> Core {
let mut config = Core {
listed: true,
..Default::default()
};

let temp_file = ephemeral_sqlite_database();
temp_file.to_str().unwrap().clone_into(&mut config.database.path);

config
}
94 changes: 84 additions & 10 deletions packages/tracker-core/src/whitelist/authorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,33 +61,107 @@ impl WhitelistAuthorization {
#[cfg(test)]
mod tests {

mod configured_as_whitelisted {
mod the_whitelist_authorization_for_announce_and_scrape_actions {
use std::sync::Arc;

use torrust_tracker_configuration::Core;

use crate::whitelist::authorization::WhitelistAuthorization;
use crate::whitelist::repository::in_memory::InMemoryWhitelist;

fn initialize_whitelist_authorization_with(config: &Core) -> Arc<WhitelistAuthorization> {
let (whitelist_authorization, _in_memory_whitelist) =
initialize_whitelist_authorization_and_dependencies_with(config);
whitelist_authorization
}

fn initialize_whitelist_authorization_and_dependencies_with(
config: &Core,
) -> (Arc<WhitelistAuthorization>, Arc<InMemoryWhitelist>) {
let in_memory_whitelist = Arc::new(InMemoryWhitelist::default());
let whitelist_authorization = Arc::new(WhitelistAuthorization::new(config, &in_memory_whitelist.clone()));

(whitelist_authorization, in_memory_whitelist)
}

mod when_the_tacker_is_configured_as_listed {

use torrust_tracker_configuration::Core;

mod handling_authorization {
use crate::core_tests::sample_info_hash;
use crate::whitelist::whitelist_tests::initialize_whitelist_services_for_listed_tracker;
use crate::error::Error;
use crate::whitelist::authorization::tests::the_whitelist_authorization_for_announce_and_scrape_actions::{
initialize_whitelist_authorization_and_dependencies_with, initialize_whitelist_authorization_with,
};

fn configuration_for_listed_tracker() -> Core {
Core {
listed: true,
..Default::default()
}
}

#[tokio::test]
async fn it_should_authorize_the_announce_and_scrape_actions_on_whitelisted_torrents() {
let (whitelist_authorization, whitelist_manager) = initialize_whitelist_services_for_listed_tracker();
async fn should_authorize_a_whitelisted_infohash() {
let (whitelist_authorization, in_memory_whitelist) =
initialize_whitelist_authorization_and_dependencies_with(&configuration_for_listed_tracker());

let info_hash = sample_info_hash();

let result = whitelist_manager.add_torrent_to_whitelist(&info_hash).await;
assert!(result.is_ok());
let _unused = in_memory_whitelist.add(&info_hash).await;

let result = 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 (whitelist_authorization, _whitelist_manager) = initialize_whitelist_services_for_listed_tracker();
async fn should_not_authorize_a_non_whitelisted_infohash() {
let whitelist_authorization = initialize_whitelist_authorization_with(&configuration_for_listed_tracker());

let result = whitelist_authorization.authorize(&sample_info_hash()).await;

assert!(matches!(result.unwrap_err(), Error::TorrentNotWhitelisted { .. }));
}
}

mod when_the_tacker_is_not_configured_as_listed {

use torrust_tracker_configuration::Core;

use crate::core_tests::sample_info_hash;
use crate::whitelist::authorization::tests::the_whitelist_authorization_for_announce_and_scrape_actions::{
initialize_whitelist_authorization_and_dependencies_with, initialize_whitelist_authorization_with,
};

fn configuration_for_non_listed_tracker() -> Core {
Core {
listed: false,
..Default::default()
}
}

#[tokio::test]
async fn should_authorize_a_whitelisted_infohash() {
let (whitelist_authorization, in_memory_whitelist) =
initialize_whitelist_authorization_and_dependencies_with(&configuration_for_non_listed_tracker());

let info_hash = sample_info_hash();

let _unused = in_memory_whitelist.add(&info_hash).await;

let result = whitelist_authorization.authorize(&info_hash).await;
assert!(result.is_err());

assert!(result.is_ok());
}

#[tokio::test]
async fn should_also_authorize_a_non_whitelisted_infohash() {
let whitelist_authorization = initialize_whitelist_authorization_with(&configuration_for_non_listed_tracker());

let result = whitelist_authorization.authorize(&sample_info_hash()).await;

assert!(result.is_ok());
}
}
}
Expand Down
80 changes: 39 additions & 41 deletions packages/tracker-core/src/whitelist/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,30 +48,6 @@ impl WhitelistManager {
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
Expand All @@ -95,17 +71,41 @@ mod tests {

use std::sync::Arc;

use torrust_tracker_test_helpers::configuration;
use torrust_tracker_configuration::Core;

use crate::core_tests::ephemeral_configuration_for_listed_tracker;
use crate::databases::setup::initialize_database;
use crate::databases::Database;
use crate::whitelist::manager::WhitelistManager;
use crate::whitelist::whitelist_tests::initialize_whitelist_services;
use crate::whitelist::repository::in_memory::InMemoryWhitelist;
use crate::whitelist::repository::persisted::DatabaseWhitelist;

fn initialize_whitelist_manager_for_whitelisted_tracker() -> Arc<WhitelistManager> {
let config = configuration::ephemeral_listed();
struct WhitelistManagerDeps {
pub _database: Arc<Box<dyn Database>>,
pub database_whitelist: Arc<DatabaseWhitelist>,
pub in_memory_whitelist: Arc<InMemoryWhitelist>,
}

let (_whitelist_authorization, whitelist_manager) = initialize_whitelist_services(&config);
fn initialize_whitelist_manager_for_whitelisted_tracker() -> (Arc<WhitelistManager>, Arc<WhitelistManagerDeps>) {
let config = ephemeral_configuration_for_listed_tracker();
initialize_whitelist_manager_and_deps(&config)
}

whitelist_manager
fn initialize_whitelist_manager_and_deps(config: &Core) -> (Arc<WhitelistManager>, Arc<WhitelistManagerDeps>) {
let database = initialize_database(config);
let database_whitelist = Arc::new(DatabaseWhitelist::new(database.clone()));
let in_memory_whitelist = Arc::new(InMemoryWhitelist::default());

let whitelist_manager = Arc::new(WhitelistManager::new(database_whitelist.clone(), in_memory_whitelist.clone()));

(
whitelist_manager,
Arc::new(WhitelistManagerDeps {
_database: database,
database_whitelist,
in_memory_whitelist,
}),
)
}

mod configured_as_whitelisted {
Expand All @@ -116,26 +116,28 @@ mod tests {

#[tokio::test]
async fn it_should_add_a_torrent_to_the_whitelist() {
let whitelist_manager = initialize_whitelist_manager_for_whitelisted_tracker();
let (whitelist_manager, services) = initialize_whitelist_manager_for_whitelisted_tracker();

let info_hash = sample_info_hash();

whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap();

assert!(whitelist_manager.is_info_hash_whitelisted(&info_hash).await);
assert!(services.in_memory_whitelist.contains(&info_hash).await);
assert!(services.database_whitelist.load_from_database().unwrap().contains(&info_hash));
}

#[tokio::test]
async fn it_should_remove_a_torrent_from_the_whitelist() {
let whitelist_manager = initialize_whitelist_manager_for_whitelisted_tracker();
let (whitelist_manager, services) = initialize_whitelist_manager_for_whitelisted_tracker();

let info_hash = sample_info_hash();

whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap();

whitelist_manager.remove_torrent_from_whitelist(&info_hash).await.unwrap();

assert!(!whitelist_manager.is_info_hash_whitelisted(&info_hash).await);
assert!(!services.in_memory_whitelist.contains(&info_hash).await);
assert!(!services.database_whitelist.load_from_database().unwrap().contains(&info_hash));
}

mod persistence {
Expand All @@ -144,19 +146,15 @@ mod tests {

#[tokio::test]
async fn it_should_load_the_whitelist_from_the_database() {
let whitelist_manager = initialize_whitelist_manager_for_whitelisted_tracker();
let (whitelist_manager, services) = initialize_whitelist_manager_for_whitelisted_tracker();

let info_hash = sample_info_hash();

whitelist_manager.add_torrent_to_whitelist(&info_hash).await.unwrap();

whitelist_manager.remove_torrent_from_memory_whitelist(&info_hash).await;

assert!(!whitelist_manager.is_info_hash_whitelisted(&info_hash).await);
services.database_whitelist.add(&info_hash).unwrap();

whitelist_manager.load_whitelist_from_database().await.unwrap();

assert!(whitelist_manager.is_info_hash_whitelisted(&info_hash).await);
assert!(services.in_memory_whitelist.contains(&info_hash).await);
}
}
}
Expand Down
76 changes: 76 additions & 0 deletions packages/tracker-core/src/whitelist/repository/persisted.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,79 @@ impl DatabaseWhitelist {
self.database.load_whitelist()
}
}

#[cfg(test)]
mod tests {
mod the_persisted_whitelist_repository {

use crate::core_tests::{ephemeral_configuration_for_listed_tracker, sample_info_hash};
use crate::databases::setup::initialize_database;
use crate::whitelist::repository::persisted::DatabaseWhitelist;

fn initialize_database_whitelist() -> DatabaseWhitelist {
let configuration = ephemeral_configuration_for_listed_tracker();
let database = initialize_database(&configuration);
DatabaseWhitelist::new(database)
}

#[test]
fn should_add_a_new_infohash_to_the_list() {
let whitelist = initialize_database_whitelist();

let infohash = sample_info_hash();

let _result = whitelist.add(&infohash);

assert_eq!(whitelist.load_from_database().unwrap(), vec!(infohash));
}

#[test]
fn should_remove_a_infohash_from_the_list() {
let whitelist = initialize_database_whitelist();

let infohash = sample_info_hash();

let _result = whitelist.add(&infohash);

let _result = whitelist.remove(&infohash);

assert_eq!(whitelist.load_from_database().unwrap(), vec!());
}

#[test]
fn should_load_all_infohashes_from_the_database() {
let whitelist = initialize_database_whitelist();

let infohash = sample_info_hash();

let _result = whitelist.add(&infohash);

let result = whitelist.load_from_database().unwrap();

assert_eq!(result, vec!(infohash));
}

#[test]
fn should_not_add_the_same_infohash_to_the_list_twice() {
let whitelist = initialize_database_whitelist();

let infohash = sample_info_hash();

let _result = whitelist.add(&infohash);
let _result = whitelist.add(&infohash);

assert_eq!(whitelist.load_from_database().unwrap(), vec!(infohash));
}

#[test]
fn should_not_fail_removing_an_infohash_that_is_not_in_the_list() {
let whitelist = initialize_database_whitelist();

let infohash = sample_info_hash();

let result = whitelist.remove(&infohash);

assert!(result.is_ok());
}
}
}
1 change: 1 addition & 0 deletions src/bootstrap/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ pub fn initialize_app_container(configuration: &Configuration) -> AppContainer {
scrape_handler,
keys_handler,
authentication_service,
in_memory_whitelist,
whitelist_authorization,
ban_service,
http_stats_event_sender,
Expand Down
2 changes: 2 additions & 0 deletions src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use bittorrent_tracker_core::torrent::repository::in_memory::InMemoryTorrentRepo
use bittorrent_tracker_core::torrent::repository::persisted::DatabasePersistentTorrentRepository;
use bittorrent_tracker_core::whitelist;
use bittorrent_tracker_core::whitelist::manager::WhitelistManager;
use bittorrent_tracker_core::whitelist::repository::in_memory::InMemoryWhitelist;
use tokio::sync::RwLock;
use torrust_tracker_configuration::{Core, HttpApi, HttpTracker, UdpTracker};

Expand All @@ -23,6 +24,7 @@ pub struct AppContainer {
pub scrape_handler: Arc<ScrapeHandler>,
pub keys_handler: Arc<KeysHandler>,
pub authentication_service: Arc<AuthenticationService>,
pub in_memory_whitelist: Arc<InMemoryWhitelist>,
pub whitelist_authorization: Arc<whitelist::authorization::WhitelistAuthorization>,
pub ban_service: Arc<RwLock<BanService>>,
pub http_stats_event_sender: Arc<Option<Box<dyn http_tracker_core::statistics::event::sender::Sender>>>,
Expand Down
Loading