use thiserror::Error;
use wildland_corex::catlib_service::error::CatlibError;
use wildland_corex::{CryptoError, LssError, StorageTemplate, StorageTemplateError};
use wildland_http_client::error::WildlandHttpClientError;
use wildland_http_client::evs::{ConfirmTokenReq, EvsClient, GetStorageReq, GetStorageRes};
use super::config::FoundationStorageApiConfig;
#[repr(C)]
#[derive(Error, Debug, Clone)]
pub enum FsaError {
#[error("Evs Error: {0}: {1}")]
EvsError(&'static str, WildlandHttpClientError),
#[error("Crypto error: {0}")]
CryptoError(CryptoError),
#[error("Evs returned unexpected response: received {0}")]
UnexpectedResponse(String),
#[error(transparent)]
LssError(#[from] LssError),
#[error(transparent)]
CatlibError(#[from] CatlibError),
#[error("Error while creating Storage Template: {0}")]
StorageTemplateError(StorageTemplateError),
#[error("Connectivity Issue {0}")]
ConnectivityIssue(String),
}
#[derive(Clone)]
pub struct FoundationStorageApi {
evs_client: EvsClient,
}
impl FoundationStorageApi {
pub fn new(config: &FoundationStorageApiConfig) -> Self {
Self {
evs_client: EvsClient::new(config.evs_url.clone()),
}
}
#[tracing::instrument(level = "debug", skip_all)]
pub fn request_free_tier_storage(
&self,
email: String,
) -> Result<FreeTierProcessHandle, FsaError> {
self.evs_client
.get_storage(GetStorageReq {
email: email.clone(),
session_id: None,
})
.map_err(|e| FsaError::EvsError("Requesting free storage", e))
.and_then(|resp| match resp {
GetStorageRes::Started { session_id } => {
tracing::debug!("Process of requesting Foundation Storage started with session id: {session_id}");
Ok(FreeTierProcessHandle {
email,
session_id,
evs_client: self.evs_client.clone(),
})
},
other => Err(FsaError::UnexpectedResponse(other.state().into())),
})
}
}
#[derive(Clone)]
pub struct FreeTierProcessHandle {
email: String,
session_id: String,
evs_client: EvsClient,
}
impl FreeTierProcessHandle {
#[tracing::instrument(level = "debug", skip_all)]
pub fn verify_email(&self, verification_token: String) -> Result<StorageTemplate, FsaError> {
self.evs_client
.confirm_token(ConfirmTokenReq {
session_id: self.session_id.clone(),
email: self.email.clone(),
verification_token,
})
.map_err(|e| match e {
WildlandHttpClientError::ClientConnectivityError(f) => {
FsaError::ConnectivityIssue(format!("Code: {f}, Error:{}", e))
}
_ => FsaError::EvsError("Confirming token", e),
})?;
self.evs_client
.get_storage(GetStorageReq {
email: self.email.clone(),
session_id: Some(self.session_id.clone()),
})
.map_err(|e| FsaError::EvsError("Getting storage after confirmation", e))
.and_then(|resp| match resp {
GetStorageRes::Finished { template } => {
serde_json::from_value(template).map_err(|err| {
FsaError::UnexpectedResponse(format!(
"Cannot deserialize storage template: {err:?}"
))
})
}
other => Err(FsaError::UnexpectedResponse(other.state().into())),
})
}
}