Compare commits
3 commits
87001a9850
...
a5c55115cf
Author | SHA1 | Date | |
---|---|---|---|
a5c55115cf | |||
569758bee5 | |||
537225dff2 |
1 changed files with 57 additions and 46 deletions
103
src/main.rs
103
src/main.rs
|
@ -1,4 +1,4 @@
|
||||||
#![warn(clippy::pedantic, clippy::cargo)]
|
#![warn(clippy::pedantic, clippy::cargo, clippy::nursery)]
|
||||||
|
|
||||||
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 {
|
||||||
OutputFormat::Table => Display::fmt("table", f),
|
Self::Table => Display::fmt("table", f),
|
||||||
OutputFormat::Json => Display::fmt("json", f),
|
Self::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 {
|
||||||
Color::Auto => Display::fmt("auto", f),
|
Self::Auto => Display::fmt("auto", f),
|
||||||
Color::Never => Display::fmt("never", f),
|
Self::Never => Display::fmt("never", f),
|
||||||
Color::Always => Display::fmt("always", f),
|
Self::Always => Display::fmt("always", f),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,18 +343,6 @@ 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
|
||||||
|
@ -394,39 +382,62 @@ 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 => {
|
OutputFormat::Table => print_table(&human_readable_mapping, output),
|
||||||
for (zone_id, data) in output {
|
OutputFormat::Json => print_json(&human_readable_mapping, 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
|
||||||
|
@ -511,7 +522,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!("{:o}", current_mode),
|
found = format!("{current_mode:o}"),
|
||||||
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