use crate::{
types::{AcrDriver, ScanFrequency, Source},
Error, HttpRequest, Response, Tenable,
};
use http::{header::HeaderValue, status::StatusCode, Method, Request};
use serde::{Deserialize, Serialize};
use std::{borrow::Cow, fmt};
#[derive(Clone, Debug)]
pub struct AssetsReq<'a> {
pub tenable: &'a Tenable<'a>,
}
impl<RE: fmt::Debug> HttpRequest<RE> for AssetsReq<'_> {
type Output = Assets;
#[inline]
fn to_request(&self) -> Result<Request<Vec<u8>>, Error<RE>> {
let req = Request::builder()
.uri(format!("{}/assets", self.tenable.uri))
.method(Method::GET)
.header(
"X-ApiKeys",
HeaderValue::from_str(self.tenable.auth.as_ref())?,
)
.header("Accept", HeaderValue::from_static("application/json"))
.body(Vec::new())?;
Ok(req)
}
#[inline]
fn from_response(&self, res: Response) -> Result<Self::Output, Error<RE>> {
match res.status {
StatusCode::OK => {}
StatusCode::FORBIDDEN => return Err(Error::InsufficientPermission),
StatusCode::TOO_MANY_REQUESTS => return Err(Error::RateLimitReached),
code => return Err(Error::UnexpectedStatusCode(code)),
}
let data = serde_json::from_slice(&res.body)?;
Ok(data)
}
}
impl<'a> From<AssetsReq<'a>> for Cow<'a, AssetsReq<'a>> {
#[inline]
fn from(req: AssetsReq<'a>) -> Self {
Cow::Owned(req)
}
}
impl<'a> From<&'a AssetsReq<'a>> for Cow<'a, AssetsReq<'a>> {
#[inline]
fn from(req: &'a AssetsReq<'a>) -> Self {
Cow::Borrowed(req)
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Assets {
#[serde(rename = "assets", skip_serializing_if = "Option::is_none")]
pub assets: Option<Vec<Asset>>,
#[serde(rename = "total", skip_serializing_if = "Option::is_none")]
pub total: Option<i32>,
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
pub struct Asset {
#[serde(rename = "id", skip_serializing_if = "Option::is_none")]
pub id: Option<String>,
#[serde(rename = "has_agent", skip_serializing_if = "Option::is_none")]
pub has_agent: Option<bool>,
#[serde(rename = "last_seen", skip_serializing_if = "Option::is_none")]
pub last_seen: Option<String>,
#[serde(rename = "last_scan_target", skip_serializing_if = "Option::is_none")]
pub last_scan_target: Option<String>,
#[serde(rename = "sources", skip_serializing_if = "Option::is_none")]
pub sources: Option<Vec<Source>>,
#[serde(rename = "acr_score", skip_serializing_if = "Option::is_none")]
pub acr_score: Option<i32>,
#[serde(rename = "acr_drivers", skip_serializing_if = "Option::is_none")]
pub acr_drivers: Option<Vec<AcrDriver>>,
#[serde(rename = "exposure_score", skip_serializing_if = "Option::is_none")]
pub exposure_score: Option<i32>,
#[serde(rename = "scan_frequency", skip_serializing_if = "Option::is_none")]
pub scan_frequency: Option<Vec<ScanFrequency>>,
#[serde(rename = "ipv4", skip_serializing_if = "Option::is_none")]
pub ipv4: Option<Vec<String>>,
#[serde(rename = "ipv6", skip_serializing_if = "Option::is_none")]
pub ipv6: Option<Vec<String>>,
#[serde(rename = "fqdn", skip_serializing_if = "Option::is_none")]
pub fqdn: Option<Vec<String>>,
#[serde(rename = "netbios_name", skip_serializing_if = "Option::is_none")]
pub netbios_name: Option<Vec<String>>,
#[serde(rename = "operating_system", skip_serializing_if = "Option::is_none")]
pub operating_system: Option<Vec<String>>,
#[serde(rename = "agent_name", skip_serializing_if = "Option::is_none")]
pub agent_name: Option<Vec<String>>,
#[serde(rename = "aws_ec2_name", skip_serializing_if = "Option::is_none")]
pub aws_ec2_name: Option<Vec<String>>,
#[serde(rename = "mac_address", skip_serializing_if = "Option::is_none")]
pub mac_address: Option<Vec<String>>,
}