use std::time::Instant;
use super::MantaClient;
#[derive(Debug)]
pub struct AuthServerUnreachable {
pub url: String,
}
impl std::fmt::Display for AuthServerUnreachable {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"cannot reach manta server at {} for authentication. \
Is the server running, and is `manta_server_url` in your \
config correct?",
self.url,
)
}
}
impl std::error::Error for AuthServerUnreachable {}
impl MantaClient {
fn map_auth_send_error(
&self,
e: reqwest::Error,
method_and_path: &str,
) -> anyhow::Error {
if e.is_connect() || e.is_timeout() {
let url = self.base_url().trim_end_matches("/api/v1").to_string();
anyhow::Error::new(e).context(AuthServerUnreachable { url })
} else {
anyhow::Error::new(e).context(format!("{method_and_path} failed"))
}
}
}
impl MantaClient {
pub async fn get_token(
&self,
username: &str,
password: &str,
) -> anyhow::Result<String> {
use manta_shared::types::auth::{AuthTokenRequest, AuthTokenResponse};
let url = format!("{}/auth/token", self.base_url());
tracing::debug!(url = %url, site = %self.site_name(), "POST /auth/token");
let builder = self
.http_client()
.post(&url)
.header("X-Manta-Site", self.site_name())
.json(&AuthTokenRequest {
username: username.to_owned(),
password: password.to_owned(),
});
Self::log_request_as_curl(&builder);
let started = Instant::now();
let resp = builder
.send()
.await
.map_err(|e| self.map_auth_send_error(e, "HTTP POST /auth/token"))?;
tracing::debug!(
status = %resp.status(),
elapsed_ms = u64::try_from(started.elapsed().as_millis()).unwrap_or(u64::MAX),
"/auth/token response"
);
let body: AuthTokenResponse = Self::parse_json(resp).await?;
Ok(body.token)
}
pub async fn validate_token(&self, token: &str) -> anyhow::Result<()> {
use manta_shared::types::auth::ValidateTokenRequest;
let url = format!("{}/auth/validate", self.base_url());
tracing::debug!(url = %url, site = %self.site_name(), "POST /auth/validate");
let builder = self
.http_client()
.post(&url)
.header("X-Manta-Site", self.site_name())
.json(&ValidateTokenRequest {
token: token.to_owned(),
});
Self::log_request_as_curl(&builder);
let started = Instant::now();
let resp = builder
.send()
.await
.map_err(|e| self.map_auth_send_error(e, "HTTP POST /auth/validate"))?;
tracing::debug!(
status = %resp.status(),
elapsed_ms = u64::try_from(started.elapsed().as_millis()).unwrap_or(u64::MAX),
"/auth/validate response"
);
Self::parse_no_content(resp).await
}
}