Better typing, (minor) documentation improvements, remove orphans.

This commit is contained in:
Philippe PITTOLI 2024-07-01 23:48:26 +02:00
parent 1e66262884
commit 2d64da170e

View File

@ -164,7 +164,8 @@ class DNSManager::Storage
Response::DomainAdded.new domain Response::DomainAdded.new domain
end end
def ask_share_token(user_id : UserDataID, domain_name : String) # Asks for a "share token".
def ask_share_token(user_id : UserDataID, domain_name : String) : IPC::JSON
user_should_own! user_id, domain_name user_should_own! user_id, domain_name
domain = @domains_by_name.get domain_name domain = @domains_by_name.get domain_name
@ -179,7 +180,8 @@ class DNSManager::Storage
end end
end end
def ask_transfer_token(user_id : UserDataID, domain_name : String) # Asks for a "transfer token".
def ask_transfer_token(user_id : UserDataID, domain_name : String) : IPC::JSON
user_should_own! user_id, domain_name user_should_own! user_id, domain_name
domain = @domains_by_name.get domain_name domain = @domains_by_name.get domain_name
@ -196,7 +198,7 @@ class DNSManager::Storage
# Check the domain owners. # Check the domain owners.
# In case there's only the requesting user, allow him to gain full control. # In case there's only the requesting user, allow him to gain full control.
def ask_unshare_domain(user_id : UserDataID, domain_name : String) def ask_unshare_domain(user_id : UserDataID, domain_name : String) : IPC::JSON
user_should_own! user_id, domain_name user_should_own! user_id, domain_name
domain = @domains_by_name.get domain_name domain = @domains_by_name.get domain_name
@ -211,7 +213,8 @@ class DNSManager::Storage
end end
end end
def gain_ownership(user_id : UserDataID, uuid : String) # Uses either a "share" or a "transfer" token.
def gain_ownership(user_id : UserDataID, uuid : String) : IPC::JSON
if domain = @domains_by_share_key.get? uuid if domain = @domains_by_share_key.get? uuid
if domain.owners.includes? user_id if domain.owners.includes? user_id
return Response::Error.new "You already own this domain." return Response::Error.new "You already own this domain."
@ -282,7 +285,7 @@ class DNSManager::Storage
# Any modification of the zone must be performed here. # Any modification of the zone must be performed here.
# This function updates the SOA serial before storing the modified zone. # This function updates the SOA serial before storing the modified zone.
# Also, this function generate the Bind9 file. # Also, this function generate the Bind9 file.
def update_zone(zone : Zone) def update_zone(zone : Zone) : Nil
zone.update_serial zone.update_serial
zones_by_domain.update_or_create zone.domain, zone zones_by_domain.update_or_create zone.domain, zone
@ -331,11 +334,12 @@ class DNSManager::Storage
Response::RRDeleted.new rrid Response::RRDeleted.new rrid
end end
# TODO # TODO: removes a Bind9 zonefile.
def remove_bind9_zonefile(domain : String) def remove_bind9_zonefile(domain : String) : Nil
Baguette::Log.info "Removing a Bind9 zone file." Baguette::Log.info "Removing a Bind9 zone file."
end end
# Deletes a domain.
def delete_domain(user_id : UserDataID, domain_name : String) : IPC::JSON def delete_domain(user_id : UserDataID, domain_name : String) : IPC::JSON
zone_must_exist! domain_name zone_must_exist! domain_name
user_should_own! user_id, domain_name user_should_own! user_id, domain_name
@ -365,38 +369,44 @@ class DNSManager::Storage
Response::DomainDeleted.new domain_name Response::DomainDeleted.new domain_name
end end
# Get all removed users from `authd`, list all their domains and remove their data from `dnsmanagerd`. # Gets all removed users from `authd`, list all their domains and remove their data from `dnsmanagerd`.
def get_orphan_domains(user_id : UserDataID) : IPC::JSON def get_orphan_domains(user_id : UserDataID) : IPC::JSON
user_must_be_admin! user_id user_must_be_admin! user_id
# Baguette::Log.debug "list all orphan domains (long computation)" Baguette::Log.debug "list all orphan domains (long computation)"
# orphans = [] of String orphans = [] of String
# user_data.each do |user| domains.each do |domain|
# begin domain.owners.each do |owner|
# dnsmanagerd().authd.get_user? user.uid begin
# rescue e user_must_exist! owner
# Baguette::Log.warning "no authd info on user #{user.uid}: #{e} (removing this user)" rescue e
# Baguette::Log.debug "user #{user.uid} had #{user.domains.size} domains" Baguette::Log.warning "no authd info on user #{owner}: #{e} (removing this user)"
# user.domains.each do |domain| if owned_domains = domains_by_owners.get? owner.to_s
# orphans << domain Baguette::Log.debug "user #{owner} had #{owned_domains.size} domains"
# end owned_domains.each do |d|
# wipe_user_data user orphans << d.name
# end end
# end else
# Baguette::Log.debug "total: #{orphans.size} orphans" Baguette::Log.warning "no domain indexed for user #{owner}, but owns domain #{domain.name}"
# end
# Response::OrphanDomainList.new orphans wipe_user_data owner
Response::Error.new "Not implemented." end
end
end
Baguette::Log.debug "total: #{orphans.size} orphans"
Response::OrphanDomainList.new orphans
end end
def get_zone(user_id : UserDataID, domain : String) : IPC::JSON def get_zone(user_id : UserDataID, domain : String) : IPC::JSON
zone = zone_must_exist! domain zone = zone_must_exist! domain
user_should_own! user_id, domain user_should_own! user_id, domain
Response::Zone.new zone Response::Zone.new zone
end end
def wipe_user_data(user_id : UserDataID) # Removes user data.
def wipe_user_data(user_id : UserDataID) : Nil
domains_by_owners.get(user_id.to_s).each do |domain| domains_by_owners.get(user_id.to_s).each do |domain|
domain_cloned = domain.clone domain_cloned = domain.clone
domain_cloned.owners.delete user_id domain_cloned.owners.delete user_id
@ -415,6 +425,7 @@ class DNSManager::Storage
Baguette::Log.error "while removing a domain: #{e}" Baguette::Log.error "while removing a domain: #{e}"
end end
# Removes user data.
def delete_user_data(user_id : UserDataID, user_to_delete : UserDataID?) : IPC::JSON def delete_user_data(user_id : UserDataID, user_to_delete : UserDataID?) : IPC::JSON
user_id_to_delete = if u = user_to_delete user_id_to_delete = if u = user_to_delete
user_must_be_admin! user_id user_must_be_admin! user_id
@ -430,6 +441,7 @@ class DNSManager::Storage
Response::Success.new Response::Success.new
end end
# Gets a list of user domains.
def user_domains(user_id : UserDataID) : Array(Domain) def user_domains(user_id : UserDataID) : Array(Domain)
if doms = domains_by_owners.get? user_id.to_s if doms = domains_by_owners.get? user_id.to_s
doms doms
@ -440,13 +452,21 @@ class DNSManager::Storage
# TODO: is the user known from authd? # TODO: is the user known from authd?
def user_must_exist!(user_id : UserDataID) def user_must_exist!(user_id : UserDataID)
dnsmanagerd().authd.get_user? user_id response = dnsmanagerd().authd.get_user? user_id
case response
when AuthD::Response::User
response.user
else
raise UnknownUserException.new "user #{user_id} doesn't exist"
end
end end
# Asks `authd` for the user's permissions and verifies the `dnsmanager` permissions are "Admin"-level.
def user_must_be_admin!(user_id : UserDataID) : Nil def user_must_be_admin!(user_id : UserDataID) : Nil
dnsmanagerd().assert_permissions! user_id, "*", AuthD::User::PermissionLevel::Admin dnsmanagerd().assert_permissions! user_id, "*", AuthD::User::PermissionLevel::Admin
end end
# Verifies the existence of a zone.
def zone_must_exist!(domain : String) : Zone def zone_must_exist!(domain : String) : Zone
zone = zones_by_domain.get? domain zone = zones_by_domain.get? domain
raise DomainNotFoundException.new unless zone raise DomainNotFoundException.new unless zone
@ -456,15 +476,15 @@ class DNSManager::Storage
# Owning a domain means to be in the owners' list of the domain. # Owning a domain means to be in the owners' list of the domain.
# TODO: accept admin users to override this test. # TODO: accept admin users to override this test.
def user_should_own!(user_id : UserDataID, domain : String) : Nil def user_should_own!(user_id : UserDataID, domain : String) : Nil
if d = domains_by_name.get? domain d = domains_by_name.get? domain
unless d.owners.includes? user_id raise DomainNotFoundException.new if d.nil?
raise NoOwnershipException.new
end unless d.owners.includes? user_id || user_must_be_admin! user_id
else raise NoOwnershipException.new
raise DomainNotFoundException.new
end end
end end
# Asks a new token for a resource record.
def new_token(user_id : UserDataID, domain : String, rrid : UInt32) : IPC::JSON def new_token(user_id : UserDataID, domain : String, rrid : UInt32) : IPC::JSON
zone = zone_must_exist! domain zone = zone_must_exist! domain
user_should_own! user_id, domain user_should_own! user_id, domain
@ -495,12 +515,14 @@ class DNSManager::Storage
Response::RRUpdated.new domain, rr Response::RRUpdated.new domain, rr
end end
# Verifies the existence and retrieves a token for automatic updates.
def token_must_exist!(token_uuid : String) : Token def token_must_exist!(token_uuid : String) : Token
token = tokens_by_uuid.get? token_uuid token = tokens_by_uuid.get? token_uuid
raise TokenNotFoundException.new unless token raise TokenNotFoundException.new unless token
token token
end end
# Uses a token to automatically update a resource record.
def use_token(token_uuid : String, address : String) : IPC::JSON def use_token(token_uuid : String, address : String) : IPC::JSON
token = token_must_exist! token_uuid token = token_must_exist! token_uuid
zone = zone_must_exist! token.domain zone = zone_must_exist! token.domain