diff --git a/src/cloudflare/mod.rs b/src/cloudflare/mod.rs index 465305c..a9818d4 100644 --- a/src/cloudflare/mod.rs +++ b/src/cloudflare/mod.rs @@ -1,20 +1,24 @@ -use reqwest::{blocking::{Response, Client}, Url}; +use reqwest::{ + blocking::{Client, Response}, + Url, +}; +use reqwest::{ + header::{HeaderMap, HeaderValue}, + Error, +}; use serde_derive::{Deserialize, Serialize}; -use reqwest::{Error, header::{HeaderMap, HeaderValue}}; -use std::{string::String, collections::HashMap}; +use std::{collections::HashMap, string::String}; use strum_macros::{Display, IntoStaticStr}; const API_BASE: &str = "https://api.cloudflare.com/client/v4/"; - #[derive(Serialize, Deserialize)] struct CloudflareDnsZone { result: Vec, - success: bool + success: bool, } -#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy)] -#[derive(Display, IntoStaticStr)] +#[derive(Serialize, Deserialize, PartialEq, Debug, Clone, Copy, Display, IntoStaticStr)] pub enum CloudflareDnsType { #[strum(serialize = "A")] A = 4, @@ -22,7 +26,7 @@ pub enum CloudflareDnsType { AAAA = 6, TXT, MX, - CAA + CAA, } #[derive(Serialize, Deserialize)] @@ -32,24 +36,31 @@ pub struct CloudflareDnsEntry { pub name: String, pub r#type: CloudflareDnsType, content: String, - proxied: bool + proxied: bool, } impl CloudflareDnsEntry { pub fn is_equal(&self, other_entry: &String) -> bool { - return if &self.name == other_entry { true } else { false }; + return if &self.name == other_entry { + true + } else { + false + }; } pub fn is_ip_new(&self, other_entry: &String) -> bool { - return if &self.content == other_entry { false } else { true }; + return if &self.content == other_entry { + false + } else { + true + }; } } - pub(crate) struct Instance { api_key: String, pub dns_entries: Vec, - dns_email: String + dns_email: String, } impl Instance { @@ -57,12 +68,12 @@ impl Instance { Instance { api_key: key.clone(), dns_entries: Vec::new(), - dns_email: "".to_string() + dns_email: "".to_string(), } } /// Loads all DNS entires in a Zone as a [`CloudflareDnsEntry`] Vector - /// + /// /// * `email` : E-Mail Address associated with the Zone, required for [`generate_headers()`] /// * `zone_id` : Zone to be used for the Request /// * `return` : Returns true if a recoverable Error was encountered, true otherwise @@ -72,104 +83,111 @@ impl Instance { match self.get(&endpoint) { Ok(response) => { - let entries = match response - .json::() { - Ok(data) => {data}, - Err(e) => panic!("{:#?}", e) - }; - - for entry in entries.result { - self.dns_entries.append(&mut vec!(entry)); + if response.status().is_success() { + let entries = match response.json::() { + Ok(data) => data, + Err(e) => { + panic!("{:#?}", e) + } + }; + + for entry in entries.result { + self.dns_entries.append(&mut vec![entry]); + } + + return Ok(()); } - - return Ok(()) - }, - Err(e) => { return Err(e) } + else { + println!("Server returned Status Code: {}", response.status()); + return Err(response.error_for_status().err().unwrap()); + } + } + Err(e) => return Err(e), } - - } /// Shorthand for Cloudflare API Requests - /// + /// /// Automatically appends Auth Headers and parses the URL - /// + /// /// * `url` : URL for the request, will be parsed to [`Url`] fn get(&self, url: &str) -> Result { let url_parsed = match Url::parse(url) { - Ok(url) => {url}, - Err(e) => panic!("{:#?}", e) // If this call fails the API changed - }; // Continuing without a code update is not possible + Ok(url) => url, + Err(e) => panic!("{:#?}", e), // If this call fails the API changed + }; // Continuing without a code update is not possible - let result = match Client::new() + let result = Client::new() .get(url_parsed) .headers(self.generate_headers()) - .send() { - Ok(res) => { Ok(res) }, - Err(e) => { Err(e) } - }; + .send(); return result; } /// Shorthand for Cloudflare API Requests - /// + /// /// Automatically appends Auth Headers and parses the URL - /// + /// /// * `url` : URL for the request, will be parsed to [`Url`] /// * `data` : PUT request body fn put(&self, url: &str, data: &HashMap<&str, &str>) -> Result { let url_parsed = match Url::parse(url) { - Ok(url) => {url}, - Err(e) => panic!("{:#?}", e)// If this call fails the API changed - }; // Continuing without a code update is not possible - + Ok(url) => url, + Err(e) => panic!("{:#?}", e), // If this call fails the API changed + }; // Continuing without a code update is not possible + let result = match Client::new() .put(url_parsed) .headers(self.generate_headers()) .json(data) - .send() { - Ok(res) => { Ok(res) }, - Err(e) => { Err(e) } + .send() + { + Ok(res) => Ok(res), + Err(e) => Err(e), }; return result; } /// Shorthand for Cloudflare API Requests - /// + /// /// Automatically appends Auth Headers and parses the URL - /// + /// /// * `url` : URL for the request, will be parsed to [`Url`] /// * `data` : POST request body fn post(&self, url: &str, data: &HashMap<&str, &str>) -> Result { let url_parsed = match Url::parse(url) { - Ok(url) => {url}, - Err(e) => panic!("{:#?}", e) // If this call fails the API changed - }; // Continuing without a code update is not possible - + Ok(url) => url, + Err(e) => panic!("{:#?}", e), // If this call fails the API changed + }; // Continuing without a code update is not possible + let result = match Client::new() .post(url_parsed) .headers(self.generate_headers()) .json(data) - .send() { - Ok(res) => { Ok(res) }, - Err(e) => { Err(e) } + .send() + { + Ok(res) => Ok(res), + Err(e) => Err(e), }; return result; } /// Updates the given DNS entry with the given IP - /// + /// /// * `entry` : DNS entry to update /// * `new_ip` : IP used to Update the DNS entry, can be IPv4 or IPv6 /// * `return1` : Returns success of the API call, extracted from the HTTP Response body pub fn update_entry(&self, entry: &CloudflareDnsEntry, new_ip: &String) -> Result { - let endpoint = format!("{}zones/{}/dns_records/{}", API_BASE, entry.zone_id, entry.id); + let endpoint = format!( + "{}zones/{}/dns_records/{}", + API_BASE, entry.zone_id, entry.id + ); let mut json_body = HashMap::new(); - json_body.insert("type", entry.r#type.clone().into()); + json_body.insert("type", entry.r#type.clone().into()); json_body.insert("name", entry.name.as_ref()); json_body.insert("content", new_ip); json_body.insert("ttl", "1"); @@ -184,16 +202,22 @@ impl Instance { .as_bool() .expect("JSON should always include success bool"); return Ok(success); - }, - Err(e) => { return Err(e) }, + } + Err(e) => return Err(e), } } - pub fn create_entry(&self, zone_id: &String, r#type: &str, name: &str, ip: &String) -> Result { + pub fn create_entry( + &self, + zone_id: &String, + r#type: &str, + name: &str, + ip: &String, + ) -> Result { let endpoint = format!("{}zones/{}/dns_records", API_BASE, zone_id); let mut json_body = HashMap::new(); - json_body.insert("type", r#type); + json_body.insert("type", r#type); json_body.insert("name", name); json_body.insert("content", ip); json_body.insert("ttl", "1"); @@ -208,18 +232,23 @@ impl Instance { .as_bool() .expect("JSON should always include success bool"); - return Ok(success) - }, - Err(e) => { return Err(e) }, + return Ok(success); + } + Err(e) => return Err(e), } } /// Generate Cloudflare API v4 Auth Headers fn generate_headers(&self) -> HeaderMap { let mut headers = HeaderMap::new(); - headers.insert("X-Auth-Key", HeaderValue::from_str(self.api_key.as_ref()).unwrap()); - headers.insert("X-Auth-Email", HeaderValue::from_str(self.dns_email.as_ref()).unwrap()); + headers.insert( + "X-Auth-Key", + HeaderValue::from_str(self.api_key.as_ref()).unwrap(), + ); + headers.insert( + "X-Auth-Email", + HeaderValue::from_str(self.dns_email.as_ref()).unwrap(), + ); headers } - -} \ No newline at end of file +}