Minor change in the code structure.
This commit is contained in:
parent
519533c02d
commit
1e66262884
4
TODO.md
4
TODO.md
@ -9,6 +9,10 @@ TODO:
|
|||||||
* (server) Resource Records to add, del and modify
|
* (server) Resource Records to add, del and modify
|
||||||
* (server) Zone validity on modification
|
* (server) Zone validity on modification
|
||||||
* (client) check for errors in the list of possible returned messages
|
* (client) check for errors in the list of possible returned messages
|
||||||
|
- optimization: RAMOnly-DB for connected users
|
||||||
|
1. dnsmanagerd should be able to (un)subscribe for a user data
|
||||||
|
2. avoid requests to AuthD (don't ask for user data twice)
|
||||||
|
3. AuthD should send updates on a user in real-time
|
||||||
|
|
||||||
DONE:
|
DONE:
|
||||||
|
|
||||||
|
39
src/exceptions.cr
Normal file
39
src/exceptions.cr
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
module DNSManager
|
||||||
|
class Exception < ::Exception
|
||||||
|
end
|
||||||
|
|
||||||
|
class NotLoggedException < ::Exception
|
||||||
|
end
|
||||||
|
|
||||||
|
class NoOwnershipException < ::Exception
|
||||||
|
end
|
||||||
|
|
||||||
|
class AuthorizationException < ::Exception
|
||||||
|
end
|
||||||
|
|
||||||
|
class UnknownUserException < ::Exception
|
||||||
|
end
|
||||||
|
|
||||||
|
class RRReadOnlyException < ::Exception
|
||||||
|
property domain : String
|
||||||
|
property rr : DNSManager::Storage::Zone::ResourceRecord
|
||||||
|
def initialize(@domain, @rr)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class CannotCheckPermissionsException < ::Exception
|
||||||
|
property uid : UserDataID
|
||||||
|
property resource : String
|
||||||
|
def initialize(@uid, @resource)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class DomainNotFoundException < ::Exception
|
||||||
|
end
|
||||||
|
|
||||||
|
class RRNotFoundException < ::Exception
|
||||||
|
end
|
||||||
|
|
||||||
|
class TokenNotFoundException < ::Exception
|
||||||
|
end
|
||||||
|
end
|
214
src/main.cr
214
src/main.cr
@ -3,220 +3,13 @@ require "option_parser"
|
|||||||
|
|
||||||
require "ipc"
|
require "ipc"
|
||||||
require "ipc/json"
|
require "ipc/json"
|
||||||
|
|
||||||
require "authd"
|
require "authd"
|
||||||
require "baguette-crystal-base"
|
require "./service"
|
||||||
|
|
||||||
require "./config"
|
|
||||||
|
|
||||||
module DNSManager
|
|
||||||
class Exception < ::Exception
|
|
||||||
end
|
|
||||||
class DomainNotFoundException < ::Exception
|
|
||||||
end
|
|
||||||
class UnknownUserException < ::Exception
|
|
||||||
end
|
|
||||||
class RRReadOnlyException < ::Exception
|
|
||||||
property domain : String
|
|
||||||
property rr : DNSManager::Storage::Zone::ResourceRecord
|
|
||||||
def initialize(@domain, @rr)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
class CannotCheckPermissionsException < ::Exception
|
|
||||||
property uid : UserDataID
|
|
||||||
property resource : String
|
|
||||||
def initialize(@uid, @resource)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
class AuthorizationException < ::Exception
|
|
||||||
end
|
|
||||||
class NoOwnershipException < ::Exception
|
|
||||||
end
|
|
||||||
class NotLoggedException < ::Exception
|
|
||||||
end
|
|
||||||
class RRNotFoundException < ::Exception
|
|
||||||
end
|
|
||||||
class TokenNotFoundException < ::Exception
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
require "./storage.cr"
|
require "./storage.cr"
|
||||||
require "./network.cr"
|
require "./network.cr"
|
||||||
|
|
||||||
|
|
||||||
class DNSManager::Service < IPC
|
|
||||||
property configuration : Baguette::Configuration::DNSManager
|
|
||||||
getter storage : DNSManager::Storage
|
|
||||||
getter logged_users : Hash(Int32, AuthD::User::Public)
|
|
||||||
|
|
||||||
property authd : AuthD::Client
|
|
||||||
|
|
||||||
def initialize(@configuration)
|
|
||||||
super()
|
|
||||||
@storage = DNSManager::Storage.new @configuration.storage_directory, @configuration.recreate_indexes
|
|
||||||
|
|
||||||
@logged_users = Hash(Int32, AuthD::User::Public).new
|
|
||||||
|
|
||||||
# TODO: auth service isn't in the FDs pool.
|
|
||||||
# If the service crashes, dnsmanagerd won't know it.
|
|
||||||
@authd = AuthD::Client.new
|
|
||||||
response = authd.login? @configuration.login, @configuration.pass.not_nil!
|
|
||||||
case response
|
|
||||||
when AuthD::Response::Login
|
|
||||||
uid = response.uid
|
|
||||||
token = response.token
|
|
||||||
Baguette::Log.info "Authenticated as #{@configuration.login} #{uid}, token: #{token}"
|
|
||||||
else
|
|
||||||
@authd.close
|
|
||||||
raise "Cannot authenticate to authd with login #{@configuration.login}: #{response}."
|
|
||||||
end
|
|
||||||
|
|
||||||
@storage.dnsmanagerd = self
|
|
||||||
self.timer @configuration.ipc_timer
|
|
||||||
self.service_init @configuration.service_name
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_logged_user(event : IPC::Event)
|
|
||||||
@logged_users[event.fd]?
|
|
||||||
end
|
|
||||||
|
|
||||||
def decode_token(token : String)
|
|
||||||
@authd.decode_token token
|
|
||||||
end
|
|
||||||
|
|
||||||
def is_admin?(uid : UInt32) : Bool
|
|
||||||
perms = check_permissions uid, "*"
|
|
||||||
(perms == AuthD::User::PermissionLevel::Admin)
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_permissions(uid : UInt32, resource : String) : AuthD::User::PermissionLevel
|
|
||||||
response = @authd.check_permission uid, "dnsmanager", resource
|
|
||||||
case response
|
|
||||||
when AuthD::Response::PermissionCheck
|
|
||||||
return response.permission
|
|
||||||
end
|
|
||||||
raise CannotCheckPermissionsException.new uid, resource
|
|
||||||
rescue e
|
|
||||||
Baguette::Log.error "error while checking permissions: #{e}"
|
|
||||||
raise CannotCheckPermissionsException.new uid, resource
|
|
||||||
end
|
|
||||||
|
|
||||||
def assert_permissions!(uid : UInt32, resource : String, perms : AuthD::User::PermissionLevel)
|
|
||||||
if check_permissions(uid, resource) < perms
|
|
||||||
raise AuthorizationException.new
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_request(event : IPC::Event)
|
|
||||||
request_start = Time.utc
|
|
||||||
|
|
||||||
array = event.message.not_nil!
|
|
||||||
slice = Slice.new array.to_unsafe, array.size
|
|
||||||
message = IPCMessage::TypedMessage.deserialize slice
|
|
||||||
request = DNSManager.requests.parse_ipc_json message.not_nil!
|
|
||||||
|
|
||||||
if request.nil?
|
|
||||||
raise "unknown request type"
|
|
||||||
end
|
|
||||||
|
|
||||||
reqname = request.class.name.sub /^DNSManager::Request::/, ""
|
|
||||||
|
|
||||||
response = begin
|
|
||||||
request.handle self, event
|
|
||||||
rescue e : AuthorizationException
|
|
||||||
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} authorization error"
|
|
||||||
Response::Error.new "authorization error"
|
|
||||||
rescue e : DomainNotFoundException
|
|
||||||
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} domain not found"
|
|
||||||
Response::DomainNotFound.new
|
|
||||||
rescue e : CannotCheckPermissionsException
|
|
||||||
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} cannot check permissions of user '#{e.uid}' on resource '#{e.resource}'"
|
|
||||||
Response::InsufficientRights.new
|
|
||||||
rescue e : UnknownUserException
|
|
||||||
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} unknown user"
|
|
||||||
Response::UnknownUser.new
|
|
||||||
rescue e : NoOwnershipException
|
|
||||||
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} no ownership error"
|
|
||||||
Response::NoOwnership.new
|
|
||||||
rescue e : NotLoggedException
|
|
||||||
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} user not logged"
|
|
||||||
Response::Error.new "user not logged"
|
|
||||||
rescue e : RRNotFoundException
|
|
||||||
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} RR not found"
|
|
||||||
Response::RRNotFound.new
|
|
||||||
rescue e : TokenNotFoundException
|
|
||||||
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} Token not found"
|
|
||||||
Response::Error.new "token not found"
|
|
||||||
rescue e : RRReadOnlyException
|
|
||||||
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} RR is read only"
|
|
||||||
Response::RRReadOnly.new e.domain, e.rr
|
|
||||||
rescue e # Generic case
|
|
||||||
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} generic error #{e}"
|
|
||||||
Response::Error.new "generic error"
|
|
||||||
end
|
|
||||||
|
|
||||||
# If clients sent requests with an “id” field, it is copied
|
|
||||||
# in the responses. Allows identifying responses easily.
|
|
||||||
response.id = request.id
|
|
||||||
|
|
||||||
schedule event.fd, response
|
|
||||||
|
|
||||||
duration = Time.utc - request_start
|
|
||||||
|
|
||||||
response_name = response.class.name.sub /^DNSManager::Response::/, ""
|
|
||||||
|
|
||||||
if response.is_a? DNSManager::Response::Error
|
|
||||||
Baguette::Log.warning "fd #{"%4d" % event.fd} (#{duration}) #{reqname} >> #{response_name} (#{response.reason})"
|
|
||||||
else
|
|
||||||
if reqname != "KeepAlive" || @configuration.print_keepalive
|
|
||||||
Baguette::Log.debug "fd #{"%4d" % event.fd} (#{duration}) #{reqname} >> #{response_name}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def run
|
|
||||||
Baguette::Log.title "Starting #{@configuration.service_name}"
|
|
||||||
|
|
||||||
self.loop do |event|
|
|
||||||
begin
|
|
||||||
case event.type
|
|
||||||
when LibIPC::EventType::Timer
|
|
||||||
Baguette::Log.debug "Timer." if @configuration.print_ipc_timer
|
|
||||||
|
|
||||||
when LibIPC::EventType::Connection
|
|
||||||
Baguette::Log.debug "New connection!" if @configuration.print_ipc_connection
|
|
||||||
|
|
||||||
when LibIPC::EventType::Disconnection
|
|
||||||
Baguette::Log.debug "Disconnection from #{event.fd}." if @configuration.print_ipc_disconnection
|
|
||||||
@logged_users.delete event.fd
|
|
||||||
|
|
||||||
when LibIPC::EventType::MessageTx
|
|
||||||
Baguette::Log.debug "Message sent to #{event.fd}." if @configuration.print_ipc_message_sent
|
|
||||||
|
|
||||||
when LibIPC::EventType::MessageRx
|
|
||||||
Baguette::Log.debug "Message received from #{event.fd}." if @configuration.print_ipc_message_received
|
|
||||||
handle_request event
|
|
||||||
|
|
||||||
else
|
|
||||||
Baguette::Log.warning "Unhandled IPC event: #{event.class}."
|
|
||||||
if event.responds_to?(:fd)
|
|
||||||
fd = event.fd
|
|
||||||
Baguette::Log.warning "closing #{fd}"
|
|
||||||
close fd
|
|
||||||
@logged_users.delete fd
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
rescue exception
|
|
||||||
Baguette::Log.error "exception: #{typeof(exception)} - #{exception.message}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
def main
|
|
||||||
|
|
||||||
# First option parsing, same with all Baguette (service) applications.
|
# First option parsing, same with all Baguette (service) applications.
|
||||||
simulation, no_configuration, configuration_file = Baguette::Configuration.option_parser
|
simulation, no_configuration, configuration_file = Baguette::Configuration.option_parser
|
||||||
|
|
||||||
@ -306,6 +99,3 @@ def main
|
|||||||
|
|
||||||
service = DNSManager::Service.new configuration
|
service = DNSManager::Service.new configuration
|
||||||
service.run
|
service.run
|
||||||
end
|
|
||||||
|
|
||||||
main
|
|
||||||
|
172
src/service.cr
172
src/service.cr
@ -1,5 +1,175 @@
|
|||||||
require "ipc"
|
require "ipc"
|
||||||
|
|
||||||
# Useful to enable the client to be built.
|
require "baguette-crystal-base"
|
||||||
|
require "./config"
|
||||||
|
require "./exceptions"
|
||||||
|
|
||||||
class DNSManager::Service < IPC
|
class DNSManager::Service < IPC
|
||||||
|
property configuration : Baguette::Configuration::DNSManager
|
||||||
|
getter storage : DNSManager::Storage
|
||||||
|
getter logged_users : Hash(Int32, AuthD::User::Public)
|
||||||
|
|
||||||
|
property authd : AuthD::Client
|
||||||
|
|
||||||
|
def initialize(@configuration)
|
||||||
|
super()
|
||||||
|
@storage = DNSManager::Storage.new @configuration.storage_directory, @configuration.recreate_indexes
|
||||||
|
|
||||||
|
@logged_users = Hash(Int32, AuthD::User::Public).new
|
||||||
|
|
||||||
|
# TODO: auth service isn't in the FDs pool.
|
||||||
|
# If the service crashes, dnsmanagerd won't know it.
|
||||||
|
@authd = AuthD::Client.new
|
||||||
|
response = authd.login? @configuration.login, @configuration.pass.not_nil!
|
||||||
|
case response
|
||||||
|
when AuthD::Response::Login
|
||||||
|
uid = response.uid
|
||||||
|
token = response.token
|
||||||
|
Baguette::Log.info "Authenticated as #{@configuration.login} #{uid}, token: #{token}"
|
||||||
|
else
|
||||||
|
@authd.close
|
||||||
|
raise "Cannot authenticate to authd with login #{@configuration.login}: #{response}."
|
||||||
|
end
|
||||||
|
|
||||||
|
@storage.dnsmanagerd = self
|
||||||
|
self.timer @configuration.ipc_timer
|
||||||
|
self.service_init @configuration.service_name
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_logged_user(event : IPC::Event)
|
||||||
|
@logged_users[event.fd]?
|
||||||
|
end
|
||||||
|
|
||||||
|
def decode_token(token : String)
|
||||||
|
@authd.decode_token token
|
||||||
|
end
|
||||||
|
|
||||||
|
def is_admin?(uid : UInt32) : Bool
|
||||||
|
perms = check_permissions uid, "*"
|
||||||
|
(perms == AuthD::User::PermissionLevel::Admin)
|
||||||
|
end
|
||||||
|
|
||||||
|
def check_permissions(uid : UInt32, resource : String) : AuthD::User::PermissionLevel
|
||||||
|
response = @authd.check_permission uid, "dnsmanager", resource
|
||||||
|
case response
|
||||||
|
when AuthD::Response::PermissionCheck
|
||||||
|
return response.permission
|
||||||
|
end
|
||||||
|
raise CannotCheckPermissionsException.new uid, resource
|
||||||
|
rescue e
|
||||||
|
Baguette::Log.error "error while checking permissions: #{e}"
|
||||||
|
raise CannotCheckPermissionsException.new uid, resource
|
||||||
|
end
|
||||||
|
|
||||||
|
def assert_permissions!(uid : UInt32, resource : String, perms : AuthD::User::PermissionLevel)
|
||||||
|
if check_permissions(uid, resource) < perms
|
||||||
|
raise AuthorizationException.new
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def handle_request(event : IPC::Event)
|
||||||
|
request_start = Time.utc
|
||||||
|
|
||||||
|
array = event.message.not_nil!
|
||||||
|
slice = Slice.new array.to_unsafe, array.size
|
||||||
|
message = IPCMessage::TypedMessage.deserialize slice
|
||||||
|
request = DNSManager.requests.parse_ipc_json message.not_nil!
|
||||||
|
|
||||||
|
if request.nil?
|
||||||
|
raise "unknown request type"
|
||||||
|
end
|
||||||
|
|
||||||
|
reqname = request.class.name.sub /^DNSManager::Request::/, ""
|
||||||
|
|
||||||
|
response = begin
|
||||||
|
request.handle self, event
|
||||||
|
rescue e : AuthorizationException
|
||||||
|
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} authorization error"
|
||||||
|
Response::Error.new "authorization error"
|
||||||
|
rescue e : DomainNotFoundException
|
||||||
|
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} domain not found"
|
||||||
|
Response::DomainNotFound.new
|
||||||
|
rescue e : CannotCheckPermissionsException
|
||||||
|
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} cannot check permissions of user '#{e.uid}' on resource '#{e.resource}'"
|
||||||
|
Response::InsufficientRights.new
|
||||||
|
rescue e : UnknownUserException
|
||||||
|
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} unknown user"
|
||||||
|
Response::UnknownUser.new
|
||||||
|
rescue e : NoOwnershipException
|
||||||
|
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} no ownership error"
|
||||||
|
Response::NoOwnership.new
|
||||||
|
rescue e : NotLoggedException
|
||||||
|
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} user not logged"
|
||||||
|
Response::Error.new "user not logged"
|
||||||
|
rescue e : RRNotFoundException
|
||||||
|
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} RR not found"
|
||||||
|
Response::RRNotFound.new
|
||||||
|
rescue e : TokenNotFoundException
|
||||||
|
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} Token not found"
|
||||||
|
Response::Error.new "token not found"
|
||||||
|
rescue e : RRReadOnlyException
|
||||||
|
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} RR is read only"
|
||||||
|
Response::RRReadOnly.new e.domain, e.rr
|
||||||
|
rescue e # Generic case
|
||||||
|
Baguette::Log.error "(fd #{"%4d" % event.fd}) #{reqname} generic error #{e}"
|
||||||
|
Response::Error.new "generic error"
|
||||||
|
end
|
||||||
|
|
||||||
|
# If clients sent requests with an “id” field, it is copied
|
||||||
|
# in the responses. Allows identifying responses easily.
|
||||||
|
response.id = request.id
|
||||||
|
|
||||||
|
schedule event.fd, response
|
||||||
|
|
||||||
|
duration = Time.utc - request_start
|
||||||
|
|
||||||
|
response_name = response.class.name.sub /^DNSManager::Response::/, ""
|
||||||
|
|
||||||
|
if response.is_a? DNSManager::Response::Error
|
||||||
|
Baguette::Log.warning "fd #{"%4d" % event.fd} (#{duration}) #{reqname} >> #{response_name} (#{response.reason})"
|
||||||
|
else
|
||||||
|
if reqname != "KeepAlive" || @configuration.print_keepalive
|
||||||
|
Baguette::Log.debug "fd #{"%4d" % event.fd} (#{duration}) #{reqname} >> #{response_name}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
Baguette::Log.title "Starting #{@configuration.service_name}"
|
||||||
|
|
||||||
|
self.loop do |event|
|
||||||
|
begin
|
||||||
|
case event.type
|
||||||
|
when LibIPC::EventType::Timer
|
||||||
|
Baguette::Log.debug "Timer." if @configuration.print_ipc_timer
|
||||||
|
|
||||||
|
when LibIPC::EventType::Connection
|
||||||
|
Baguette::Log.debug "New connection!" if @configuration.print_ipc_connection
|
||||||
|
|
||||||
|
when LibIPC::EventType::Disconnection
|
||||||
|
Baguette::Log.debug "Disconnection from #{event.fd}." if @configuration.print_ipc_disconnection
|
||||||
|
@logged_users.delete event.fd
|
||||||
|
|
||||||
|
when LibIPC::EventType::MessageTx
|
||||||
|
Baguette::Log.debug "Message sent to #{event.fd}." if @configuration.print_ipc_message_sent
|
||||||
|
|
||||||
|
when LibIPC::EventType::MessageRx
|
||||||
|
Baguette::Log.debug "Message received from #{event.fd}." if @configuration.print_ipc_message_received
|
||||||
|
handle_request event
|
||||||
|
|
||||||
|
else
|
||||||
|
Baguette::Log.warning "Unhandled IPC event: #{event.class}."
|
||||||
|
if event.responds_to?(:fd)
|
||||||
|
fd = event.fd
|
||||||
|
Baguette::Log.warning "closing #{fd}"
|
||||||
|
close fd
|
||||||
|
@logged_users.delete fd
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
rescue exception
|
||||||
|
Baguette::Log.error "exception: #{typeof(exception)} - #{exception.message}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
@ -71,6 +71,9 @@ class DNSManager::Storage
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Generate Bind9 zone files.
|
||||||
|
# The file is written in a temporary file then moved, enabling safe manipulation of the file
|
||||||
|
# since its content always will be consistent even if not up-to-date.
|
||||||
def generate_bind9_zonefile(domain : String) : Nil
|
def generate_bind9_zonefile(domain : String) : Nil
|
||||||
zone = zone_must_exist! domain
|
zone = zone_must_exist! domain
|
||||||
|
|
||||||
@ -87,7 +90,8 @@ class DNSManager::Storage
|
|||||||
File.rename filename_wip, filename_final
|
File.rename filename_wip, filename_final
|
||||||
end
|
end
|
||||||
|
|
||||||
# Only an admin can access this function.
|
# Request to generate a zone file.
|
||||||
|
# Only an admin can access this function, so there is no need to verify user's authorizations a second time.
|
||||||
def generate_zonefile(domain : String) : IPC::JSON
|
def generate_zonefile(domain : String) : IPC::JSON
|
||||||
generate_bind9_zonefile domain
|
generate_bind9_zonefile domain
|
||||||
Response::Success.new
|
Response::Success.new
|
||||||
@ -102,6 +106,7 @@ class DNSManager::Storage
|
|||||||
Response::Success.new
|
Response::Success.new
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Provides the generated zone file to a user.
|
||||||
def get_generated_zonefile(user_id : UserDataID, domain : String) : IPC::JSON
|
def get_generated_zonefile(user_id : UserDataID, domain : String) : IPC::JSON
|
||||||
zone = zone_must_exist! domain
|
zone = zone_must_exist! domain
|
||||||
user_should_own! user_id, zone.domain
|
user_should_own! user_id, zone.domain
|
||||||
@ -111,8 +116,8 @@ class DNSManager::Storage
|
|||||||
Response::GeneratedZone.new domain, (String.new io.buffer, io.pos)
|
Response::GeneratedZone.new domain, (String.new io.buffer, io.pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Adds a new domain.
|
||||||
def new_domain(user_id : UserDataID, domain : String) : IPC::JSON
|
def new_domain(user_id : UserDataID, domain : String) : IPC::JSON
|
||||||
|
|
||||||
accepted_domains = dnsmanagerd.configuration.accepted_domains.not_nil!
|
accepted_domains = dnsmanagerd.configuration.accepted_domains.not_nil!
|
||||||
template_directory = dnsmanagerd.configuration.template_directory
|
template_directory = dnsmanagerd.configuration.template_directory
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
require "authd"
|
require "authd"
|
||||||
require "ipc"
|
require "ipc"
|
||||||
|
|
||||||
require "../src/client.cr"
|
require "../src/client.cr"
|
||||||
require "http/server"
|
require "http/server"
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user