Add and replace RR.

This commit is contained in:
Philippe Pittoli 2023-05-08 17:34:50 +02:00
parent 05aa4421b3
commit 8528f74fae
6 changed files with 143 additions and 16 deletions

View File

@ -18,7 +18,7 @@ class DNSManager::Client < IPC
expected_messages.each do |e|
em << e
end
em << DNSManager::Response::Error
em << Response::Error
em.parse_ipc_json message
end
@ -27,35 +27,42 @@ class DNSManager::Client < IPC
#
def login(token : String)
request = DNSManager::Request::Login.new token
request = Request::Login.new token
send_now request
parse_message [ Response::Success ], read
end
# Adding a full zone.
def user_zone_add(zone : DNSManager::Storage::Zone)
request = DNSManager::Request::AddOrUpdateZone.new zone
def user_zone_add(zone : Storage::Zone)
request = Request::AddOrUpdateZone.new zone
send_now request
parse_message [ Response::Success ], read
end
# Removing a zone.
def user_zone_del(domain : String)
request = DNSManager::Request::DeleteZone.new domain
request = Request::DeleteZone.new domain
send_now request
parse_message [ Response::Success ], read
end
# Get a zone.
def user_zone_get(domain : String)
request = DNSManager::Request::GetZone.new domain
request = Request::GetZone.new domain
send_now request
parse_message [ Response::Zone ], read
end
# Add a RR.
def user_rr_add(domain : String, rr : Storage::Zone::ResourceRecord)
request = Request::AddRR.new domain, rr
send_now request
parse_message [ Response::Success ], read
end
# Get user domain list.
def user_domain_list()
request = DNSManager::Request::UserDomains.new
request = Request::UserDomains.new
send_now request
parse_message [ Response::DomainList ], read
end
@ -64,13 +71,13 @@ class DNSManager::Client < IPC
# Admin stuff.
#
def admin_maintenance(key : String, subject : DNSManager::Request::Maintenance::Subject, value : Int32? = nil)
request = DNSManager::Request::Maintenance.new(key,subject)
def admin_maintenance(key : String, subject : Request::Maintenance::Subject, value : Int32? = nil)
request = Request::Maintenance.new(key,subject)
if value
request.value = value
end
send_now request
parse_message [ DNSManager::Response::Success ], read
parse_message [ Response::Success ], read
end
def send_now(msg : IPC::JSON)

View File

@ -35,12 +35,17 @@ class Actions
# Admin section.
#
# Maintenance
# Maintenance.
@the_call["admin-maintenance"] = ->admin_maintenance
# Zone operations.
@the_call["user-zone-add"] = ->user_zone_add
@the_call["user-zone-del"] = ->user_zone_del
@the_call["user-zone-get"] = ->user_zone_get
# Zone RR operations.
@the_call["user-rr-add-a"] = ->user_rr_add_a
@the_call["user-domain-list"] = ->user_domain_list
end
@ -129,6 +134,16 @@ class Actions
puts "error for user_zone_del: #{e.message}"
end
def user_rr_add_a
domain, name, ttl, target = Context.args.not_nil!
begin
rr = DNSManager::Storage::Zone::A.new name, ttl.to_u32, target
pp! @dnsmanagerd.user_rr_add domain, rr
rescue e
puts "error for user_rr_add_a: #{e.message}"
end
end
end
def main

View File

@ -143,6 +143,19 @@ def parsing_cli(authd_config : Baguette::Configuration::Auth)
end
end
parser.on("rr", "Zone Resource Record operations.") do
parser.on("add", "Add new RR.") do
Baguette::Log.info "Add RR."
parser.banner = "COMMAND: user rr add [A|AAAA|CNAME|MX|SRV|TXT|NS]"
parser.on("A", "Add new A RR.") do
Baguette::Log.info "add new A RR."
Context.command = "user-rr-add-a"
parser.banner = "COMMAND: user rr add A <domain> <NAME> <TTL> <TARGET>"
unrecognized_args_to_context_args.call parser, 4, nil
end
end
end
end
opt_help.call parser

View File

@ -56,4 +56,34 @@ class DNSManager::Request
end
end
DNSManager.requests << UserDomains
IPC::JSON.message AddRR, 14 do
property domain : String
property rr : DNSManager::Storage::Zone::ResourceRecord
def initialize(@domain, @rr)
end
def handle(dnsmanagerd : DNSManager::Service, event : IPC::Event) : IPC::JSON
user = dnsmanagerd.get_logged_user event
raise NotLoggedException.new if user.nil?
dnsmanagerd.storage.add_rr user.uid, @domain, @rr
end
end
DNSManager.requests << AddRR
IPC::JSON.message UpdateRR, 15 do
property domain : String
property rr : DNSManager::Storage::Zone::ResourceRecord
def initialize(@domain, @rr)
end
def handle(dnsmanagerd : DNSManager::Service, event : IPC::Event) : IPC::JSON
user = dnsmanagerd.get_logged_user event
raise NotLoggedException.new if user.nil?
dnsmanagerd.storage.update_rr user.uid, @domain, @rr
end
end
DNSManager.requests << UpdateRR
end

View File

@ -48,7 +48,7 @@ class DNSManager::Storage
user_data = user_data_by_uid.get? user_id.to_s
unless user_data
Baguette::Log.info "New user #{user_id}"
@user_data << Storage::UserData.new user_id
@user_data << UserData.new user_id
end
Response::Success.new
@ -58,7 +58,7 @@ class DNSManager::Storage
# Test zone validity.
if errors = zone.get_errors?
Baguette::Log.warning "zone #{zone.domain} update with errors: #{errors}"
return DNSManager::Response::InvalidZone.new errors
return Response::InvalidZone.new errors
end
# User must exist.
@ -92,6 +92,68 @@ class DNSManager::Storage
Response::Error.new "error while updating the domain #{zone.domain}"
end
def add_rr(user_id : Int32, domain : String, rr : Zone::ResourceRecord) : IPC::JSON
# User must exist.
user_data = user_data_by_uid.get? user_id.to_s
unless user_data
Baguette::Log.warning "unknown user #{user_id} tries to add a RR in domain #{domain}"
return Response::UnknownUser.new
end
# Zone must exist.
zone = zones_by_domain.get? domain
unless zone
return Response::InvalidZone.new ["Domain not found."]
end
# User must own the zone.
unless user_data.domains.includes? domain
Baguette::Log.warning "user #{user_id} doesn't own domain #{domain}"
return Response::NoOwnership.new
end
zone << rr
# Update the zone.
zones_by_domain.update_or_create zone.domain, zone
Response::Success.new
rescue e
Baguette::Log.error "trying to add a resource record in domain #{domain}: #{e}"
Response::Error.new "error while adding a resource record in domain #{domain}"
end
def update_rr(user_id : Int32, domain : String, rr : Zone::ResourceRecord) : IPC::JSON
# User must exist.
user_data = user_data_by_uid.get? user_id.to_s
unless user_data
Baguette::Log.warning "unknown user #{user_id} tries to add -or update- zone #{domain}"
return Response::UnknownUser.new
end
# Zone must exist.
zone = zones_by_domain.get? domain
unless zone
return Response::InvalidZone.new ["Domain not found."]
end
# User must own the zone.
unless user_data.domains.includes? domain
Baguette::Log.warning "user #{user_id} doesn't own domain #{domain}"
return Response::NoOwnership.new
end
zone.resources.map { |x| x.rrid == rr.rrid ? rr : x }
# Update the zone.
zones_by_domain.update_or_create zone.domain, zone
Response::Success.new
rescue e
Baguette::Log.error "trying to replace a resource record in domain #{domain}: #{e}"
Response::Error.new "error while replacing a resource record in domain #{domain}"
end
def delete_domain(user_id : Int32, domain : String) : IPC::JSON
# User must exist.
user_data = user_data_by_uid.get? user_id.to_s

View File

@ -50,7 +50,7 @@ class DNSManager::Storage::Zone
end
def to_s(io : IO)
io << "#{ "%30s" % @name} #{ "%6d" % @ttl} IN #{ "%10s" % @rrtype.upcase} #{ "%30s" % @target}\n"
io << "(#{ "%4d" % @rrid }) #{ "%30s" % @name} #{ "%6d" % @ttl} IN #{ "%10s" % @rrtype.upcase} #{ "%30s" % @target}\n"
end
end
@ -70,7 +70,7 @@ class DNSManager::Storage::Zone
end
def to_s(io : IO)
io << "#{name} #{ttl} #{target} #{@rrtype.upcase} (#{mname} #{rname}\n"
io << "(#{ "%4d" % @rrid }) #{name} #{ttl} #{target} #{@rrtype.upcase} (#{mname} #{rname}\n"
io << "\t\t#{ "%10d" % serial} ; serial\n"
io << "\t\t#{ "%10d" % refresh} ; refresh\n"
io << "\t\t#{ "%10d" % retry} ; retry\n"
@ -225,7 +225,7 @@ class DNSManager::Storage::Zone
end
def to_s(io : IO)
io << "#{ "%30s" % @name} #{ "%6d" % @ttl} IN MX #{ "%3d" % @priority} #{ "%30s" % @target}\n"
io << "(#{ "%4d" % @rrid }) #{ "%30s" % @name} #{ "%6d" % @ttl} IN MX #{ "%3d" % @priority} #{ "%30s" % @target}\n"
end
def get_errors : Array(Error)