From 7786f1d3b850190daa0decbfbd28716292d890f8 Mon Sep 17 00:00:00 2001 From: Philippe Pittoli Date: Thu, 14 Mar 2024 02:43:00 +0100 Subject: [PATCH] Can now use tokens. --- src/main.cr | 7 ++++++- src/storage.cr | 43 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 43 insertions(+), 7 deletions(-) diff --git a/src/main.cr b/src/main.cr index 33b6896..1285710 100644 --- a/src/main.cr +++ b/src/main.cr @@ -29,6 +29,8 @@ module DNSManager end class RRNotFoundException < ::Exception end + class TokenNotFoundException < ::Exception + end class AdminAuthorizationException < ::Exception end end @@ -117,12 +119,15 @@ class DNSManager::Service < IPC rescue e : RRNotFoundException Baguette::Log.error "#{reqname} RR not found" Response::RRNotFound.new + rescue e : TokenNotFoundException + Baguette::Log.error "#{reqname} Token not found" + Response::Error.new "token not found" rescue e : RRReadOnlyException Baguette::Log.error "#{reqname} RR is read only" Response::RRReadOnly.new e.domain, e.rr rescue e # Generic case Baguette::Log.error "#{reqname} generic error #{e}" - DNSManager::Response::Error.new "generic error" + Response::Error.new "generic error" end # If clients sent requests with an “id” field, it is copied diff --git a/src/storage.cr b/src/storage.cr index 775d581..ef96efd 100644 --- a/src/storage.cr +++ b/src/storage.cr @@ -29,7 +29,6 @@ class DNSManager::Storage @tokens_by_domain = @tokens.new_partition "domain", &.domain @zonefiledir = "#{@root}/bind9-zones" - # TODO: create the directory Dir.mkdir_p @zonefiledir Baguette::Log.info "storage initialized" @@ -85,8 +84,7 @@ class DNSManager::Storage # Only an admin can access this function. def generate_zonefile(domain : String) : IPC::JSON - zone = zones_by_domain.get? domain - return Response::DomainNotFound.new unless zone + zone = zone_must_exist! domain Baguette::Log.info "writing zone file #{@zonefiledir}/#{zone.domain}" # TODO: safe write. @@ -281,6 +279,12 @@ class DNSManager::Storage user_data end + def user_must_be_admin!(user_id : Int32) : UserData + user_data = user_must_exist! user_id + raise AdminAuthorizationException.new unless user_data.admin + user_data + end + def zone_must_exist!(domain : String) : Zone zone = zones_by_domain.get? domain raise DomainNotFoundException.new unless zone @@ -323,9 +327,36 @@ class DNSManager::Storage Response::RRUpdated.new domain, rr end - def use_token(user_id : Int32, token : String, address : String) : IPC::JSON - puts "use token #{token} address #{address}" - Response::Error.new "unimplemented" + def token_must_exist!(token_uuid : String) : Token + token = tokens_by_uuid.get? token_uuid + raise TokenNotFoundException.new unless token + token + end + + def use_token(user_id : Int32, token_uuid : String, address : String) : IPC::JSON + puts "use token #{token_uuid} address #{address}" + + user_data = user_must_be_admin! user_id + token = token_must_exist! token_uuid + zone = zone_must_exist! token.domain + rr = zone.rr_must_exist! token.rrid + + # TODO: validate target? + + case rr + when Zone::A + rr.target = address + zone.update_rr rr + zones_by_domain.update_or_create zone.domain, zone + Response::Success.new + when Zone::AAAA + rr.target = address + zone.update_rr rr + zones_by_domain.update_or_create zone.domain, zone + Response::Success.new + else + Response::Error.new "use token on invalid entry (not A or AAAA)" + end end end