Skip to content

Commit

Permalink
refactor: [#157] extract API context: whitelist
Browse files Browse the repository at this point in the history
  • Loading branch information
josecelano committed Mar 10, 2023
1 parent f1b3d84 commit 996dffd
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 74 deletions.
1 change: 1 addition & 0 deletions src/apis/context/mod.rs
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pub mod auth_key;
pub mod stats;
pub mod whitelist;
46 changes: 46 additions & 0 deletions src/apis/context/whitelist/handlers.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use std::str::FromStr;
use std::sync::Arc;

use axum::extract::{Path, State};
use axum::response::Response;

use super::responses::{
failed_to_reload_whitelist_response, failed_to_remove_torrent_from_whitelist_response, failed_to_whitelist_torrent_response,
};
use crate::apis::responses::{invalid_info_hash_param_response, ok_response};
use crate::apis::InfoHashParam;
use crate::protocol::info_hash::InfoHash;
use crate::tracker::Tracker;

pub async fn add_torrent_to_whitelist_handler(
State(tracker): State<Arc<Tracker>>,
Path(info_hash): Path<InfoHashParam>,
) -> Response {
match InfoHash::from_str(&info_hash.0) {
Err(_) => invalid_info_hash_param_response(&info_hash.0),
Ok(info_hash) => match tracker.add_torrent_to_whitelist(&info_hash).await {
Ok(_) => ok_response(),
Err(e) => failed_to_whitelist_torrent_response(e),
},
}
}

pub async fn remove_torrent_from_whitelist_handler(
State(tracker): State<Arc<Tracker>>,
Path(info_hash): Path<InfoHashParam>,
) -> Response {
match InfoHash::from_str(&info_hash.0) {
Err(_) => invalid_info_hash_param_response(&info_hash.0),
Ok(info_hash) => match tracker.remove_torrent_from_whitelist(&info_hash).await {
Ok(_) => ok_response(),
Err(e) => failed_to_remove_torrent_from_whitelist_response(e),
},
}
}

pub async fn reload_whitelist_handler(State(tracker): State<Arc<Tracker>>) -> Response {
match tracker.load_whitelist_from_database().await {
Ok(_) => ok_response(),
Err(e) => failed_to_reload_whitelist_response(e),
}
}
3 changes: 3 additions & 0 deletions src/apis/context/whitelist/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pub mod handlers;
pub mod responses;
pub mod routes;
20 changes: 20 additions & 0 deletions src/apis/context/whitelist/responses.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use std::error::Error;

use axum::response::Response;

use crate::apis::responses::unhandled_rejection_response;

#[must_use]
pub fn failed_to_remove_torrent_from_whitelist_response<E: Error>(e: E) -> Response {
unhandled_rejection_response(format!("failed to remove torrent from whitelist: {e}"))
}

#[must_use]
pub fn failed_to_whitelist_torrent_response<E: Error>(e: E) -> Response {
unhandled_rejection_response(format!("failed to whitelist torrent: {e}"))
}

#[must_use]
pub fn failed_to_reload_whitelist_response<E: Error>(e: E) -> Response {
unhandled_rejection_response(format!("failed to reload whitelist: {e}"))
}
22 changes: 22 additions & 0 deletions src/apis/context/whitelist/routes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use std::sync::Arc;

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::tracker::Tracker;

pub fn add(router: Router, tracker: Arc<Tracker>) -> Router {
router
// Whitelisted torrents
.route(
"/api/whitelist/:info_hash",
post(add_torrent_to_whitelist_handler).with_state(tracker.clone()),
)
.route(
"/api/whitelist/:info_hash",
delete(remove_torrent_from_whitelist_handler).with_state(tracker.clone()),
)
// Whitelist commands
.route("/api/whitelist/reload", get(reload_whitelist_handler).with_state(tracker))
}
38 changes: 2 additions & 36 deletions src/apis/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@ use axum::response::{IntoResponse, Json, Response};
use serde::{de, Deserialize, Deserializer};

use super::responses::{
failed_to_reload_whitelist_response, failed_to_remove_torrent_from_whitelist_response, failed_to_whitelist_torrent_response,
invalid_info_hash_param_response, ok_response, torrent_info_response, torrent_list_response, torrent_not_known_response,
invalid_info_hash_param_response, torrent_info_response, torrent_list_response, torrent_not_known_response,
};
use crate::apis::resources::torrent::ListItem;
use crate::protocol::info_hash::InfoHash;
use crate::tracker::services::torrent::{get_torrent_info, get_torrents, Pagination};
use crate::tracker::Tracker;

#[derive(Deserialize)]
pub struct InfoHashParam(String);
pub struct InfoHashParam(pub String);

pub async fn get_torrent_handler(State(tracker): State<Arc<Tracker>>, Path(info_hash): Path<InfoHashParam>) -> Response {
match InfoHash::from_str(&info_hash.0) {
Expand Down Expand Up @@ -48,39 +47,6 @@ pub async fn get_torrents_handler(
)
}

pub async fn add_torrent_to_whitelist_handler(
State(tracker): State<Arc<Tracker>>,
Path(info_hash): Path<InfoHashParam>,
) -> Response {
match InfoHash::from_str(&info_hash.0) {
Err(_) => invalid_info_hash_param_response(&info_hash.0),
Ok(info_hash) => match tracker.add_torrent_to_whitelist(&info_hash).await {
Ok(_) => ok_response(),
Err(e) => failed_to_whitelist_torrent_response(e),
},
}
}

pub async fn remove_torrent_from_whitelist_handler(
State(tracker): State<Arc<Tracker>>,
Path(info_hash): Path<InfoHashParam>,
) -> Response {
match InfoHash::from_str(&info_hash.0) {
Err(_) => invalid_info_hash_param_response(&info_hash.0),
Ok(info_hash) => match tracker.remove_torrent_from_whitelist(&info_hash).await {
Ok(_) => ok_response(),
Err(e) => failed_to_remove_torrent_from_whitelist_response(e),
},
}
}

pub async fn reload_whitelist_handler(State(tracker): State<Arc<Tracker>>) -> Response {
match tracker.load_whitelist_from_database().await {
Ok(_) => ok_response(),
Err(e) => failed_to_reload_whitelist_response(e),
}
}

/// Serde deserialization decorator to map empty Strings to None,
fn empty_string_as_none<'de, D, T>(de: D) -> Result<Option<T>, D::Error>
where
Expand Down
17 changes: 0 additions & 17 deletions src/apis/responses.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
use std::error::Error;

use axum::http::{header, StatusCode};
use axum::response::{IntoResponse, Json, Response};
use serde::Serialize;
Expand Down Expand Up @@ -88,21 +86,6 @@ pub fn torrent_not_known_response() -> Response {
Json(json!("torrent not known")).into_response()
}

#[must_use]
pub fn failed_to_remove_torrent_from_whitelist_response<E: Error>(e: E) -> Response {
unhandled_rejection_response(format!("failed to remove torrent from whitelist: {e}"))
}

#[must_use]
pub fn failed_to_whitelist_torrent_response<E: Error>(e: E) -> Response {
unhandled_rejection_response(format!("failed to whitelist torrent: {e}"))
}

#[must_use]
pub fn failed_to_reload_whitelist_response<E: Error>(e: E) -> Response {
unhandled_rejection_response(format!("failed to reload whitelist: {e}"))
}

/// This error response is to keep backward compatibility with the old API.
/// It should be a plain text or json.
#[must_use]
Expand Down
26 changes: 5 additions & 21 deletions src/apis/routes.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
use std::sync::Arc;

use axum::routing::{delete, get, post};
use axum::routing::get;
use axum::{middleware, Router};

use super::context::{auth_key, stats};
use super::handlers::{
add_torrent_to_whitelist_handler, get_torrent_handler, get_torrents_handler, reload_whitelist_handler,
remove_torrent_from_whitelist_handler,
};
use super::context::{auth_key, stats, whitelist};
use super::handlers::{get_torrent_handler, get_torrents_handler};
use super::middlewares::auth::auth;
use crate::tracker::Tracker;

#[allow(clippy::needless_pass_by_value)]
pub fn router(tracker: Arc<Tracker>) -> Router {
let router = Router::new();

let router = stats::routes::add(router, tracker.clone());
let router = auth_key::routes::add(router, tracker.clone());
let router = stats::routes::add(router, tracker.clone());
let router = whitelist::routes::add(router, tracker.clone());

// Torrents
router
Expand All @@ -25,19 +23,5 @@ pub fn router(tracker: Arc<Tracker>) -> Router {
get(get_torrent_handler).with_state(tracker.clone()),
)
.route("/api/torrents", get(get_torrents_handler).with_state(tracker.clone()))
// Whitelisted torrents
.route(
"/api/whitelist/:info_hash",
post(add_torrent_to_whitelist_handler).with_state(tracker.clone()),
)
.route(
"/api/whitelist/:info_hash",
delete(remove_torrent_from_whitelist_handler).with_state(tracker.clone()),
)
// Whitelist command
.route(
"/api/whitelist/reload",
get(reload_whitelist_handler).with_state(tracker.clone()),
)
.layer(middleware::from_fn_with_state(tracker.config.clone(), auth))
}

0 comments on commit 996dffd

Please sign in to comment.