Compare commits
No commits in common. "a5c55115cf585880bae6cc9dcc62e7c55a2a8f72" and "87001a98500b37c6d10c558a6251d6b6ba8d60ed" have entirely different histories.
a5c55115cf
...
87001a9850
1 changed files with 46 additions and 57 deletions
103
src/main.rs
103
src/main.rs
|
@ -1,4 +1,4 @@
|
||||||
#![warn(clippy::pedantic, clippy::cargo, clippy::nursery)]
|
#![warn(clippy::pedantic, clippy::cargo)]
|
||||||
|
|
||||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||||
use std::fmt::{Debug, Display};
|
use std::fmt::{Debug, Display};
|
||||||
|
@ -83,8 +83,8 @@ enum OutputFormat {
|
||||||
impl Display for OutputFormat {
|
impl Display for OutputFormat {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Table => Display::fmt("table", f),
|
OutputFormat::Table => Display::fmt("table", f),
|
||||||
Self::Json => Display::fmt("json", f),
|
OutputFormat::Json => Display::fmt("json", f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,9 +100,9 @@ enum Color {
|
||||||
impl Display for Color {
|
impl Display for Color {
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Self::Auto => Display::fmt("auto", f),
|
Color::Auto => Display::fmt("auto", f),
|
||||||
Self::Never => Display::fmt("never", f),
|
Color::Never => Display::fmt("never", f),
|
||||||
Self::Always => Display::fmt("always", f),
|
Color::Always => Display::fmt("always", f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,6 +343,18 @@ async fn handle_list(conf: Config, args: List) -> Result<()> {
|
||||||
result: Vec<DnsResponse>,
|
result: Vec<DnsResponse>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Tabled)]
|
||||||
|
#[tabled(rename_all = "PascalCase")]
|
||||||
|
struct DnsResponse {
|
||||||
|
name: String,
|
||||||
|
#[tabled(rename = "Type")]
|
||||||
|
r#type: RecordType,
|
||||||
|
#[tabled(rename = "IP Address")]
|
||||||
|
content: IpAddr,
|
||||||
|
proxied: bool,
|
||||||
|
id: String,
|
||||||
|
}
|
||||||
|
|
||||||
let mut entries = vec![];
|
let mut entries = vec![];
|
||||||
for page_no in 1.. {
|
for page_no in 1.. {
|
||||||
// This technically requests one more than optimal, but tbh it
|
// This technically requests one more than optimal, but tbh it
|
||||||
|
@ -382,62 +394,39 @@ async fn handle_list(conf: Config, args: List) -> Result<()> {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(human, zone)| (zone.id, human))
|
.map(|(human, zone)| (zone.id, human))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
match args.output {
|
match args.output {
|
||||||
OutputFormat::Table => print_table(&human_readable_mapping, output),
|
OutputFormat::Table => {
|
||||||
OutputFormat::Json => print_json(&human_readable_mapping, output),
|
for (zone_id, data) in output {
|
||||||
|
println!(
|
||||||
|
"{} ({zone_id})\n{}",
|
||||||
|
human_readable_mapping.get(&zone_id).unwrap(),
|
||||||
|
Table::new(data).with(Modify::new(Column::from(0)).with(Alignment::right()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
OutputFormat::Json => {
|
||||||
|
let map: serde_json::Map<String, serde_json::Value> = output
|
||||||
|
.into_iter()
|
||||||
|
.map(|(zone_id, data)| {
|
||||||
|
(
|
||||||
|
human_readable_mapping.get(&zone_id).unwrap().clone(),
|
||||||
|
json!({
|
||||||
|
"id": zone_id,
|
||||||
|
"records": data,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
println!(
|
||||||
|
"{}",
|
||||||
|
serde_json::to_string(&map).expect("serialization to work")
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Tabled)]
|
|
||||||
#[tabled(rename_all = "PascalCase")]
|
|
||||||
struct DnsResponse {
|
|
||||||
name: String,
|
|
||||||
#[tabled(rename = "Type")]
|
|
||||||
r#type: RecordType,
|
|
||||||
#[tabled(rename = "IP Address")]
|
|
||||||
content: IpAddr,
|
|
||||||
proxied: bool,
|
|
||||||
id: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print_table(
|
|
||||||
human_readable_mapping: &HashMap<String, String>,
|
|
||||||
output: BTreeMap<String, Vec<DnsResponse>>,
|
|
||||||
) {
|
|
||||||
for (zone_id, data) in output {
|
|
||||||
println!(
|
|
||||||
"{} ({zone_id})\n{}",
|
|
||||||
human_readable_mapping.get(&zone_id).unwrap(),
|
|
||||||
Table::new(data).with(Modify::new(Column::from(0)).with(Alignment::right()))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn print_json(
|
|
||||||
human_readable_mapping: &HashMap<String, String>,
|
|
||||||
output: BTreeMap<String, Vec<DnsResponse>>,
|
|
||||||
) {
|
|
||||||
let map: serde_json::Map<String, serde_json::Value> = output
|
|
||||||
.into_iter()
|
|
||||||
.map(|(zone_id, data)| {
|
|
||||||
(
|
|
||||||
human_readable_mapping.get(&zone_id).unwrap().clone(),
|
|
||||||
json!({
|
|
||||||
"id": zone_id,
|
|
||||||
"records": data,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
println!(
|
|
||||||
"{}",
|
|
||||||
serde_json::to_string(&map).expect("serialization to work")
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn get_ipv4(url: Url) -> Result<Ipv4Addr> {
|
async fn get_ipv4(url: Url) -> Result<Ipv4Addr> {
|
||||||
reqwest::get(url)
|
reqwest::get(url)
|
||||||
.await
|
.await
|
||||||
|
@ -522,7 +511,7 @@ fn load_config_from_path<P: AsRef<Path>>(path: P) -> Option<Config> {
|
||||||
let current_mode = metadata.permissions().mode() & 0o777;
|
let current_mode = metadata.permissions().mode() & 0o777;
|
||||||
if current_mode != 0o600 {
|
if current_mode != 0o600 {
|
||||||
warn!(
|
warn!(
|
||||||
found = format!("{current_mode:o}"),
|
found = format!("{:o}", current_mode),
|
||||||
expected = "600",
|
expected = "600",
|
||||||
"File permissions too broad! Your GLOBAL Cloudflare API key is accessible to all users on the system!"
|
"File permissions too broad! Your GLOBAL Cloudflare API key is accessible to all users on the system!"
|
||||||
);
|
);
|
||||||
|
|
Loading…
Reference in a new issue