Skip to content

Commit

Permalink
feat: [#978] add semantic validation for configuration
Browse files Browse the repository at this point in the history
The section [core.provate_mode] can be inlcuded in the configration TOML
file only if the tracker is running in private mode (`private = true`).

This commits adds that validation and makes it possible to add more
semantic validations in the future.

Semantic validations are validations that depend on more than one value.
Like the one added, it could be any other incompatible combination.
  • Loading branch information
josecelano committed Aug 1, 2024
1 parent e8e935c commit d7dfc3b
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 1 deletion.
1 change: 1 addition & 0 deletions packages/configuration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
//!
//! The current version for configuration is [`v2`].
pub mod v2;
pub mod validator;

use std::collections::HashMap;
use std::env;
Expand Down
11 changes: 11 additions & 0 deletions packages/configuration/src/v2/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize};

use super::network::Network;
use crate::v2::database::Database;
use crate::validator::{SemanticValidationError, Validator};
use crate::{AnnouncePolicy, TrackerPolicy};

#[allow(clippy::struct_excessive_bools)]
Expand Down Expand Up @@ -131,3 +132,13 @@ impl PrivateMode {
true
}
}

impl Validator for Core {
fn validate(&self) -> Result<(), SemanticValidationError> {
if self.private_mode.is_some() && !self.private {
return Err(SemanticValidationError::UselessPrivateModeSection);
}

Ok(())
}
}
7 changes: 7 additions & 0 deletions packages/configuration/src/v2/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ use self::health_check_api::HealthCheckApi;
use self::http_tracker::HttpTracker;
use self::tracker_api::HttpApi;
use self::udp_tracker::UdpTracker;
use crate::validator::{SemanticValidationError, Validator};
use crate::{Error, Info, Metadata, Version};

/// This configuration version
Expand Down Expand Up @@ -394,6 +395,12 @@ impl Configuration {
}
}

impl Validator for Configuration {
fn validate(&self) -> Result<(), SemanticValidationError> {
self.core.validate()
}
}

#[cfg(test)]
mod tests {

Expand Down
19 changes: 19 additions & 0 deletions packages/configuration/src/validator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//! Trait to validate semantic errors.
//!
//! Errors could involve more than one configuration option. Some configuration
//! combinations can be incompatible.
use thiserror::Error;

/// Errors that can occur validating the configuration.
#[derive(Error, Debug)]
pub enum SemanticValidationError {
#[error("Private mode section in configuration can only be included when the tracker is running in private mode.")]
UselessPrivateModeSection,
}

pub trait Validator {
/// # Errors
///
/// Will return an error if the configuration is invalid.
fn validate(&self) -> Result<(), SemanticValidationError>;
}
9 changes: 9 additions & 0 deletions src/bootstrap/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use std::sync::Arc;

use torrust_tracker_clock::static_time;
use torrust_tracker_configuration::validator::Validator;
use torrust_tracker_configuration::Configuration;
use tracing::info;

Expand All @@ -24,10 +25,18 @@ use crate::core::Tracker;
use crate::shared::crypto::ephemeral_instance_keys;

/// It loads the configuration from the environment and builds the main domain [`Tracker`] struct.
///
/// # Panics
///
/// Setup can file if the configuration is invalid.
#[must_use]
pub fn setup() -> (Configuration, Arc<Tracker>) {
let configuration = initialize_configuration();

if let Err(e) = configuration.validate() {
panic!("Configuration error: {e}");
}

let tracker = initialize_with_configuration(&configuration);

info!("Configuration:\n{}", configuration.clone().mask_secrets().to_json());
Expand Down
2 changes: 1 addition & 1 deletion src/core/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
//! Tracker keys are tokens used to authenticate the tracker clients when the tracker runs
//! in `private` or `private_listed` modes.
//!
//! There are services to [`generate_key`] and [`verify_key`] authentication keys.
//! There are services to [`generate_key`] and [`verify_key_expiration`] authentication keys.
//!
//! Authentication keys are used only by [`HTTP`](crate::servers::http) trackers. All keys have an expiration time, that means
//! they are only valid during a period of time. After that time the expiring key will no longer be valid.
Expand Down

0 comments on commit d7dfc3b

Please sign in to comment.