Refactoring in progress. Still a few classes to go.
This commit is contained in:
parent
7958e7812e
commit
2786e2f7ff
10 changed files with 55 additions and 90 deletions
|
@ -10,6 +10,9 @@ require "ipc"
|
||||||
|
|
||||||
require "baguette-crystal-base"
|
require "baguette-crystal-base"
|
||||||
|
|
||||||
|
# In any message, a user can be referred by its Int32 uid or its login.
|
||||||
|
alias UserID = Int32 | String
|
||||||
|
|
||||||
# Allows get configuration from a provided file.
|
# Allows get configuration from a provided file.
|
||||||
# See Baguette::Configuration::Base.get
|
# See Baguette::Configuration::Base.get
|
||||||
class Baguette::Configuration
|
class Baguette::Configuration
|
||||||
|
|
|
@ -158,13 +158,12 @@ module AuthD
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def mod_user(uid_or_login : Int32 | String, password : String? = nil, email : String? = nil, phone : String? = nil, avatar : String? = nil) : Bool | Exception
|
def mod_user(uid_or_login : Int32 | String, password : String? = nil, email : String? = nil, phone : String? = nil) : Bool | Exception
|
||||||
request = Request::ModUser.new uid_or_login
|
request = Request::ModUser.new uid_or_login
|
||||||
|
|
||||||
request.password = password if password
|
request.password = password if password
|
||||||
request.email = email if email
|
request.email = email if email
|
||||||
request.phone = phone if phone
|
request.phone = phone if phone
|
||||||
request.avatar = avatar if avatar
|
|
||||||
|
|
||||||
send_now request
|
send_now request
|
||||||
|
|
||||||
|
|
|
@ -71,5 +71,22 @@ class AuthD::User
|
||||||
def to_public : Public
|
def to_public : Public
|
||||||
Public.new @uid, @login, @admin, @profile, @date_registration
|
Public.new @uid, @login, @admin, @profile, @date_registration
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
|
def assert_permission(service : String, resource : String, level : User::PermissionLevel)
|
||||||
|
return if @admin # skip if admin
|
||||||
|
|
||||||
|
permissions = @permissions[service]?
|
||||||
|
unless permissions
|
||||||
|
raise AdminAuthorizationException.new "unauthorized (not admin nor in #{service} group)"
|
||||||
|
end
|
||||||
|
|
||||||
|
rights = permissions[resource]?
|
||||||
|
unless rights
|
||||||
|
raise AdminAuthorizationException.new "unauthorized (no rights on '#{service}/#{resource}')"
|
||||||
|
end
|
||||||
|
|
||||||
|
if rights < level
|
||||||
|
raise AdminAuthorizationException.new "unauthorized (insufficient rights on '#{service}/#{resource}')"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -49,28 +49,24 @@ class AuthD::Request
|
||||||
end
|
end
|
||||||
AuthD.requests << AddUser
|
AuthD.requests << AddUser
|
||||||
|
|
||||||
|
|
||||||
IPC::JSON.message ModUser, 5 do
|
IPC::JSON.message ModUser, 5 do
|
||||||
property user : Int32 | String
|
property user : UserID
|
||||||
property admin : Bool = false
|
property admin : Bool = false
|
||||||
property password : String? = nil
|
property password : String? = nil
|
||||||
property email : String? = nil
|
property email : String? = nil
|
||||||
property phone : String? = nil
|
property phone : String? = nil
|
||||||
property avatar : String? = nil
|
|
||||||
|
|
||||||
def initialize(@user, @admin, @password, @email, @phone, @avatar)
|
def initialize(@user, @admin, @password, @email, @phone)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
logged_user = authd.get_logged_user? fd
|
logged_user = authd.get_logged_user? fd
|
||||||
|
|
||||||
return Response::Error.new "you must be logged" if logged_user.nil?
|
return Response::Error.new "you must be logged" if logged_user.nil?
|
||||||
|
|
||||||
user = authd.user? @user
|
user = authd.user? @user
|
||||||
|
|
||||||
return Response::Error.new "user not found" if user.nil?
|
return Response::Error.new "user not found" if user.nil?
|
||||||
|
|
||||||
# Only an admin can create an admin.
|
# Only an admin can uprank someone.
|
||||||
if @admin
|
if @admin
|
||||||
return Response::Error.new "unauthorized (not admin)" unless logged_user.admin
|
return Response::Error.new "unauthorized (not admin)" unless logged_user.admin
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,32 +1,28 @@
|
||||||
class AuthD::Request
|
class AuthD::Request
|
||||||
IPC::JSON.message Delete, 17 do
|
IPC::JSON.message Delete, 17 do
|
||||||
# Deletion can be triggered by either an admin or the related user.
|
# Deletion can be triggered by either an admin or the related user.
|
||||||
property user : String | Int32
|
property user : UserID
|
||||||
|
|
||||||
def initialize(@user)
|
def initialize(@user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
user_to_delete = authd.user? @user
|
|
||||||
return Response::Error.new "invalid user" if user_to_delete.nil?
|
|
||||||
|
|
||||||
# Get currently logged user.
|
|
||||||
logged_user = authd.get_logged_user? fd
|
logged_user = authd.get_logged_user? fd
|
||||||
if logged_user.nil?
|
return Response::Error.new "you must be logged" if logged_user.nil?
|
||||||
return Response::Error.new "you must be logged"
|
|
||||||
end
|
# Get the full AuthD::User instance, not just the public view.
|
||||||
|
user_to_delete = authd.user? logged_user.uid
|
||||||
|
return Response::Error.new "unknown user" if user_to_delete.nil?
|
||||||
|
|
||||||
unless logged_user.admin
|
unless logged_user.admin
|
||||||
# Is the logged user the target?
|
# Is the logged user the target?
|
||||||
if logged_user.uid != user_to_delete.uid
|
return Response::Error.new "invalid credentials" if logged_user.uid != user_to_delete.uid
|
||||||
return Response::Error.new "invalid credentials"
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# User or admin is now verified: let's proceed with the user deletion.
|
# User or admin is now verified: let's proceed with the user deletion.
|
||||||
authd.users_per_login.delete user_to_delete.login
|
authd.users_per_login.delete user_to_delete.login
|
||||||
|
|
||||||
# TODO: if the current user is deleted, unlog!
|
# If the current user is deleted, unlog!
|
||||||
if logged_user.uid == user_to_delete.uid
|
if logged_user.uid == user_to_delete.uid
|
||||||
authd.close fd
|
authd.close fd
|
||||||
authd.logged_users.delete fd
|
authd.logged_users.delete fd
|
||||||
|
|
|
@ -1,38 +1,17 @@
|
||||||
class AuthD::Request
|
class AuthD::Request
|
||||||
IPC::JSON.message ListUsers, 8 do
|
IPC::JSON.message ListUsers, 8 do
|
||||||
property token : String? = nil
|
def initialize()
|
||||||
property key : String? = nil
|
|
||||||
|
|
||||||
def initialize(@token, @key)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
# FIXME: Lines too long, repeatedly (>80c with 4c tabs).
|
logged_user = authd.get_logged_user? fd
|
||||||
@token.try do |token|
|
return Response::Error.new "you must be logged" if logged_user.nil?
|
||||||
user = authd.get_user_from_token token
|
|
||||||
|
|
||||||
return Response::Error.new "unauthorized (user not found from token)" unless user
|
user = authd.user? logged_user.uid
|
||||||
|
return Response::Error.new "user not found" if user.nil?
|
||||||
|
|
||||||
# Test if the user is a moderator.
|
# Test if the user is a moderator.
|
||||||
if permissions = user.permissions["authd"]?
|
user.assert_permission("authd", "*", User::PermissionLevel::Read)
|
||||||
if rights = permissions["*"]?
|
|
||||||
if rights >= User::PermissionLevel::Read
|
|
||||||
else
|
|
||||||
raise AdminAuthorizationException.new "unauthorized (insufficient rights on '*')"
|
|
||||||
end
|
|
||||||
else
|
|
||||||
raise AdminAuthorizationException.new "unauthorized (no rights on '*')"
|
|
||||||
end
|
|
||||||
else
|
|
||||||
raise AdminAuthorizationException.new "unauthorized (user not in authd group)"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
@key.try do |key|
|
|
||||||
return Response::Error.new "unauthorized (wrong shared key)" unless key == authd.configuration.shared_key
|
|
||||||
end
|
|
||||||
|
|
||||||
return Response::Error.new "unauthorized (no key nor token)" unless @key || @token
|
|
||||||
|
|
||||||
Response::UsersList.new authd.users.to_h.map &.[1].to_public
|
Response::UsersList.new authd.users.to_h.map &.[1].to_public
|
||||||
end
|
end
|
||||||
|
|
|
@ -13,9 +13,7 @@ class AuthD::Request
|
||||||
return Response::Error.new "invalid credentials"
|
return Response::Error.new "invalid credentials"
|
||||||
end
|
end
|
||||||
|
|
||||||
if user.nil?
|
return Response::Error.new "invalid credentials" if user.nil?
|
||||||
return Response::Error.new "invalid credentials"
|
|
||||||
end
|
|
||||||
|
|
||||||
if user.password_hash != authd.hash_password @password
|
if user.password_hash != authd.hash_password @password
|
||||||
return Response::Error.new "invalid credentials"
|
return Response::Error.new "invalid credentials"
|
||||||
|
|
|
@ -1,22 +1,16 @@
|
||||||
class AuthD::Request
|
class AuthD::Request
|
||||||
IPC::JSON.message UpdatePassword, 7 do
|
IPC::JSON.message UpdatePassword, 7 do
|
||||||
property login : String
|
|
||||||
property old_password : String
|
|
||||||
property new_password : String
|
property new_password : String
|
||||||
|
|
||||||
def initialize(@login, @old_password, @new_password)
|
def initialize(@new_password)
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
user = authd.users_per_login.get? @login
|
logged_user = authd.get_logged_user? fd
|
||||||
|
return Response::Error.new "you must be logged" if logged_user.nil?
|
||||||
|
|
||||||
unless user
|
user = authd.user? logged_user.uid
|
||||||
return Response::Error.new "invalid credentials"
|
return Response::Error.new "user not found" if user.nil?
|
||||||
end
|
|
||||||
|
|
||||||
if authd.hash_password(@old_password) != user.password_hash
|
|
||||||
return Response::Error.new "invalid credentials"
|
|
||||||
end
|
|
||||||
|
|
||||||
user.password_hash = authd.hash_password @new_password
|
user.password_hash = authd.hash_password @new_password
|
||||||
|
|
||||||
|
@ -28,7 +22,7 @@ class AuthD::Request
|
||||||
AuthD.requests << UpdatePassword
|
AuthD.requests << UpdatePassword
|
||||||
|
|
||||||
IPC::JSON.message PasswordRecovery, 11 do
|
IPC::JSON.message PasswordRecovery, 11 do
|
||||||
property user : Int32 | String
|
property user : UserID
|
||||||
property password_renew_key : String
|
property password_renew_key : String
|
||||||
property new_password : String
|
property new_password : String
|
||||||
|
|
||||||
|
@ -36,16 +30,8 @@ class AuthD::Request
|
||||||
end
|
end
|
||||||
|
|
||||||
def handle(authd : AuthD::Service, fd : Int32)
|
def handle(authd : AuthD::Service, fd : Int32)
|
||||||
uid_or_login = @user
|
user = authd.user? @user
|
||||||
user = if uid_or_login.is_a? Int32
|
return Response::Error.new "user not found" if user.nil?
|
||||||
authd.users_per_uid.get? uid_or_login.to_s
|
|
||||||
else
|
|
||||||
authd.users_per_login.get? uid_or_login
|
|
||||||
end
|
|
||||||
|
|
||||||
if user.nil?
|
|
||||||
return Response::Error.new "user not found"
|
|
||||||
end
|
|
||||||
|
|
||||||
if user.password_renew_key == @password_renew_key
|
if user.password_renew_key == @password_renew_key
|
||||||
user.password_hash = authd.hash_password @new_password
|
user.password_hash = authd.hash_password @new_password
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
class AuthD::Request
|
class AuthD::Request
|
||||||
IPC::JSON.message CheckPermission, 9 do
|
IPC::JSON.message CheckPermission, 9 do
|
||||||
property user : Int32 | String
|
property user : UserID
|
||||||
property service : String
|
property service : String
|
||||||
property resource : String
|
property resource : String
|
||||||
|
|
||||||
|
@ -13,16 +13,8 @@ class AuthD::Request
|
||||||
return Response::Error.new "you must be logged" if logged_user.nil?
|
return Response::Error.new "you must be logged" if logged_user.nil?
|
||||||
return Response::Error.new "unauthorized (not admin)" unless logged_user.admin
|
return Response::Error.new "unauthorized (not admin)" unless logged_user.admin
|
||||||
|
|
||||||
user = case u = @user
|
user = authd.user? @user
|
||||||
when .is_a? Int32
|
return Response::Error.new "no such user" if user.nil?
|
||||||
authd.users_per_uid.get? u.to_s
|
|
||||||
else
|
|
||||||
authd.users_per_login.get? u
|
|
||||||
end
|
|
||||||
|
|
||||||
if user.nil?
|
|
||||||
return Response::Error.new "no such user"
|
|
||||||
end
|
|
||||||
|
|
||||||
service = @service
|
service = @service
|
||||||
service_permissions = user.permissions[service]?
|
service_permissions = user.permissions[service]?
|
||||||
|
@ -43,7 +35,7 @@ class AuthD::Request
|
||||||
AuthD.requests << CheckPermission
|
AuthD.requests << CheckPermission
|
||||||
|
|
||||||
IPC::JSON.message SetPermission, 10 do
|
IPC::JSON.message SetPermission, 10 do
|
||||||
property user : Int32 | String
|
property user : UserID
|
||||||
property service : String
|
property service : String
|
||||||
property resource : String
|
property resource : String
|
||||||
property permission : ::AuthD::User::PermissionLevel
|
property permission : ::AuthD::User::PermissionLevel
|
||||||
|
@ -57,8 +49,7 @@ class AuthD::Request
|
||||||
return Response::Error.new "you must be logged" if logged_user.nil?
|
return Response::Error.new "you must be logged" if logged_user.nil?
|
||||||
return Response::Error.new "unauthorized (not admin)" unless logged_user.admin
|
return Response::Error.new "unauthorized (not admin)" unless logged_user.admin
|
||||||
|
|
||||||
user = authd.users_per_uid.get? @user.to_s
|
user = authd.user? @user
|
||||||
|
|
||||||
return Response::Error.new "no such user" if user.nil?
|
return Response::Error.new "no such user" if user.nil?
|
||||||
|
|
||||||
service = @service
|
service = @service
|
||||||
|
|
|
@ -83,7 +83,7 @@ class AuthD::Service < IPC
|
||||||
@logged_users[fd]?
|
@logged_users[fd]?
|
||||||
end
|
end
|
||||||
|
|
||||||
def user?(uid_or_login : Int32 | String)
|
def user?(uid_or_login : UserID)
|
||||||
if uid_or_login.is_a? Int32
|
if uid_or_login.is_a? Int32
|
||||||
@users_per_uid.get? uid_or_login.to_s
|
@users_per_uid.get? uid_or_login.to_s
|
||||||
else
|
else
|
||||||
|
|
Loading…
Add table
Reference in a new issue