From e1db03b459bcced1c95bf26765c788b76661a410 Mon Sep 17 00:00:00 2001 From: Philippe Pittoli Date: Thu, 29 Jun 2023 18:29:25 +0200 Subject: [PATCH] Verify accepted domains and pre-load some RRs. --- src/requests/zone.cr | 5 ++++- src/responses/error.cr | 6 ++++++ src/storage.cr | 36 +++++++++++++++++++++++------------- src/storage/zone.cr | 15 +++++++++++++++ 4 files changed, 48 insertions(+), 14 deletions(-) diff --git a/src/requests/zone.cr b/src/requests/zone.cr index 8a7031f..dc21804 100644 --- a/src/requests/zone.cr +++ b/src/requests/zone.cr @@ -12,7 +12,10 @@ class DNSManager::Request def handle(dnsmanagerd : DNSManager::Service, event : IPC::Event) : IPC::JSON user = dnsmanagerd.get_logged_user event return Response::ErrorUserNotLogged.new unless user - dnsmanagerd.storage.new_domain dnsmanagerd.configuration.accepted_domains.not_nil!, user.uid, @domain + + accepted_domains = dnsmanagerd.configuration.accepted_domains.not_nil! + template_directory = dnsmanagerd.configuration.template_directory + dnsmanagerd.storage.new_domain accepted_domains, template_directory, user.uid, @domain end end DNSManager.requests << NewDomain diff --git a/src/responses/error.cr b/src/responses/error.cr index 53f9019..245b1d5 100644 --- a/src/responses/error.cr +++ b/src/responses/error.cr @@ -42,4 +42,10 @@ class DNSManager::Response end end DNSManager.responses << UnacceptableDomain + + IPC::JSON.message InvalidDomainName, 8 do + def initialize() + end + end + DNSManager.responses << InvalidDomainName end diff --git a/src/storage.cr b/src/storage.cr index 85ad999..e2a42a0 100644 --- a/src/storage.cr +++ b/src/storage.cr @@ -54,7 +54,11 @@ class DNSManager::Storage Response::Success.new end - def new_domain(accepted_domains : Array(String), user_id : Int32, domain : String) : IPC::JSON + def new_domain(accepted_domains : Array(String), + template_directory : String, + user_id : Int32, + domain : String) : IPC::JSON + # User must exist. user_data = user_data_by_uid.get? user_id.to_s unless user_data @@ -64,9 +68,7 @@ class DNSManager::Storage return Response::DomainAlreadyExists.new if zones_by_domain.get? domain - # TODO: verify the domain name validity. - - # TODO: verify if the domain is acceptable. + # Verify if the domain is acceptable. matching_domains = accepted_domains.select { |adomain| domain.ends_with? adomain } unless matching_domains Baguette::Log.warning "trying to add an unacceptable domain: #{domain}" @@ -74,21 +76,29 @@ class DNSManager::Storage end matching_domains.each do |md| - Baguette::Log.info "Add new domain in #{md}: #{domain}" + Baguette::Log.info "Add new domain #{domain} (matching domain #{md})" end + # Verify the domain name validity. + return Response::InvalidDomainName.new unless Zone.is_domain_valid? domain + + # Fill a template zone. + tld = matching_domains.pop + default_zone = Zone.from_json File.read "#{template_directory}/#{tld}.json" + + # Replace domain by the real domain. + default_zone.replace_domain domain + + # + # Actually write data on-disk. + # + # Add the domain to the user's domain. user_data.domains << domain - - # Actually write data on-disk. update_user_data user_data - # TODO: Fill a template zone. - - ## # 2 NS - ## zone << rr - ## # Update the zone. - ## zones_by_domain.update_or_create zone.domain, zone + # Add the new zone in the database. + zones_by_domain.update_or_create default_zone.domain, default_zone Response::Success.new end diff --git a/src/storage/zone.cr b/src/storage/zone.cr index 29f125d..f7e27eb 100644 --- a/src/storage/zone.cr +++ b/src/storage/zone.cr @@ -397,4 +397,19 @@ class DNSManager::Storage::Zone false end + # When a new domain is recorded, we load a template which contains a placeholder domain. + # `replace_domain` replaces this domain name by the real one in the different (preloaded) RR. + def replace_domain(new_domain : String) + @domain = new_domain + @resources.each do |rr| + case rr + when SOA + rr.name = domain + when NS + rr.name = domain + else + Baguette::Log.debug "new domain, rr type #{rr.class} (nothing to do)" + end + end + end end