diff --git a/src/requests/admin.cr b/src/requests/admin.cr index e972110..97c355d 100644 --- a/src/requests/admin.cr +++ b/src/requests/admin.cr @@ -46,46 +46,4 @@ class AuthD::Request end end AuthD.requests << AddUser - - IPC::JSON.message ModUser, 5 do - property user : UserID | Nil = nil - property admin : Bool? = nil - property password : String? = nil - property email : String? = nil - - def initialize(@user, @admin, @password, @email) - end - - def handle(authd : AuthD::Service, fd : Int32) - logged_user = authd.get_logged_user_full? fd - return Response::Error.new "you must be logged" if logged_user.nil? - - user = if u = @user - logged_user.assert_permission("authd", "*", User::PermissionLevel::Edit) - authd.user? u - else - logged_user - end - return Response::Error.new "user not found" if user.nil? - - # Only an admin can uprank or downrank someone. - if admin = @admin - logged_user.assert_permission("authd", "*", User::PermissionLevel::Admin) - user.admin = admin - end - - @password.try do |s| - user.password_hash = authd.hash_password s - end - - @email.try do |email| - user.contact.email = email - end - - authd.users_per_uid.update user.uid.to_s, user - - Response::UserEdited.new user.uid - end - end - AuthD.requests << ModUser end diff --git a/src/requests/contact.cr b/src/requests/contact.cr deleted file mode 100644 index db9ccf1..0000000 --- a/src/requests/contact.cr +++ /dev/null @@ -1,15 +0,0 @@ -class AuthD::Request - IPC::JSON.message GetContacts, 18 do - def initialize() - end - - def handle(authd : AuthD::Service, fd : Int32) - logged_user = authd.get_logged_user_full? fd - return Response::Error.new "you must be logged" if logged_user.nil? - - _c = logged_user.contact - Response::Contacts.new logged_user.uid, _c.email - end - end - AuthD.requests << GetContacts -end diff --git a/src/requests/list.cr b/src/requests/list.cr deleted file mode 100644 index 1f0538e..0000000 --- a/src/requests/list.cr +++ /dev/null @@ -1,23 +0,0 @@ -class AuthD::Request - IPC::JSON.message ListUsers, 8 do - - # Since the list could be long, here is a way to get it at a reasonable pace. - property offset : Int32 = 0 - # By default, authd will send 10 users at a time. - - def initialize() - end - - def handle(authd : AuthD::Service, fd : Int32) - logged_user = authd.get_logged_user_full? fd - return Response::Error.new "you must be logged" if logged_user.nil? - - # Test if the user is a moderator. - logged_user.assert_permission("authd", "*", User::PermissionLevel::Read) - - list = authd.users.to_h.map &.[1].to_public - Response::UsersList.new list[offset..offset+10] - end - end - AuthD.requests << ListUsers -end diff --git a/src/requests/moduser.cr b/src/requests/moduser.cr new file mode 100644 index 0000000..ecc43f2 --- /dev/null +++ b/src/requests/moduser.cr @@ -0,0 +1,43 @@ +class AuthD::Request + IPC::JSON.message ModUser, 5 do + property user : UserID | Nil = nil + property admin : Bool? = nil + property password : String? = nil + property email : String? = nil + + def initialize(@user, @admin, @password, @email) + end + + def handle(authd : AuthD::Service, fd : Int32) + logged_user = authd.get_logged_user_full? fd + return Response::Error.new "you must be logged" if logged_user.nil? + + user = if u = @user + logged_user.assert_permission("authd", "*", User::PermissionLevel::Edit) + authd.user? u + else + logged_user + end + return Response::Error.new "user not found" if user.nil? + + # Only an admin can uprank or downrank someone. + if admin = @admin + logged_user.assert_permission("authd", "*", User::PermissionLevel::Admin) + user.admin = admin + end + + @password.try do |s| + user.password_hash = authd.hash_password s + end + + @email.try do |email| + user.contact.email = email + end + + authd.users_per_uid.update user.uid.to_s, user + + Response::UserEdited.new user.uid + end + end + AuthD.requests << ModUser +end diff --git a/src/requests/password.cr b/src/requests/password.cr index 08b4ed8..ed4d706 100644 --- a/src/requests/password.cr +++ b/src/requests/password.cr @@ -1,22 +1,4 @@ class AuthD::Request - IPC::JSON.message UpdatePassword, 7 do - property new_password : String - - def initialize(@new_password) - end - - def handle(authd : AuthD::Service, fd : Int32) - logged_user = authd.get_logged_user_full? fd - return Response::Error.new "you must be logged" if logged_user.nil? - - logged_user.password_hash = authd.hash_password @new_password - authd.users_per_uid.update logged_user.uid.to_s, logged_user - - Response::UserEdited.new logged_user.uid - end - end - AuthD.requests << UpdatePassword - IPC::JSON.message PasswordRecovery, 11 do property user : UserID property password_renew_key : String diff --git a/src/requests/profile.cr b/src/requests/profile.cr index ef12668..a47f511 100644 --- a/src/requests/profile.cr +++ b/src/requests/profile.cr @@ -1,42 +1,11 @@ class AuthD::Request - IPC::JSON.message ReplaceProfile, 14 do - property new_profile : Hash(String, JSON::Any) - - def initialize(@new_profile) - end - - def handle(authd : AuthD::Service, fd : Int32) - logged_user = authd.get_logged_user_full? fd - return Response::Error.new "you must be logged" if logged_user.nil? - - profile = logged_user.profile || Hash(String, JSON::Any).new - - # Skip this verification for authd administrators. - unless logged_user.admin - authd.configuration.read_only_profile_keys.each do |key| - if @new_profile[key]? != profile[key]? - return Response::Error.new "tried to edit read only key" - end - end - end - - logged_user.profile = @new_profile - - authd.users_per_uid.update logged_user.uid.to_s, logged_user - - Response::User.new logged_user.to_public - end - end - AuthD.requests << ReplaceProfile - - # Same as above, but doesn’t reset the whole profile, only resets elements - # for which keys are present in `new_profile`. + # Reset elements for which keys are present in `new_profile_entries`. IPC::JSON.message EditProfileEntries, 15 do property user : UserID | Nil = nil - property new_profile : Hash(String, JSON::Any) + property new_profile_entries : Hash(String, JSON::Any) - def initialize(@new_profile, @user = nil) + def initialize(@new_profile_entries, @user = nil) end def handle(authd : AuthD::Service, fd : Int32) @@ -51,21 +20,21 @@ class AuthD::Request end return Response::Error.new "user not found" if user.nil? - new_profile = user.profile || Hash(String, JSON::Any).new + new_profile_entries = user.profile || Hash(String, JSON::Any).new unless logged_user.admin authd.configuration.read_only_profile_keys.each do |key| - if @new_profile.has_key? key + if @new_profile_entries.has_key? key return Response::Error.new "tried to edit read only key" end end end - @new_profile.each do |key, value| - new_profile[key] = value + @new_profile_entries.each do |key, value| + new_profile_entries[key] = value end - user.profile = new_profile + user.profile = new_profile_entries authd.users_per_uid.update user.uid.to_s, user diff --git a/src/requests/search.cr b/src/requests/search.cr index 16b5b17..e7bc4d2 100644 --- a/src/requests/search.cr +++ b/src/requests/search.cr @@ -1,12 +1,12 @@ class AuthD::Request IPC::JSON.message SearchUser, 13 do - property user : String + property regex : String? = nil # Since the list could be long, here is a way to get it at a reasonable pace. property offset : Int32 = 0 # By default, authd will send 10 users at a time. - def initialize(@user, @offset = 0) + def initialize(@regex = nil, @offset = 0) end def handle(authd : AuthD::Service, fd : Int32) @@ -14,28 +14,36 @@ class AuthD::Request return Response::Error.new "you must be logged" if logged_user.nil? logged_user.assert_permission("authd", "*", User::PermissionLevel::Read) - pattern = Regex.new @user, Regex::Options::IGNORE_CASE - + users = authd.users.to_a matching_users = Array(AuthD::User::Public).new - users = authd.users.to_a - users.each do |u| - if pattern =~ u.login || u.profile.try do |profile| - full_name = profile["full_name"]? - if full_name.nil? - false - else - pattern =~ full_name.as_s + # FIXME: could be optimized. + result = if regex = @regex + pattern = Regex.new regex, Regex::Options::IGNORE_CASE + users.each do |u| + if pattern =~ u.login || u.profile.try do |profile| + full_name = profile["full_name"]? + if full_name.nil? + false + else + pattern =~ full_name.as_s + end end + Baguette::Log.debug "#{u.login} matches #{pattern}" + matching_users << u.to_public + else + Baguette::Log.debug "#{u.login} doesn't match #{pattern}" end - Baguette::Log.debug "#{u.login} matches #{pattern}" - matching_users << u.to_public - else - Baguette::Log.debug "#{u.login} doesn't match #{pattern}" end + matching_users[offset..offset+10] + else + users[offset..offset+10].each do |u| + matching_users << u.to_public + end + matching_users end - Response::MatchingUsers.new matching_users[offset..offset+10] + Response::MatchingUsers.new result end end AuthD.requests << SearchUser