WIP: Tokens. Can create tokens for RRs and their indexes + partitions.
This commit is contained in:
parent
0c817e1f96
commit
088980109d
35
src/requests/token.cr
Normal file
35
src/requests/token.cr
Normal file
@ -0,0 +1,35 @@
|
||||
require "ipc/json"
|
||||
require "grok"
|
||||
|
||||
class DNSManager::Request
|
||||
IPC::JSON.message NewToken, 18 do
|
||||
property domain : String
|
||||
property rrid : UInt32
|
||||
|
||||
def initialize(@domain, @rrid)
|
||||
end
|
||||
|
||||
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_token user.uid, @domain, @rrid
|
||||
end
|
||||
end
|
||||
DNSManager.requests << NewToken
|
||||
|
||||
IPC::JSON.message UseToken, 19 do
|
||||
property token : String
|
||||
property address : String
|
||||
|
||||
def initialize(@token, @address)
|
||||
end
|
||||
|
||||
def handle(dnsmanagerd : DNSManager::Service, event : IPC::Event) : IPC::JSON
|
||||
user = dnsmanagerd.get_logged_user event
|
||||
return Response::ErrorUserNotLogged.new unless user
|
||||
return Response::InsufficientRights.new unless user.admin
|
||||
dnsmanagerd.storage.use_token user.uid, @token, @address
|
||||
end
|
||||
end
|
||||
DNSManager.requests << UseToken
|
||||
end
|
@ -12,6 +12,10 @@ class DNSManager::Storage
|
||||
getter zones : DODB::CachedDataBase(Zone)
|
||||
getter zones_by_domain : DODB::Index(Zone)
|
||||
|
||||
getter tokens : DODB::CachedDataBase(Token)
|
||||
getter tokens_by_uuid : DODB::Index(Token)
|
||||
getter tokens_by_domain : DODB::Partition(Token)
|
||||
|
||||
getter root : String
|
||||
getter zonefiledir : String
|
||||
|
||||
@ -20,6 +24,9 @@ class DNSManager::Storage
|
||||
@user_data_by_uid = @user_data.new_index "uid", &.uid.to_s
|
||||
@zones = DODB::CachedDataBase(Zone).new "#{@root}/zones"
|
||||
@zones_by_domain = @zones.new_index "domain", &.domain
|
||||
@tokens = DODB::CachedDataBase(Token).new "#{@root}/tokens"
|
||||
@tokens_by_uuid = @tokens.new_index "uuid", &.uuid
|
||||
@tokens_by_domain = @tokens.new_partition "domain", &.domain
|
||||
|
||||
@zonefiledir = "#{@root}/bind9-zones"
|
||||
# TODO: create the directory
|
||||
@ -32,6 +39,8 @@ class DNSManager::Storage
|
||||
@user_data.reindex_everything!
|
||||
Baguette::Log.debug "Reindexing zones..."
|
||||
@zones.reindex_everything!
|
||||
Baguette::Log.debug "Reindexing tokens..."
|
||||
@tokens.reindex_everything!
|
||||
Baguette::Log.debug "Reindexed!"
|
||||
end
|
||||
end
|
||||
@ -331,8 +340,9 @@ class DNSManager::Storage
|
||||
# Update on-disk user data.
|
||||
update_user_data user_data
|
||||
|
||||
# Remove the related zone.
|
||||
# Remove the related zone and their registered tokens.
|
||||
zones_by_domain.delete domain
|
||||
tokens_by_domain.delete domain
|
||||
|
||||
Response::DomainDeleted.new domain
|
||||
rescue e
|
||||
@ -378,6 +388,60 @@ class DNSManager::Storage
|
||||
Baguette::Log.error "trying to list all user #{user_id} domains: #{e}"
|
||||
Response::Error.new "error while listing domains"
|
||||
end
|
||||
|
||||
def new_token(user_id : Int32, domain : String, rrid : UInt32) : IPC::JSON
|
||||
puts "new token for domain #{domain} rrid #{rrid}"
|
||||
|
||||
# 0. verifications: must exist: user, zone, RR. Zone must be owned by user.
|
||||
|
||||
# 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 get a new token for a RR in domain #{domain}"
|
||||
return Response::UnknownUser.new
|
||||
end
|
||||
|
||||
# Zone must exist.
|
||||
zone = zones_by_domain.get? domain
|
||||
return Response::DomainNotFound.new unless zone
|
||||
|
||||
# User should own it.
|
||||
unless user_data.domains.includes?(domain) || user_data.admin
|
||||
Baguette::Log.warning "user #{user_id} doesn't own domain #{domain}"
|
||||
return Response::NoOwnership.new
|
||||
end
|
||||
|
||||
# RR must exist.
|
||||
rr = zone.get_rr rrid
|
||||
return Response::RRNotFound.new unless rr
|
||||
|
||||
old_token = rr.token
|
||||
|
||||
# 1. create token
|
||||
token = Token.new domain, rrid
|
||||
|
||||
# 2. add token to the RR.
|
||||
rr.token = token.uuid
|
||||
zone.update_rr rr
|
||||
|
||||
# 3. update the zone (no need to call `update_zone` to change the zone serial).
|
||||
zones_by_domain.update_or_create zone.domain, zone
|
||||
|
||||
# 4. if there is an old token, remove it.
|
||||
if old_token_uuid = old_token
|
||||
tokens_by_uuid.delete old_token_uuid
|
||||
end
|
||||
|
||||
# 5. add token to the db.
|
||||
@tokens << token
|
||||
|
||||
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"
|
||||
end
|
||||
end
|
||||
|
||||
require "./storage/*"
|
||||
|
13
src/storage/token.cr
Normal file
13
src/storage/token.cr
Normal file
@ -0,0 +1,13 @@
|
||||
require "uuid"
|
||||
|
||||
class DNSManager::Storage::Token
|
||||
include JSON::Serializable
|
||||
|
||||
property uuid : String
|
||||
property domain : String
|
||||
property rrid : UInt32
|
||||
|
||||
def initialize(@domain, @rrid)
|
||||
@uuid = UUID.random.to_s
|
||||
end
|
||||
end
|
@ -55,8 +55,12 @@ class DNSManager::Storage::Zone
|
||||
# Yes. It already happened. Many, MANY times. I WANT MY FUCKING TIME BACK.
|
||||
property readonly : Bool = false
|
||||
|
||||
# RR entries can have an update token.
|
||||
# This way, users can automatically update their IP address using a simple HTTP request (ex: with `wget`).
|
||||
property token : String? = nil
|
||||
|
||||
# zone class is omited, it always will be IN in our case.
|
||||
def initialize(@name, @ttl, @target)
|
||||
def initialize(@name, @ttl, @target, @token = nil)
|
||||
@rrtype = self.class.name.upcase.gsub /DNSMANAGER::STORAGE::ZONE::/, ""
|
||||
end
|
||||
|
||||
@ -619,6 +623,18 @@ class DNSManager::Storage::Zone
|
||||
@current_rrid += 1
|
||||
end
|
||||
|
||||
def get_rr(rrid : UInt32) : ResourceRecord?
|
||||
@resources.each do |rr|
|
||||
return rr if rr.rrid = rrid
|
||||
end
|
||||
end
|
||||
|
||||
def update_rr(rr : ResourceRecord)
|
||||
puts "updating rr #{rr.rrid}"
|
||||
@resources.select! { |x| x.rrid == rr.rrid }
|
||||
@resources << rr
|
||||
end
|
||||
|
||||
def to_s(io : IO)
|
||||
io << "DOMAIN #{@domain}.\n"
|
||||
@resources.each do |rr|
|
||||
@ -754,6 +770,17 @@ class DNSManager::Storage::Zone
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def new_token(rrid : UInt32, token : String)
|
||||
old_token : String? = nil
|
||||
@resources.each do |rr|
|
||||
if rr.rrid == rrid
|
||||
old_token = rr.token
|
||||
rr.token = token
|
||||
end
|
||||
end
|
||||
old_token
|
||||
end
|
||||
end
|
||||
|
||||
def qualifier_to_char(qualifier : DNSManager::Storage::Zone::SPF::Qualifier) : Char
|
||||
|
Loading…
Reference in New Issue
Block a user