Compilable. Nothing to see, yet.
This commit is contained in:
parent
b4c4588416
commit
2b9360acb4
3 changed files with 168 additions and 45 deletions
11
shard.yml
11
shard.yml
|
@ -1,5 +1,5 @@
|
||||||
name: dnsmanager
|
name: dnsmanager
|
||||||
version: 0.1.0
|
version: 0.2.0
|
||||||
|
|
||||||
authors:
|
authors:
|
||||||
- karchnu <karchnu@karchnu.fr>
|
- karchnu <karchnu@karchnu.fr>
|
||||||
|
@ -9,11 +9,14 @@ description: |
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
ipc:
|
ipc:
|
||||||
git: https://git.karchnu.fr/WeirdOS/ipc.cr
|
git: https://git.baguette.netlib.re/Baguette/ipc.cr
|
||||||
dodb:
|
dodb:
|
||||||
git: https://git.karchnu.fr/WeirdOS/dodb.cr
|
git: https://git.baguette.netlib.re/Baguette/dodb.cr
|
||||||
authd:
|
authd:
|
||||||
git: https://git.karchnu.fr/WeirdOS/authd
|
git: https://git.baguette.netlib.re/Baguette/authd
|
||||||
|
baguette-crystal-base:
|
||||||
|
git: https://git.baguette.netlib.re/Baguette/baguette-crystal-base
|
||||||
|
branch: master
|
||||||
|
|
||||||
targets:
|
targets:
|
||||||
dnsmanager:
|
dnsmanager:
|
||||||
|
|
175
src/main.cr
175
src/main.cr
|
@ -1,29 +1,176 @@
|
||||||
require "http/server"
|
require "http/server"
|
||||||
require "option_parser"
|
|
||||||
|
|
||||||
|
require "ipc"
|
||||||
|
require "ipc/json"
|
||||||
require "authd"
|
require "authd"
|
||||||
|
require "baguette-crystal-base"
|
||||||
|
|
||||||
service_name = "dnsmanager"
|
class Context
|
||||||
verbosity = 1
|
class_property service_name = "dnsmanager"
|
||||||
authd_key_file = nil
|
class_property recreate_indexes = false
|
||||||
|
class_property print_timer = false
|
||||||
|
end
|
||||||
|
|
||||||
require "./parser"
|
module DNSManager
|
||||||
|
class Exception < ::Exception
|
||||||
|
end
|
||||||
|
class AuthorizationException < ::Exception
|
||||||
|
end
|
||||||
|
class NotLoggedException < ::Exception
|
||||||
|
end
|
||||||
|
class AdminAuthorizationException < ::Exception
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
begin
|
|
||||||
authd = AuthD::Client.new
|
|
||||||
authd.key = File.read(Context.authd_key_file.not_nil!).chomp
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
def run
|
||||||
|
Baguette::Log.title "Starting #{Context.service_name}"
|
||||||
|
|
||||||
|
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
|
||||||
server = HTTP::Server.new do |context|
|
server = HTTP::Server.new do |context|
|
||||||
context.response.content_type = "text/plain"
|
context.response.content_type = "text/plain"
|
||||||
pp! context.request
|
pp! context.request
|
||||||
context.response.print "Hello. New version of DNSManager, soon."
|
context.response.print "Hello. New version of dnsmanager, soon."
|
||||||
end
|
end
|
||||||
|
|
||||||
address = server.bind_tcp Context.activation_server_port
|
address = server.bind_tcp Context.webserver_domain, Context.webserver_port
|
||||||
puts "Listening on http://#{address}"
|
puts "Listening on http://#{address}"
|
||||||
server.listen
|
|
||||||
|
|
||||||
rescue e
|
server
|
||||||
puts "Error: #{e}"
|
|
||||||
exit 1
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
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
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
|
|
||||||
class Context
|
|
||||||
class_property verbosity = 1
|
|
||||||
class_property authd_key_file : String? = nil
|
|
||||||
class_property activation_server_port : Int32 = 9000
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
OptionParser.parse do |parser|
|
|
||||||
|
|
||||||
parser.on "-v verbosity-level", "--verbosity level", "Verbosity." do |opt|
|
|
||||||
Context.verbosity = opt.to_i
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on "-p port", "--port port", "Listening port." do |port|
|
|
||||||
Context.activation_server_port = port.to_i
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on "-K key-file", "--key-file file", "Key file." do |opt|
|
|
||||||
Context.authd_key_file = opt
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on "-h", "--help", "Show this help" do
|
|
||||||
puts parser
|
|
||||||
exit 0
|
|
||||||
end
|
|
||||||
end
|
|
Loading…
Add table
Reference in a new issue