Skip to content

Commit

Permalink
refactor: [torrust#979] finished. Move logic from handler to domain s…
Browse files Browse the repository at this point in the history
…ervice
  • Loading branch information
josecelano committed Jul 31, 2024
1 parent adcea24 commit b9ec3c7
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 55 deletions.
23 changes: 18 additions & 5 deletions src/core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,6 @@ use self::auth::Key;
use self::error::Error;
use self::torrent::Torrents;
use crate::core::databases::Database;
use crate::servers::apis::v1::context::auth_key::forms::AddKeyForm;
use crate::CurrentClock;

/// The domain layer tracker service.
Expand Down Expand Up @@ -559,6 +558,20 @@ impl ScrapeData {
}
}

/// This type contains the info needed to add a new tracker key.
///
/// You can upload a pre-generated key or let the app to generate a new one.
/// You can also set an expiration date or leave it empty (`None`) if you want
/// to create a permanent key that does not expire.
#[derive(Debug)]
pub struct AddKeyRequest {
/// The pre-generated key. Use `None` to generate a random key.
pub opt_key: Option<String>,

/// How long the key will be valid in seconds. Use `None` for permanent keys.
pub opt_seconds_valid: Option<u64>,
}

impl Tracker {
/// `Tracker` constructor.
///
Expand Down Expand Up @@ -807,13 +820,13 @@ impl Tracker {
/// - The key duration overflows the duration type maximum value.
/// - The provided pre-generated key is invalid.
/// - The key could not been persisted due to database issues.
pub async fn add_peer_key(&self, add_key_form: AddKeyForm) -> Result<auth::PeerKey, PeerKeyError> {
pub async fn add_peer_key(&self, add_key_req: AddKeyRequest) -> Result<auth::PeerKey, PeerKeyError> {
// code-review: all methods related to keys should be moved to a new independent "keys" service.

match add_key_form.opt_key {
match add_key_req.opt_key {
// Upload pre-generated key
Some(pre_existing_key) => {
if let Some(seconds_valid) = add_key_form.opt_seconds_valid {
if let Some(seconds_valid) = add_key_req.opt_seconds_valid {
// Expiring key
let Some(valid_until) = CurrentClock::now_add(&Duration::from_secs(seconds_valid)) else {
return Err(PeerKeyError::DurationOverflow { seconds_valid });
Expand Down Expand Up @@ -852,7 +865,7 @@ impl Tracker {
}
}
// Generate a new random key
None => match add_key_form.opt_seconds_valid {
None => match add_key_req.opt_seconds_valid {
// Expiring key
Some(seconds_valid) => match self.generate_auth_key(Some(Duration::from_secs(seconds_valid))).await {
Ok(auth_key) => Ok(auth_key),
Expand Down
63 changes: 16 additions & 47 deletions src/servers/apis/v1/context/auth_key/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,16 @@ use std::time::Duration;
use axum::extract::{self, Path, State};
use axum::response::Response;
use serde::Deserialize;
use torrust_tracker_clock::clock::Time;

use super::forms::AddKeyForm;
use super::responses::{
auth_key_response, failed_to_add_key_response, failed_to_delete_key_response, failed_to_generate_key_response,
failed_to_reload_keys_response, invalid_auth_key_duration_response, invalid_auth_key_response,
auth_key_response, failed_to_delete_key_response, failed_to_generate_key_response, failed_to_reload_keys_response,
invalid_auth_key_duration_response, invalid_auth_key_response,
};
use crate::core::auth::Key;
use crate::core::Tracker;
use crate::core::{AddKeyRequest, Tracker};
use crate::servers::apis::v1::context::auth_key::resources::AuthKey;
use crate::servers::apis::v1::responses::{invalid_auth_key_param_response, ok_response};
use crate::CurrentClock;

/// It handles the request to add a new authentication key.
///
Expand All @@ -36,49 +34,20 @@ pub async fn add_auth_key_handler(
State(tracker): State<Arc<Tracker>>,
extract::Json(add_key_form): extract::Json<AddKeyForm>,
) -> Response {
match add_key_form.opt_key {
// Upload pre-generated key
Some(pre_existing_key) => {
if let Some(seconds_valid) = add_key_form.opt_seconds_valid {
// Expiring key
let Some(valid_until) = CurrentClock::now_add(&Duration::from_secs(seconds_valid)) else {
return invalid_auth_key_duration_response(seconds_valid);
};

let key = pre_existing_key.parse::<Key>();

match key {
Ok(key) => match tracker.add_auth_key(key, Some(valid_until)).await {
Ok(auth_key) => auth_key_response(&AuthKey::from(auth_key)),
Err(e) => failed_to_add_key_response(e),
},
Err(e) => invalid_auth_key_response(&pre_existing_key, &e),
}
} else {
// Permanent key
let key = pre_existing_key.parse::<Key>();

match key {
Ok(key) => match tracker.add_permanent_auth_key(key).await {
Ok(auth_key) => auth_key_response(&AuthKey::from(auth_key)),
Err(e) => failed_to_add_key_response(e),
},
Err(e) => invalid_auth_key_response(&pre_existing_key, &e),
}
match tracker
.add_peer_key(AddKeyRequest {
opt_key: add_key_form.opt_key.clone(),
opt_seconds_valid: add_key_form.opt_seconds_valid,
})
.await
{
Ok(auth_key) => auth_key_response(&AuthKey::from(auth_key)),
Err(err) => match err {
crate::core::error::PeerKeyError::DurationOverflow { seconds_valid } => {
invalid_auth_key_duration_response(seconds_valid)
}
}
// Generate a new random key
None => match add_key_form.opt_seconds_valid {
// Expiring key
Some(seconds_valid) => match tracker.generate_auth_key(Some(Duration::from_secs(seconds_valid))).await {
Ok(auth_key) => auth_key_response(&AuthKey::from(auth_key)),
Err(e) => failed_to_generate_key_response(e),
},
// Permanent key
None => match tracker.generate_permanent_auth_key().await {
Ok(auth_key) => auth_key_response(&AuthKey::from(auth_key)),
Err(e) => failed_to_generate_key_response(e),
},
crate::core::error::PeerKeyError::InvalidKey { key, source } => invalid_auth_key_response(&key, source),
crate::core::error::PeerKeyError::DatabaseError { source } => failed_to_generate_key_response(source),
},
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/servers/apis/v1/context/auth_key/responses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ use std::error::Error;
use axum::http::{header, StatusCode};
use axum::response::{IntoResponse, Response};

use crate::core::auth::ParseKeyError;
use crate::servers::apis::v1::context::auth_key::resources::AuthKey;
use crate::servers::apis::v1::responses::{bad_request_response, unhandled_rejection_response};

Expand Down Expand Up @@ -51,8 +50,8 @@ pub fn failed_to_reload_keys_response<E: Error>(e: E) -> Response {
}

#[must_use]
pub fn invalid_auth_key_response(auth_key: &str, error: &ParseKeyError) -> Response {
bad_request_response(&format!("Invalid URL: invalid auth key: string \"{auth_key}\", {error}"))
pub fn invalid_auth_key_response<E: Error>(auth_key: &str, e: E) -> Response {
bad_request_response(&format!("Invalid URL: invalid auth key: string \"{auth_key}\", {e}"))
}

#[must_use]
Expand Down

0 comments on commit b9ec3c7

Please sign in to comment.