use std::rc::Rc;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::cross_platform_http_client::{Body, CurrentPlatformClient, HttpClient};
use crate::error::WildlandHttpClientError;
use crate::response_handler::check_status_code;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ConfirmTokenReq {
pub session_id: String,
pub email: String,
pub verification_token: String,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct GetStorageReq {
pub session_id: Option<String>,
pub email: String,
}
#[derive(Debug, Clone, Deserialize, Serialize)]
pub struct StorageCredentials {
pub id: Uuid,
#[serde(rename = "credentialID")]
pub credential_id: String,
#[serde(rename = "credentialSecret")]
pub credential_secret: String,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(tag = "state")]
pub enum GetStorageRes {
#[serde(rename = "started")]
Started { session_id: String },
#[serde(rename = "ongoing")]
Ongoing,
#[serde(rename = "finished")]
Finished { template: serde_json::Value },
}
impl GetStorageRes {
pub fn state(&self) -> &str {
match self {
GetStorageRes::Started { .. } => "started",
GetStorageRes::Ongoing => "ongoing",
GetStorageRes::Finished { .. } => "finished",
}
}
}
#[derive(Clone)]
pub struct EvsClient {
http_client: Rc<dyn HttpClient>,
base_url: String,
}
impl EvsClient {
#[tracing::instrument(level = "debug", skip_all)]
pub fn new(base_url: String) -> Self {
let http_client = Rc::new(CurrentPlatformClient {});
Self {
http_client,
base_url,
}
}
#[tracing::instrument(level = "debug", skip_all)]
pub fn confirm_token(&self, request: ConfirmTokenReq) -> Result<(), WildlandHttpClientError> {
let request = http::Request::put(format!("{}/confirm_token", self.base_url))
.body(Body::json(request))?;
let response = self.http_client.send(request)?;
check_status_code(response)?;
Ok(())
}
#[tracing::instrument(level = "debug", skip_all)]
pub fn get_storage(
&self,
request: GetStorageReq,
) -> Result<GetStorageRes, WildlandHttpClientError> {
let request = http::Request::put(format!("{}/get_storage", self.base_url))
.body(Body::json(request))?;
let response = self.http_client.send(request)?;
check_status_code(response)?
.map(|body| serde_json::from_slice(&body))
.into_body()
.map_err(Into::into)
}
}
#[cfg(test)]
mod tests {
use serde_json::json;
use super::*;
use crate::cross_platform_http_client::MockHttpClient;
use crate::evs::constants::test_utilities::{EMAIL, VERIFICATION_TOKEN};
#[test]
fn should_confirm_token() {
let mut http_client = Box::new(MockHttpClient::new());
let request = ConfirmTokenReq {
email: EMAIL.into(),
verification_token: VERIFICATION_TOKEN.into(),
session_id: "some uuid".to_string(),
};
let http_request = http::Request::put("/confirm_token")
.body(Body::json(request.clone()))
.unwrap();
http_client
.as_mut()
.expect_send()
.withf(move |request| {
request.method() == http_request.method()
&& request.uri() == http_request.uri()
&& request.headers() == http_request.headers()
&& request.body() == http_request.body()
})
.times(1)
.returning(|_| {
Ok(http::Response::builder()
.status(200)
.body(Vec::default())
.unwrap())
});
let response = EvsClient {
http_client: Rc::from(http_client as Box<_>),
base_url: "".into(),
}
.confirm_token(request);
assert!(response.is_ok());
}
#[test]
fn should_get_storage() {
let mut http_client = Box::new(MockHttpClient::new());
let request = GetStorageReq {
email: EMAIL.into(),
session_id: Some("some uuid".to_string()),
};
let http_request = http::Request::put("/get_storage")
.body(Body::json(request.clone()))
.unwrap();
let expected_template = json!({
"login": "bar",
"credentials": "foo",
});
http_client
.as_mut()
.expect_send()
.withf(move |request| {
request.method() == http_request.method()
&& request.uri() == http_request.uri()
&& request.headers() == http_request.headers()
&& request.body() == http_request.body()
})
.times(1)
.returning({
let expected_template = expected_template.clone();
move |_| {
Ok(http::Response::builder()
.status(200)
.body(
serde_json::to_vec(&serde_json::json!(
{
"state": "finished",
"template": expected_template,
}
))
.unwrap(),
)
.unwrap())
}
});
if let GetStorageRes::Finished { template } = (EvsClient {
http_client: Rc::from(http_client as Box<_>),
base_url: "".into(),
})
.get_storage(request)
.unwrap()
{
assert_eq!(template, expected_template);
} else {
panic!("invalid enum variant");
}
}
}