Update whole structure + new LibIPC API.
This commit is contained in:
parent
3ddcd181dd
commit
34f1077757
21 changed files with 376 additions and 378 deletions
52
shard.yml
52
shard.yml
|
@ -1,12 +1,11 @@
|
||||||
name: authd
|
name: authd
|
||||||
version: 0.2.0
|
version: 0.1.0
|
||||||
|
|
||||||
authors:
|
|
||||||
- Karchnu <karchnu@karchnu.fr>
|
|
||||||
- Luka Vandervelden <lukc@upyum.com>
|
|
||||||
|
|
||||||
description: |
|
description: |
|
||||||
JWT-based authentication daemon.
|
JWT-based authentication daemon.
|
||||||
|
|
||||||
|
authors:
|
||||||
|
- Philippe Pittoli <karchnu@karchnu.fr>
|
||||||
|
|
||||||
targets:
|
targets:
|
||||||
authd:
|
authd:
|
||||||
|
@ -14,25 +13,28 @@ targets:
|
||||||
authc:
|
authc:
|
||||||
main: utils/authc.cr
|
main: utils/authc.cr
|
||||||
|
|
||||||
crystal: 0.35.1
|
crystal: 1.7.1
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
grok:
|
grok:
|
||||||
github: spinscale/grok.cr
|
github: spinscale/grok.cr
|
||||||
passwd:
|
passwd:
|
||||||
git: https://git.baguette.netlib.re/Baguette/passwd.cr
|
git: https://git.baguette.netlib.re/Baguette/passwd.cr
|
||||||
branch: master
|
branch: master
|
||||||
ipc:
|
jwt:
|
||||||
git: https://git.baguette.netlib.re/Baguette/ipc.cr
|
github: crystal-community/jwt
|
||||||
branch: master
|
branch: master
|
||||||
jwt:
|
baguette-crystal-base:
|
||||||
github: crystal-community/jwt
|
git: https://git.baguette.netlib.re/Baguette/baguette-crystal-base
|
||||||
branch: master
|
branch: master
|
||||||
baguette-crystal-base:
|
dodb:
|
||||||
git: https://git.baguette.netlib.re/Baguette/baguette-crystal-base
|
git: https://git.baguette.netlib.re/Baguette/dodb.cr
|
||||||
branch: master
|
branch: master
|
||||||
dodb:
|
cbor:
|
||||||
git: https://git.baguette.netlib.re/Baguette/dodb.cr
|
git: https://git.baguette.netlib.re/Baguette/crystal-cbor
|
||||||
branch: master
|
branch: master
|
||||||
|
ipc:
|
||||||
|
git: https://git.baguette.netlib.re/Baguette/ipc.cr
|
||||||
|
branch: master
|
||||||
|
|
||||||
license: EUPL
|
license: ISC
|
||||||
|
|
251
src/authd.cr
251
src/authd.cr
|
@ -1,34 +1,239 @@
|
||||||
require "json"
|
extend AuthD
|
||||||
require "jwt"
|
|
||||||
require "ipc"
|
|
||||||
|
|
||||||
require "baguette-crystal-base"
|
|
||||||
require "./user.cr"
|
|
||||||
|
|
||||||
# Allows get configuration from a provided file.
|
|
||||||
# See Baguette::Configuration::Base.get
|
|
||||||
class Baguette::Configuration
|
class Baguette::Configuration
|
||||||
class Auth < IPC
|
class Auth < IPC
|
||||||
include YAML::Serializable
|
property recreate_indexes : Bool = false
|
||||||
|
property storage : String = "storage"
|
||||||
|
property registrations : Bool = false
|
||||||
|
property require_email : Bool = false
|
||||||
|
property activation_template : String = "email-activation"
|
||||||
|
property recovery_template : String = "email-recovery"
|
||||||
|
property mailer_exe : String = "mailer"
|
||||||
|
property read_only_profile_keys : Array(String) = Array(String).new
|
||||||
|
|
||||||
property login : String? = nil
|
property print_password_recovery_parameters : Bool = false
|
||||||
property pass : String? = nil
|
|
||||||
property shared_key : String = "nico-nico-nii" # Default authd key, as per the specs. :eyes:
|
|
||||||
property shared_key_file : String? = nil
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class AuthD::Service < IPC::Server
|
# Provides a JWT-based authentication scheme for service-specific users.
|
||||||
|
class AuthD::Service < IPC
|
||||||
|
property configuration : Baguette::Configuration::Auth
|
||||||
|
|
||||||
|
# DB and its indexes.
|
||||||
|
property users : DODB::DataBase(User)
|
||||||
|
property users_per_uid : DODB::Index(User)
|
||||||
|
property users_per_login : DODB::Index(User)
|
||||||
|
|
||||||
|
# #{@configuration.storage}/last_used_uid
|
||||||
|
property last_uid_file : String
|
||||||
|
|
||||||
|
def initialize(@configuration)
|
||||||
|
super()
|
||||||
|
|
||||||
|
@users = DODB::DataBase(User).new @configuration.storage
|
||||||
|
@users_per_uid = @users.new_index "uid", &.uid.to_s
|
||||||
|
@users_per_login = @users.new_index "login", &.login
|
||||||
|
|
||||||
|
@last_uid_file = "#{@configuration.storage}/last_used_uid"
|
||||||
|
|
||||||
|
if @configuration.recreate_indexes
|
||||||
|
@users.reindex_everything!
|
||||||
|
end
|
||||||
|
|
||||||
|
self.timer @configuration.ipc_timer
|
||||||
|
self.service_init "auth"
|
||||||
|
end
|
||||||
|
|
||||||
|
def hash_password(password : String) : String
|
||||||
|
digest = OpenSSL::Digest.new "sha256"
|
||||||
|
digest << password
|
||||||
|
digest.hexfinal
|
||||||
|
end
|
||||||
|
|
||||||
|
# new_uid reads the last given UID and returns it incremented.
|
||||||
|
# Splitting the retrieval and record of new user ids allows to
|
||||||
|
# only increment when an user fully registers, thus avoiding a
|
||||||
|
# Denial of Service attack.
|
||||||
|
#
|
||||||
|
# WARNING: to record this new UID, new_uid_commit must be called.
|
||||||
|
# WARNING: new_uid isn't thread safe.
|
||||||
|
def new_uid
|
||||||
|
begin
|
||||||
|
uid = File.read(@last_uid_file).to_i
|
||||||
|
rescue
|
||||||
|
uid = 999
|
||||||
|
end
|
||||||
|
|
||||||
|
uid += 1
|
||||||
|
end
|
||||||
|
|
||||||
|
# new_uid_commit records the new UID.
|
||||||
|
# WARNING: new_uid_commit isn't thread safe.
|
||||||
|
def new_uid_commit(uid : Int)
|
||||||
|
File.write @last_uid_file, uid.to_s
|
||||||
|
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 = AuthD.requests.parse_ipc_json message.not_nil!
|
||||||
|
|
||||||
|
if request.nil?
|
||||||
|
raise "unknown request type"
|
||||||
|
end
|
||||||
|
|
||||||
|
request_name = request.class.name.sub /^AuthD::Request::/, ""
|
||||||
|
Baguette::Log.debug "<< #{request_name}"
|
||||||
|
|
||||||
|
response = begin
|
||||||
|
request.handle self
|
||||||
|
rescue e : UserNotFound
|
||||||
|
Baguette::Log.error "#{request_name} user not found"
|
||||||
|
AuthD::Response::Error.new "authorization error"
|
||||||
|
rescue e : AuthenticationInfoLacking
|
||||||
|
Baguette::Log.error "#{request_name} lacking authentication info"
|
||||||
|
AuthD::Response::Error.new "authorization error"
|
||||||
|
rescue e : AdminAuthorizationException
|
||||||
|
Baguette::Log.error "#{request_name} admin authentication failed"
|
||||||
|
AuthD::Response::Error.new "authorization error"
|
||||||
|
rescue e
|
||||||
|
Baguette::Log.error "#{request_name} generic error #{e}"
|
||||||
|
AuthD::Response::Error.new "unknown 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 /^AuthD::Response::/, ""
|
||||||
|
|
||||||
|
if response.is_a? AuthD::Response::Error
|
||||||
|
Baguette::Log.warning ">> #{response_name} (#{response.reason})"
|
||||||
|
else
|
||||||
|
Baguette::Log.debug ">> #{response_name} (Total duration: #{duration})"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_user_from_token(token : String)
|
||||||
|
token_payload = Token.from_s(@configuration.shared_key, token)
|
||||||
|
|
||||||
|
@users_per_uid.get? token_payload.uid.to_s
|
||||||
|
end
|
||||||
|
|
||||||
|
def run
|
||||||
|
Baguette::Log.title "Starting authd"
|
||||||
|
|
||||||
|
Baguette::Log.info "(mailer) Email activation template: #{@configuration.activation_template}"
|
||||||
|
Baguette::Log.info "(mailer) Email recovery template: #{@configuration.recovery_template}"
|
||||||
|
|
||||||
|
self.loop do |event|
|
||||||
|
case event.type
|
||||||
|
when LibIPC::EventType::Timer
|
||||||
|
Baguette::Log.debug "Timer" if @configuration.print_ipc_timer
|
||||||
|
|
||||||
|
when LibIPC::EventType::MessageRx
|
||||||
|
Baguette::Log.debug "Received message from #{event.fd}" if @configuration.print_ipc_message_received
|
||||||
|
begin
|
||||||
|
handle_request event
|
||||||
|
rescue e
|
||||||
|
Baguette::Log.error "#{e.message}"
|
||||||
|
# send event.fd, Response::Error.new e.message
|
||||||
|
end
|
||||||
|
|
||||||
|
when LibIPC::EventType::MessageTx
|
||||||
|
Baguette::Log.debug "Message sent to #{event.fd}" if @configuration.print_ipc_message_sent
|
||||||
|
|
||||||
|
when LibIPC::EventType::Connection
|
||||||
|
Baguette::Log.debug "Connection from #{event.fd}" if @configuration.print_ipc_connection
|
||||||
|
when LibIPC::EventType::Disconnection
|
||||||
|
Baguette::Log.debug "Disconnection from #{event.fd}" if @configuration.print_ipc_disconnection
|
||||||
|
else
|
||||||
|
Baguette::Log.error "Not implemented behavior for event: #{event}"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Requests and responses.
|
|
||||||
require "./exceptions"
|
|
||||||
|
|
||||||
# Requests and responses.
|
begin
|
||||||
require "./network"
|
simulation, no_configuration, configuration_file = Baguette::Configuration.option_parser
|
||||||
|
|
||||||
# Functions to request the authd server.
|
configuration = if no_configuration
|
||||||
require "./libclient.cr"
|
Baguette::Log.info "do not load a configuration file."
|
||||||
|
Baguette::Configuration::Auth.new
|
||||||
|
else
|
||||||
|
Baguette::Configuration::Auth.get(configuration_file) ||
|
||||||
|
Baguette::Configuration::Auth.new
|
||||||
|
end
|
||||||
|
|
||||||
|
Baguette::Context.verbosity = configuration.verbosity
|
||||||
|
|
||||||
|
if key_file = configuration.shared_key_file
|
||||||
|
configuration.shared_key = File.read(key_file).chomp
|
||||||
|
end
|
||||||
|
|
||||||
|
OptionParser.parse do |parser|
|
||||||
|
parser.banner = "usage: authd [options]"
|
||||||
|
|
||||||
|
parser.on "--storage directory", "Directory in which to store users." do |directory|
|
||||||
|
configuration.storage = directory
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.on "-K file", "--key-file file", "JWT key file" do |file_name|
|
||||||
|
configuration.shared_key = File.read(file_name).chomp
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.on "-R", "--allow-registrations", "Allow user registration." do
|
||||||
|
configuration.registrations = true
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.on "-E", "--require-email", "Require an email." do
|
||||||
|
configuration.require_email = true
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.on "-t activation-template-name", "--activation-template name", "Email activation template." do |opt|
|
||||||
|
configuration.activation_template = opt
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.on "-r recovery-template-name", "--recovery-template name", "Email recovery template." do |opt|
|
||||||
|
configuration.recovery_template = opt
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.on "-m mailer-exe", "--mailer mailer-exe", "Application to send registration emails." do |opt|
|
||||||
|
configuration.mailer_exe = opt
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
parser.on "-x key", "--read-only-profile-key key", "Marks a user profile key as being read-only." do |key|
|
||||||
|
configuration.read_only_profile_keys.push key
|
||||||
|
end
|
||||||
|
|
||||||
|
parser.on "-h", "--help", "Show this help" do
|
||||||
|
puts parser
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if simulation
|
||||||
|
pp! configuration
|
||||||
|
exit 0
|
||||||
|
end
|
||||||
|
|
||||||
|
AuthD::Service.new(configuration).run
|
||||||
|
|
||||||
|
rescue e : OptionParser::Exception
|
||||||
|
Baguette::Log.error e.message
|
||||||
|
rescue e
|
||||||
|
Baguette::Log.error "exception raised: #{e.message}"
|
||||||
|
e.backtrace.try &.each do |line|
|
||||||
|
STDERR << " - " << line << '\n'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -1,13 +1,25 @@
|
||||||
require "ipc/json"
|
require "ipc/json"
|
||||||
|
require "json"
|
||||||
|
|
||||||
module AuthD
|
module AuthD
|
||||||
class Client < IPC::Client
|
class Client < IPC
|
||||||
property key : String
|
property key : String
|
||||||
|
property server_fd : Int32 = -1
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
|
super
|
||||||
@key = ""
|
@key = ""
|
||||||
|
fd = self.connect "auth"
|
||||||
|
if fd.nil?
|
||||||
|
raise "couldn't connect to 'auth' IPC service"
|
||||||
|
end
|
||||||
|
@server_fd = fd
|
||||||
|
end
|
||||||
|
|
||||||
initialize "auth"
|
def read
|
||||||
|
slice = self.read @server_fd
|
||||||
|
m = IPCMessage::TypedMessage.deserialize slice
|
||||||
|
m.not_nil!
|
||||||
end
|
end
|
||||||
|
|
||||||
def get_token?(login : String, password : String) : String?
|
def get_token?(login : String, password : String) : String?
|
||||||
|
@ -46,8 +58,14 @@ module AuthD
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def send_now(msg : IPC::JSON)
|
||||||
|
m = IPCMessage::TypedMessage.new msg.type.to_u8, msg.to_json
|
||||||
|
write @server_fd, m
|
||||||
|
end
|
||||||
|
|
||||||
def send_now(type : Request::Type, payload)
|
def send_now(type : Request::Type, payload)
|
||||||
send_now @server_fd, type.value.to_u8, payload
|
m = IPCMessage::TypedMessage.new type.value.to_u8, payload
|
||||||
|
write @server_fd, m
|
||||||
end
|
end
|
||||||
|
|
||||||
def decode_token(token)
|
def decode_token(token)
|
||||||
|
@ -62,7 +80,7 @@ module AuthD
|
||||||
def add_user(login : String, password : String,
|
def add_user(login : String, password : String,
|
||||||
email : String?,
|
email : String?,
|
||||||
phone : String?,
|
phone : String?,
|
||||||
profile : Hash(String, JSON::Any)?) : ::AuthD::User::Public | Exception
|
profile : Hash(String, ::JSON::Any)?) : ::AuthD::User::Public | Exception
|
||||||
|
|
||||||
send_now Request::AddUser.new @key, login, password, email, phone, profile
|
send_now Request::AddUser.new @key, login, password, email, phone, profile
|
||||||
|
|
||||||
|
@ -127,7 +145,7 @@ module AuthD
|
||||||
password : String,
|
password : String,
|
||||||
email : String?,
|
email : String?,
|
||||||
phone : String?,
|
phone : String?,
|
||||||
profile : Hash(String, JSON::Any)?) : ::AuthD::User::Public?
|
profile : Hash(String, ::JSON::Any)?) : ::AuthD::User::Public?
|
||||||
|
|
||||||
send_now Request::Register.new login, password, email, phone, profile
|
send_now Request::Register.new login, password, email, phone, profile
|
||||||
response = AuthD.responses.parse_ipc_json read
|
response = AuthD.responses.parse_ipc_json read
|
|
@ -1,9 +1,6 @@
|
||||||
require "json"
|
require "json"
|
||||||
|
|
||||||
require "uuid"
|
require "uuid"
|
||||||
|
|
||||||
require "./token.cr"
|
|
||||||
|
|
||||||
class AuthD::User
|
class AuthD::User
|
||||||
include JSON::Serializable
|
include JSON::Serializable
|
||||||
|
|
34
src/libauth.cr
Normal file
34
src/libauth.cr
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
require "json"
|
||||||
|
require "jwt"
|
||||||
|
require "ipc"
|
||||||
|
|
||||||
|
require "baguette-crystal-base"
|
||||||
|
|
||||||
|
# Allows get configuration from a provided file.
|
||||||
|
# See Baguette::Configuration::Base.get
|
||||||
|
class Baguette::Configuration
|
||||||
|
class Auth < IPC
|
||||||
|
include YAML::Serializable
|
||||||
|
|
||||||
|
property login : String? = nil
|
||||||
|
property pass : String? = nil
|
||||||
|
property shared_key : String = "nico-nico-nii" # Default authd key, as per the specs. :eyes:
|
||||||
|
property shared_key_file : String? = nil
|
||||||
|
|
||||||
|
def initialize
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Token and user classes.
|
||||||
|
require "./authd/token.cr"
|
||||||
|
require "./authd/user.cr"
|
||||||
|
|
||||||
|
# Requests and responses.
|
||||||
|
require "./authd/exceptions"
|
||||||
|
|
||||||
|
# Requests and responses.
|
||||||
|
require "./network"
|
||||||
|
|
||||||
|
# Functions to request the authd server.
|
||||||
|
require "./authd/client.cr"
|
238
src/main.cr
238
src/main.cr
|
@ -2,240 +2,12 @@ require "uuid"
|
||||||
require "option_parser"
|
require "option_parser"
|
||||||
require "openssl"
|
require "openssl"
|
||||||
require "colorize"
|
require "colorize"
|
||||||
|
|
||||||
require "jwt"
|
require "jwt"
|
||||||
require "ipc"
|
|
||||||
require "dodb"
|
|
||||||
|
|
||||||
require "baguette-crystal-base"
|
|
||||||
require "grok"
|
require "grok"
|
||||||
|
|
||||||
|
require "dodb"
|
||||||
|
require "baguette-crystal-base"
|
||||||
|
|
||||||
|
require "ipc"
|
||||||
|
require "./libauth.cr"
|
||||||
require "./authd.cr"
|
require "./authd.cr"
|
||||||
|
|
||||||
extend AuthD
|
|
||||||
|
|
||||||
class Baguette::Configuration
|
|
||||||
class Auth < IPC
|
|
||||||
property recreate_indexes : Bool = false
|
|
||||||
property storage : String = "storage"
|
|
||||||
property registrations : Bool = false
|
|
||||||
property require_email : Bool = false
|
|
||||||
property activation_url : String? = nil
|
|
||||||
property field_subject : String? = nil
|
|
||||||
property field_from : String? = nil
|
|
||||||
property read_only_profile_keys : Array(String) = Array(String).new
|
|
||||||
|
|
||||||
property print_password_recovery_parameters : Bool = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
# Provides a JWT-based authentication scheme for service-specific users.
|
|
||||||
class AuthD::Service < IPC::Server
|
|
||||||
property configuration : Baguette::Configuration::Auth
|
|
||||||
|
|
||||||
# DB and its indexes.
|
|
||||||
property users : DODB::DataBase(User)
|
|
||||||
property users_per_uid : DODB::Index(User)
|
|
||||||
property users_per_login : DODB::Index(User)
|
|
||||||
|
|
||||||
# #{@configuration.storage}/last_used_uid
|
|
||||||
property last_uid_file : String
|
|
||||||
|
|
||||||
def initialize(@configuration)
|
|
||||||
@users = DODB::DataBase(User).new @configuration.storage
|
|
||||||
@users_per_uid = @users.new_index "uid", &.uid.to_s
|
|
||||||
@users_per_login = @users.new_index "login", &.login
|
|
||||||
|
|
||||||
@last_uid_file = "#{@configuration.storage}/last_used_uid"
|
|
||||||
|
|
||||||
if @configuration.recreate_indexes
|
|
||||||
@users.reindex_everything!
|
|
||||||
end
|
|
||||||
|
|
||||||
super "auth"
|
|
||||||
end
|
|
||||||
|
|
||||||
def hash_password(password : String) : String
|
|
||||||
digest = OpenSSL::Digest.new "sha256"
|
|
||||||
digest << password
|
|
||||||
digest.hexfinal
|
|
||||||
end
|
|
||||||
|
|
||||||
def new_uid
|
|
||||||
begin
|
|
||||||
uid = File.read(@last_uid_file).to_i
|
|
||||||
rescue
|
|
||||||
uid = 999
|
|
||||||
end
|
|
||||||
|
|
||||||
uid += 1
|
|
||||||
|
|
||||||
File.write @last_uid_file, uid.to_s
|
|
||||||
|
|
||||||
uid
|
|
||||||
end
|
|
||||||
|
|
||||||
def handle_request(event : IPC::Event::MessageReceived)
|
|
||||||
request_start = Time.utc
|
|
||||||
|
|
||||||
request = AuthD.requests.parse_ipc_json event.message
|
|
||||||
|
|
||||||
if request.nil?
|
|
||||||
raise "unknown request type"
|
|
||||||
end
|
|
||||||
|
|
||||||
request_name = request.class.name.sub /^AuthD::Request::/, ""
|
|
||||||
Baguette::Log.debug "<< #{request_name}"
|
|
||||||
|
|
||||||
response = begin
|
|
||||||
request.handle self, event
|
|
||||||
rescue e : UserNotFound
|
|
||||||
Baguette::Log.error "#{request_name} user not found"
|
|
||||||
AuthD::Response::Error.new "authorization error"
|
|
||||||
rescue e : AuthenticationInfoLacking
|
|
||||||
Baguette::Log.error "#{request_name} lacking authentication info"
|
|
||||||
AuthD::Response::Error.new "authorization error"
|
|
||||||
rescue e : AdminAuthorizationException
|
|
||||||
Baguette::Log.error "#{request_name} admin authentication failed"
|
|
||||||
AuthD::Response::Error.new "authorization error"
|
|
||||||
rescue e
|
|
||||||
Baguette::Log.error "#{request_name} generic error #{e}"
|
|
||||||
AuthD::Response::Error.new "unknown error"
|
|
||||||
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_name = response.class.name.sub /^AuthD::Response::/, ""
|
|
||||||
|
|
||||||
if response.is_a? AuthD::Response::Error
|
|
||||||
Baguette::Log.warning ">> #{response_name} (#{response.reason})"
|
|
||||||
else
|
|
||||||
Baguette::Log.debug ">> #{response_name} (Total duration: #{duration})"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def get_user_from_token(token : String)
|
|
||||||
token_payload = Token.from_s(@configuration.shared_key, token)
|
|
||||||
|
|
||||||
@users_per_uid.get? token_payload.uid.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
def run
|
|
||||||
Baguette::Log.title "Starting authd"
|
|
||||||
|
|
||||||
@base_timer = @configuration.ipc_timer
|
|
||||||
@timer = @configuration.ipc_timer
|
|
||||||
|
|
||||||
self.loop do |event|
|
|
||||||
case event
|
|
||||||
when IPC::Event::Timer
|
|
||||||
Baguette::Log.debug "Timer" if @configuration.print_ipc_timer
|
|
||||||
|
|
||||||
when IPC::Event::MessageReceived
|
|
||||||
Baguette::Log.debug "Received message from #{event.fd}" if @configuration.print_ipc_message_received
|
|
||||||
begin
|
|
||||||
handle_request event
|
|
||||||
rescue e
|
|
||||||
Baguette::Log.error "#{e.message}"
|
|
||||||
# send event.fd, Response::Error.new e.message
|
|
||||||
end
|
|
||||||
|
|
||||||
when IPC::Event::MessageSent
|
|
||||||
Baguette::Log.debug "Message sent to #{event.fd}" if @configuration.print_ipc_message_sent
|
|
||||||
|
|
||||||
when IPC::Exception
|
|
||||||
Baguette::Log.error "IPC::Exception"
|
|
||||||
pp! event
|
|
||||||
when IPC::Event::Connection
|
|
||||||
Baguette::Log.debug "Connection from #{event.fd}" if @configuration.print_ipc_connection
|
|
||||||
when IPC::Event::Disconnection
|
|
||||||
Baguette::Log.debug "Disconnection from #{event.fd}" if @configuration.print_ipc_disconnection
|
|
||||||
else
|
|
||||||
Baguette::Log.error "Not implemented behavior for event: #{event}"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
begin
|
|
||||||
simulation, no_configuration, configuration_file = Baguette::Configuration.option_parser
|
|
||||||
|
|
||||||
configuration = if no_configuration
|
|
||||||
Baguette::Log.info "do not load a configuration file."
|
|
||||||
Baguette::Configuration::Auth.new
|
|
||||||
else
|
|
||||||
Baguette::Configuration::Auth.get(configuration_file) ||
|
|
||||||
Baguette::Configuration::Auth.new
|
|
||||||
end
|
|
||||||
|
|
||||||
Baguette::Context.verbosity = configuration.verbosity
|
|
||||||
|
|
||||||
if key_file = configuration.shared_key_file
|
|
||||||
configuration.shared_key = File.read(key_file).chomp
|
|
||||||
end
|
|
||||||
|
|
||||||
OptionParser.parse do |parser|
|
|
||||||
parser.banner = "usage: authd [options]"
|
|
||||||
|
|
||||||
parser.on "--storage directory", "Directory in which to store users." do |directory|
|
|
||||||
configuration.storage = directory
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on "-K file", "--key-file file", "JWT key file" do |file_name|
|
|
||||||
configuration.shared_key = File.read(file_name).chomp
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on "-R", "--allow-registrations" do
|
|
||||||
configuration.registrations = true
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on "-E", "--require-email" do
|
|
||||||
configuration.require_email = true
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on "-t subject", "--subject title", "Subject of the email." do |s|
|
|
||||||
configuration.field_subject = s
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on "-f from-email", "--from email", "'From:' field to use in activation email." do |f|
|
|
||||||
configuration.field_from = f
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on "-u", "--activation-url url", "Activation URL." do |opt|
|
|
||||||
configuration.activation_url = opt
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on "-x key", "--read-only-profile-key key", "Marks a user profile key as being read-only." do |key|
|
|
||||||
configuration.read_only_profile_keys.push key
|
|
||||||
end
|
|
||||||
|
|
||||||
parser.on "-h", "--help", "Show this help" do
|
|
||||||
puts parser
|
|
||||||
exit 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if simulation
|
|
||||||
pp! configuration
|
|
||||||
exit 0
|
|
||||||
end
|
|
||||||
|
|
||||||
AuthD::Service.new(configuration).run
|
|
||||||
|
|
||||||
rescue e : OptionParser::Exception
|
|
||||||
Baguette::Log.error e.message
|
|
||||||
rescue e
|
|
||||||
Baguette::Log.error "exception raised: #{e.message}"
|
|
||||||
e.backtrace.try &.each do |line|
|
|
||||||
STDERR << " - " << line << '\n'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
require "ipc"
|
require "ipc"
|
||||||
require "json"
|
|
||||||
require "ipc/json"
|
require "ipc/json"
|
||||||
|
|
||||||
class IPC::JSON
|
class IPC::JSON
|
||||||
def handle(service : AuthD::Service, event : IPC::Event::Events)
|
def handle(service : AuthD::Service)
|
||||||
raise "unimplemented"
|
raise "unimplemented"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -13,22 +12,11 @@ module AuthD
|
||||||
class_getter responses = [] of IPC::JSON.class
|
class_getter responses = [] of IPC::JSON.class
|
||||||
end
|
end
|
||||||
|
|
||||||
class IPC::Context
|
class IPC
|
||||||
def send(fd, response : AuthD::Response)
|
def schedule(fd, m : (AuthD::Request | AuthD::Response))
|
||||||
send fd, response.type.to_u8, response.to_json
|
schedule fd, m.type.to_u8, m.to_json
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
class IPC::Client
|
|
||||||
def send(request : AuthD::Request)
|
|
||||||
unless (fd = @server_fd).nil?
|
|
||||||
send_now fd, request.type.to_u8, request.to_json
|
|
||||||
else
|
|
||||||
raise "Client not connected to the server"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
require "./requests/*"
|
require "./requests/*"
|
||||||
require "./responses/*"
|
require "./responses/*"
|
||||||
|
|
|
@ -13,7 +13,7 @@ class AuthD::Request
|
||||||
def initialize(@shared_key, @login, @password, @email, @phone, @profile)
|
def initialize(@shared_key, @login, @password, @email, @phone, @profile)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
# No verification of the users' informations when an admin adds it.
|
# No verification of the users' informations when an admin adds it.
|
||||||
# No mail address verification.
|
# No mail address verification.
|
||||||
if @shared_key != authd.configuration.shared_key
|
if @shared_key != authd.configuration.shared_key
|
||||||
|
@ -44,7 +44,7 @@ class AuthD::Request
|
||||||
user.date_registration = Time.local
|
user.date_registration = Time.local
|
||||||
|
|
||||||
authd.users << user
|
authd.users << user
|
||||||
|
authd.new_uid_commit uid
|
||||||
Response::UserAdded.new user.to_public
|
Response::UserAdded.new user.to_public
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -63,7 +63,7 @@ class AuthD::Request
|
||||||
def initialize(@shared_key, @user)
|
def initialize(@shared_key, @user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
if @shared_key != authd.configuration.shared_key
|
if @shared_key != authd.configuration.shared_key
|
||||||
return Response::Error.new "invalid authentication key"
|
return Response::Error.new "invalid authentication key"
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,7 +8,7 @@ class AuthD::Request
|
||||||
def initialize(@token)
|
def initialize(@token)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
user = authd.get_user_from_token @token
|
user = authd.get_user_from_token @token
|
||||||
|
|
||||||
return Response::Error.new "invalid user" unless user
|
return Response::Error.new "invalid user" unless user
|
||||||
|
@ -32,7 +32,7 @@ class AuthD::Request
|
||||||
def initialize(@token)
|
def initialize(@token)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
user = authd.get_user_from_token @token
|
user = authd.get_user_from_token @token
|
||||||
|
|
||||||
return Response::Error.new "invalid user" unless user
|
return Response::Error.new "invalid user" unless user
|
||||||
|
|
|
@ -13,7 +13,7 @@ class AuthD::Request
|
||||||
def initialize(@user, @shared_key)
|
def initialize(@user, @shared_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
uid_or_login = @user
|
uid_or_login = @user
|
||||||
user_to_delete = if uid_or_login.is_a? Int32
|
user_to_delete = if uid_or_login.is_a? Int32
|
||||||
authd.users_per_uid.get? uid_or_login.to_s
|
authd.users_per_uid.get? uid_or_login.to_s
|
||||||
|
|
|
@ -6,7 +6,7 @@ class AuthD::Request
|
||||||
def initialize(@token, @key)
|
def initialize(@token, @key)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
# FIXME: Lines too long, repeatedly (>80c with 4c tabs).
|
# FIXME: Lines too long, repeatedly (>80c with 4c tabs).
|
||||||
@token.try do |token|
|
@token.try do |token|
|
||||||
user = authd.get_user_from_token token
|
user = authd.get_user_from_token token
|
||||||
|
|
|
@ -7,7 +7,7 @@ class AuthD::Request
|
||||||
def initialize(@login, @old_password, @new_password)
|
def initialize(@login, @old_password, @new_password)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
user = authd.users_per_login.get? @login
|
user = authd.users_per_login.get? @login
|
||||||
|
|
||||||
unless user
|
unless user
|
||||||
|
@ -35,7 +35,7 @@ class AuthD::Request
|
||||||
def initialize(@user, @password_renew_key, @new_password)
|
def initialize(@user, @password_renew_key, @new_password)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
uid_or_login = @user
|
uid_or_login = @user
|
||||||
user = if uid_or_login.is_a? Int32
|
user = if uid_or_login.is_a? Int32
|
||||||
authd.users_per_uid.get? uid_or_login.to_s
|
authd.users_per_uid.get? uid_or_login.to_s
|
||||||
|
@ -69,7 +69,7 @@ class AuthD::Request
|
||||||
def initialize(@user, @email)
|
def initialize(@user, @email)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
uid_or_login = @user
|
uid_or_login = @user
|
||||||
user = if uid_or_login.is_a? Int32
|
user = if uid_or_login.is_a? Int32
|
||||||
authd.users_per_uid.get? uid_or_login.to_s
|
authd.users_per_uid.get? uid_or_login.to_s
|
||||||
|
@ -90,32 +90,29 @@ class AuthD::Request
|
||||||
|
|
||||||
authd.users_per_uid.update user.uid.to_s, user
|
authd.users_per_uid.update user.uid.to_s, user
|
||||||
|
|
||||||
unless (activation_url = authd.configuration.activation_url).nil?
|
# Once the user is created and stored, we try to contact him
|
||||||
|
if authd.configuration.print_password_recovery_parameters
|
||||||
|
pp! user.login,
|
||||||
|
user.contact.email.not_nil!,
|
||||||
|
user.password_renew_key.not_nil!
|
||||||
|
end
|
||||||
|
|
||||||
field_from = authd.configuration.field_from.not_nil!
|
mailer_exe = authd.configuration.mailer_exe
|
||||||
activation_url = authd.configuration.activation_url.not_nil!
|
template_name = authd.configuration.recovery_template
|
||||||
|
|
||||||
# Once the user is created and stored, we try to contact him
|
u_login = user.login
|
||||||
|
u_email = user.contact.email.not_nil!
|
||||||
|
u_token = user.password_renew_key.not_nil!
|
||||||
|
|
||||||
if authd.configuration.print_password_recovery_parameters
|
# Once the user is created and stored, we try to contact him.
|
||||||
pp! user.login,
|
unless Process.run(mailer_exe,
|
||||||
user.contact.email.not_nil!,
|
# PARAMETERS
|
||||||
field_from,
|
[ "send", template_name, u_email ],
|
||||||
activation_url,
|
# ENV
|
||||||
user.password_renew_key.not_nil!
|
{ "LOGIN" => u_login, "TOKEN" => u_token },
|
||||||
end
|
true # clear environment
|
||||||
|
).success?
|
||||||
unless Process.run("password-recovery-mailer", [
|
raise "cannot contact user #{u_login} address #{u_email}"
|
||||||
"-l", user.login,
|
|
||||||
"-e", user.contact.email.not_nil!,
|
|
||||||
"-t", "Password recovery email",
|
|
||||||
"-f", field_from,
|
|
||||||
"-u", activation_url,
|
|
||||||
"-a", user.password_renew_key.not_nil!
|
|
||||||
]).success?
|
|
||||||
|
|
||||||
return Response::Error.new "cannot contact the user for password recovery"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
Response::PasswordRecoverySent.new user.to_public
|
Response::PasswordRecoverySent.new user.to_public
|
||||||
|
|
|
@ -10,7 +10,7 @@ class AuthD::Request
|
||||||
def initialize(@shared_key, @user, @service, @resource)
|
def initialize(@shared_key, @user, @service, @resource)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
authorized = false
|
authorized = false
|
||||||
|
|
||||||
if key = @shared_key
|
if key = @shared_key
|
||||||
|
@ -79,7 +79,7 @@ class AuthD::Request
|
||||||
def initialize(@shared_key, @user, @service, @resource, @permission)
|
def initialize(@shared_key, @user, @service, @resource, @permission)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
unless @shared_key == authd.configuration.shared_key
|
unless @shared_key == authd.configuration.shared_key
|
||||||
return Response::Error.new "unauthorized"
|
return Response::Error.new "unauthorized"
|
||||||
end
|
end
|
||||||
|
|
|
@ -6,7 +6,7 @@ class AuthD::Request
|
||||||
def initialize(@token, @new_profile)
|
def initialize(@token, @new_profile)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
user = authd.get_user_from_token @token
|
user = authd.get_user_from_token @token
|
||||||
|
|
||||||
return Response::Error.new "invalid user" unless user
|
return Response::Error.new "invalid user" unless user
|
||||||
|
@ -45,7 +45,7 @@ class AuthD::Request
|
||||||
def initialize(@token, @new_profile)
|
def initialize(@token, @new_profile)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
user = if token = @token
|
user = if token = @token
|
||||||
u = authd.get_user_from_token token
|
u = authd.get_user_from_token token
|
||||||
raise UserNotFound.new unless u
|
raise UserNotFound.new unless u
|
||||||
|
|
|
@ -9,7 +9,7 @@ class AuthD::Request
|
||||||
def initialize(@login, @password, @email, @phone, @profile)
|
def initialize(@login, @password, @email, @phone, @profile)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
if ! authd.configuration.registrations
|
if ! authd.configuration.registrations
|
||||||
return Response::Error.new "registrations not allowed"
|
return Response::Error.new "registrations not allowed"
|
||||||
end
|
end
|
||||||
|
@ -22,12 +22,6 @@ class AuthD::Request
|
||||||
return Response::Error.new "email required"
|
return Response::Error.new "email required"
|
||||||
end
|
end
|
||||||
|
|
||||||
activation_url = authd.configuration.activation_url
|
|
||||||
if activation_url.nil?
|
|
||||||
# In this case we should not accept its registration.
|
|
||||||
return Response::Error.new "No activation URL were entered. Cannot send activation mails."
|
|
||||||
end
|
|
||||||
|
|
||||||
if ! @email.nil?
|
if ! @email.nil?
|
||||||
# Test on the email address format.
|
# Test on the email address format.
|
||||||
grok = Grok.new [ "%{EMAILADDRESS:email}" ]
|
grok = Grok.new [ "%{EMAILADDRESS:email}" ]
|
||||||
|
@ -58,33 +52,31 @@ class AuthD::Request
|
||||||
user.date_registration = Time.local
|
user.date_registration = Time.local
|
||||||
|
|
||||||
begin
|
begin
|
||||||
field_subject = authd.configuration.field_subject.not_nil!
|
mailer_exe = authd.configuration.mailer_exe
|
||||||
field_from = authd.configuration.field_from.not_nil!
|
template_name = authd.configuration.activation_template
|
||||||
activation_url = authd.configuration.activation_url.not_nil!
|
|
||||||
|
|
||||||
u_login = user.login
|
u_login = user.login
|
||||||
u_email = user.contact.email.not_nil!
|
u_email = user.contact.email.not_nil!
|
||||||
u_activation_key = user.contact.activation_key.not_nil!
|
u_activation_key = user.contact.activation_key.not_nil!
|
||||||
|
|
||||||
# Once the user is created and stored, we try to contact him
|
# Once the user is created and stored, we try to contact him.
|
||||||
unless Process.run("activation-mailer", [
|
unless Process.run(mailer_exe,
|
||||||
"-l", u_login,
|
# PARAMETERS
|
||||||
"-e", u_email,
|
[ "send", template_name, u_email ],
|
||||||
"-t", field_subject,
|
# ENV
|
||||||
"-f", field_from,
|
{ "LOGIN" => u_login, "TOKEN" => u_activation_key },
|
||||||
"-u", activation_url,
|
true # clear environment
|
||||||
"-a", u_activation_key
|
).success?
|
||||||
]).success?
|
raise "cannot contact user #{u_login} address #{u_email}"
|
||||||
raise "cannot contact user #{user.login} address #{user.contact.email}"
|
|
||||||
end
|
end
|
||||||
rescue e
|
rescue e
|
||||||
Baguette::Log.error "activation-mailer: #{e}"
|
Baguette::Log.error "mailer: #{e}"
|
||||||
return Response::Error.new "cannot contact the user (not registered)"
|
return Response::Error.new "cannot contact the user (not registered)"
|
||||||
end
|
end
|
||||||
|
|
||||||
# add the user only if we were able to send the confirmation mail
|
# add the user only if we were able to send the confirmation mail
|
||||||
authd.users << user
|
authd.users << user
|
||||||
|
authd.new_uid_commit uid
|
||||||
Response::UserAdded.new user.to_public
|
Response::UserAdded.new user.to_public
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,7 +5,7 @@ class AuthD::Request
|
||||||
def initialize(@user)
|
def initialize(@user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
pattern = Regex.new @user, Regex::Options::IGNORE_CASE
|
pattern = Regex.new @user, Regex::Options::IGNORE_CASE
|
||||||
|
|
||||||
matching_users = Array(AuthD::User::Public).new
|
matching_users = Array(AuthD::User::Public).new
|
||||||
|
|
|
@ -6,7 +6,7 @@ class AuthD::Request
|
||||||
def initialize(@login, @password)
|
def initialize(@login, @password)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
begin
|
begin
|
||||||
user = authd.users_per_login.get @login
|
user = authd.users_per_login.get @login
|
||||||
rescue e : DODB::MissingEntry
|
rescue e : DODB::MissingEntry
|
||||||
|
|
|
@ -6,7 +6,7 @@ class AuthD::Request
|
||||||
def initialize(@login, @activation_key)
|
def initialize(@login, @activation_key)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
user = authd.users_per_login.get? @login
|
user = authd.users_per_login.get? @login
|
||||||
|
|
||||||
if user.nil?
|
if user.nil?
|
||||||
|
@ -37,7 +37,7 @@ class AuthD::Request
|
||||||
def initialize(@user)
|
def initialize(@user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
uid_or_login = @user
|
uid_or_login = @user
|
||||||
user = if uid_or_login.is_a? Int32
|
user = if uid_or_login.is_a? Int32
|
||||||
authd.users_per_uid.get? uid_or_login.to_s
|
authd.users_per_uid.get? uid_or_login.to_s
|
||||||
|
@ -61,7 +61,7 @@ class AuthD::Request
|
||||||
def initialize(@login, @password)
|
def initialize(@login, @password)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, event : IPC::Event::Events)
|
def handle(authd : AuthD::Service)
|
||||||
user = authd.users_per_login.get? @login
|
user = authd.users_per_login.get? @login
|
||||||
|
|
||||||
unless user
|
unless user
|
||||||
|
|
|
@ -5,12 +5,7 @@ require "yaml"
|
||||||
|
|
||||||
require "baguette-crystal-base"
|
require "baguette-crystal-base"
|
||||||
|
|
||||||
require "../src/authd.cr"
|
require "../src/libauth.cr"
|
||||||
|
|
||||||
# require "./altideal-client.cr"
|
|
||||||
# require "./yaml_uuid.cr" # YAML UUID parser
|
|
||||||
# require "./authd_api.cr" # Authd interface functions
|
|
||||||
|
|
||||||
|
|
||||||
class Context
|
class Context
|
||||||
class_property simulation = false # do not perform the action
|
class_property simulation = false # do not perform the action
|
||||||
|
@ -35,7 +30,6 @@ class Context
|
||||||
class_property args : Array(String)? = nil
|
class_property args : Array(String)? = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
# require "./parse-me"
|
|
||||||
require "./better-parser"
|
require "./better-parser"
|
||||||
|
|
||||||
class Actions
|
class Actions
|
||||||
|
@ -106,7 +100,7 @@ class Actions
|
||||||
|
|
||||||
res = authd.register login, password.not_nil!, email, phone, profile: profile
|
res = authd.register login, password.not_nil!, email, phone, profile: profile
|
||||||
puts res
|
puts res
|
||||||
rescue e : AuthD::Exception
|
rescue e
|
||||||
puts "error: #{e.message}"
|
puts "error: #{e.message}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -229,4 +223,3 @@ end
|
||||||
# tool [options] command [options-for-command]
|
# tool [options] command [options-for-command]
|
||||||
|
|
||||||
main
|
main
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue