docs: api docs for everyone
cargo devel CI / cargo CI (push) Successful in 1m32s Details

This commit is contained in:
Christoph J. Scherr 2024-09-06 23:09:10 +02:00
parent de7e046ae7
commit bfa532cbd2
5 changed files with 125 additions and 20 deletions

View File

@ -1,3 +1,8 @@
//! Challenges and their common interface.
//!
//! This module is the core of the Wooly Vault application, as it defines the interface that all
//! challenges must implement, and contains the challenge modules themselves.
use anyhow::anyhow;
use async_trait::async_trait;
@ -8,17 +13,70 @@ pub mod c1;
pub mod c2;
pub mod c3;
/// Defines the behavior of a challenge.
///
/// Any type that implements this trait can be served as a challenge in the Wooly Vault application.
#[async_trait]
pub trait Challenge
where
Self: Sized,
{
/// Creates a new instance of the challenge with the given configuration and vault.
///
/// # Arguments
///
/// * `config` - The configuration for the challenge.
/// * `vault` - The vault that holds the secret for the challenge.
///
/// # Returns
///
/// A new instance of the challenge.
fn new(config: Config, vault: VaultRef) -> Self;
/// Returns a list of hints for the challenge.
///
/// A hint is a short text to be given to the contestants in case the host thinks they need
/// it. The first hint is the most vague, afterwards the hints become more and more helpful.
///
/// # Returns
///
/// A vector of strings containing hints for the challenge.
fn hints() -> Vec<String>;
/// Returns the solution to the challenge.
///
/// A solution is a short description of what has to be done to solve the challenge and get the
/// secret of the vault.
///
/// # Returns
///
/// A string containing the solution to the challenge.
fn solution() -> String;
/// Starts the challenge and serves it to the contestants.
///
/// This method is asynchronous and returns a result indicating whether the challenge was
/// successful only after the challenge has ended.
///
/// # Returns
///
/// A result indicating whether the challenge was successful ended.
async fn serve(self) -> anyhow::Result<()>;
}
/// Selects a challenge by index and serves it with the given configuration and vault.
///
/// # Arguments
///
/// * `index` - The index of the challenge to select.
/// * `config` - The configuration for the challenge.
/// * `vault` - The vault that holds the secret for the challenge.
///
/// # Returns
///
/// A result indicating whether the challenge has successfully ended.
///
/// # Errors
///
/// Returns an error if no challenge with the given index exists, or if the challenge that is being
/// served errors.
pub async fn select_and_start(index: u16, config: Config, vault: VaultRef) -> anyhow::Result<()> {
match index {
1 => c1::C1::new(config, vault).serve().await?,

View File

@ -1,11 +1,15 @@
//! Common configuration options for the challenges.
use std::fmt::Debug;
use std::net::SocketAddr;
use std::str::FromStr;
use anyhow::Result;
use clap::Parser;
use libpt::cli::args::VerbosityLevel;
use serde::Serialize;
/// The environment variable that can hold the secret for a challenge
pub const ENV_SECRET: &str = "WOOLY_SECRET";
/// Wooly Vault --- A few small hacking challenges
@ -41,7 +45,6 @@ pub const ENV_SECRET: &str = "WOOLY_SECRET";
about,
long_about,
help_template = libpt::cli::args::HELP_TEMPLATE)]
pub struct Config {
/// Index of the challenge
pub challenge: u16,
@ -69,3 +72,24 @@ impl Debug for Config {
.finish()
}
}
impl Config {
/// Load or input the secret
///
/// This will try to get the secret from the [`ENV_SECRET`] environment variable. If that
/// variable is not set, the user will be asked to input a secret manually.
///
/// # Errors
///
/// When the environment variable is not set and the reading from stdin fails.
pub fn secret() -> Result<String> {
if let Ok(v) = std::env::var(ENV_SECRET) {
return Ok(v);
}
println!("Input the secret and press enter");
let mut buf: String = String::new();
std::io::stdin().read_line(&mut buf)?;
Ok(buf.trim().to_string())
}
}

View File

@ -1,3 +1,19 @@
//! # Wooly Vault
//!
//! Wooly Vault is a set of smaller challenges for Rust hackers.
//!
//! A host may choose to open a challenge, set a secret and ask a contestant to try and solve the
//! challenge to get the secret. The contestant can then prove with the secret to the host that
//! they absolved the challenge.
//!
//! Wooly Vault has multiple challenges, and only one can be hosted per instance of this
//! application. The challenges all bind to a pre-set [Network Adress](crate::config::Config::addr).
//! The contestants can then connect to that adress with TCP. The first few challenges use raw TCP,
//! but some of the later ones are small HTTP webservices.
//!
//! Wooly Vault is programmed asynchronously with [tokio] to be able to handle many contestants at
//! once if needed.
pub mod challenge;
pub mod config;
pub mod vault;

View File

@ -2,7 +2,6 @@ use anyhow::Result;
use clap::Parser;
use libpt::log::{debug, info};
use wooly_vault::config::ENV_SECRET;
use wooly_vault::{challenge::select_and_start, config::Config, vault::Vault};
#[tokio::main(flavor = "current_thread")]
@ -16,27 +15,10 @@ async fn main() -> Result<()> {
debug!("logger active");
info!("Configuration: {conf:?}");
let secret = get_secret()?;
let secret = Config::secret()?;
let v = Vault::new(&secret);
select_and_start(conf.challenge, conf, v).await?;
Ok(())
}
fn get_secret() -> Result<String> {
if let Ok(v) = std::env::var(ENV_SECRET) {
return Ok(v);
}
println!("Input the secret and press enter");
let mut buf: String = String::new();
std::io::stdin().read_line(&mut buf)?;
Ok(buf.trim().to_string())
}
fn select_challenge() -> Result<u16> {
let mut buf: String = String::new();
std::io::stdin().read_line(&mut buf)?;
Ok(buf.trim().parse()?)
}

View File

@ -1,19 +1,44 @@
//! A module for managing and sharing secrets in the Wooly Vault application.
//!
//! This module provides a [`Vault`] struct that holds a secret and allows it to be shared safely
//! across the application using an [`Arc`] (Atomic Reference Counted) pointer.
use std::sync::Arc;
/// A type alias for an [`Arc`] pointer to a [`Vault`] instance.
///
/// This type is used to share a [`Vault`] instance across multiple parts of the application.
pub type VaultRef = Arc<Vault>;
/// A struct that holds a secret and provides methods for accessing it.
///
/// The [`Vault`] struct is designed to be shared safely across the application using an [`Arc`] pointer.
#[derive(Debug, Clone, PartialEq)]
pub struct Vault {
/// The secret stored in the vault
secret: String,
}
impl Vault {
/// Creates a new [`Vault`] instance with the given secret.
///
/// Returns an [`Arc`] pointer to the new [`Vault`] instance.
///
/// # Returns
///
/// A new [`Vault`] instance with the given secret.
pub fn new(secret: &str) -> VaultRef {
let v = Self {
secret: secret.to_string(),
};
Arc::new(v)
}
/// Returns a reference to the secret stored in the vault.
///
/// # Returns
///
/// A reference to the secret stored in the vault.
pub fn secret(&self) -> &str {
&self.secret
}