dnsmanager/src/main.cr

177 lines
4.5 KiB
Crystal
Raw Normal View History

2020-01-23 20:42:01 +01:00
require "http/server"
2020-10-18 02:49:45 +02:00
require "ipc"
require "ipc/json"
2020-01-23 20:42:01 +01:00
require "authd"
2020-10-18 02:49:45 +02:00
require "baguette-crystal-base"
2020-01-23 20:42:01 +01:00
2020-10-18 02:49:45 +02:00
class Context
class_property service_name = "dnsmanager"
class_property recreate_indexes = false
class_property print_timer = false
end
module DNSManager
class Exception < ::Exception
end
class AuthorizationException < ::Exception
end
class NotLoggedException < ::Exception
end
class AdminAuthorizationException < ::Exception
end
end
require "./cli-parser"
require "./storage.cr"
require "./network.cr"
class DNSManager::Service < IPC::Server
getter storage_directory : String
getter storage : DNSManager::Storage
getter logged_users : Hash(Int32, AuthD::User::Public)
# getter logged_connections : Hash(Int32, IPC::Connection)
@authd : AuthD::Client
def initialize(service_name, @storage_directory : String, @authd : AuthD::Client)
@storage = DNSManager::Storage.new @storage_directory
@logged_users = Hash(Int32, AuthD::User::Public).new
# @logged_connections = Hash(Int32, IPC::Connection).new
super service_name
end
def get_logged_user(event : IPC::Event::Events)
fd = event.connection.fd
@logged_users[fd]?
end
def decode_token(token : String)
@auth.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
2020-01-23 20:42:01 +01:00
2020-10-18 02:49:45 +02:00
def update_user_data(user_data : UserData)
@storage.user_data_per_user.update_or_create user_data.uid.to_s, user_data
end
def handle_request(event : IPC::Event::MessageReceived)
request_start = Time.utc
request = DNSManager.requests.parse_ipc_json event.message
if request.nil?
raise "unknown request type"
end
reqname = request.class.name.sub /^DNSManager::Request::/, ""
Baguette::Log.debug "<< #{reqname}"
response = DNSManager::Response::Error.new "generic error"
begin
response = request.handle self, event
rescue e : AuthorizationException
Baguette::Log.error "#{reqname} authorization error"
response = DNSManager::Response::Error.new "authorization error"
rescue e : AdminAuthorizationException
Baguette::Log.error "#{reqname} no admin authorization"
response = DNSManager::Response::Error.new "admin authorization error"
rescue e : NotLoggedException
Baguette::Log.error "#{reqname} user not logged"
response = DNSManager::Response::Error.new "user not logged"
# Do not handle generic exception case: do not provide a response.
# rescue e # Generic case
# Baguette::Log.error "#{reqname} generic error #{e}"
end
# If clients sent requests with an “id” field, it is copied
# in the responses. Allows identifying responses easily.
response.id = request.id
send event.fd, response
duration = Time.utc - request_start
response_str = response.class.name.sub /^DNSManager::Response::/, ""
if response.is_a? DNSManager::Response::Error
Baguette::Log.warning ">> #{response_str} (#{response.reason})"
else
Baguette::Log.debug ">> #{response_str} (Total duration: #{duration})"
end
end
2020-01-23 20:42:01 +01:00
2020-10-18 02:49:45 +02:00
def run
Baguette::Log.title "Starting #{Context.service_name}"
2020-01-23 20:42:01 +01:00
2020-10-18 02:49:45 +02:00
self.loop do |event|
begin
case event
when IPC::Event::Timer
Baguette::Log.debug "Timer" if Context.print_timer
when IPC::Event::Connection
Baguette::Log.debug "connection from #{event.fd}"
when IPC::Event::Disconnection
Baguette::Log.debug "disconnection from #{event.fd}"
fd = event.fd
# @logged_connections.delete fd
@logged_users.delete fd
when IPC::Event::MessageSent
Baguette::Log.debug "message sent to #{event.fd}"
when IPC::Event::MessageReceived
Baguette::Log.debug "message sent to #{event.fd}"
handle_request event
else
Baguette::Log.warning "unhandled IPC event: #{event.class}"
end
rescue exception
Baguette::Log.error "exception: #{typeof(exception)} - #{exception.message}"
end
end
end
end
def dnsmanager_webserver_init
2020-01-23 20:42:01 +01:00
server = HTTP::Server.new do |context|
context.response.content_type = "text/plain"
pp! context.request
2020-10-18 02:49:45 +02:00
context.response.print "Hello. New version of dnsmanager, soon."
2020-01-23 20:42:01 +01:00
end
2020-10-18 02:49:45 +02:00
address = server.bind_tcp Context.webserver_domain, Context.webserver_port
2020-01-23 20:42:01 +01:00
puts "Listening on http://#{address}"
2020-10-18 02:49:45 +02:00
server
2020-01-23 20:42:01 +01:00
end
2020-10-18 02:49:45 +02:00
authd = AuthD::Client.new
authd.key = Context.authd_key.not_nil!
server = dnsmanager_webserver_init
spawn server.listen
service = DNSManager::Service.new Context.service_name, Context.storage_directory, authd
service.run