Grooming.
parent
32a8c23524
commit
297471b504
202
src/authd.cr
202
src/authd.cr
|
@ -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
|
|
||||||
GetUser
|
|
||||||
GetUserByCredentials
|
|
||||||
ModUser # Edit user attributes.
|
|
||||||
end
|
|
||||||
|
|
||||||
class GetToken
|
annotation MessageType
|
||||||
JSON.mapping({
|
end
|
||||||
# FIXME: Rename to "login" for consistency.
|
|
||||||
login: String,
|
|
||||||
password: String
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
class AddUser
|
class_getter type = -1
|
||||||
JSON.mapping({
|
|
||||||
# Only clients that have the right shared key will be allowed
|
|
||||||
# to create users.
|
|
||||||
shared_key: String,
|
|
||||||
|
|
||||||
login: String,
|
macro inherited
|
||||||
password: String,
|
def self.type
|
||||||
uid: Int32?,
|
::AuthD::Request::Type::{{ @type.name.split("::").last.id }}
|
||||||
gid: Int32?,
|
|
||||||
home: String?,
|
|
||||||
shell: String?
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
class GetUser
|
|
||||||
JSON.mapping({
|
|
||||||
uid: Int32
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
class GetUserByCredentials
|
|
||||||
JSON.mapping({
|
|
||||||
login: String,
|
|
||||||
password: String
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
class ModUser
|
|
||||||
JSON.mapping({
|
|
||||||
shared_key: String,
|
|
||||||
|
|
||||||
uid: Int32,
|
|
||||||
password: String?,
|
|
||||||
avatar: String?
|
|
||||||
})
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
macro initialize(*properties)
|
||||||
|
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
|
||||||
|
# to create users.
|
||||||
|
property shared_key : String
|
||||||
|
|
||||||
|
property login : String
|
||||||
|
property password : String
|
||||||
|
property uid : Int32?
|
||||||
|
property gid : Int32?
|
||||||
|
property home : String?
|
||||||
|
property shell : String?
|
||||||
|
|
||||||
|
initialize :shared_key, :login, :password
|
||||||
|
end
|
||||||
|
|
||||||
|
class GetUser < Request
|
||||||
|
property uid : Int32
|
||||||
|
|
||||||
|
initialize :uid
|
||||||
|
end
|
||||||
|
|
||||||
|
class GetUserByCredentials < Request
|
||||||
|
property login : String
|
||||||
|
property password : String
|
||||||
|
|
||||||
|
initialize :login, :password
|
||||||
|
end
|
||||||
|
|
||||||
|
class ModUser < Request
|
||||||
|
property shared_key : String
|
||||||
|
|
||||||
|
property uid : Int32
|
||||||
|
property password : String?
|
||||||
|
property avatar : String?
|
||||||
|
|
||||||
|
initialize :shared_key, :uid
|
||||||
|
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
|
||||||
|
|
||||||
|
|
49
src/main.cr
49
src/main.cr
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue