diff --git a/src/apis/mod.rs b/src/apis/mod.rs index c2ee0fc3..f2ec6ffb 100644 --- a/src/apis/mod.rs +++ b/src/apis/mod.rs @@ -1,2 +1,2 @@ -pub mod server; pub mod routes; +pub mod server; diff --git a/src/apis/server.rs b/src/apis/server.rs index 3bef7536..d42ae895 100644 --- a/src/apis/server.rs +++ b/src/apis/server.rs @@ -25,6 +25,8 @@ pub fn start_tls( _ssl_key_path: &str, _tracker: &Arc, ) -> impl Future> { + // todo: for the time being, it's just a copy & paste from start(...). + let app = Router::new().route("/", get(root)); let server = axum::Server::bind(&socket_addr).serve(app.into_make_service()); diff --git a/src/jobs/mod.rs b/src/jobs/mod.rs index a06e7d53..6f9b12ba 100644 --- a/src/jobs/mod.rs +++ b/src/jobs/mod.rs @@ -1,5 +1,5 @@ pub mod http_tracker; pub mod torrent_cleanup; pub mod tracker_api; -pub mod udp_tracker; pub mod tracker_apis; +pub mod udp_tracker; diff --git a/src/lib.rs b/src/lib.rs index 6edb96df..ebf589aa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,5 @@ pub mod api; +pub mod apis; pub mod config; pub mod databases; pub mod http; @@ -9,7 +10,6 @@ pub mod setup; pub mod stats; pub mod tracker; pub mod udp; -pub mod apis; #[macro_use] extern crate lazy_static; diff --git a/tests/api/asserts.rs b/tests/api/asserts.rs new file mode 100644 index 00000000..5d664d5c --- /dev/null +++ b/tests/api/asserts.rs @@ -0,0 +1,17 @@ +use reqwest::Response; + +pub async fn assert_token_not_valid(response: Response) { + assert_eq!(response.status(), 500); + assert_eq!( + response.text().await.unwrap(), + "Unhandled rejection: Err { reason: \"token not valid\" }" + ); +} + +pub async fn assert_unauthorized(response: Response) { + assert_eq!(response.status(), 500); + assert_eq!( + response.text().await.unwrap(), + "Unhandled rejection: Err { reason: \"unauthorized\" }" + ); +} diff --git a/tests/api/client.rs b/tests/api/client.rs new file mode 100644 index 00000000..e507d817 --- /dev/null +++ b/tests/api/client.rs @@ -0,0 +1,162 @@ +use reqwest::Response; + +use super::connection_info::ConnectionInfo; +use super::Version; + +pub struct Client { + connection_info: ConnectionInfo, + base_path: String, +} + +type ReqwestQuery = Vec; +type ReqwestQueryParam = (String, String); + +#[derive(Default, Debug)] +pub struct Query { + params: Vec, +} + +impl Query { + pub fn empty() -> Self { + Self { params: vec![] } + } + + pub fn params(params: Vec) -> Self { + Self { params } + } + + pub fn add_param(&mut self, param: QueryParam) { + self.params.push(param); + } + + fn with_token(token: &str) -> Self { + Self { + params: vec![QueryParam::new("token", token)], + } + } +} + +impl From for ReqwestQuery { + fn from(url_search_params: Query) -> Self { + url_search_params + .params + .iter() + .map(|param| ReqwestQueryParam::from((*param).clone())) + .collect() + } +} + +#[derive(Clone, Debug)] +pub struct QueryParam { + name: String, + value: String, +} + +impl QueryParam { + pub fn new(name: &str, value: &str) -> Self { + Self { + name: name.to_string(), + value: value.to_string(), + } + } +} + +impl From for ReqwestQueryParam { + fn from(param: QueryParam) -> Self { + (param.name, param.value) + } +} + +impl Client { + pub fn new(connection_info: ConnectionInfo, version: &Version) -> Self { + Self { + connection_info, + base_path: match version { + Version::Warp => "/api/".to_string(), + Version::Axum => "/".to_string(), + }, + } + } + + pub async fn generate_auth_key(&self, seconds_valid: i32) -> Response { + self.post(&format!("key/{}", &seconds_valid)).await + } + + pub async fn delete_auth_key(&self, key: &str) -> Response { + self.delete(&format!("key/{}", &key)).await + } + + pub async fn reload_keys(&self) -> Response { + self.get("keys/reload", Query::default()).await + } + + pub async fn whitelist_a_torrent(&self, info_hash: &str) -> Response { + self.post(&format!("whitelist/{}", &info_hash)).await + } + + pub async fn remove_torrent_from_whitelist(&self, info_hash: &str) -> Response { + self.delete(&format!("whitelist/{}", &info_hash)).await + } + + pub async fn reload_whitelist(&self) -> Response { + self.get("whitelist/reload", Query::default()).await + } + + pub async fn get_torrent(&self, info_hash: &str) -> Response { + self.get(&format!("torrent/{}", &info_hash), Query::default()).await + } + + pub async fn get_torrents(&self, params: Query) -> Response { + self.get("torrents", params).await + } + + pub async fn get_tracker_statistics(&self) -> Response { + self.get("stats", Query::default()).await + } + + pub async fn get(&self, path: &str, params: Query) -> Response { + let mut query: Query = params; + + if let Some(token) = &self.connection_info.api_token { + query.add_param(QueryParam::new("token", token)); + }; + + reqwest::Client::builder() + .build() + .unwrap() + .get(self.base_url(path)) + .query(&ReqwestQuery::from(query)) + .send() + .await + .unwrap() + } + + async fn post(&self, path: &str) -> Response { + reqwest::Client::new() + .post(self.base_url(path).clone()) + .query(&ReqwestQuery::from(self.query_with_token())) + .send() + .await + .unwrap() + } + + async fn delete(&self, path: &str) -> Response { + reqwest::Client::new() + .delete(self.base_url(path).clone()) + .query(&ReqwestQuery::from(self.query_with_token())) + .send() + .await + .unwrap() + } + + fn base_url(&self, path: &str) -> String { + format!("http://{}{}{path}", &self.connection_info.bind_address, &self.base_path) + } + + fn query_with_token(&self) -> Query { + match &self.connection_info.api_token { + Some(token) => Query::with_token(token), + None => Query::default(), + } + } +} diff --git a/tests/api/connection_info.rs b/tests/api/connection_info.rs new file mode 100644 index 00000000..35314a2f --- /dev/null +++ b/tests/api/connection_info.rs @@ -0,0 +1,29 @@ +pub fn connection_with_invalid_token(bind_address: &str) -> ConnectionInfo { + ConnectionInfo::authenticated(bind_address, "invalid token") +} + +pub fn connection_with_no_token(bind_address: &str) -> ConnectionInfo { + ConnectionInfo::anonymous(bind_address) +} + +#[derive(Clone)] +pub struct ConnectionInfo { + pub bind_address: String, + pub api_token: Option, +} + +impl ConnectionInfo { + pub fn authenticated(bind_address: &str, api_token: &str) -> Self { + Self { + bind_address: bind_address.to_string(), + api_token: Some(api_token.to_string()), + } + } + + pub fn anonymous(bind_address: &str) -> Self { + Self { + bind_address: bind_address.to_string(), + api_token: None, + } + } +} diff --git a/tests/api/fixtures.rs b/tests/api/fixtures.rs new file mode 100644 index 00000000..fa609930 --- /dev/null +++ b/tests/api/fixtures.rs @@ -0,0 +1,17 @@ +use std::net::{IpAddr, Ipv4Addr, SocketAddr}; + +use aquatic_udp_protocol::{AnnounceEvent, NumberOfBytes}; +use torrust_tracker::protocol::clock::DurationSinceUnixEpoch; +use torrust_tracker::tracker::peer; + +pub fn sample_peer() -> peer::Peer { + peer::Peer { + peer_id: peer::Id(*b"-qB00000000000000000"), + peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080), + updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), + uploaded: NumberOfBytes(0), + downloaded: NumberOfBytes(0), + left: NumberOfBytes(0), + event: AnnounceEvent::Started, + } +} diff --git a/tests/api/mod.rs b/tests/api/mod.rs index 49fde7a8..52980581 100644 --- a/tests/api/mod.rs +++ b/tests/api/mod.rs @@ -1,314 +1,10 @@ -use core::panic; -use std::env; -use std::net::{IpAddr, Ipv4Addr, SocketAddr}; -use std::sync::Arc; - -use aquatic_udp_protocol::{AnnounceEvent, NumberOfBytes}; -use reqwest::Response; -use torrust_tracker::config::Configuration; -use torrust_tracker::jobs::{tracker_api, tracker_apis}; -use torrust_tracker::protocol::clock::DurationSinceUnixEpoch; -use torrust_tracker::protocol::info_hash::InfoHash; -use torrust_tracker::tracker::peer::{self, Peer}; -use torrust_tracker::tracker::statistics::Keeper; -use torrust_tracker::{ephemeral_instance_keys, logging, static_time, tracker}; - -use crate::common::ephemeral_random_port; - -pub fn sample_peer() -> peer::Peer { - peer::Peer { - peer_id: peer::Id(*b"-qB00000000000000000"), - peer_addr: SocketAddr::new(IpAddr::V4(Ipv4Addr::new(126, 0, 0, 1)), 8080), - updated: DurationSinceUnixEpoch::new(1_669_397_478_934, 0), - uploaded: NumberOfBytes(0), - downloaded: NumberOfBytes(0), - left: NumberOfBytes(0), - event: AnnounceEvent::Started, - } -} - -pub fn tracker_configuration() -> Arc { - let mut config = Configuration { - log_level: Some("off".to_owned()), - ..Default::default() - }; - - // Ephemeral socket address - let port = ephemeral_random_port(); - config.http_api.bind_address = format!("127.0.0.1:{}", &port); - - // Ephemeral database - let temp_directory = env::temp_dir(); - let temp_file = temp_directory.join(format!("data_{}.db", &port)); - config.db_path = temp_file.to_str().unwrap().to_owned(); - - Arc::new(config) -} - -#[derive(Clone)] -pub struct ConnectionInfo { - pub bind_address: String, - pub api_token: Option, -} - -impl ConnectionInfo { - pub fn authenticated(bind_address: &str, api_token: &str) -> Self { - Self { - bind_address: bind_address.to_string(), - api_token: Some(api_token.to_string()), - } - } - - pub fn anonymous(bind_address: &str) -> Self { - Self { - bind_address: bind_address.to_string(), - api_token: None, - } - } -} - -pub async fn start_default_api_server(version: &Version) -> Server { - let configuration = tracker_configuration(); - start_custom_api_server(configuration.clone(), version).await -} - -pub async fn start_custom_api_server(configuration: Arc, version: &Version) -> Server { - match &version { - Version::Warp => start_warp_api(configuration).await, - Version::Axum => start_axum_api(configuration).await, - } -} - -async fn start_warp_api(configuration: Arc) -> Server { - let server = start(&configuration); - - // Start the HTTP API job - tracker_api::start_job(&configuration.http_api, server.tracker.clone()).await; - - server -} - -async fn start_axum_api(configuration: Arc) -> Server { - let server = start(&configuration); - - // Start HTTP APIs server (multiple API versions) - // Temporarily run the new API on a port number after the current API port - tracker_apis::start_job(&configuration.http_api, server.tracker.clone()).await; - - server -} - -fn start(configuration: &Arc) -> Server { - let connection_info = ConnectionInfo::authenticated( - &configuration.http_api.bind_address.clone(), - &configuration.http_api.access_tokens.get_key_value("admin").unwrap().1.clone(), - ); - - // Set the time of Torrust app starting - lazy_static::initialize(&static_time::TIME_AT_APP_START); - - // Initialize the Ephemeral Instance Random Seed - lazy_static::initialize(&ephemeral_instance_keys::RANDOM_SEED); - - // Initialize stats tracker - let (stats_event_sender, stats_repository) = Keeper::new_active_instance(); - - // Initialize Torrust tracker - let tracker = match tracker::Tracker::new(configuration, Some(stats_event_sender), stats_repository) { - Ok(tracker) => Arc::new(tracker), - Err(error) => { - panic!("{}", error) - } - }; - - // Initialize logging - logging::setup(configuration); - - Server { - tracker, - connection_info, - } -} - -pub struct Server { - pub tracker: Arc, - pub connection_info: ConnectionInfo, -} - -impl Server { - pub fn get_connection_info(&self) -> ConnectionInfo { - self.connection_info.clone() - } - - pub fn get_bind_address(&self) -> String { - self.connection_info.bind_address.clone() - } - - /// Add a torrent to the tracker - pub async fn add_torrent(&self, info_hash: &InfoHash, peer: &Peer) { - self.tracker.update_torrent_with_peer_and_get_stats(info_hash, peer).await; - } -} - -pub struct Client { - connection_info: ConnectionInfo, - base_path: String, -} - -type ReqwestQuery = Vec; -type ReqwestQueryParam = (String, String); - -#[derive(Default, Debug)] -pub struct Query { - params: Vec, -} - -impl Query { - pub fn empty() -> Self { - Self { params: vec![] } - } - - pub fn params(params: Vec) -> Self { - Self { params } - } - - pub fn add_param(&mut self, param: QueryParam) { - self.params.push(param); - } - - fn with_token(token: &str) -> Self { - Self { - params: vec![QueryParam::new("token", token)], - } - } -} - -impl From for ReqwestQuery { - fn from(url_search_params: Query) -> Self { - url_search_params - .params - .iter() - .map(|param| ReqwestQueryParam::from((*param).clone())) - .collect() - } -} - -#[derive(Clone, Debug)] -pub struct QueryParam { - name: String, - value: String, -} - -impl QueryParam { - pub fn new(name: &str, value: &str) -> Self { - Self { - name: name.to_string(), - value: value.to_string(), - } - } -} - -impl From for ReqwestQueryParam { - fn from(param: QueryParam) -> Self { - (param.name, param.value) - } -} +pub mod asserts; +pub mod client; +pub mod connection_info; +pub mod fixtures; +pub mod server; pub enum Version { Warp, Axum, } - -impl Client { - pub fn new(connection_info: ConnectionInfo, version: &Version) -> Self { - Self { - connection_info, - base_path: match version { - Version::Warp => "/api/".to_string(), - Version::Axum => String::new(), - }, - } - } - - pub async fn generate_auth_key(&self, seconds_valid: i32) -> Response { - self.post(&format!("key/{}", &seconds_valid)).await - } - - pub async fn delete_auth_key(&self, key: &str) -> Response { - self.delete(&format!("key/{}", &key)).await - } - - pub async fn reload_keys(&self) -> Response { - self.get("keys/reload", Query::default()).await - } - - pub async fn whitelist_a_torrent(&self, info_hash: &str) -> Response { - self.post(&format!("whitelist/{}", &info_hash)).await - } - - pub async fn remove_torrent_from_whitelist(&self, info_hash: &str) -> Response { - self.delete(&format!("whitelist/{}", &info_hash)).await - } - - pub async fn reload_whitelist(&self) -> Response { - self.get("whitelist/reload", Query::default()).await - } - - pub async fn get_torrent(&self, info_hash: &str) -> Response { - self.get(&format!("torrent/{}", &info_hash), Query::default()).await - } - - pub async fn get_torrents(&self, params: Query) -> Response { - self.get("torrents", params).await - } - - pub async fn get_tracker_statistics(&self) -> Response { - self.get("stats", Query::default()).await - } - - pub async fn get(&self, path: &str, params: Query) -> Response { - let mut query: Query = params; - - if let Some(token) = &self.connection_info.api_token { - query.add_param(QueryParam::new("token", token)); - }; - - reqwest::Client::builder() - .build() - .unwrap() - .get(self.base_url(path)) - .query(&ReqwestQuery::from(query)) - .send() - .await - .unwrap() - } - - async fn post(&self, path: &str) -> Response { - reqwest::Client::new() - .post(self.base_url(path).clone()) - .query(&ReqwestQuery::from(self.query_with_token())) - .send() - .await - .unwrap() - } - - async fn delete(&self, path: &str) -> Response { - reqwest::Client::new() - .delete(self.base_url(path).clone()) - .query(&ReqwestQuery::from(self.query_with_token())) - .send() - .await - .unwrap() - } - - fn base_url(&self, path: &str) -> String { - format!("http://{}{}{path}", &self.connection_info.bind_address, &self.base_path) - } - - fn query_with_token(&self) -> Query { - match &self.connection_info.api_token { - Some(token) => Query::with_token(token), - None => Query::default(), - } - } -} diff --git a/tests/api/server.rs b/tests/api/server.rs new file mode 100644 index 00000000..338b068c --- /dev/null +++ b/tests/api/server.rs @@ -0,0 +1,115 @@ +use core::panic; +use std::env; +use std::sync::Arc; + +use torrust_tracker::config::Configuration; +use torrust_tracker::jobs::{tracker_api, tracker_apis}; +use torrust_tracker::protocol::info_hash::InfoHash; +use torrust_tracker::tracker::peer::Peer; +use torrust_tracker::tracker::statistics::Keeper; +use torrust_tracker::{ephemeral_instance_keys, logging, static_time, tracker}; + +use super::connection_info::ConnectionInfo; +use super::Version; +use crate::common::ephemeral_random_port; + +pub fn tracker_configuration() -> Arc { + let mut config = Configuration { + log_level: Some("off".to_owned()), + ..Default::default() + }; + + // Ephemeral socket address + let port = ephemeral_random_port(); + config.http_api.bind_address = format!("127.0.0.1:{}", &port); + + // Ephemeral database + let temp_directory = env::temp_dir(); + let temp_file = temp_directory.join(format!("data_{}.db", &port)); + config.db_path = temp_file.to_str().unwrap().to_owned(); + + Arc::new(config) +} + +pub async fn start_default_api(version: &Version) -> Server { + let configuration = tracker_configuration(); + start_custom_api(configuration.clone(), version).await +} + +pub async fn start_custom_api(configuration: Arc, version: &Version) -> Server { + match &version { + Version::Warp => start_warp_api(configuration).await, + Version::Axum => start_axum_api(configuration).await, + } +} + +async fn start_warp_api(configuration: Arc) -> Server { + let server = start(&configuration); + + // Start the HTTP API job + tracker_api::start_job(&configuration.http_api, server.tracker.clone()).await; + + server +} + +async fn start_axum_api(configuration: Arc) -> Server { + let server = start(&configuration); + + // Start HTTP APIs server (multiple API versions) + // Temporarily run the new API on a port number after the current API port + tracker_apis::start_job(&configuration.http_api, server.tracker.clone()).await; + + server +} + +fn start(configuration: &Arc) -> Server { + let connection_info = ConnectionInfo::authenticated( + &configuration.http_api.bind_address.clone(), + &configuration.http_api.access_tokens.get_key_value("admin").unwrap().1.clone(), + ); + + // Set the time of Torrust app starting + lazy_static::initialize(&static_time::TIME_AT_APP_START); + + // Initialize the Ephemeral Instance Random Seed + lazy_static::initialize(&ephemeral_instance_keys::RANDOM_SEED); + + // Initialize stats tracker + let (stats_event_sender, stats_repository) = Keeper::new_active_instance(); + + // Initialize Torrust tracker + let tracker = match tracker::Tracker::new(configuration, Some(stats_event_sender), stats_repository) { + Ok(tracker) => Arc::new(tracker), + Err(error) => { + panic!("{}", error) + } + }; + + // Initialize logging + logging::setup(configuration); + + Server { + tracker, + connection_info, + } +} + +pub struct Server { + pub tracker: Arc, + pub connection_info: ConnectionInfo, +} + +impl Server { + pub fn get_connection_info(&self) -> ConnectionInfo { + self.connection_info.clone() + } + + pub fn get_bind_address(&self) -> String { + self.connection_info.bind_address.clone() + } + + /// Add a torrent to the tracker + pub async fn add_torrent(&self, info_hash: &InfoHash, peer: &Peer) { + self.tracker.update_torrent_with_peer_and_get_stats(info_hash, peer).await; + } +} diff --git a/tests/tracker_api.rs b/tests/tracker_api.rs index 68a295ac..5f022167 100644 --- a/tests/tracker_api.rs +++ b/tests/tracker_api.rs @@ -43,47 +43,22 @@ mod tracker_api { */ - use reqwest::Response; - - use crate::api::ConnectionInfo; - - async fn assert_token_not_valid(response: Response) { - assert_eq!(response.status(), 500); - assert_eq!( - response.text().await.unwrap(), - "Unhandled rejection: Err { reason: \"token not valid\" }" - ); - } - - async fn assert_unauthorized(response: Response) { - assert_eq!(response.status(), 500); - assert_eq!( - response.text().await.unwrap(), - "Unhandled rejection: Err { reason: \"unauthorized\" }" - ); - } - - fn connection_with_invalid_token(bind_address: &str) -> ConnectionInfo { - ConnectionInfo::authenticated(bind_address, "invalid token") - } - - fn connection_with_no_token(bind_address: &str) -> ConnectionInfo { - ConnectionInfo::anonymous(bind_address) - } - mod for_stats_resources { use std::str::FromStr; use torrust_tracker::api::resource::stats::Stats; use torrust_tracker::protocol::info_hash::InfoHash; - use super::{connection_with_invalid_token, connection_with_no_token}; - use crate::api::{sample_peer, start_default_api_server, Client, Version}; - use crate::tracker_api::{assert_token_not_valid, assert_unauthorized}; + use crate::api::asserts::{assert_token_not_valid, assert_unauthorized}; + use crate::api::client::Client; + use crate::api::connection_info::{connection_with_invalid_token, connection_with_no_token}; + use crate::api::fixtures::sample_peer; + use crate::api::server::start_default_api; + use crate::api::Version; #[tokio::test] async fn should_allow_getting_tracker_statistics() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; api_server .add_torrent( @@ -122,7 +97,7 @@ mod tracker_api { #[tokio::test] async fn should_not_allow_getting_tracker_statistics_for_unauthenticated_users() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let response = Client::new(connection_with_invalid_token(&api_server.get_bind_address()), &Version::Warp) .get_tracker_statistics() @@ -145,13 +120,16 @@ mod tracker_api { use torrust_tracker::api::resource::torrent::{self, Torrent}; use torrust_tracker::protocol::info_hash::InfoHash; - use super::{connection_with_invalid_token, connection_with_no_token}; - use crate::api::{sample_peer, start_default_api_server, Client, Query, QueryParam, Version}; - use crate::tracker_api::{assert_token_not_valid, assert_unauthorized}; + use crate::api::asserts::{assert_token_not_valid, assert_unauthorized}; + use crate::api::client::{Client, Query, QueryParam}; + use crate::api::connection_info::{connection_with_invalid_token, connection_with_no_token}; + use crate::api::fixtures::sample_peer; + use crate::api::server::start_default_api; + use crate::api::Version; #[tokio::test] async fn should_allow_getting_torrents() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let info_hash = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); @@ -176,7 +154,7 @@ mod tracker_api { #[tokio::test] async fn should_allow_limiting_the_torrents_in_the_result() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; // torrents are ordered alphabetically by infohashes let info_hash_1 = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); @@ -204,7 +182,7 @@ mod tracker_api { #[tokio::test] async fn should_allow_the_torrents_result_pagination() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; // torrents are ordered alphabetically by infohashes let info_hash_1 = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); @@ -232,7 +210,7 @@ mod tracker_api { #[tokio::test] async fn should_not_allow_getting_torrents_for_unauthenticated_users() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let response = Client::new(connection_with_invalid_token(&api_server.get_bind_address()), &Version::Warp) .get_torrents(Query::empty()) @@ -249,7 +227,7 @@ mod tracker_api { #[tokio::test] async fn should_allow_getting_a_torrent_info() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let info_hash = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); @@ -276,7 +254,7 @@ mod tracker_api { #[tokio::test] async fn should_not_allow_getting_a_torrent_info_for_unauthenticated_users() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let info_hash = InfoHash::from_str("9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d").unwrap(); @@ -301,13 +279,15 @@ mod tracker_api { use torrust_tracker::protocol::info_hash::InfoHash; - use super::{assert_token_not_valid, connection_with_invalid_token, connection_with_no_token}; - use crate::api::{start_default_api_server, Client, Version}; - use crate::tracker_api::assert_unauthorized; + use crate::api::asserts::{assert_token_not_valid, assert_unauthorized}; + use crate::api::client::Client; + use crate::api::connection_info::{connection_with_invalid_token, connection_with_no_token}; + use crate::api::server::start_default_api; + use crate::api::Version; #[tokio::test] async fn should_allow_whitelisting_a_torrent() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let info_hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); @@ -326,7 +306,7 @@ mod tracker_api { #[tokio::test] async fn should_allow_whitelisting_a_torrent_that_has_been_already_whitelisted() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let info_hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); @@ -341,7 +321,7 @@ mod tracker_api { #[tokio::test] async fn should_not_allow_whitelisting_a_torrent_for_unauthenticated_users() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let info_hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); @@ -360,7 +340,7 @@ mod tracker_api { #[tokio::test] async fn should_allow_removing_a_torrent_from_the_whitelist() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash = InfoHash::from_str(&hash).unwrap(); @@ -376,7 +356,7 @@ mod tracker_api { #[tokio::test] async fn should_not_allow_removing_a_torrent_from_the_whitelist_for_unauthenticated_users() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash = InfoHash::from_str(&hash).unwrap(); @@ -398,7 +378,7 @@ mod tracker_api { #[tokio::test] async fn should_allow_reload_the_whitelist_from_the_database() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let hash = "9e0217d0fa71c87332cd8bf9dbeabcb2c2cf3c4d".to_owned(); let info_hash = InfoHash::from_str(&hash).unwrap(); @@ -428,13 +408,15 @@ mod tracker_api { use torrust_tracker::api::resource::auth_key::AuthKey; use torrust_tracker::tracker::auth::Key; - use super::{connection_with_invalid_token, connection_with_no_token}; - use crate::api::{start_default_api_server, Client, Version}; - use crate::tracker_api::{assert_token_not_valid, assert_unauthorized}; + use crate::api::asserts::{assert_token_not_valid, assert_unauthorized}; + use crate::api::client::Client; + use crate::api::connection_info::{connection_with_invalid_token, connection_with_no_token}; + use crate::api::server::start_default_api; + use crate::api::Version; #[tokio::test] async fn should_allow_generating_a_new_auth_key() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let seconds_valid = 60; @@ -452,7 +434,7 @@ mod tracker_api { #[tokio::test] async fn should_not_allow_generating_a_new_auth_key_for_unauthenticated_users() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let seconds_valid = 60; @@ -471,7 +453,7 @@ mod tracker_api { #[tokio::test] async fn should_allow_deleting_an_auth_key() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let seconds_valid = 60; let auth_key = api_server @@ -490,7 +472,7 @@ mod tracker_api { #[tokio::test] async fn should_not_allow_deleting_an_auth_key_for_unauthenticated_users() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let seconds_valid = 60; @@ -523,7 +505,7 @@ mod tracker_api { #[tokio::test] async fn should_allow_reloading_keys() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let seconds_valid = 60; api_server @@ -541,7 +523,7 @@ mod tracker_api { #[tokio::test] async fn should_not_allow_reloading_keys_for_unauthenticated_users() { - let api_server = start_default_api_server(&Version::Warp).await; + let api_server = start_default_api(&Version::Warp).await; let seconds_valid = 60; api_server @@ -565,13 +547,14 @@ mod tracker_api { } } +/// The new API implementation using Axum mod tracker_apis { /* Endpoints: - Root: + Root (dummy endpoint to test Axum configuration. To be removed): - [x] GET / Stats: @@ -598,7 +581,9 @@ mod tracker_apis { */ mod for_entrypoint { - use crate::api::{start_default_api_server, Client, Query, Version}; + use crate::api::client::{Client, Query}; + use crate::api::server::start_default_api_server; + use crate::api::Version; #[tokio::test] async fn test_entrypoint() {