use crate::decipher;
use crate::enums::Method;
use crate::parser::ArgConfig;
use crate::parser::EnvConfig;
use reqwest::blocking::Client;
use serde_json::Value;
use std::collections::HashMap;
use std::process::exit;
pub struct PreparedRequest {
pub url: String,
pub method: Method,
pub params: HashMap<String, String>,
pub payload: HashMap<String, Value>,
pub headers: HashMap<String, String>,
}
pub fn auth_headers(apikey: &String) -> HashMap<String, String> {
let mut headers = HashMap::new();
let bearer = format!("Bearer {}", apikey);
headers.insert("Authorization".to_string(), bearer);
headers.insert("Accept".to_string(), "application/json".to_string());
headers
}
fn create_request_materials(arg_config: &ArgConfig, env_config: &EnvConfig) -> PreparedRequest {
let mut url = String::new();
let mut params = HashMap::new();
if !arg_config.table_name.is_empty() {
params.insert("table_name".to_string(), arg_config.table_name.to_string());
} else if !arg_config.get_table.is_empty() {
params.insert("table_name".to_string(), arg_config.get_table.to_string());
} else {
println!("Table name is mandatory to retrieve the secret");
exit(1)
}
if !arg_config.get_secrets.is_empty() {
url = format!("{}get-secrets", &env_config.vault_server);
params.insert("keys".to_string(), arg_config.get_secrets.to_string());
} else if !arg_config.get_secret.is_empty() {
url = format!("{}get-secret", &env_config.vault_server);
params.insert("key".to_string(), arg_config.get_secret.to_string());
} else if !arg_config.get_table.is_empty() {
url = format!("{}get-table", &env_config.vault_server);
} else if arg_config.table_name.is_empty() {
println!("Required parameters unfilled!");
exit(1)
}
PreparedRequest {
url,
method: Method::Get,
params,
payload: HashMap::new(),
headers: auth_headers(&env_config.apikey),
}
}
pub fn decrypt_response(env_config: &EnvConfig, response: &Value) -> Result<Value, String> {
match response {
Value::Null => {
println!("No 'detail' key found in the response.");
exit(1)
}
Value::String(cipher_text) => {
return decipher::transit_decrypt(
&env_config.apikey,
&env_config.secret,
cipher_text,
env_config.transit_key_length,
env_config.transit_time_bucket,
)
}
Value::Object(obj) => {
println!("Detail is an object: {:?}", obj);
}
_ => {
println!("Unexpected value returned: {:?}", response);
}
}
exit(1)
}
pub fn server_connection(arg_config: &ArgConfig, env_config: &EnvConfig) -> Result<Value, String> {
let prepared_request = create_request_materials(arg_config, env_config);
let response = make_request(prepared_request);
decrypt_response(env_config, &response)
}
pub fn make_request(prepared_request: PreparedRequest) -> Value {
let client = Client::new();
let mut url = match reqwest::Url::parse(&prepared_request.url) {
Ok(url) => url,
Err(_) => {
eprintln!("Invalid URL: {}", prepared_request.url);
exit(1)
}
};
if !prepared_request.params.is_empty() {
let query: Vec<(String, String)> = prepared_request.params.into_iter().collect();
url.query_pairs_mut().extend_pairs(query);
}
let mut request = match prepared_request.method {
Method::Get => client.get(url),
Method::Post => client.post(url),
Method::Put => client.put(url),
Method::Delete => client.delete(url),
};
if !prepared_request.headers.is_empty() {
for (key, value) in prepared_request.headers {
request = request.header(&key, value);
}
}
if !prepared_request.payload.is_empty() {
request = request.json(&prepared_request.payload)
}
match request.send() {
Ok(init_response) => {
match init_response.error_for_status() {
Ok(response) => {
match response.json::<Value>() {
Ok(json) => {
if let Some(detail) = json.get("detail") {
detail.clone()
} else {
Value::Null
}
}
Err(err) => {
println!("Failed to parse response as JSON: {}", err);
exit(1);
}
}
}
Err(err) => {
println!("Server response: {}", err);
exit(1)
}
}
}
Err(err) => {
println!(
"Failed to fetch data from {}: {}",
prepared_request.url, err
);
exit(1);
}
}
}