diff --git a/assets/styles/main.css b/assets/styles/main.css index 5521aa9..c947a75 100644 --- a/assets/styles/main.css +++ b/assets/styles/main.css @@ -21,6 +21,7 @@ html, body { main { max-width: 55rem; margin: auto; + padding: .5rem } h1 { @@ -177,3 +178,42 @@ a.button:focus-visible { color: white; background-color: #850085; } + +form h3 { + margin-top: 0; +} + +fieldset { + margin: 0; + padding: 0; + border: none; +} + +legend { + padding: 0; + margin-bottom: .5rem; + font-size: 1.1rem; +} + +input[type="text"] { + font-size: 1rem; +} + +textarea { + resize: vertical; +} + +.form-input { + display: flex; + flex-direction: column; + gap: .5rem; + flex-grow: 1; + margin-bottom: 1rem; +} + +.form-row { + display: flex; + width: 100%; + gap: 1rem; + flex-wrap: wrap; +} diff --git a/dev-scripts/zones/example.com.zone b/dev-scripts/zones/example.com.zone index f1a62de..dc86fee 100644 --- a/dev-scripts/zones/example.com.zone +++ b/dev-scripts/zones/example.com.zone @@ -12,6 +12,8 @@ example.com. 600 IN AAAA 2001:db8:cafe:bc68::2 example.com. 3600 IN MX 1 srv1.example.com. example.com. 3600 IN MX 100 mail.example.net. +_imap._tcp.example.com. 3600 IN SRV 1 1 143 mail.example.net. + example.com. 84600 IN NS ns.example.com. ns.example.com. 84600 IN A 198.51.100.3 diff --git a/locales/en/main.ftl b/locales/en/main.ftl index 197b9fc..5a28eda 100644 --- a/locales/en/main.ftl +++ b/locales/en/main.ftl @@ -1,3 +1,5 @@ +## Zone content + zone-header = Zone { $zone_name } zone-content-title = Zone content @@ -18,4 +20,12 @@ zone-content-record-type-mailserver = zone-content-record-type-nameserver = .type-name = Name servers +zone-content-record-type-service = + .type-name = Services + .data-address = Address: { $address } + .data-priority = Priority: { $priority } + .data-weight = Weight: { $weight } + zone-content-new-record-button = New record + +## Create record diff --git a/locales/fr/main.ftl b/locales/fr/main.ftl index 33d21ee..63ba1e0 100644 --- a/locales/fr/main.ftl +++ b/locales/fr/main.ftl @@ -1,3 +1,4 @@ +## Zone content zone-header = Zone { $zone_name } @@ -19,4 +20,12 @@ zone-content-record-type-mailserver = zone-content-record-type-nameserver = .type-name = Serveurs de noms +zone-content-record-type-service = + .type-name = Services + .data-address = Adresse : { $address } + .data-priority = Priorité : { $priority } + .data-weight = Poids : { $weight } + zone-content-new-record-button = Nouvel enregistrement + +## Create record diff --git a/src/resources/dns/external/rdata.rs b/src/resources/dns/external/rdata.rs index 2202364..bec92d1 100644 --- a/src/resources/dns/external/rdata.rs +++ b/src/resources/dns/external/rdata.rs @@ -90,6 +90,7 @@ impl A { pub fn validate(self) -> Result> { let mut errors = Vec::new(); + // TODO: replace with custom validation let address = push_error!(self.address.parse::().map_err(|e| { Error::from(RDataValidationError::Ip4Address { input: self.address }) .with_cause(&e.to_string()) diff --git a/src/resources/dns/friendly/rdata.rs b/src/resources/dns/friendly/rdata.rs index e016d2c..9cdb40f 100644 --- a/src/resources/dns/friendly/rdata.rs +++ b/src/resources/dns/friendly/rdata.rs @@ -201,7 +201,7 @@ impl From for FriendlyRecords { continue; } - let rdata = rdata.unwrap(); + let (name, rdata) = rdata.unwrap(); if let FriendlyRData::Alias(alias) = rdata { records.aliases.push(alias) diff --git a/src/resources/dns/internal/rdata.rs b/src/resources/dns/internal/rdata.rs index 920c1bc..395cbe4 100644 --- a/src/resources/dns/internal/rdata.rs +++ b/src/resources/dns/internal/rdata.rs @@ -32,13 +32,13 @@ impl RData { } } - pub fn friendly(self, owner: &str, ttl: u32) -> Option { + pub fn friendly(self, owner: &str, ttl: u32) -> Option<(String, friendly::FriendlyRData)> { match self { - RData::A(data) => data.friendly(), - RData::Aaaa(data) => data.friendly(), + RData::A(data) => data.friendly(owner), + RData::Aaaa(data) => data.friendly(owner), RData::Cname(data) => data.friendly(owner, ttl), - RData::Mx(data) => data.friendly(), - RData::Ns(data) => data.friendly(), + RData::Mx(data) => data.friendly(owner), + RData::Ns(data) => data.friendly(owner), RData::Srv(data) => data.friendly(owner), _ => None, } @@ -51,10 +51,10 @@ pub struct A { } impl A { - pub fn friendly(self) -> Option { - Some(friendly::FriendlyRData::Address(friendly::Address { + pub fn friendly(self, owner: &str) -> Option<(String, friendly::FriendlyRData)> { + Some((owner.to_string(), friendly::FriendlyRData::Address(friendly::Address { address: self.address.to_string() - })) + }))) } } @@ -64,10 +64,10 @@ pub struct Aaaa { } impl Aaaa { - pub fn friendly(self) -> Option { - Some(friendly::FriendlyRData::Address(friendly::Address { + pub fn friendly(self, owner: &str) -> Option<(String, friendly::FriendlyRData)> { + Some((owner.to_string(), friendly::FriendlyRData::Address(friendly::Address { address: self.address.to_string() - })) + }))) } } @@ -77,12 +77,12 @@ pub struct Cname { } impl Cname { - pub fn friendly(self, owner: &str, ttl: u32) -> Option { - Some(friendly::FriendlyRData::Alias(friendly::Alias { + pub fn friendly(self, owner: &str, ttl: u32) -> Option<(String, friendly::FriendlyRData)> { + Some((owner.to_string(), friendly::FriendlyRData::Alias(friendly::Alias { from: owner.into(), target: self.target.to_string(), ttl: ttl.into(), - })) + }))) } } @@ -93,11 +93,11 @@ pub struct Mx { } impl Mx { - pub fn friendly(self) -> Option { - Some(friendly::FriendlyRData::MailServer(friendly::MailServer { + pub fn friendly(self, owner: &str) -> Option<(String, friendly::FriendlyRData)> { + Some((owner.to_string(), friendly::FriendlyRData::MailServer(friendly::MailServer { preference: self.preference.into(), mail_exchanger: self.mail_exchanger.to_string(), - })) + }))) } } @@ -107,10 +107,10 @@ pub struct Ns { } impl Ns { - pub fn friendly(self) -> Option { - Some(friendly::FriendlyRData::NameServer(friendly::NameServer { + pub fn friendly(self, owner: &str) -> Option<(String, friendly::FriendlyRData)> { + Some((owner.to_string(), friendly::FriendlyRData::NameServer(friendly::NameServer { target: self.target.to_string(), - })) + }))) } } @@ -139,7 +139,7 @@ pub struct Srv { } impl Srv { - pub fn friendly(self, owner: &str) -> Option { + pub fn friendly(self, owner: &str) -> Option<(String, friendly::FriendlyRData)> { let labels: Vec<_> = owner.splitn(3, '.').collect(); if labels.len() != 3 { None @@ -147,7 +147,7 @@ impl Srv { let service_name = labels[0]. strip_prefix('_'); let protocol = labels[1]. strip_prefix('_'); if let (Some(service_name), Some(protocol)) = (service_name, protocol) { - Some(friendly::FriendlyRData::Service(friendly::Service { + Some((labels[2].to_string(), friendly::FriendlyRData::Service(friendly::Service { service_type: friendly::ServiceType::Other, service_name: Some(service_name.into()), service_protocol: Some(protocol.into()), @@ -155,7 +155,7 @@ impl Srv { weight: self.weight.into(), priority: self.priority.into(), server: self.server.to_string(), - })) + }))) } else { None } diff --git a/templates/macros.html b/templates/macros/display_rrset.html similarity index 72% rename from templates/macros.html rename to templates/macros/display_rrset.html index 3386d21..0542d21 100644 --- a/templates/macros.html +++ b/templates/macros/display_rrset.html @@ -3,12 +3,6 @@
- Priority: {{ data.priority }} + {{ tr( + msg="zone-content-record-type-service", + attr="data-priority", + priority=data.priority, + lang=lang) }} - Weight: {{ data.weight }} + {{ tr( + msg="zone-content-record-type-service", + attr="data-weight", + weight=data.weight, + lang=lang) }}
{% endif %} diff --git a/templates/pages/new_record.html b/templates/pages/new_record.html index 6bab4a4..f145cbe 100644 --- a/templates/pages/new_record.html +++ b/templates/pages/new_record.html @@ -1,4 +1,5 @@ {% extends "bases/app.html" %} +{% import "macros/new_rrset.html" as new_rrset %} {% block title %}New record - {{ current_zone }} - {% endblock title %} {% block main %} @@ -20,14 +21,14 @@ {% if domain_error %}

{{ domain_error.description }}

{% endif %} -

Only the subdomain, without the main domain. For instance, "www" to create the subdomain "www.{{ current_zone }}".

+

Only the subdomain, without the parent domain. For instance, "www" to create the subdomain "www.{{ current_zone }}".

{% elif not config and not rtype %}

Configure the domain {{ new_record_name }}...

...or create a new record for the domain {{ new_record_name }}

@@ -39,10 +40,10 @@
  • Service (SRV)
  • E-mails

    - {% else %} + +{% if config == "web" %} + +

    Configure a web site for the domain {{ new_record_name }}

    + +
    +

    Web servers

    +
    + + +
    + + +
    + +{% elif config == "mail" %} + +

    Configure e-mails for the domain {{ new_record_name }}

    + +
    +

    Mail servers

    +
    + Mail server #1 + +
    +
    + + +
    + +
    + + +
    +
    +
    + +

    Security

    + +
    + + +
    + +
    + + +
    + +
    + Cryptographic signature (DKIM) #1 + +
    +
    + + +
    + +
    + + +
    +
    +
    + + + +
    +{% endif %} + + + {% endif %} {% endblock %} diff --git a/templates/pages/records.html b/templates/pages/records.html index 23f853f..025332d 100644 --- a/templates/pages/records.html +++ b/templates/pages/records.html @@ -1,4 +1,4 @@ -{% import "macros.html" as macros %} +{% import "macros/display_rrset.html" as rrset %} {% extends "bases/app.html" %} {% block title %}{{ tr(msg="zone-content-title", lang=lang) }} - {{ current_zone }} - {% endblock title %} @@ -32,7 +32,7 @@

    {{ tr(msg="zone-content-section-web-header", lang=lang) }}

      {% if group.web.addresses %} - {{ macros::rrset( + {{ rrset::rrset( rtype=group.web.addresses.rtype, ttl=group.web.addresses.ttl, data=group.web.addresses.data, @@ -46,7 +46,7 @@

      {{ tr(msg="zone-content-section-mail-header", lang=lang) }}

        {% if group.mail.servers %} - {{ macros::rrset( + {{ rrset::rrset( rtype=group.mail.servers.rtype, ttl=group.mail.servers.ttl, data=group.mail.servers.data, @@ -54,7 +54,7 @@ lang=lang) }} {% endif %} {% if group.mail.spf %} - {{ macros::rrset( + {{ rrset::rrset( rtype=group.mail.spf.rtype, ttl=group.mail.spf.ttl, data=group.mail.spf.data, @@ -68,7 +68,7 @@

        {{ tr(msg="zone-content-section-general-header", lang=lang) }}

          {% for rrset in group.general_records %} - {{ macros::rrset( + {{ rrset::rrset( rtype=rrset.rtype, ttl=rrset.ttl, data=rrset.data,