crystal-gauntlet/src/template_endpoints/login.cr

64 lines
1.8 KiB
Crystal

require "uri"
require "http-session"
include CrystalGauntlet
CrystalGauntlet.template_endpoints[{
name: "login",
path: "/login",
methods: ["get", "post"]
}] = ->(context : HTTP::Server::Context, params : Hash(String, String?)) {
if session = CrystalGauntlet.sessions.get(context)
logged_in = true
account_id = session.account_id
user_id = session.user_id
username = session.username
else
logged_in = false
account_id = nil
user_id = nil
username = nil
end
body = context.request.body
if body
begin
params = URI::Params.parse(body.gets_to_end)
username = params["username"].strip
password = params["password"].strip
if username.empty? || password.empty?
raise "Invalid username or password"
end
# todo: dedup this code with the login account endpoint maybe
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)
logged_in = true
LOG.debug { "#{username} logged in" }
CrystalGauntlet.sessions.set(context, UserSession.new(username, account_id, user_id))
else
raise "Invalid password"
end
else
raise "No such user exists"
end
rescue error
LOG.error(exception: error) {"whar...."}
end
end
if logged_in
context.response.headers.add("Location", "#{context.request.query_params["redir"]? || "/accounts"}")
context.response.status = HTTP::Status::SEE_OTHER
return
else
ECR.embed("./public/template/login.ecr", context.response)
end
}