add basic record creation route
This commit is contained in:
parent
936addb624
commit
b7db84e9a8
3 changed files with 60 additions and 20 deletions
|
@ -18,7 +18,7 @@ use super::trust_dns_types::{self, Name};
|
|||
use crate::config::Config;
|
||||
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[derive(Deserialize, Serialize, Clone)]
|
||||
#[serde(tag = "Type")]
|
||||
#[serde(rename_all = "UPPERCASE")]
|
||||
pub enum RData {
|
||||
|
@ -101,6 +101,8 @@ pub enum RData {
|
|||
data: String,
|
||||
},
|
||||
// ZERO,
|
||||
|
||||
// TODO: DS
|
||||
}
|
||||
|
||||
impl From<trust_dns_types::RData> for RData {
|
||||
|
@ -156,6 +158,7 @@ impl From<trust_dns_types::RData> for RData {
|
|||
fingerprint: trust_dns_types::sshfp::HEX.encode(sshfp.fingerprint()),
|
||||
},
|
||||
//TODO: This might alter data if not utf8 compatible, probably need to be replaced
|
||||
//TODO: check whether concatenating txt data is harmful or not
|
||||
trust_dns_types::RData::TXT(txt) => RData::TXT { text: format!("{}", txt) },
|
||||
trust_dns_types::RData::DNSSEC(data) => RData::DNSSEC(data),
|
||||
rdata => {
|
||||
|
@ -284,7 +287,7 @@ impl<'a> fmt::Display for CAAValue<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[derive(Deserialize, Serialize, Clone)]
|
||||
pub enum DNSClass {
|
||||
IN,
|
||||
CH,
|
||||
|
@ -340,7 +343,7 @@ where
|
|||
|
||||
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
#[derive(Deserialize, Serialize, Clone)]
|
||||
pub struct Record {
|
||||
#[serde(rename = "Name")]
|
||||
pub name: SerdeName,
|
||||
|
@ -374,7 +377,7 @@ impl TryFrom<Record> for trust_dns_types::Record {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SerdeName(Name);
|
||||
|
||||
impl<'de> Deserialize<'de> for SerdeName {
|
||||
|
|
|
@ -24,7 +24,7 @@ use crate::models::errors::{ErrorResponse, make_500};
|
|||
use crate::models::dns::AbsoluteName;
|
||||
|
||||
const BEARER: &str = "Bearer ";
|
||||
const AUTH_HEADER: &str = "Authentication";
|
||||
const AUTH_HEADER: &str = "Authorization";
|
||||
|
||||
|
||||
#[derive(Debug, DbEnum, Deserialize, Clone)]
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
use std::convert::TryFrom;
|
||||
use std::convert::TryInto;
|
||||
|
||||
use serde_json::json;
|
||||
use rocket::Response;
|
||||
use rocket::http::Status;
|
||||
|
||||
use rocket_contrib::json::Json;
|
||||
|
||||
use serde_json::json;
|
||||
|
||||
use trust_dns_client::{client::ClientHandle, op::UpdateMessage};
|
||||
use trust_dns_client::op::ResponseCode;
|
||||
use trust_dns_client::rr::{DNSClass, RecordType};
|
||||
|
@ -50,8 +47,10 @@ pub async fn get_zone_records(
|
|||
println!("Querrying AXFR of zone {} failed with code {}", *zone, response.response_code());
|
||||
return ErrorResponse::new(
|
||||
Status::NotFound,
|
||||
format!("Zone {} could not be found", *zone)
|
||||
).err()
|
||||
"Zone could not be found".into()
|
||||
).with_details(json!({
|
||||
"zone_name": zone.to_utf8()
|
||||
})).err();
|
||||
}
|
||||
|
||||
let answers = response.answers();
|
||||
|
@ -85,21 +84,46 @@ pub async fn create_zone_records(
|
|||
user_info.get_zone(c, &zone_name)
|
||||
}
|
||||
}).await?;
|
||||
|
||||
// TODO: What about relative names (also in cnames and stuff)
|
||||
// TODO: error handling
|
||||
let records: Vec<trust_dns_types::Record> = new_records.into_inner().into_iter().map(|r| r.try_into().unwrap()).collect();
|
||||
let mut bad_records = Vec::new();
|
||||
let mut records: Vec<trust_dns_types::Record> = Vec::new();
|
||||
|
||||
for record in new_records.into_inner().into_iter() {
|
||||
let this_record = record.clone();
|
||||
if let Ok(record) = record.try_into() {
|
||||
records.push(record);
|
||||
} else {
|
||||
bad_records.push(this_record.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let bad_zone_records: Vec<_> = records.iter().filter(|record| !zone.zone_of(record.name())).collect();
|
||||
// TODO: Get zone class from somewhere instead of always assuming IN
|
||||
let bad_class_records: Vec<_> = records.iter().filter(|record| record.dns_class() != DNSClass::IN).collect();
|
||||
|
||||
if !bad_records.is_empty() {
|
||||
return ErrorResponse::new(
|
||||
Status::BadRequest,
|
||||
"Record list contains records that could not been parsed into DNS records".into()
|
||||
).with_details(
|
||||
json!({
|
||||
"zone_name": zone.to_utf8(),
|
||||
"records": bad_records
|
||||
})
|
||||
).err();
|
||||
}
|
||||
|
||||
if !bad_zone_records.is_empty() {
|
||||
return ErrorResponse::new(
|
||||
Status::BadRequest,
|
||||
format!("Record list contains records whose name that do not belong to the zone {}", *zone)
|
||||
"Record list contains records whose name does not belong to the zone".into()
|
||||
).with_details(
|
||||
json!(bad_zone_records.into_iter().map(|r| r.name().to_utf8()).collect::<Vec<_>>())
|
||||
).err()
|
||||
json!({
|
||||
"zone_name": zone.to_utf8(),
|
||||
"records": bad_zone_records.into_iter().map(|r| r.clone().into()).collect::<Vec<dns::Record>>()
|
||||
})
|
||||
).err();
|
||||
}
|
||||
|
||||
if !bad_class_records.is_empty() {
|
||||
|
@ -107,8 +131,11 @@ pub async fn create_zone_records(
|
|||
Status::BadRequest,
|
||||
"Record list contains records whose class differs from the zone class `IN`".into()
|
||||
).with_details(
|
||||
json!(bad_class_records.into_iter().map(|r| r.name().to_utf8()).collect::<Vec<_>>())
|
||||
).err()
|
||||
json!({
|
||||
"zone_name": zone.to_utf8(),
|
||||
"records": bad_class_records.into_iter().map(|r| r.clone().into()).collect::<Vec<dns::Record>>()
|
||||
})
|
||||
).err();
|
||||
}
|
||||
|
||||
let mut zone_query = Query::new();
|
||||
|
@ -132,12 +159,22 @@ pub async fn create_zone_records(
|
|||
edns.set_version(0);
|
||||
}
|
||||
|
||||
// TODO: check if NOERROR or something
|
||||
let _response = {
|
||||
let response = {
|
||||
let query = dns::ClientResponse(client.send(message));
|
||||
query.await.map_err(make_500)?
|
||||
};
|
||||
|
||||
// TODO: better error handling
|
||||
if response.response_code() != ResponseCode::NoError {
|
||||
println!("Update of zone {} failed with code {}", *zone, response.response_code());
|
||||
return ErrorResponse::new(
|
||||
Status::NotFound,
|
||||
"Update of zone failed".into()
|
||||
).with_details(json!({
|
||||
"zone_name": zone.to_utf8()
|
||||
})).err();
|
||||
}
|
||||
|
||||
Ok(Json(()))
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue