From 93f9e977b806fa8bd5260f9fddee30c35c74f7ce Mon Sep 17 00:00:00 2001 From: Karchnu Date: Thu, 26 Nov 2020 03:15:50 +0100 Subject: [PATCH] Going full CBOR. --- shard.yml | 2 +- src/authd.cr | 2 +- src/libclient.cr | 67 ++++++++++++++++++------------------ src/main.cr | 2 +- src/network.cr | 14 ++++---- src/requests/admin.cr | 6 ++-- src/requests/contact.cr | 4 +-- src/requests/delete.cr | 2 +- src/requests/list.cr | 2 +- src/requests/password.cr | 6 ++-- src/requests/permissions.cr | 6 ++-- src/requests/profile.cr | 12 +++---- src/requests/register.cr | 4 +-- src/requests/search.cr | 2 +- src/requests/token.cr | 2 +- src/requests/users.cr | 6 ++-- src/responses/contact.cr | 3 +- src/responses/errors.cr | 3 +- src/responses/password.cr | 6 ++-- src/responses/permissions.cr | 6 ++-- src/responses/token.cr | 3 +- src/responses/users.cr | 18 ++++++---- src/token.cr | 4 +-- src/user.cr | 20 +++++------ utils/authc.cr | 5 +-- utils/better-parser.cr | 8 ++++- 26 files changed, 119 insertions(+), 96 deletions(-) diff --git a/shard.yml b/shard.yml index 2e10eef..69145d6 100644 --- a/shard.yml +++ b/shard.yml @@ -33,6 +33,6 @@ dependencies: branch: master dodb: git: https://git.baguette.netlib.re/Baguette/dodb.cr - branch: master + branch: cbor license: EUPL diff --git a/src/authd.cr b/src/authd.cr index 2b4d0b6..9d72d95 100644 --- a/src/authd.cr +++ b/src/authd.cr @@ -1,4 +1,4 @@ -require "json" +require "cbor" require "jwt" require "ipc" diff --git a/src/libclient.cr b/src/libclient.cr index f168f12..395d35d 100644 --- a/src/libclient.cr +++ b/src/libclient.cr @@ -1,3 +1,4 @@ +require "ipc/cbor" module AuthD class Client < IPC::Client @@ -10,9 +11,9 @@ module AuthD end def get_token?(login : String, password : String) : String? - send Request::GetToken.new login, password + send_now Request::GetToken.new login, password - response = Response.from_ipc read + response = AuthD.responses.parse_ipc_cbor read if response.is_a?(Response::Token) response.token @@ -22,9 +23,9 @@ module AuthD end def get_user?(login : String, password : String) : AuthD::User::Public? - send Request::GetUserByCredentials.new login, password + send_now Request::GetUserByCredentials.new login, password - response = Response.from_ipc read + response = AuthD.responses.parse_ipc_cbor read if response.is_a? Response::User response.user @@ -34,9 +35,9 @@ module AuthD end def get_user?(uid_or_login : Int32 | String) : ::AuthD::User::Public? - send Request::GetUser.new uid_or_login + send_now Request::GetUser.new uid_or_login - response = Response.from_ipc read + response = AuthD.responses.parse_ipc_cbor read if response.is_a? Response::User response.user @@ -45,14 +46,14 @@ module AuthD end end - def send(type : Request::Type, payload) + def send_now(type : Request::Type, payload) send_now @server_fd, type.value.to_u8, payload end def decode_token(token) user, meta = JWT.decode token, @key, JWT::Algorithm::HS256 - user = ::AuthD::User::Public.from_json user.to_json + user = ::AuthD::User::Public.from_cbor user.to_cbor {user, meta} end @@ -61,11 +62,11 @@ module AuthD def add_user(login : String, password : String, email : String?, phone : String?, - profile : Hash(String, JSON::Any)?) : ::AuthD::User::Public | Exception + profile : Hash(String, CBOR::Any)?) : ::AuthD::User::Public | Exception - send Request::AddUser.new @key, login, password, email, phone, profile + send_now Request::AddUser.new @key, login, password, email, phone, profile - response = Response.from_ipc read + response = AuthD.responses.parse_ipc_cbor read case response when Response::UserAdded @@ -80,9 +81,9 @@ module AuthD end def validate_user(login : String, activation_key : String) : ::AuthD::User::Public | Exception - send Request::ValidateUser.new login, activation_key + send_now Request::ValidateUser.new login, activation_key - response = Response.from_ipc read + response = AuthD.responses.parse_ipc_cbor read case response when Response::UserValidated @@ -97,8 +98,8 @@ module AuthD end def ask_password_recovery(uid_or_login : String | Int32, email : String) - send Request::AskPasswordRecovery.new uid_or_login, email - response = Response.from_ipc read + send_now Request::AskPasswordRecovery.new uid_or_login, email + response = AuthD.responses.parse_ipc_cbor read case response when Response::PasswordRecoverySent @@ -110,8 +111,8 @@ module AuthD end def change_password(uid_or_login : String | Int32, new_pass : String, renew_key : String) - send Request::PasswordRecovery.new uid_or_login, renew_key, new_pass - response = Response.from_ipc read + send_now Request::PasswordRecovery.new uid_or_login, renew_key, new_pass + response = AuthD.responses.parse_ipc_cbor read case response when Response::PasswordRecovered @@ -126,10 +127,10 @@ module AuthD password : String, email : String?, phone : String?, - profile : Hash(String, JSON::Any)?) : ::AuthD::User::Public? + profile : Hash(String, CBOR::Any)?) : ::AuthD::User::Public? - send Request::Register.new login, password, email, phone, profile - response = Response.from_ipc read + send_now Request::Register.new login, password, email, phone, profile + response = AuthD.responses.parse_ipc_cbor read case response when Response::UserAdded @@ -146,9 +147,9 @@ module AuthD request.phone = phone if phone request.avatar = avatar if avatar - send request + send_now request - response = Response.from_ipc read + response = AuthD.responses.parse_ipc_cbor read case response when Response::UserEdited @@ -163,9 +164,9 @@ module AuthD def check_permission(user : Int32, service_name : String, resource_name : String) : User::PermissionLevel request = Request::CheckPermission.new @key, user, service_name, resource_name - send request + send_now request - response = Response.from_ipc read + response = AuthD.responses.parse_ipc_cbor read case response when Response::PermissionCheck @@ -180,9 +181,9 @@ module AuthD def set_permission(uid : Int32, service : String, resource : String, permission : User::PermissionLevel) request = Request::SetPermission.new @key, uid, service, resource, permission - send request + send_now request - response = Response.from_ipc read + response = AuthD.responses.parse_ipc_cbor read case response when Response::PermissionSet @@ -195,8 +196,8 @@ module AuthD end def search_user(user_login : String) - send Request::SearchUser.new user_login - response = Response.from_ipc read + send_now Request::SearchUser.new user_login + response = AuthD.responses.parse_ipc_cbor read case response when Response::MatchingUsers @@ -209,8 +210,8 @@ module AuthD end def edit_profile_content(user : Int32 | String, new_values) - send Request::EditProfileContent.new key, user, new_values - response = Response.from_ipc read + send_now Request::EditProfileContent.new key, user, new_values + response = AuthD.responses.parse_ipc_cbor read case response when Response::User @@ -223,15 +224,15 @@ module AuthD end def delete(user : Int32 | String, key : String) - send Request::Delete.new user, key + send_now Request::Delete.new user, key delete_ end def delete(user : Int32 | String, login : String, pass : String) - send Request::Delete.new user, login, pass + send_now Request::Delete.new user, login, pass delete_ end def delete_ - response = Response.from_ipc read + response = AuthD.responses.parse_ipc_cbor read case response when Response::Error raise Exception.new response.reason diff --git a/src/main.cr b/src/main.cr index 4d925fd..f12cb3b 100644 --- a/src/main.cr +++ b/src/main.cr @@ -78,7 +78,7 @@ class AuthD::Service < IPC::Server def handle_request(event : IPC::Event::MessageReceived) request_start = Time.utc - request = AuthD.requests.parse_ipc_json event.message + request = AuthD.requests.parse_ipc_cbor event.message if request.nil? raise "unknown request type" diff --git a/src/network.cr b/src/network.cr index d74c23b..d828b16 100644 --- a/src/network.cr +++ b/src/network.cr @@ -1,28 +1,28 @@ require "ipc" -require "json" -require "ipc/json" +require "cbor" +require "ipc/cbor" -class IPC::JSON +class IPC::CBOR def handle(service : AuthD::Service, event : IPC::Event::Events) raise "unimplemented" end end module AuthD - class_getter requests = [] of IPC::JSON.class - class_getter responses = [] of IPC::JSON.class + class_getter requests = [] of IPC::CBOR.class + class_getter responses = [] of IPC::CBOR.class end class IPC::Context def send(fd, response : AuthD::Response) - send fd, response.type.to_u8, response.to_json + send fd, response.type.to_u8, response.to_cbor 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 + send_now fd, request.type.to_u8, request.to_cbor else raise "Client not connected to the server" end diff --git a/src/requests/admin.cr b/src/requests/admin.cr index 8ff4e54..42f838d 100644 --- a/src/requests/admin.cr +++ b/src/requests/admin.cr @@ -1,5 +1,5 @@ class AuthD::Request - IPC::JSON.message AddUser, 1 do + IPC::CBOR.message AddUser, 1 do # Only clients that have the right shared key will be allowed # to create users. property shared_key : String @@ -8,7 +8,7 @@ class AuthD::Request property password : String property email : String? = nil property phone : String? = nil - property profile : Hash(String, JSON::Any)? = nil + property profile : Hash(String, CBOR::Any)? = nil def initialize(@shared_key, @login, @password, @email, @phone, @profile) end @@ -51,7 +51,7 @@ class AuthD::Request AuthD.requests << AddUser - IPC::JSON.message ModUser, 5 do + IPC::CBOR.message ModUser, 5 do property shared_key : String property user : Int32 | String diff --git a/src/requests/contact.cr b/src/requests/contact.cr index 5149ebc..733e6a3 100644 --- a/src/requests/contact.cr +++ b/src/requests/contact.cr @@ -1,5 +1,5 @@ class AuthD::Request - IPC::JSON.message EditContacts, 16 do + IPC::CBOR.message EditContacts, 16 do property token : String property email : String? = nil @@ -26,7 +26,7 @@ class AuthD::Request end AuthD.requests << EditContacts - IPC::JSON.message GetContacts, 18 do + IPC::CBOR.message GetContacts, 18 do property token : String def initialize(@token) diff --git a/src/requests/delete.cr b/src/requests/delete.cr index e2e30ad..5e41ee8 100644 --- a/src/requests/delete.cr +++ b/src/requests/delete.cr @@ -1,5 +1,5 @@ class AuthD::Request - IPC::JSON.message Delete, 17 do + IPC::CBOR.message Delete, 17 do # Deletion can be triggered by either an admin or the user. property shared_key : String? = nil diff --git a/src/requests/list.cr b/src/requests/list.cr index edd05d1..db12146 100644 --- a/src/requests/list.cr +++ b/src/requests/list.cr @@ -1,5 +1,5 @@ class AuthD::Request - IPC::JSON.message ListUsers, 8 do + IPC::CBOR.message ListUsers, 8 do property token : String? = nil property key : String? = nil diff --git a/src/requests/password.cr b/src/requests/password.cr index 646f469..8231eef 100644 --- a/src/requests/password.cr +++ b/src/requests/password.cr @@ -1,5 +1,5 @@ class AuthD::Request - IPC::JSON.message UpdatePassword, 7 do + IPC::CBOR.message UpdatePassword, 7 do property login : String property old_password : String property new_password : String @@ -27,7 +27,7 @@ class AuthD::Request end AuthD.requests << UpdatePassword - IPC::JSON.message PasswordRecovery, 11 do + IPC::CBOR.message PasswordRecovery, 11 do property user : Int32 | String property password_renew_key : String property new_password : String @@ -62,7 +62,7 @@ class AuthD::Request end AuthD.requests << PasswordRecovery - IPC::JSON.message AskPasswordRecovery, 12 do + IPC::CBOR.message AskPasswordRecovery, 12 do property user : Int32 | String property email : String diff --git a/src/requests/permissions.cr b/src/requests/permissions.cr index fdc2b6c..df2f83c 100644 --- a/src/requests/permissions.cr +++ b/src/requests/permissions.cr @@ -1,5 +1,5 @@ class AuthD::Request - IPC::JSON.message CheckPermission, 9 do + IPC::CBOR.message CheckPermission, 9 do property shared_key : String? = nil property token : String? = nil @@ -41,8 +41,10 @@ class AuthD::Request user = case u = @user when .is_a? Int32 + puts "searching for the user (Int32): #{u}" authd.users_per_uid.get? u.to_s else + puts "searching for the user (string): #{u}" authd.users_per_login.get? u end @@ -68,7 +70,7 @@ class AuthD::Request end AuthD.requests << CheckPermission - IPC::JSON.message SetPermission, 10 do + IPC::CBOR.message SetPermission, 10 do property shared_key : String property user : Int32 | String diff --git a/src/requests/profile.cr b/src/requests/profile.cr index daa2a16..048d49b 100644 --- a/src/requests/profile.cr +++ b/src/requests/profile.cr @@ -1,7 +1,7 @@ class AuthD::Request - IPC::JSON.message EditProfile, 14 do + IPC::CBOR.message EditProfile, 14 do property token : String - property new_profile : Hash(String, JSON::Any) + property new_profile : Hash(String, CBOR::Any) def initialize(@token, @new_profile) end @@ -13,7 +13,7 @@ class AuthD::Request new_profile = @new_profile - profile = user.profile || Hash(String, JSON::Any).new + profile = user.profile || Hash(String, CBOR::Any).new authd.configuration.read_only_profile_keys.each do |key| if new_profile[key]? != profile[key]? @@ -32,13 +32,13 @@ class AuthD::Request # Same as above, but doesn’t reset the whole profile, only resets elements # for which keys are present in `new_profile`. - IPC::JSON.message EditProfileContent, 15 do + IPC::CBOR.message EditProfileContent, 15 do property token : String? = nil property shared_key : String? = nil property user : Int32 | String | Nil - property new_profile : Hash(String, JSON::Any) + property new_profile : Hash(String, CBOR::Any) def initialize(@shared_key, @user, @new_profile) end @@ -68,7 +68,7 @@ class AuthD::Request raise AuthenticationInfoLacking.new end - new_profile = user.profile || Hash(String, JSON::Any).new + new_profile = user.profile || Hash(String, CBOR::Any).new unless @shared_key authd.configuration.read_only_profile_keys.each do |key| diff --git a/src/requests/register.cr b/src/requests/register.cr index 8407174..e036556 100644 --- a/src/requests/register.cr +++ b/src/requests/register.cr @@ -1,10 +1,10 @@ class AuthD::Request - IPC::JSON.message Register, 6 do + IPC::CBOR.message Register, 6 do property login : String property password : String property email : String? = nil property phone : String? = nil - property profile : Hash(String, JSON::Any)? = nil + property profile : Hash(String, CBOR::Any)? = nil def initialize(@login, @password, @email, @phone, @profile) end diff --git a/src/requests/search.cr b/src/requests/search.cr index b42f3b6..e03f1a9 100644 --- a/src/requests/search.cr +++ b/src/requests/search.cr @@ -1,5 +1,5 @@ class AuthD::Request - IPC::JSON.message SearchUser, 13 do + IPC::CBOR.message SearchUser, 13 do property user : String def initialize(@user) diff --git a/src/requests/token.cr b/src/requests/token.cr index 6749285..f2b9a92 100644 --- a/src/requests/token.cr +++ b/src/requests/token.cr @@ -1,5 +1,5 @@ class AuthD::Request - IPC::JSON.message GetToken, 0 do + IPC::CBOR.message GetToken, 0 do property login : String property password : String diff --git a/src/requests/users.cr b/src/requests/users.cr index 0bf573b..35d9744 100644 --- a/src/requests/users.cr +++ b/src/requests/users.cr @@ -1,5 +1,5 @@ class AuthD::Request - IPC::JSON.message ValidateUser, 2 do + IPC::CBOR.message ValidateUser, 2 do property login : String property activation_key : String @@ -31,7 +31,7 @@ class AuthD::Request end AuthD.requests << ValidateUser - IPC::JSON.message GetUser, 3 do + IPC::CBOR.message GetUser, 3 do property user : Int32 | String def initialize(@user) @@ -54,7 +54,7 @@ class AuthD::Request end AuthD.requests << GetUser - IPC::JSON.message GetUserByCredentials, 4 do + IPC::CBOR.message GetUserByCredentials, 4 do property login : String property password : String diff --git a/src/responses/contact.cr b/src/responses/contact.cr index 2ed1d24..3d66bbd 100644 --- a/src/responses/contact.cr +++ b/src/responses/contact.cr @@ -1,9 +1,10 @@ class AuthD::Response - IPC::JSON.message Contacts, 12 do + IPC::CBOR.message Contacts, 12 do property user : Int32 property email : String? = nil property phone : String? = nil def initialize(@user, @email, @phone) end end + AuthD.responses << Contacts end diff --git a/src/responses/errors.cr b/src/responses/errors.cr index 8b4f83f..28699b0 100644 --- a/src/responses/errors.cr +++ b/src/responses/errors.cr @@ -1,7 +1,8 @@ class AuthD::Response - IPC::JSON.message Error, 0 do + IPC::CBOR.message Error, 0 do property reason : String? = nil def initialize(@reason) end end + AuthD.responses << Error end diff --git a/src/responses/password.cr b/src/responses/password.cr index 40524c4..9009387 100644 --- a/src/responses/password.cr +++ b/src/responses/password.cr @@ -1,13 +1,15 @@ class AuthD::Response - IPC::JSON.message PasswordRecoverySent, 9 do + IPC::CBOR.message PasswordRecoverySent, 9 do property user : ::AuthD::User::Public def initialize(@user) end end + AuthD.responses << PasswordRecoverySent - IPC::JSON.message PasswordRecovered, 10 do + IPC::CBOR.message PasswordRecovered, 10 do property user : ::AuthD::User::Public def initialize(@user) end end + AuthD.responses << PasswordRecovered end diff --git a/src/responses/permissions.cr b/src/responses/permissions.cr index ec4d336..6e160cf 100644 --- a/src/responses/permissions.cr +++ b/src/responses/permissions.cr @@ -1,5 +1,5 @@ class AuthD::Response - IPC::JSON.message PermissionCheck, 7 do + IPC::CBOR.message PermissionCheck, 7 do property user : Int32 property service : String property resource : String @@ -7,8 +7,9 @@ class AuthD::Response def initialize(@service, @resource, @user, @permission) end end + AuthD.responses << PermissionCheck - IPC::JSON.message PermissionSet, 8 do + IPC::CBOR.message PermissionSet, 8 do property user : Int32 property service : String property resource : String @@ -16,4 +17,5 @@ class AuthD::Response def initialize(@user, @service, @resource, @permission) end end + AuthD.responses << PermissionSet end diff --git a/src/responses/token.cr b/src/responses/token.cr index 04de31d..0837313 100644 --- a/src/responses/token.cr +++ b/src/responses/token.cr @@ -1,8 +1,9 @@ class AuthD::Response - IPC::JSON.message Token, 1 do + IPC::CBOR.message Token, 1 do property uid : Int32 property token : String def initialize(@token, @uid) end end + AuthD.responses << Token end diff --git a/src/responses/users.cr b/src/responses/users.cr index 47c5487..48ce6ec 100644 --- a/src/responses/users.cr +++ b/src/responses/users.cr @@ -1,37 +1,43 @@ class AuthD::Response - IPC::JSON.message User, 2 do + IPC::CBOR.message User, 2 do property user : ::AuthD::User::Public def initialize(@user) end end + AuthD.responses << User - IPC::JSON.message UserAdded, 3 do + IPC::CBOR.message UserAdded, 3 do property user : ::AuthD::User::Public def initialize(@user) end end + AuthD.responses << UserAdded - IPC::JSON.message UserEdited, 4 do + IPC::CBOR.message UserEdited, 4 do property uid : Int32 def initialize(@uid) end end + AuthD.responses << UserEdited - IPC::JSON.message UserValidated, 5 do + IPC::CBOR.message UserValidated, 5 do property user : ::AuthD::User::Public def initialize(@user) end end + AuthD.responses << UserValidated - IPC::JSON.message UsersList, 6 do + IPC::CBOR.message UsersList, 6 do property users : Array(::AuthD::User::Public) def initialize(@users) end end + AuthD.responses << UsersList - IPC::JSON.message MatchingUsers, 11 do + IPC::CBOR.message MatchingUsers, 11 do property users : Array(::AuthD::User::Public) def initialize(@users) end end + AuthD.responses << MatchingUsers end diff --git a/src/token.cr b/src/token.cr index 5c8d844..79d843f 100644 --- a/src/token.cr +++ b/src/token.cr @@ -1,7 +1,7 @@ -require "json" +require "cbor" class AuthD::Token - include JSON::Serializable + include CBOR::Serializable property login : String property uid : Int32 diff --git a/src/user.cr b/src/user.cr index 00246e9..8315df7 100644 --- a/src/user.cr +++ b/src/user.cr @@ -1,11 +1,11 @@ -require "json" +require "cbor" require "uuid" require "./token.cr" class AuthD::User - include JSON::Serializable + include CBOR::Serializable enum PermissionLevel None @@ -13,13 +13,13 @@ class AuthD::User Edit Admin - def to_json(o) - to_s.downcase.to_json o + def to_cbor(o) + to_s.downcase.to_cbor o end end class Contact - include JSON::Serializable + include CBOR::Serializable # the activation key is removed once the user is validated property activation_key : String? @@ -34,7 +34,7 @@ class AuthD::User # Public. property login : String property uid : Int32 - property profile : Hash(String, JSON::Any)? + property profile : Hash(String, CBOR::Any)? # Private. property contact : Contact @@ -42,7 +42,7 @@ class AuthD::User property password_renew_key : String? # service => resource => permission level property permissions : Hash(String, Hash(String, PermissionLevel)) - property configuration : Hash(String, Hash(String, JSON::Any)) + property configuration : Hash(String, Hash(String, CBOR::Any)) property date_last_connection : Time? = nil property date_registration : Time? = nil @@ -53,15 +53,15 @@ class AuthD::User def initialize(@uid, @login, @password_hash) @contact = Contact.new @permissions = Hash(String, Hash(String, PermissionLevel)).new - @configuration = Hash(String, Hash(String, JSON::Any)).new + @configuration = Hash(String, Hash(String, CBOR::Any)).new end class Public - include JSON::Serializable + include CBOR::Serializable property login : String property uid : Int32 - property profile : Hash(String, JSON::Any)? + property profile : Hash(String, CBOR::Any)? property date_registration : Time? diff --git a/utils/authc.cr b/utils/authc.cr index 5edd5a0..9250df7 100644 --- a/utils/authc.cr +++ b/utils/authc.cr @@ -1,6 +1,7 @@ require "option_parser" require "ipc" +require "cbor" require "yaml" require "baguette-crystal-base" @@ -27,7 +28,7 @@ class Context class_property command = "not-implemented" - class_property user_profile : Hash(String,JSON::Any)? + class_property user_profile : Hash(String,CBOR::Any)? class_property phone : String? class_property email : String? @@ -215,7 +216,7 @@ def main begin actions.the_call[Context.command].call rescue e - Baguette::Log.info "The command is not recognized (or implemented)." + Baguette::Log.info "#{e}" end # authd disconnection diff --git a/utils/better-parser.cr b/utils/better-parser.cr index c266e8b..f62cb2f 100644 --- a/utils/better-parser.cr +++ b/utils/better-parser.cr @@ -28,7 +28,13 @@ opt_help = -> (parser : OptionParser) { opt_profile = -> (parser : OptionParser) { parser.on "-P file", "--profile file", "Read the user profile from a file." do |file| - Context.user_profile = JSON.parse(File.read file).as_h + profile = JSON.parse(File.read file).as_h + user_profile = {} of String => CBOR::Any + profile.each do |k,v| + user_profile[k] = CBOR::Any.new v + end + Context.user_profile = user_profile + Baguette::Log.info "Reading the user profile: #{Context.user_profile}." end }