Storage is here, with user_data and zone classes.

This commit is contained in:
Karchnu 2020-12-09 19:01:33 +01:00
parent 5dd1d13b46
commit 11c30dd057
4 changed files with 154 additions and 19 deletions

View File

@ -38,7 +38,7 @@ class DNSManager::Service < IPC::Server
getter storage : DNSManager::Storage getter storage : DNSManager::Storage
getter logged_users : Hash(Int32, AuthD::User::Public) getter logged_users : Hash(Int32, AuthD::User::Public)
@authd : AuthD::Client property authd : AuthD::Client
def initialize(@configuration, @authd : AuthD::Client) def initialize(@configuration, @authd : AuthD::Client)
@storage = DNSManager::Storage.new @configuration.storage_directory @storage = DNSManager::Storage.new @configuration.storage_directory
@ -55,22 +55,7 @@ class DNSManager::Service < IPC::Server
end end
def decode_token(token : String) def decode_token(token : String)
@auth.decode_token token @authd.decode_token token
end
def get_user_data(uid : Int32)
@storage.user_data_per_user.get uid.to_s
rescue e : DODB::MissingEntry
entry = UserData.new uid
entry
end
def get_user_data(user : ::AuthD::User::Public)
get_user_data user.uid
end
def update_user_data(user_data : UserData)
@storage.user_data_per_user.update_or_create user_data.uid.to_s, user_data
end end
def handle_request(event : IPC::Event::MessageReceived) def handle_request(event : IPC::Event::MessageReceived)

View File

@ -1,12 +1,56 @@
require "json" require "json"
require "uuid" require "uuid"
require "uuid/json" require "uuid/json"
require "baguette-crystal-base"
require "dodb" require "dodb"
# require "./storage/*"
class DNSManager::Storage class DNSManager::Storage
getter user_data : DODB::CachedDataBase(UserData)
getter user_data_by_uid : DODB::Index(UserData)
getter zones : DODB::CachedDataBase(Zone)
getter zones_by_domain : DODB::Index(Zone)
def initialize(@root : String) def initialize(@root : String)
@user_data = DODB::CachedDataBase(UserData).new "#{@root}/user-data"
@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
Baguette::Log.info "storage initialized"
end
def get_user_data(uid : Int32)
user_data_by_uid.get uid.to_s
rescue e : DODB::MissingEntry
entry = UserData.new uid
entry
end
def get_user_data(user : ::AuthD::User::Public)
get_user_data user.uid
end
def update_user_data(user_data : UserData)
user_data_by_uid.update_or_create user_data.uid.to_s, user_data
end
def new_domain(user_id : Int32, zone : Zone)
user_data = user_data_by_uid.get? user_id.to_s
if user_data
# store the new zone
@zones << zone
# update user data only after ensuring this zone isn't already existing
user_data.domains << zone.domain
update_user_data user_data
else
Baguette::Log.error "trying to add zone #{zone.domain} to unknown user #{user_id}"
end
rescue e
Baguette::Log.error "trying to add zone #{zone.domain} #{e}"
end end
end end
require "./storage/*"

15
src/storage/user_data.cr Normal file
View File

@ -0,0 +1,15 @@
require "json"
require "uuid"
require "uuid/json"
class DNSManager::Storage::UserData
include JSON::Serializable
property uid : Int32
# Users may have many domains, and a domain can have many owners.
property domains = [] of String
def initialize(@uid)
end
end

91
src/storage/zone.cr Normal file
View File

@ -0,0 +1,91 @@
# Store a DNS zone.
class DNSManager::Storage::Zone
include JSON::Serializable
property domain : String
property resources = [] of DNSManager::Storage::Zone::ResourceRecord
def initialize(@domain)
end
# Store a Resource Record: A, AAAA, TXT, PTR, CNAME…
abstract class ResourceRecord
include JSON::Serializable
use_json_discriminator "type", {
a: A,
aaaa: AAAA,
soa: SOA,
txt: TXT,
ptr: PTR,
ns: NS,
cname: CNAME,
mx: MX,
srv: SRV
}
# Used to discriminate between classes.
property type : String = ""
property name : String
property ttl : UInt32
property target : String
# zone class is omited, it always will be IN in our case.
def initialize(@name, @ttl, @target)
@type = self.name.downcase.gsub /dnsmanager::storage::zone::/, ""
end
end
class SOA < ResourceRecord
# Start of Authority
property mname : String # Master Name Server for the zone.
property rname : String # admin email address john.doe@example.com => john\.doe.example.com
property serial : UInt64 = 0 # Number for tracking new versions of the zone (master-slaves).
property refresh : UInt64 = 86400 # #seconds before requesting new zone version (master-slave).
property retry : UInt64 = 7200 # #seconds before retry accessing new data from the master.
property expire : UInt64 = 3600000# #seconds slaves should consider master dead.
def initialize(@name, @ttl, @target,
@mname, @rname,
@serial = 0, @refresh = 86400, @retry = 7200, @expire = 3600000)
@type = "soa"
end
end
class A < ResourceRecord
end
class AAAA < ResourceRecord
end
class TXT < ResourceRecord
end
class PTR < ResourceRecord
end
class NS < ResourceRecord
end
class CNAME < ResourceRecord
end
class MX < ResourceRecord
property priority : UInt32 = 10
def initialize(@name, @ttl, @target, @priority = 10)
@type = "mx"
end
end
class SRV < ResourceRecord
property port : UInt16
property protocol : String = "tcp"
property priority : UInt32 = 10
property weight : UInt32 = 10
def initialize(@name, @ttl, @target, @port, @protocol = "tcp", @priority = 10, @weight = 10)
@type = "srv"
end
end
def to_s(io : IO)
io << "TEST"
end
end