authd/src/authd.cr

185 lines
3.2 KiB
Crystal
Raw Normal View History

require "jwt"
require "ipc"
require "./user.cr"
module AuthD
2019-11-22 17:31:56 +01:00
class Response
enum Type
Ok
Malformed
InvalidCredentials
InvalidUser
UserNotFound # For UID-based GetUser requests.
AuthenticationError
end
end
2019-11-22 17:31:56 +01:00
class Request
enum Type
GetToken
AddUser
GetUser
GetUserByCredentials
ModUser # Edit user attributes.
end
2019-11-22 17:31:56 +01:00
class GetToken
JSON.mapping({
# FIXME: Rename to "login" for consistency.
login: String,
password: String
})
end
2019-11-22 17:31:56 +01:00
class AddUser
JSON.mapping({
# Only clients that have the right shared key will be allowed
# to create users.
shared_key: String,
login: String,
password: String,
uid: Int32?,
gid: Int32?,
home: String?,
shell: String?
})
end
2018-12-19 13:54:19 +01:00
2019-11-22 17:31:56 +01:00
class GetUser
JSON.mapping({
uid: Int32
})
end
2019-01-07 17:04:20 +01:00
2019-11-22 17:31:56 +01:00
class GetUserByCredentials
JSON.mapping({
login: String,
password: String
})
end
2019-11-22 17:31:56 +01:00
class ModUser
JSON.mapping({
shared_key: String,
2019-11-22 17:31:56 +01:00
uid: Int32,
password: String?,
avatar: String?
})
end
2019-05-29 16:06:11 +02:00
end
2019-06-05 22:30:29 +02:00
class Client < IPC::Connection
property key : String
def initialize
@key = ""
initialize "auth"
end
2019-06-06 01:16:52 +02:00
def get_token?(login : String, password : String) : String?
2019-11-22 17:31:56 +01:00
send Request::Type::GetToken, {
:login => login,
:password => password
}.to_json
response = read
2019-11-22 17:31:56 +01:00
if response.type == Response::Type::Ok.value.to_u8
2019-06-06 01:16:52 +02:00
String.new response.payload
else
nil
end
end
2019-11-17 15:50:26 +01:00
def get_user?(login : String, password : String) : Passwd::User?
2019-11-22 17:31:56 +01:00
send Request::Type::GetUserByCredentials, {
:login => login,
:password => password
}.to_json
response = read
2019-11-22 17:31:56 +01:00
if response.type == Response::Type::Ok.value.to_u8
2019-11-17 15:50:26 +01:00
Passwd::User.from_json String.new response.payload
else
nil
end
end
2019-01-07 17:04:20 +01:00
def get_user?(uid : Int32)
2019-11-22 17:31:56 +01:00
send Request::Type::GetUser, {:uid => uid}.to_json
2019-01-07 17:04:20 +01:00
response = read
2019-11-22 17:31:56 +01:00
if response.type == Response::Type::Ok.value.to_u8
User.from_json String.new response.payload
2019-01-07 17:04:20 +01:00
else
nil
end
end
2019-11-22 17:31:56 +01:00
def send(type : Request::Type, payload)
2018-12-19 13:54:19 +01:00
send type.value.to_u8, payload
end
def decode_token(token)
2019-06-28 18:20:34 +02:00
user, meta = JWT.decode token, @key, JWT::Algorithm::HS256
2019-11-17 15:50:26 +01:00
user = Passwd::User.from_json user.to_json
{user, meta}
end
2018-12-19 13:54:19 +01:00
# FIXME: Extra options may be useful to implement here.
2019-11-17 15:50:26 +01:00
def add_user(login : String, password : String) : Passwd::User | Exception
2019-11-22 17:31:56 +01:00
send Request::Type::AddUser, {
:shared_key => @key,
2018-12-19 13:54:19 +01:00
:login => login,
:password => password
}.to_json
response = read
2019-06-06 01:16:52 +02:00
payload = String.new response.payload
2019-11-22 17:31:56 +01:00
case Response::Type.new response.type.to_i
when Response::Type::Ok
2019-11-17 15:50:26 +01:00
Passwd::User.from_json payload
2018-12-19 13:54:19 +01:00
else
2019-06-06 01:16:52 +02:00
Exception.new payload
2018-12-19 13:54:19 +01:00
end
end
2019-05-29 16:06:11 +02:00
2019-05-29 19:45:03 +02:00
def mod_user(uid : Int32, password : String? = nil, avatar : String? = nil) : Bool | Exception
2019-05-29 16:06:11 +02:00
payload = Hash(String, String|Int32).new
payload["uid"] = uid
payload["shared_key"] = @key
2019-05-29 16:06:11 +02:00
password.try do |password|
payload["password"] = password
end
2019-05-29 19:45:03 +02:00
avatar.try do |avatar|
payload["avatar"] = avatar
end
2019-11-22 17:31:56 +01:00
send Request::Type::ModUser, payload.to_json
2019-05-29 16:06:11 +02:00
response = read
2019-11-22 17:31:56 +01:00
case Response::Type.new response.type.to_i
when Response::Type::Ok
2019-05-29 16:06:11 +02:00
true
else
2019-06-06 01:16:52 +02:00
Exception.new String.new response.payload
2019-05-29 16:06:11 +02:00
end
end
end
end