htb-cli 0.1.8

Hack The Box CLI
Documentation
use serde::{Deserialize, Serialize};

use crate::output::Tabular;

#[derive(Debug, Deserialize)]
pub struct ConnectionsResponse {
    pub data: Vec<Connection>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Connection {
    #[serde(rename = "type")]
    pub connection_type: String,
    #[serde(default)]
    pub location_type_friendly: Option<String>,
    #[serde(default)]
    pub assigned_server: Option<AssignedServer>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct AssignedServer {
    pub id: u32,
    pub friendly_name: String,
    #[serde(default)]
    pub current_clients: u32,
    #[serde(default)]
    pub location: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct VpnSwitchResponse {
    #[serde(default)]
    pub status: bool,
    #[serde(default)]
    pub message: Option<String>,
    #[serde(default)]
    pub data: Option<AssignedServer>,
}

impl Tabular for Connection {
    fn headers() -> Vec<&'static str> {
        vec!["Type", "Location", "Server", "Clients"]
    }

    fn row(&self) -> Vec<String> {
        let (server, clients) = match &self.assigned_server {
            Some(s) => (s.friendly_name.clone(), s.current_clients.to_string()),
            None => ("-".into(), "-".into()),
        };
        vec![
            self.connection_type.clone(),
            self.location_type_friendly.clone().unwrap_or_default(),
            server,
            clients,
        ]
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn deserialize_connections() {
        let json = include_str!("../../tests/fixtures/v5-connections.json");
        let result: ConnectionsResponse = serde_json::from_str(json).unwrap();
        assert!(!result.data.is_empty());
        let labs = result.data.iter().find(|c| c.connection_type == "labs");
        assert!(labs.is_some());
        assert!(labs.unwrap().assigned_server.is_some());
    }

    #[test]
    fn deserialize_connection_status_empty() {
        let json = include_str!("../../tests/fixtures/connection-status.json");
        let result: Vec<serde_json::Value> = serde_json::from_str(json).unwrap();
        assert!(result.is_empty());
    }
}