Grooming.

ipc07
Luka Vandervelden 2019-11-22 18:14:52 +01:00
parent 32a8c23524
commit 297471b504
2 changed files with 134 additions and 117 deletions

View File

@ -1,3 +1,4 @@
require "json"
require "jwt" require "jwt"
@ -16,63 +17,131 @@ module AuthD
AuthenticationError AuthenticationError
end end
end end
end
class Request class AuthD::Request
enum Type include JSON::Serializable
GetToken
AddUser annotation MessageType
GetUser
GetUserByCredentials
ModUser # Edit user attributes.
end end
class GetToken class_getter type = -1
JSON.mapping({
# FIXME: Rename to "login" for consistency. macro inherited
login: String, def self.type
password: String ::AuthD::Request::Type::{{ @type.name.split("::").last.id }}
}) end
end end
class AddUser macro initialize(*properties)
JSON.mapping({ def initialize(
{% for value in properties %}
@{{value.id}}{% if value != properties.last %},{% end %}
{% end %}
)
end
def type
Type::{{ @type.name.split("::").last.id }}
end
end
class GetToken < Request
property login : String
property password : String
initialize :login, :password
end
class AddUser < Request
# Only clients that have the right shared key will be allowed # Only clients that have the right shared key will be allowed
# to create users. # to create users.
shared_key: String, property shared_key : String
login: String, property login : String
password: String, property password : String
uid: Int32?, property uid : Int32?
gid: Int32?, property gid : Int32?
home: String?, property home : String?
shell: String? property shell : String?
})
initialize :shared_key, :login, :password
end end
class GetUser class GetUser < Request
JSON.mapping({ property uid : Int32
uid: Int32
}) initialize :uid
end end
class GetUserByCredentials class GetUserByCredentials < Request
JSON.mapping({ property login : String
login: String, property password : String
password: String
}) initialize :login, :password
end end
class ModUser class ModUser < Request
JSON.mapping({ property shared_key : String
shared_key: String,
uid: Int32, property uid : Int32
password: String?, property password : String?
avatar: String? property avatar : String?
})
end initialize :shared_key, :uid
end end
# This creates a Request::Type enumeration. One entry for each request type.
{% begin %}
enum Type
{% for ivar in @type.subclasses %}
{% klass = ivar.name %}
{% name = ivar.name.split("::").last.id %}
{% a = ivar.annotation(MessageType) %}
{% if a %}
{% value = a[0] %}
{{ name }} = {{ value }}
{% else %}
{{ name }}
{% end %}
{% end %}
end
{% end %}
# This is an array of all requests types.
{% begin %}
class_getter requests = [
{% for ivar in @type.subclasses %}
{% klass = ivar.name %}
{{klass}},
{% end %}
]
{% end %}
def self.from_ipc(message : IPC::Message)
payload = String.new message.payload
type = Type.new message.type.to_i
begin
request = requests.find(&.type.==(type)).try &.from_json(payload)
rescue e : JSON::ParseException
raise Exception.new "misformed request"
end
request
end
end
class IPC::Connection
def send(request : AuthD::Request)
send request.type.to_u8, request.to_json
end
end
module AuthD
class Client < IPC::Connection class Client < IPC::Connection
property key : String property key : String
@ -83,10 +152,7 @@ module AuthD
end end
def get_token?(login : String, password : String) : String? def get_token?(login : String, password : String) : String?
send Request::Type::GetToken, { send Request::GetToken.new login, password
:login => login,
:password => password
}.to_json
response = read response = read
@ -98,10 +164,7 @@ module AuthD
end end
def get_user?(login : String, password : String) : Passwd::User? def get_user?(login : String, password : String) : Passwd::User?
send Request::Type::GetUserByCredentials, { send Request::GetUserByCredentials.new login, password
:login => login,
:password => password
}.to_json
response = read response = read
@ -113,7 +176,7 @@ module AuthD
end end
def get_user?(uid : Int32) def get_user?(uid : Int32)
send Request::Type::GetUser, {:uid => uid}.to_json send Request::GetUser.new uid
response = read response = read
@ -138,11 +201,7 @@ module AuthD
# FIXME: Extra options may be useful to implement here. # FIXME: Extra options may be useful to implement here.
def add_user(login : String, password : String) : Passwd::User | Exception def add_user(login : String, password : String) : Passwd::User | Exception
send Request::Type::AddUser, { send Request::AddUser.new @key, login, password
:shared_key => @key,
:login => login,
:password => password
}.to_json
response = read response = read
@ -156,19 +215,12 @@ module AuthD
end end
def mod_user(uid : Int32, password : String? = nil, avatar : String? = nil) : Bool | Exception def mod_user(uid : Int32, password : String? = nil, avatar : String? = nil) : Bool | Exception
payload = Hash(String, String|Int32).new request = Request::ModUser.new @key, uid
payload["uid"] = uid
payload["shared_key"] = @key
password.try do |password| request.password = password if password
payload["password"] = password request.avatar = avatar if avatar
end
avatar.try do |avatar| send request
payload["avatar"] = avatar
end
send Request::Type::ModUser, payload.to_json
response = read response = read

View File

@ -58,16 +58,10 @@ IPC::Service.new "auth" do |event|
message = event.message message = event.message
payload = message.payload payload = message.payload
case Request::Type.new message.type.to_i request = Request.from_ipc message
when Request::Type::GetToken
begin
request = Request::GetToken.from_json String.new payload
rescue e
client.send Response::Type::Malformed.value.to_u8, e.message || ""
next
end
case request
when Request::GetToken
user = passwd.get_user request.login, request.password user = passwd.get_user request.login, request.password
if user.nil? if user.nil?
@ -78,15 +72,7 @@ IPC::Service.new "auth" do |event|
client.send Response::Type::Ok.value.to_u8, client.send Response::Type::Ok.value.to_u8,
JWT.encode user.to_h, authd_jwt_key, JWT::Algorithm::HS256 JWT.encode user.to_h, authd_jwt_key, JWT::Algorithm::HS256
when Request::Type::AddUser when Request::AddUser
begin
request = Request::AddUser.from_json String.new payload
rescue e
client.send Response::Type::Malformed.value.to_u8, e.message || ""
next
end
if request.shared_key != authd_jwt_key if request.shared_key != authd_jwt_key
client.send Response::Type::AuthenticationError, "Invalid authentication key." client.send Response::Type::AuthenticationError, "Invalid authentication key."
next next
@ -101,14 +87,7 @@ IPC::Service.new "auth" do |event|
user = passwd.add_user request.login, request.password user = passwd.add_user request.login, request.password
client.send Response::Type::Ok, user.sanitize!.to_json client.send Response::Type::Ok, user.sanitize!.to_json
when Request::Type::GetUserByCredentials when Request::GetUserByCredentials
begin
request = Request::GetUserByCredentials.from_json String.new payload
rescue e
client.send Response::Type::Malformed, e.message || ""
next
end
user = passwd.get_user request.login, request.password user = passwd.get_user request.login, request.password
if user if user
@ -116,14 +95,7 @@ IPC::Service.new "auth" do |event|
else else
client.send Response::Type::UserNotFound, "" client.send Response::Type::UserNotFound, ""
end end
when Request::Type::GetUser when Request::GetUser
begin
request = Request::GetUser.from_json String.new payload
rescue e
client.send Response::Type::Malformed, e.message || ""
next
end
user = passwd.get_user request.uid user = passwd.get_user request.uid
if user if user
@ -131,14 +103,7 @@ IPC::Service.new "auth" do |event|
else else
client.send Response::Type::UserNotFound, "" client.send Response::Type::UserNotFound, ""
end end
when Request::Type::ModUser when Request::ModUser
begin
request = Request::ModUser.from_json String.new payload
rescue e
client.send Response::Type::Malformed, e.message || ""
next
end
if request.shared_key != authd_jwt_key if request.shared_key != authd_jwt_key
client.send Response::Type::AuthenticationError, "Invalid authentication key." client.send Response::Type::AuthenticationError, "Invalid authentication key."
next next