rearchitecture modules
This commit is contained in:
parent
d4079b0674
commit
ae6c94e2a7
11 changed files with 173 additions and 167 deletions
|
@ -1,40 +0,0 @@
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use super::trust_dns_types;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Deserialize, Serialize, Clone)]
|
|
||||||
pub enum DNSClass {
|
|
||||||
IN,
|
|
||||||
CH,
|
|
||||||
HS,
|
|
||||||
NONE,
|
|
||||||
ANY,
|
|
||||||
OPT(u16),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<trust_dns_types::DNSClass> for DNSClass {
|
|
||||||
fn from(dns_class: trust_dns_types::DNSClass) -> DNSClass {
|
|
||||||
match dns_class {
|
|
||||||
trust_dns_types::DNSClass::IN => DNSClass::IN,
|
|
||||||
trust_dns_types::DNSClass::CH => DNSClass::CH,
|
|
||||||
trust_dns_types::DNSClass::HS => DNSClass::HS,
|
|
||||||
trust_dns_types::DNSClass::NONE => DNSClass::NONE,
|
|
||||||
trust_dns_types::DNSClass::ANY => DNSClass::ANY,
|
|
||||||
trust_dns_types::DNSClass::OPT(v) => DNSClass::OPT(v),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<DNSClass> for trust_dns_types::DNSClass {
|
|
||||||
fn from(dns_class: DNSClass) -> trust_dns_types::DNSClass {
|
|
||||||
match dns_class {
|
|
||||||
DNSClass::IN => trust_dns_types::DNSClass::IN,
|
|
||||||
DNSClass::CH => trust_dns_types::DNSClass::CH,
|
|
||||||
DNSClass::HS => trust_dns_types::DNSClass::HS,
|
|
||||||
DNSClass::NONE => trust_dns_types::DNSClass::NONE,
|
|
||||||
DNSClass::ANY => trust_dns_types::DNSClass::ANY,
|
|
||||||
DNSClass::OPT(v) => trust_dns_types::DNSClass::OPT(v),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,7 @@ use trust_dns_client::error::ClientError;
|
||||||
use trust_dns_proto::error::ProtoError;
|
use trust_dns_proto::error::ProtoError;
|
||||||
use trust_dns_client::proto::xfer::{DnsRequestOptions};
|
use trust_dns_client::proto::xfer::{DnsRequestOptions};
|
||||||
|
|
||||||
use super::trust_dns_types::{Name, Record, RData};
|
use super::{Name, Record, RData};
|
||||||
use super::client::{ClientResponse};
|
use super::client::{ClientResponse};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
pub mod class;
|
|
||||||
pub mod name;
|
|
||||||
pub mod rdata;
|
|
||||||
pub mod record;
|
|
||||||
pub mod client;
|
pub mod client;
|
||||||
pub mod message;
|
pub mod message;
|
||||||
|
|
||||||
pub mod trust_dns_types {
|
// Reexport trust dns types for convenience
|
||||||
pub use trust_dns_client::rr::rdata::{
|
pub use trust_dns_client::rr::rdata::{
|
||||||
DNSSECRData, caa, sshfp, mx, null, soa, srv, txt
|
DNSSECRData, caa, sshfp, mx, null, soa, srv, txt
|
||||||
};
|
};
|
||||||
|
@ -13,4 +9,3 @@ pub mod trust_dns_types {
|
||||||
RData, DNSClass, Record
|
RData, DNSClass, Record
|
||||||
};
|
};
|
||||||
pub use trust_dns_proto::rr::Name;
|
pub use trust_dns_proto::rr::Name;
|
||||||
}
|
|
40
src/models/class.rs
Normal file
40
src/models/class.rs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
use crate::dns;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize, Clone)]
|
||||||
|
pub enum DNSClass {
|
||||||
|
IN,
|
||||||
|
CH,
|
||||||
|
HS,
|
||||||
|
NONE,
|
||||||
|
ANY,
|
||||||
|
OPT(u16),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<dns::DNSClass> for DNSClass {
|
||||||
|
fn from(dns_class: dns::DNSClass) -> DNSClass {
|
||||||
|
match dns_class {
|
||||||
|
dns::DNSClass::IN => DNSClass::IN,
|
||||||
|
dns::DNSClass::CH => DNSClass::CH,
|
||||||
|
dns::DNSClass::HS => DNSClass::HS,
|
||||||
|
dns::DNSClass::NONE => DNSClass::NONE,
|
||||||
|
dns::DNSClass::ANY => DNSClass::ANY,
|
||||||
|
dns::DNSClass::OPT(v) => DNSClass::OPT(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<DNSClass> for dns::DNSClass {
|
||||||
|
fn from(dns_class: DNSClass) -> dns::DNSClass {
|
||||||
|
match dns_class {
|
||||||
|
DNSClass::IN => dns::DNSClass::IN,
|
||||||
|
DNSClass::CH => dns::DNSClass::CH,
|
||||||
|
DNSClass::HS => dns::DNSClass::HS,
|
||||||
|
DNSClass::NONE => dns::DNSClass::NONE,
|
||||||
|
DNSClass::ANY => dns::DNSClass::ANY,
|
||||||
|
DNSClass::OPT(v) => dns::DNSClass::OPT(v),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,19 @@
|
||||||
//pub mod dns;
|
//pub mod dns;
|
||||||
|
pub mod auth;
|
||||||
|
pub mod class;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
|
pub mod name;
|
||||||
|
pub mod rdata;
|
||||||
|
pub mod record;
|
||||||
pub mod user;
|
pub mod user;
|
||||||
pub mod zone;
|
pub mod zone;
|
||||||
pub mod auth;
|
|
||||||
|
// Reexport types for convenience
|
||||||
|
pub use auth::{AuthClaims, AuthTokenRequest, AuthTokenResponse};
|
||||||
|
pub use class::DNSClass;
|
||||||
|
pub use errors::{UserError, ErrorResponse, make_500};
|
||||||
|
pub use name::{AbsoluteName, SerdeName};
|
||||||
|
pub use user::{LocalUser, UserInfo, Role, UserZone, User, CreateUserRequest};
|
||||||
|
pub use rdata::RData;
|
||||||
|
pub use record::Record;
|
||||||
|
pub use zone::{Zone, AddZoneMemberRequest, CreateZoneRequest};
|
|
@ -5,7 +5,7 @@ use rocket::request::FromParam;
|
||||||
use serde::{Deserialize, Serialize, Deserializer, Serializer};
|
use serde::{Deserialize, Serialize, Deserializer, Serializer};
|
||||||
use trust_dns_proto::error::ProtoError;
|
use trust_dns_proto::error::ProtoError;
|
||||||
|
|
||||||
use super::trust_dns_types::Name;
|
use crate::dns::Name;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
|
@ -7,7 +7,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use trust_dns_client::serialize::binary::BinEncoder;
|
use trust_dns_client::serialize::binary::BinEncoder;
|
||||||
use trust_dns_proto::error::ProtoError;
|
use trust_dns_proto::error::ProtoError;
|
||||||
|
|
||||||
use super::trust_dns_types;
|
use crate::dns;
|
||||||
use super::name::SerdeName;
|
use super::name::SerdeName;
|
||||||
|
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ pub enum RData {
|
||||||
|
|
||||||
// TODO: Eventually allow deserialization of DNSSEC records
|
// TODO: Eventually allow deserialization of DNSSEC records
|
||||||
#[serde(skip)]
|
#[serde(skip)]
|
||||||
DNSSEC(trust_dns_types::DNSSECRData),
|
DNSSEC(dns::DNSSECRData),
|
||||||
#[serde(rename_all = "PascalCase")]
|
#[serde(rename_all = "PascalCase")]
|
||||||
Unknown {
|
Unknown {
|
||||||
code: u16,
|
code: u16,
|
||||||
|
@ -99,39 +99,39 @@ pub enum RData {
|
||||||
// TODO: TLSA
|
// TODO: TLSA
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<trust_dns_types::RData> for RData {
|
impl From<dns::RData> for RData {
|
||||||
fn from(rdata: trust_dns_types::RData) -> RData {
|
fn from(rdata: dns::RData) -> RData {
|
||||||
match rdata {
|
match rdata {
|
||||||
trust_dns_types::RData::A(address) => RData::A { address },
|
dns::RData::A(address) => RData::A { address },
|
||||||
trust_dns_types::RData::AAAA(address) => RData::AAAA { address },
|
dns::RData::AAAA(address) => RData::AAAA { address },
|
||||||
// Still a draft, no iana number yet, I don't to put something that is not currently supported so that's why NULL and not unknown.
|
// Still a draft, no iana number yet, I don't to put something that is not currently supported so that's why NULL and not unknown.
|
||||||
// TODO: probably need better error here, I don't know what to do about that as this would require to change the From for something else.
|
// TODO: probably need better error here, I don't know what to do about that as this would require to change the From for something else.
|
||||||
// (empty data because I'm lazy)
|
// (empty data because I'm lazy)
|
||||||
trust_dns_types::RData::ANAME(_) => RData::NULL {
|
dns::RData::ANAME(_) => RData::NULL {
|
||||||
data: String::new()
|
data: String::new()
|
||||||
},
|
},
|
||||||
trust_dns_types::RData::CNAME(target) => RData::CNAME {
|
dns::RData::CNAME(target) => RData::CNAME {
|
||||||
target: SerdeName(target)
|
target: SerdeName(target)
|
||||||
},
|
},
|
||||||
trust_dns_types::RData::CAA(caa) => RData::CAA {
|
dns::RData::CAA(caa) => RData::CAA {
|
||||||
issuer_critical: caa.issuer_critical(),
|
issuer_critical: caa.issuer_critical(),
|
||||||
value: format!("{}", CAAValue(caa.value())),
|
value: format!("{}", CAAValue(caa.value())),
|
||||||
property_tag: caa.tag().as_str().to_string(),
|
property_tag: caa.tag().as_str().to_string(),
|
||||||
},
|
},
|
||||||
trust_dns_types::RData::MX(mx) => RData::MX {
|
dns::RData::MX(mx) => RData::MX {
|
||||||
preference: mx.preference(),
|
preference: mx.preference(),
|
||||||
mail_exchanger: SerdeName(mx.exchange().clone())
|
mail_exchanger: SerdeName(mx.exchange().clone())
|
||||||
},
|
},
|
||||||
trust_dns_types::RData::NULL(null) => RData::NULL {
|
dns::RData::NULL(null) => RData::NULL {
|
||||||
data: base64::encode(null.anything().map(|data| data.to_vec()).unwrap_or_default())
|
data: base64::encode(null.anything().map(|data| data.to_vec()).unwrap_or_default())
|
||||||
},
|
},
|
||||||
trust_dns_types::RData::NS(target) => RData::NS {
|
dns::RData::NS(target) => RData::NS {
|
||||||
target: SerdeName(target)
|
target: SerdeName(target)
|
||||||
},
|
},
|
||||||
trust_dns_types::RData::PTR(target) => RData::PTR {
|
dns::RData::PTR(target) => RData::PTR {
|
||||||
target: SerdeName(target)
|
target: SerdeName(target)
|
||||||
},
|
},
|
||||||
trust_dns_types::RData::SOA(soa) => RData::SOA {
|
dns::RData::SOA(soa) => RData::SOA {
|
||||||
master_server_name: SerdeName(soa.mname().clone()),
|
master_server_name: SerdeName(soa.mname().clone()),
|
||||||
maintainer_name: SerdeName(soa.rname().clone()),
|
maintainer_name: SerdeName(soa.rname().clone()),
|
||||||
refresh: soa.refresh(),
|
refresh: soa.refresh(),
|
||||||
|
@ -140,21 +140,21 @@ impl From<trust_dns_types::RData> for RData {
|
||||||
minimum: soa.minimum(),
|
minimum: soa.minimum(),
|
||||||
serial: soa.serial()
|
serial: soa.serial()
|
||||||
},
|
},
|
||||||
trust_dns_types::RData::SRV(srv) => RData::SRV {
|
dns::RData::SRV(srv) => RData::SRV {
|
||||||
server: SerdeName(srv.target().clone()),
|
server: SerdeName(srv.target().clone()),
|
||||||
port: srv.port(),
|
port: srv.port(),
|
||||||
priority: srv.priority(),
|
priority: srv.priority(),
|
||||||
weight: srv.weight(),
|
weight: srv.weight(),
|
||||||
},
|
},
|
||||||
trust_dns_types::RData::SSHFP(sshfp) => RData::SSHFP {
|
dns::RData::SSHFP(sshfp) => RData::SSHFP {
|
||||||
algorithm: sshfp.algorithm().into(),
|
algorithm: sshfp.algorithm().into(),
|
||||||
digest_type: sshfp.fingerprint_type().into(),
|
digest_type: sshfp.fingerprint_type().into(),
|
||||||
fingerprint: trust_dns_types::sshfp::HEX.encode(sshfp.fingerprint()),
|
fingerprint: dns::sshfp::HEX.encode(sshfp.fingerprint()),
|
||||||
},
|
},
|
||||||
//TODO: This might alter data if not utf8 compatible, probably need to be replaced
|
//TODO: This might alter data if not utf8 compatible, probably need to be replaced
|
||||||
//TODO: check whether concatenating txt data is harmful or not
|
//TODO: check whether concatenating txt data is harmful or not
|
||||||
trust_dns_types::RData::TXT(txt) => RData::TXT { text: format!("{}", txt) },
|
dns::RData::TXT(txt) => RData::TXT { text: format!("{}", txt) },
|
||||||
trust_dns_types::RData::DNSSEC(data) => RData::DNSSEC(data),
|
dns::RData::DNSSEC(data) => RData::DNSSEC(data),
|
||||||
rdata => {
|
rdata => {
|
||||||
let code = rdata.to_record_type().into();
|
let code = rdata.to_record_type().into();
|
||||||
let mut data = Vec::new();
|
let mut data = Vec::new();
|
||||||
|
@ -171,48 +171,48 @@ impl From<trust_dns_types::RData> for RData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<RData> for trust_dns_types::RData {
|
impl TryFrom<RData> for dns::RData {
|
||||||
type Error = ProtoError;
|
type Error = ProtoError;
|
||||||
|
|
||||||
fn try_from(rdata: RData) -> Result<Self, Self::Error> {
|
fn try_from(rdata: RData) -> Result<Self, Self::Error> {
|
||||||
Ok(match rdata {
|
Ok(match rdata {
|
||||||
RData::A { address } => trust_dns_types::RData::A(address),
|
RData::A { address } => dns::RData::A(address),
|
||||||
RData::AAAA { address } => trust_dns_types::RData::AAAA(address),
|
RData::AAAA { address } => dns::RData::AAAA(address),
|
||||||
// TODO: Round trip test all types below (currently not tested...)
|
// TODO: Round trip test all types below (currently not tested...)
|
||||||
RData::CAA { issuer_critical, value, property_tag } => {
|
RData::CAA { issuer_critical, value, property_tag } => {
|
||||||
let property = trust_dns_types::caa::Property::from(property_tag);
|
let property = dns::caa::Property::from(property_tag);
|
||||||
let caa_value = {
|
let caa_value = {
|
||||||
// TODO: duplicate of trust_dns_client::serialize::txt::rdata_parser::caa::parse
|
// TODO: duplicate of trust_dns_client::serialize::txt::rdata_parser::caa::parse
|
||||||
// because caa::read_value is private
|
// because caa::read_value is private
|
||||||
match property {
|
match property {
|
||||||
trust_dns_types::caa::Property::Issue | trust_dns_types::caa::Property::IssueWild => {
|
dns::caa::Property::Issue | dns::caa::Property::IssueWild => {
|
||||||
let value = trust_dns_types::caa::read_issuer(value.as_bytes())?;
|
let value = dns::caa::read_issuer(value.as_bytes())?;
|
||||||
trust_dns_types::caa::Value::Issuer(value.0, value.1)
|
dns::caa::Value::Issuer(value.0, value.1)
|
||||||
}
|
}
|
||||||
trust_dns_types::caa::Property::Iodef => {
|
dns::caa::Property::Iodef => {
|
||||||
let url = trust_dns_types::caa::read_iodef(value.as_bytes())?;
|
let url = dns::caa::read_iodef(value.as_bytes())?;
|
||||||
trust_dns_types::caa::Value::Url(url)
|
dns::caa::Value::Url(url)
|
||||||
}
|
}
|
||||||
trust_dns_types::caa::Property::Unknown(_) => trust_dns_types::caa::Value::Unknown(value.as_bytes().to_vec()),
|
dns::caa::Property::Unknown(_) => dns::caa::Value::Unknown(value.as_bytes().to_vec()),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
trust_dns_types::RData::CAA(trust_dns_types::caa::CAA {
|
dns::RData::CAA(dns::caa::CAA {
|
||||||
issuer_critical,
|
issuer_critical,
|
||||||
tag: property,
|
tag: property,
|
||||||
value: caa_value,
|
value: caa_value,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
RData::CNAME { target } => trust_dns_types::RData::CNAME(target.into_inner()),
|
RData::CNAME { target } => dns::RData::CNAME(target.into_inner()),
|
||||||
RData::MX { preference, mail_exchanger } => trust_dns_types::RData::MX(
|
RData::MX { preference, mail_exchanger } => dns::RData::MX(
|
||||||
trust_dns_types::mx::MX::new(preference, mail_exchanger.into_inner())
|
dns::mx::MX::new(preference, mail_exchanger.into_inner())
|
||||||
),
|
),
|
||||||
RData::NULL { data } => trust_dns_types::RData::NULL(
|
RData::NULL { data } => dns::RData::NULL(
|
||||||
trust_dns_types::null::NULL::with(
|
dns::null::NULL::with(
|
||||||
base64::decode(data).map_err(|e| ProtoError::from(format!("{}", e)))?
|
base64::decode(data).map_err(|e| ProtoError::from(format!("{}", e)))?
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
RData::NS { target } => trust_dns_types::RData::NS(target.into_inner()),
|
RData::NS { target } => dns::RData::NS(target.into_inner()),
|
||||||
RData::PTR { target } => trust_dns_types::RData::PTR(target.into_inner()),
|
RData::PTR { target } => dns::RData::PTR(target.into_inner()),
|
||||||
RData::SOA {
|
RData::SOA {
|
||||||
master_server_name,
|
master_server_name,
|
||||||
maintainer_name,
|
maintainer_name,
|
||||||
|
@ -221,8 +221,8 @@ impl TryFrom<RData> for trust_dns_types::RData {
|
||||||
expire,
|
expire,
|
||||||
minimum,
|
minimum,
|
||||||
serial
|
serial
|
||||||
} => trust_dns_types::RData::SOA(
|
} => dns::RData::SOA(
|
||||||
trust_dns_types::soa::SOA::new(
|
dns::soa::SOA::new(
|
||||||
master_server_name.into_inner(),
|
master_server_name.into_inner(),
|
||||||
maintainer_name.into_inner(),
|
maintainer_name.into_inner(),
|
||||||
serial,
|
serial,
|
||||||
|
@ -232,18 +232,18 @@ impl TryFrom<RData> for trust_dns_types::RData {
|
||||||
minimum,
|
minimum,
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
RData::SRV { server, port, priority, weight } => trust_dns_types::RData::SRV(
|
RData::SRV { server, port, priority, weight } => dns::RData::SRV(
|
||||||
trust_dns_types::srv::SRV::new(priority, weight, port, server.into_inner())
|
dns::srv::SRV::new(priority, weight, port, server.into_inner())
|
||||||
),
|
),
|
||||||
RData::SSHFP { algorithm, digest_type, fingerprint } => trust_dns_types::RData::SSHFP(
|
RData::SSHFP { algorithm, digest_type, fingerprint } => dns::RData::SSHFP(
|
||||||
trust_dns_types::sshfp::SSHFP::new(
|
dns::sshfp::SSHFP::new(
|
||||||
// NOTE: This allows unassigned algorithms
|
// NOTE: This allows unassigned algorithms
|
||||||
trust_dns_types::sshfp::Algorithm::from(algorithm),
|
dns::sshfp::Algorithm::from(algorithm),
|
||||||
trust_dns_types::sshfp::FingerprintType::from(digest_type),
|
dns::sshfp::FingerprintType::from(digest_type),
|
||||||
trust_dns_types::sshfp::HEX.decode(fingerprint.as_bytes()).map_err(|e| ProtoError::from(format!("{}", e)))?
|
dns::sshfp::HEX.decode(fingerprint.as_bytes()).map_err(|e| ProtoError::from(format!("{}", e)))?
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
RData::TXT { text } => trust_dns_types::RData::TXT(trust_dns_types::txt::TXT::new(vec![text])),
|
RData::TXT { text } => dns::RData::TXT(dns::txt::TXT::new(vec![text])),
|
||||||
// TODO: Error out for DNSSEC? Prefer downstream checks?
|
// TODO: Error out for DNSSEC? Prefer downstream checks?
|
||||||
RData::DNSSEC(_) => todo!(),
|
RData::DNSSEC(_) => todo!(),
|
||||||
// TODO: Disallow unknown? (could be used to bypass unsopported types?) Prefer downstream checks?
|
// TODO: Disallow unknown? (could be used to bypass unsopported types?) Prefer downstream checks?
|
||||||
|
@ -252,7 +252,7 @@ impl TryFrom<RData> for trust_dns_types::RData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CAAValue<'a>(&'a trust_dns_types::caa::Value);
|
struct CAAValue<'a>(&'a dns::caa::Value);
|
||||||
|
|
||||||
// trust_dns Display implementation panics if no parameters
|
// trust_dns Display implementation panics if no parameters
|
||||||
// Implementation based on caa::emit_value
|
// Implementation based on caa::emit_value
|
||||||
|
@ -260,7 +260,7 @@ struct CAAValue<'a>(&'a trust_dns_types::caa::Value);
|
||||||
impl<'a> fmt::Display for CAAValue<'a> {
|
impl<'a> fmt::Display for CAAValue<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
|
||||||
match self.0 {
|
match self.0 {
|
||||||
trust_dns_types::caa::Value::Issuer(name, parameters) => {
|
dns::caa::Value::Issuer(name, parameters) => {
|
||||||
|
|
||||||
if let Some(name) = name {
|
if let Some(name) = name {
|
||||||
write!(f, "{}", name)?;
|
write!(f, "{}", name)?;
|
||||||
|
@ -274,8 +274,8 @@ impl<'a> fmt::Display for CAAValue<'a> {
|
||||||
write!(f, "; {}", value)?;
|
write!(f, "; {}", value)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
trust_dns_types::caa::Value::Url(url) => write!(f, "{}", url)?,
|
dns::caa::Value::Url(url) => write!(f, "{}", url)?,
|
||||||
trust_dns_types::caa::Value::Unknown(v) => write!(f, "{:?}", v)?,
|
dns::caa::Value::Unknown(v) => write!(f, "{:?}", v)?,
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@ use std::convert::{TryFrom, TryInto};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use trust_dns_proto::error::ProtoError;
|
use trust_dns_proto::error::ProtoError;
|
||||||
|
|
||||||
use super::trust_dns_types;
|
use crate::dns;
|
||||||
use super::name::SerdeName;
|
use super::name::SerdeName;
|
||||||
use super::class::DNSClass;
|
use super::class::DNSClass;
|
||||||
use super::rdata::RData;
|
use super::rdata::RData;
|
||||||
|
@ -21,8 +21,8 @@ pub struct Record {
|
||||||
pub rdata: RData,
|
pub rdata: RData,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<trust_dns_types::Record> for Record {
|
impl From<dns::Record> for Record {
|
||||||
fn from(record: trust_dns_types::Record) -> Record {
|
fn from(record: dns::Record) -> Record {
|
||||||
Record {
|
Record {
|
||||||
name: SerdeName(record.name().clone()),
|
name: SerdeName(record.name().clone()),
|
||||||
dns_class: record.dns_class().into(),
|
dns_class: record.dns_class().into(),
|
||||||
|
@ -32,11 +32,11 @@ impl From<trust_dns_types::Record> for Record {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<Record> for trust_dns_types::Record {
|
impl TryFrom<Record> for dns::Record {
|
||||||
type Error = ProtoError;
|
type Error = ProtoError;
|
||||||
|
|
||||||
fn try_from(record: Record) -> Result<Self, Self::Error> {
|
fn try_from(record: Record) -> Result<Self, Self::Error> {
|
||||||
let mut trust_dns_record = trust_dns_types::Record::from_rdata(record.name.into_inner(), record.ttl, record.rdata.try_into()?);
|
let mut trust_dns_record = dns::Record::from_rdata(record.name.into_inner(), record.ttl, record.rdata.try_into()?);
|
||||||
trust_dns_record.set_dns_class(record.dns_class.into());
|
trust_dns_record.set_dns_class(record.dns_class.into());
|
||||||
Ok(trust_dns_record)
|
Ok(trust_dns_record)
|
||||||
}
|
}
|
|
@ -6,9 +6,9 @@ use diesel::result::Error as DieselError;
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
use crate::schema::*;
|
use crate::schema::*;
|
||||||
use crate::dns::name::AbsoluteName;
|
use super::name::AbsoluteName;
|
||||||
use crate::models::user::UserZone;
|
use super::user::UserZone;
|
||||||
use crate::models::errors::UserError;
|
use super::errors::UserError;
|
||||||
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Queryable, Identifiable, Insertable)]
|
#[derive(Debug, Serialize, Queryable, Identifiable, Insertable)]
|
||||||
|
|
|
@ -4,34 +4,32 @@ use rocket::http::Status;
|
||||||
|
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::DbConn;
|
use crate::DbConn;
|
||||||
use crate::models::errors::{ErrorResponse, make_500};
|
use crate::models;
|
||||||
use crate::models::user::{LocalUser, CreateUserRequest};
|
|
||||||
use crate::models::auth::{AuthClaims, AuthTokenRequest, AuthTokenResponse};
|
|
||||||
|
|
||||||
|
|
||||||
#[post("/users/me/token", data = "<auth_request>")]
|
#[post("/users/me/token", data = "<auth_request>")]
|
||||||
pub async fn create_auth_token(
|
pub async fn create_auth_token(
|
||||||
conn: DbConn,
|
conn: DbConn,
|
||||||
config: State<'_, Config>,
|
config: State<'_, Config>,
|
||||||
auth_request: Json<AuthTokenRequest>
|
auth_request: Json<models::AuthTokenRequest>
|
||||||
) -> Result<Json<AuthTokenResponse>, ErrorResponse> {
|
) -> Result<Json<models::AuthTokenResponse>, models::ErrorResponse> {
|
||||||
|
|
||||||
let user_info = conn.run(move |c| {
|
let user_info = conn.run(move |c| {
|
||||||
LocalUser::get_user_by_creds(c, &auth_request.username, &auth_request.password)
|
models::LocalUser::get_user_by_creds(c, &auth_request.username, &auth_request.password)
|
||||||
}).await?;
|
}).await?;
|
||||||
|
|
||||||
let token = AuthClaims::new(&user_info, config.web_app.token_duration)
|
let token = models::AuthClaims::new(&user_info, config.web_app.token_duration)
|
||||||
.encode(&config.web_app.secret)
|
.encode(&config.web_app.secret)
|
||||||
.map_err(make_500)?;
|
.map_err(models::make_500)?;
|
||||||
|
|
||||||
Ok(Json(AuthTokenResponse { token }))
|
Ok(Json(models::AuthTokenResponse { token }))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[post("/users", data = "<user_request>")]
|
#[post("/users", data = "<user_request>")]
|
||||||
pub async fn create_user<'r>(conn: DbConn, user_request: Json<CreateUserRequest>) -> Result<Response<'r>, ErrorResponse> {
|
pub async fn create_user<'r>(conn: DbConn, user_request: Json<models::CreateUserRequest>) -> Result<Response<'r>, models::ErrorResponse> {
|
||||||
// TODO: Check current user if any to check if user has permission to create users (with or without role)
|
// TODO: Check current user if any to check if user has permission to create users (with or without role)
|
||||||
conn.run(|c| {
|
conn.run(|c| {
|
||||||
LocalUser::create_user(&c, user_request.into_inner())
|
models::LocalUser::create_user(&c, user_request.into_inner())
|
||||||
}).await?;
|
}).await?;
|
||||||
|
|
||||||
Response::build()
|
Response::build()
|
||||||
|
|
|
@ -9,46 +9,45 @@ use trust_dns_client::client::ClientHandle;
|
||||||
use trust_dns_client::op::ResponseCode;
|
use trust_dns_client::op::ResponseCode;
|
||||||
use trust_dns_client::rr::{DNSClass, RecordType};
|
use trust_dns_client::rr::{DNSClass, RecordType};
|
||||||
|
|
||||||
use crate::{dns::{self, trust_dns_types}, DbConn};
|
use crate::DbConn;
|
||||||
use crate::models::errors::{ErrorResponse, make_500};
|
use crate::dns;
|
||||||
use crate::models::user::{LocalUser, UserInfo};
|
|
||||||
use crate::models::zone::{Zone, AddZoneMemberRequest, CreateZoneRequest};
|
|
||||||
use crate::dns::message::DnsMessage;
|
use crate::dns::message::DnsMessage;
|
||||||
use crate::dns::message::MessageError;
|
use crate::dns::message::MessageError;
|
||||||
|
use crate::models;
|
||||||
|
|
||||||
|
|
||||||
#[get("/zones/<zone>/records")]
|
#[get("/zones/<zone>/records")]
|
||||||
pub async fn get_zone_records(
|
pub async fn get_zone_records(
|
||||||
mut client: dns::client::DnsClient,
|
mut client: dns::client::DnsClient,
|
||||||
conn: DbConn,
|
conn: DbConn,
|
||||||
user_info: Result<UserInfo, ErrorResponse>,
|
user_info: Result<models::UserInfo, models::ErrorResponse>,
|
||||||
zone: dns::name::AbsoluteName
|
zone: models::AbsoluteName
|
||||||
) -> Result<Json<Vec<dns::record::Record>>, ErrorResponse> {
|
) -> Result<Json<Vec<models::Record>>, models::ErrorResponse> {
|
||||||
|
|
||||||
let user_info = user_info?;
|
let user_info = user_info?;
|
||||||
let zone_name = zone.to_string();
|
let zone_name = zone.to_string();
|
||||||
|
|
||||||
conn.run(move |c| {
|
conn.run(move |c| {
|
||||||
if user_info.is_admin() {
|
if user_info.is_admin() {
|
||||||
Zone::get_by_name(c, &zone_name)
|
models::Zone::get_by_name(c, &zone_name)
|
||||||
} else {
|
} else {
|
||||||
user_info.get_zone(c, &zone_name)
|
user_info.get_zone(c, &zone_name)
|
||||||
}
|
}
|
||||||
}).await?;
|
}).await?;
|
||||||
|
|
||||||
let records: Vec<_> = match client.get_records(zone.clone(), DNSClass::IN).await {
|
let records: Vec<_> = match client.get_records(zone.clone(), DNSClass::IN).await {
|
||||||
Ok(records) => records.into_iter().map(dns::record::Record::from).collect(),
|
Ok(records) => records.into_iter().map(models::Record::from).collect(),
|
||||||
|
|
||||||
Err(MessageError::ResponceNotOk(code)) => {
|
Err(MessageError::ResponceNotOk(code)) => {
|
||||||
println!("Querrying AXFR of zone {} failed with code {}", *zone, code);
|
println!("Querrying AXFR of zone {} failed with code {}", *zone, code);
|
||||||
return ErrorResponse::new(
|
return models::ErrorResponse::new(
|
||||||
Status::NotFound,
|
Status::NotFound,
|
||||||
"Zone could not be found".into()
|
"Zone could not be found".into()
|
||||||
).with_details(json!({
|
).with_details(json!({
|
||||||
"zone_name": zone.to_utf8()
|
"zone_name": zone.to_utf8()
|
||||||
})).err();
|
})).err();
|
||||||
},
|
},
|
||||||
Err(err) => { return make_500(err).err(); },
|
Err(err) => { return models::make_500(err).err(); },
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Json(records))
|
Ok(Json(records))
|
||||||
|
@ -58,17 +57,17 @@ pub async fn get_zone_records(
|
||||||
pub async fn create_zone_records(
|
pub async fn create_zone_records(
|
||||||
mut client: dns::client::DnsClient,
|
mut client: dns::client::DnsClient,
|
||||||
conn: DbConn,
|
conn: DbConn,
|
||||||
user_info: Result<UserInfo, ErrorResponse>,
|
user_info: Result<models::UserInfo, models::ErrorResponse>,
|
||||||
zone: dns::name::AbsoluteName,
|
zone: models::AbsoluteName,
|
||||||
new_records: Json<Vec<dns::record::Record>>
|
new_records: Json<Vec<models::Record>>
|
||||||
) -> Result<Json<()>, ErrorResponse> {
|
) -> Result<Json<()>, models::ErrorResponse> {
|
||||||
|
|
||||||
let user_info = user_info?;
|
let user_info = user_info?;
|
||||||
let zone_name = zone.to_utf8();
|
let zone_name = zone.to_utf8();
|
||||||
|
|
||||||
conn.run(move |c| {
|
conn.run(move |c| {
|
||||||
if user_info.is_admin() {
|
if user_info.is_admin() {
|
||||||
Zone::get_by_name(c, &zone_name)
|
models::Zone::get_by_name(c, &zone_name)
|
||||||
} else {
|
} else {
|
||||||
user_info.get_zone(c, &zone_name)
|
user_info.get_zone(c, &zone_name)
|
||||||
}
|
}
|
||||||
|
@ -76,7 +75,7 @@ pub async fn create_zone_records(
|
||||||
|
|
||||||
// TODO: What about relative names (also in cnames and stuff)
|
// TODO: What about relative names (also in cnames and stuff)
|
||||||
let mut bad_records = Vec::new();
|
let mut bad_records = Vec::new();
|
||||||
let mut records: Vec<trust_dns_types::Record> = Vec::new();
|
let mut records: Vec<dns::Record> = Vec::new();
|
||||||
|
|
||||||
for record in new_records.into_inner().into_iter() {
|
for record in new_records.into_inner().into_iter() {
|
||||||
let this_record = record.clone();
|
let this_record = record.clone();
|
||||||
|
@ -88,7 +87,7 @@ pub async fn create_zone_records(
|
||||||
}
|
}
|
||||||
|
|
||||||
if !bad_records.is_empty() {
|
if !bad_records.is_empty() {
|
||||||
return ErrorResponse::new(
|
return models::ErrorResponse::new(
|
||||||
Status::BadRequest,
|
Status::BadRequest,
|
||||||
"Record list contains records that could not been parsed into DNS records".into()
|
"Record list contains records that could not been parsed into DNS records".into()
|
||||||
).with_details(
|
).with_details(
|
||||||
|
@ -100,27 +99,27 @@ pub async fn create_zone_records(
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = match client.add_records(zone.clone(), DNSClass::IN, records) {
|
let response = match client.add_records(zone.clone(), DNSClass::IN, records) {
|
||||||
Ok(query) => query.await.map_err(make_500)?,
|
Ok(query) => query.await.map_err(models::make_500)?,
|
||||||
Err(MessageError::RecordNotInZone { zone, class, mismatched_class, mismatched_zone}) => {
|
Err(MessageError::RecordNotInZone { zone, class, mismatched_class, mismatched_zone}) => {
|
||||||
return ErrorResponse::new(
|
return models::ErrorResponse::new(
|
||||||
Status::BadRequest,
|
Status::BadRequest,
|
||||||
"Record list contains records that do not belong to the zone".into()
|
"Record list contains records that do not belong to the zone".into()
|
||||||
).with_details(
|
).with_details(
|
||||||
json!({
|
json!({
|
||||||
"zone_name": zone.to_utf8(),
|
"zone_name": zone.to_utf8(),
|
||||||
"class": dns::class::DNSClass::from(class),
|
"class": models::DNSClass::from(class),
|
||||||
"mismatched_class": mismatched_class.into_iter().map(|r| r.clone().into()).collect::<Vec<dns::record::Record>>(),
|
"mismatched_class": mismatched_class.into_iter().map(|r| r.clone().into()).collect::<Vec<models::Record>>(),
|
||||||
"mismatched_zone": mismatched_zone.into_iter().map(|r| r.clone().into()).collect::<Vec<dns::record::Record>>(),
|
"mismatched_zone": mismatched_zone.into_iter().map(|r| r.clone().into()).collect::<Vec<models::Record>>(),
|
||||||
})
|
})
|
||||||
).err();
|
).err();
|
||||||
},
|
},
|
||||||
Err(e) => return make_500(e).err()
|
Err(e) => return models::make_500(e).err()
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: better error handling
|
// TODO: better error handling
|
||||||
if response.response_code() != ResponseCode::NoError {
|
if response.response_code() != ResponseCode::NoError {
|
||||||
println!("Update of zone {} failed with code {}", *zone, response.response_code());
|
println!("Update of zone {} failed with code {}", *zone, response.response_code());
|
||||||
return ErrorResponse::new(
|
return models::ErrorResponse::new(
|
||||||
Status::NotFound,
|
Status::NotFound,
|
||||||
"Update of zone failed".into()
|
"Update of zone failed".into()
|
||||||
).with_details(json!({
|
).with_details(json!({
|
||||||
|
@ -134,13 +133,13 @@ pub async fn create_zone_records(
|
||||||
#[get("/zones")]
|
#[get("/zones")]
|
||||||
pub async fn get_zones(
|
pub async fn get_zones(
|
||||||
conn: DbConn,
|
conn: DbConn,
|
||||||
user_info: Result<UserInfo, ErrorResponse>,
|
user_info: Result<models::UserInfo, models::ErrorResponse>,
|
||||||
) -> Result<Json<Vec<Zone>>, ErrorResponse> {
|
) -> Result<Json<Vec<models::Zone>>, models::ErrorResponse> {
|
||||||
let user_info = user_info?;
|
let user_info = user_info?;
|
||||||
|
|
||||||
let zones = conn.run(move |c| {
|
let zones = conn.run(move |c| {
|
||||||
if user_info.is_admin() {
|
if user_info.is_admin() {
|
||||||
Zone::get_all(c)
|
models::Zone::get_all(c)
|
||||||
} else {
|
} else {
|
||||||
user_info.get_zones(c)
|
user_info.get_zones(c)
|
||||||
}
|
}
|
||||||
|
@ -153,27 +152,27 @@ pub async fn get_zones(
|
||||||
pub async fn create_zone(
|
pub async fn create_zone(
|
||||||
conn: DbConn,
|
conn: DbConn,
|
||||||
mut client: dns::client::DnsClient,
|
mut client: dns::client::DnsClient,
|
||||||
user_info: Result<UserInfo, ErrorResponse>,
|
user_info: Result<models::UserInfo, models::ErrorResponse>,
|
||||||
zone_request: Json<CreateZoneRequest>,
|
zone_request: Json<models::CreateZoneRequest>,
|
||||||
) -> Result<Json<Zone>, ErrorResponse> {
|
) -> Result<Json<models::Zone>, models::ErrorResponse> {
|
||||||
user_info?.check_admin()?;
|
user_info?.check_admin()?;
|
||||||
|
|
||||||
// Check if the zone exists in the DNS server
|
// Check if the zone exists in the DNS server
|
||||||
let response = {
|
let response = {
|
||||||
let query = client.query(zone_request.name.clone(), DNSClass::IN, RecordType::SOA);
|
let query = client.query(zone_request.name.clone(), DNSClass::IN, RecordType::SOA);
|
||||||
query.await.map_err(make_500)?
|
query.await.map_err(models::make_500)?
|
||||||
};
|
};
|
||||||
|
|
||||||
if response.response_code() != ResponseCode::NoError {
|
if response.response_code() != ResponseCode::NoError {
|
||||||
println!("Querrying SOA of zone {} failed with code {}", *zone_request.name, response.response_code());
|
println!("Querrying SOA of zone {} failed with code {}", *zone_request.name, response.response_code());
|
||||||
return ErrorResponse::new(
|
return models::ErrorResponse::new(
|
||||||
Status::NotFound,
|
Status::NotFound,
|
||||||
format!("Zone {} could not be found", *zone_request.name)
|
format!("Zone {} could not be found", *zone_request.name)
|
||||||
).err()
|
).err()
|
||||||
}
|
}
|
||||||
|
|
||||||
let zone = conn.run(move |c| {
|
let zone = conn.run(move |c| {
|
||||||
Zone::create_zone(c, zone_request.into_inner())
|
models::Zone::create_zone(c, zone_request.into_inner())
|
||||||
}).await?;
|
}).await?;
|
||||||
|
|
||||||
Ok(Json(zone))
|
Ok(Json(zone))
|
||||||
|
@ -183,21 +182,21 @@ pub async fn create_zone(
|
||||||
#[post("/zones/<zone>/members", data = "<zone_member_request>")]
|
#[post("/zones/<zone>/members", data = "<zone_member_request>")]
|
||||||
pub async fn add_member_to_zone<'r>(
|
pub async fn add_member_to_zone<'r>(
|
||||||
conn: DbConn,
|
conn: DbConn,
|
||||||
zone: dns::name::AbsoluteName,
|
zone: models::AbsoluteName,
|
||||||
user_info: Result<UserInfo, ErrorResponse>,
|
user_info: Result<models::UserInfo, models::ErrorResponse>,
|
||||||
zone_member_request: Json<AddZoneMemberRequest>
|
zone_member_request: Json<models::AddZoneMemberRequest>
|
||||||
) -> Result<Response<'r>, ErrorResponse> {
|
) -> Result<Response<'r>, models::ErrorResponse> {
|
||||||
let user_info = user_info?;
|
let user_info = user_info?;
|
||||||
let zone_name = zone.to_utf8();
|
let zone_name = zone.to_utf8();
|
||||||
|
|
||||||
conn.run(move |c| {
|
conn.run(move |c| {
|
||||||
let zone = if user_info.is_admin() {
|
let zone = if user_info.is_admin() {
|
||||||
Zone::get_by_name(c, &zone_name)
|
models::Zone::get_by_name(c, &zone_name)
|
||||||
} else {
|
} else {
|
||||||
user_info.get_zone(c, &zone_name)
|
user_info.get_zone(c, &zone_name)
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
let new_member = LocalUser::get_user_by_uuid(c, &zone_member_request.id)?;
|
let new_member = models::LocalUser::get_user_by_uuid(c, &zone_member_request.id)?;
|
||||||
zone.add_member(&c, &new_member)
|
zone.add_member(&c, &new_member)
|
||||||
}).await?;
|
}).await?;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue