153 lines
5.0 KiB
Ruby
153 lines
5.0 KiB
Ruby
# class Sessions
|
|
class Sessions
|
|
def initialize(request, response)
|
|
@request = request
|
|
@response = response
|
|
end
|
|
|
|
def signed_in?
|
|
$active_users[self["user"]]
|
|
end
|
|
|
|
def logout
|
|
uid = self["user"]
|
|
$active_users.delete(uid)
|
|
delete("user")
|
|
DB["delete from SignedInUsers where code = ?", uid].delete
|
|
true
|
|
rescue Sequel::Error => e
|
|
Logman.log "DB Error: #{e.message}"
|
|
false
|
|
end
|
|
|
|
def login(username, pass)
|
|
Logman.log "Logging in: #{username} & #{pass} #{ENV_HASH["SALT"]}"
|
|
player = Players.authorized?(username, pass)
|
|
if player
|
|
code = Array.new(24) { ALPHANUM.sample }.join
|
|
self["user"] = code
|
|
$active_users[code] = username
|
|
begin
|
|
DB["insert into SignedInUsers (code, player) values (?, ?)", code, username].insert
|
|
rescue Sequel::Error => e
|
|
Logman.log "DB Error: #{e.message}"
|
|
return [500, "Internal server error when signing you in!"]
|
|
end
|
|
return [200, "Remember to verify your email!"] unless Players.verified?(username)
|
|
[200, "Signed in successfully!"]
|
|
else
|
|
[200, "Couldn't sign you in (Username or password incorrect)!"]
|
|
end
|
|
end
|
|
|
|
# TODO: Use .all here
|
|
def []=(key, val)
|
|
session = @request.cookies["session"]
|
|
session = session.nil? ? "{}" : Zlib::Inflate.inflate(Base64.decode64(session))
|
|
session = JSON.parse(session)
|
|
session[key] = val
|
|
Logman.log "Updated: #{key} to #{val}"
|
|
compressed = Zlib::Deflate.deflate(JSON.generate(session))
|
|
encoded = Base64.encode64(compressed)
|
|
@response.set_cookie("session",
|
|
value: encoded,
|
|
path: "/",
|
|
expires: Time.now + 360 * 24 * 60 * 60,
|
|
httponly: true,
|
|
secure: ENV_HASH["ENV"] == "prod",
|
|
samesite: :strict)
|
|
uid = session["user"]
|
|
DB["UPDATE SignedInUsers SET last_used_at = CURRENT_TIMESTAMP WHERE code = ?", uid].update if uid
|
|
rescue JSON::ParserError, Zlib::Error
|
|
@response.delete_cookie("session")
|
|
rescue Sequel::Error => e
|
|
Logman.log "DB Error: #{e.message} when updating last_used_at for #{uid}"
|
|
end
|
|
|
|
def [](key)
|
|
session = @request.cookies["session"]
|
|
session = session.nil? ? "{}" : Zlib::Inflate.inflate(Base64.decode64(session))
|
|
session = JSON.parse(session)
|
|
begin
|
|
uid = session["user"]
|
|
DB["UPDATE SignedInUsers SET last_used_at = CURRENT_TIMESTAMP WHERE code = ?", uid].update if uid
|
|
rescue Sequel::Error => e
|
|
Logman.log "DB Error: #{e.message} when updating last_used_at for #{uid}"
|
|
end
|
|
session[key]
|
|
rescue JSON::ParserError, Zlib::Error
|
|
@response.delete_cookie("session")
|
|
""
|
|
end
|
|
|
|
def message=(val)
|
|
@response.set_cookie("message",
|
|
value: val,
|
|
path: "/",
|
|
expires: Time.now + 360 * 24 * 60 * 60,
|
|
secure: ENV_HASH["ENV"] == "prod",
|
|
samesite: :strict)
|
|
end
|
|
|
|
def message
|
|
@request.cookies["message"]
|
|
end
|
|
|
|
def csrf_auth?
|
|
@request.env["HTTP_X_CSRF_TOKEN"] == self["csrf_token"]
|
|
end
|
|
|
|
def all
|
|
session = @request.cookies["session"]
|
|
session = session.nil? ? "{}" : Zlib::Inflate.inflate(Base64.decode64(session))
|
|
JSON.parse(session)
|
|
rescue JSON::ParserError, Zlib::Error
|
|
@response.delete_cookie("session")
|
|
{}
|
|
end
|
|
|
|
def delete(key)
|
|
session = @request.cookies["session"]
|
|
session = session.nil? ? "{}" : Zlib::Inflate.inflate(Base64.decode64(session))
|
|
session = JSON.parse(session)
|
|
session.delete(key)
|
|
Logman.log "Deleted: #{key}"
|
|
Logman.log session.inspect
|
|
compressed = Zlib::Deflate.deflate(JSON.generate(session))
|
|
encoded = Base64.encode64(compressed)
|
|
@response.set_cookie("session",
|
|
value: encoded,
|
|
path: "/",
|
|
expires: Time.now + 360 * 24 * 60 * 60,
|
|
httponly: true,
|
|
secure: ENV_HASH["ENV"] == "prod",
|
|
samesite: :strict)
|
|
rescue JSON::ParserError, Zlib::Error
|
|
@response.delete_cookie("session")
|
|
end
|
|
|
|
Thread.new do
|
|
loop do
|
|
now = Time.now
|
|
fifteen_days_ago = now - (60 * 60 * 24 * 15)
|
|
six_days_ago = now - (60 * 60 * 24 * 6)
|
|
old_sessions = (DB[:SignedInUsers].where { created_at < fifteen_days_ago }.all +
|
|
DB[:SignedInUsers].where { last_used_at < six_days_ago }.all).uniq { |s| s[:code] }
|
|
old_sessions.each do |session|
|
|
begin
|
|
DB[:SignedInUsers].where(code: session[:code]).delete
|
|
rescue StandardError => e
|
|
Logman.log "Thread DB error: #{e.message} on #{session[:code]} for #{session[:player]}"
|
|
end
|
|
$active_users.delete(session[:code])
|
|
puts "Auto-logged out: #{session[:player]} (expired session)"
|
|
end
|
|
rescue StandardError => e
|
|
Logman.log "Thread error: #{e.message}"
|
|
ensure
|
|
sleep 60 * 60 * 24
|
|
Logman.log "Thread sleeping"
|
|
end
|
|
end
|
|
end
|