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

migration
Philippe PITTOLI 2024-07-01 23:48:26 +02:00
parent 1e66262884
commit 2d64da170e
1 changed files with 57 additions and 35 deletions

View File

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