crystal-gauntlet/src/lib/accounts.cr

128 lines
4.1 KiB
Crystal
Raw Normal View History

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
# 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
# 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
# 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
2022-12-31 17:59:43 +01:00
# returns userid, accountid
def auth(params : URI::Params) : (Tuple(Int32, Int32) | Tuple(Nil, Nil))
gjp = params["gjp"]?
udid = params["udid"]?
account_id = params["accountID"]?
2023-01-03 18:05:38 +01:00
if AUTH_CACHE[{gjp, udid, account_id}]?
LOG.debug {"#{account_id || udid || "???"}: gjp cache hit"}
2023-01-03 18:05:38 +01:00
return AUTH_CACHE[{gjp, udid, account_id}]
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?
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 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
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