2022-12-30 17:04:27 +01:00
require " uri "
2022-12-30 18:34:55 +01:00
require " crypto/bcrypt/password "
2022-12-30 17:04:27 +01:00
include CrystalGauntlet
module CrystalGauntlet::Accounts
extend self
2023-01-02 17:07:33 +01:00
# DOESN'T VERIFY PASSWORD
2022-12-31 07:28:06 +01:00
def get_account_id_from_params ( params : URI :: Params ) : Int32 | Nil
if params [ " accountID " ]? && params [ " accountID " ]? != " 0 "
params [ " accountID " ] . to_i32
else
nil
end
end
2023-01-02 17:07:33 +01:00
# DOESN'T VERIFY PASSWORD
2022-12-31 18:12:22 +01:00
def get_ext_id_from_params ( params : URI :: Params ) : Int32 | Nil
2023-01-04 13:05:27 +01:00
if params . has_key? ( " udid " ) && ! params [ " udid " ] . blank?
2022-12-31 18:12:22 +01:00
params [ " udid " ] . to_i32?
2022-12-30 17:04:27 +01:00
else
2022-12-31 18:12:22 +01:00
get_account_id_from_params ( params )
2022-12-30 17:04:27 +01:00
end
end
2023-01-02 17:07:33 +01:00
# todo: clean this periodically
AUTH_CACHE = Hash ( Tuple ( String | Nil , String | Nil , String | Nil ) , Tuple ( Int32 , Int32 ) | Tuple ( Nil , Nil ) ) . new
2023-01-08 08:10:27 +01:00
SESSIONS = Hash ( Tuple ( String | Nil , String | Nil ) , Tuple ( Int32 , Int32 , Int64 ) ) . new
2023-01-02 17:07:33 +01:00
2022-12-31 17:59:43 +01:00
# returns userid, accountid
def auth ( params : URI :: Params ) : ( Tuple ( Int32 , Int32 ) | Tuple ( Nil , Nil ) )
2023-01-02 17:07:33 +01:00
gjp = params [ " gjp " ]?
udid = params [ " udid " ]?
2023-01-03 11:38:23 +01:00
account_id = params [ " accountID " ]?
2023-01-02 17:07:33 +01:00
2023-01-03 18:05:38 +01:00
if AUTH_CACHE [ { gjp , udid , account_id } ]?
2023-01-02 17:07:33 +01:00
LOG . debug { " #{ account_id || udid || " ??? " } : gjp cache hit " }
2023-01-03 18:05:38 +01:00
return AUTH_CACHE [ { gjp , udid , account_id } ]
2023-01-02 17:07:33 +01:00
end
LOG . debug { " #{ account_id || udid || " ??? " } : gjp cache miss " }
2023-01-05 10:08:36 +01:00
ext_id = Accounts . get_account_id_from_params ( params )
2023-01-03 18:05:38 +01:00
if ! ext_id || ! Accounts . verify_gjp ( ext_id . to_i , gjp || " " )
2022-12-31 17:59:43 +01:00
return nil , nil
end
user_id = Accounts . get_user_id ( ext_id )
if ! user_id
return nil , nil
end
2023-01-03 18:05:38 +01:00
AUTH_CACHE [ { gjp , udid , account_id } ] = { user_id , ext_id . to_i }
2022-12-31 17:59:43 +01:00
return user_id , ext_id . to_i
end
2023-01-08 08:10:27 +01:00
def auth_old ( req : HTTP :: Request , params : URI :: Params ) : ( Tuple ( Int32 , Int32 ) | Tuple ( Nil , Nil ) )
account_id = params [ " accountID " ]
ip = IPs . get_real_ip ( req )
if SESSIONS . has_key? ( { account_id , ip } )
LOG . debug { " #{ account_id || " ??? " } : session exists " }
user_id , ext_id , expiry_time = SESSIONS [ { account_id , ip } ]
if Time . utc . to_unix > expiry_time
LOG . debug { " #{ account_id || " ??? " } : session expired " }
SESSIONS . delete ( { account_id , ip } )
return nil , nil
else
LOG . debug { " #{ account_id || " ??? " } : session valid " }
return user_id , ext_id
end
end
LOG . debug { " #{ account_id || " ??? " } : session does not exist " }
return nil , nil
end
def new_session ( req : HTTP :: Request , username : String , password : String ) : Bool
if ! config_get ( " sessions.allow " ) . as ( Bool | Nil )
return false
end
ip = IPs . get_real_ip ( req )
result = DATABASE . query_all ( " select id, password from accounts where username = ? " , username , as : { Int32 , String } )
if result . size > 0
account_id , hash = result [ 0 ]
bcrypt = Crypto :: Bcrypt :: Password . new ( hash )
if bcrypt . verify ( password )
user_id = Accounts . get_user_id ( account_id )
expiry_time = Time . utc . to_unix + ( config_get ( " sessions.expiry_time " ) . as ( Int64 | Nil ) || 604800 )
SESSIONS [ { account_id . to_s , ip } ] = { user_id , account_id , expiry_time }
return true
else
return false
end
else
return false
end
end
2022-12-31 18:12:22 +01:00
def get_user_id ( ext_id : Int32 ) : Int32
2022-12-30 17:04:27 +01:00
DATABASE . query ( " select id from users where udid = ? or account_id = ? " , ext_id , ext_id ) do | rs |
2022-12-30 18:34:55 +01:00
if rs . move_next
2022-12-30 17:04:27 +01:00
return rs . read ( Int32 )
else
raise " no user associated with account?! "
end
end
end
2022-12-30 18:34:55 +01:00
2022-12-31 07:28:06 +01:00
def verify_gjp ( account_id : Int32 , gjp : String ) : Bool
2023-01-04 13:05:27 +01:00
if gjp . blank?
2023-01-02 17:07:33 +01:00
return false
end
2022-12-30 18:34:55 +01:00
hash = DATABASE . scalar ( " select password from accounts where id = ? " , account_id ) . as ( String )
bcrypt = Crypto :: Bcrypt :: Password . new ( hash )
bcrypt . verify ( GJP . decrypt ( gjp ) )
end
2023-01-06 09:51:11 +01:00
2023-01-06 15:58:34 +01:00
def is_blocked_by ( account_id : Int32 , by : Int32 )
DATABASE . scalar ( " select count(*) from block_links where (from_account_id = ? and to_account_id = ?) " , by , account_id ) . as ( Int64 ) > 0
end
2023-01-06 09:51:11 +01:00
def are_friends ( account_id_1 : Int32 , account_id_2 : Int32 )
DATABASE . scalar ( " select count(*) from friend_links where (account_id_1 = ? and account_id_2 = ?) or (account_id_2 = ? and account_id_1 = ?) " , account_id_1 , account_id_2 , account_id_1 , account_id_2 ) . as ( Int64 ) > 0
end
2022-12-30 17:04:27 +01:00
end