163 lines
4.9 KiB
Ruby
163 lines
4.9 KiB
Ruby
require "yaml"
|
|
require_relative "./auth.rb"
|
|
require_relative "./csrf.rb"
|
|
|
|
class LifePex::Systems::UserSystem < LifePex::Systems::AuthSystem
|
|
include LifePex::Systems::CrlfHelper
|
|
|
|
DEFAULT_PEXS_FOR_NEW_USERS = YAML.load_file "config/default_pexs_for_new_users.yaml"
|
|
|
|
get "/login" do
|
|
slim :login
|
|
end
|
|
|
|
def login(params)
|
|
user = LifePex::User.where(username: params["username"]).first
|
|
if user && BCrypt::Password.new(user[:hashed_password]) == params["password"]
|
|
setup_user_cookie!(user[:id])
|
|
user
|
|
else
|
|
nil
|
|
end
|
|
end
|
|
|
|
post "/login", provides: 'html' do
|
|
if user = login(params)
|
|
redirect "/"
|
|
else
|
|
slim :login, locals: { flash: { danger: "Failed to login" } }
|
|
end
|
|
end
|
|
|
|
get "/register" do
|
|
slim :register
|
|
end
|
|
|
|
def register(params)
|
|
user = LifePex::User.where(username: params["username"]).first
|
|
if !user
|
|
hashed_password = BCrypt::Password.create params["password"]
|
|
user = LifePex::User.new(username: params["username"], hashed_password: hashed_password).save
|
|
cookies["auth"] = JWT.encode({ "user_id" => user.id }, LifePex::SECRET)
|
|
DEFAULT_PEXS_FOR_NEW_USERS.each do |pex|
|
|
LifePex::Pex.new(**pex, user_id: user.id).save
|
|
end
|
|
user.id
|
|
else
|
|
nil
|
|
end
|
|
end
|
|
|
|
post "/register", provides: 'html' do
|
|
if user_id = register(params)
|
|
redirect "/"
|
|
else
|
|
slim :register, locals: { flash: { danger: "Failed to register as #{params['username']}" } }
|
|
end
|
|
end
|
|
|
|
post "/logout", auth: [] do
|
|
cookies.delete "auth"
|
|
slim :logout, locals: { flash: { success: "Logged out" } }
|
|
end
|
|
|
|
get "/password", auth: [] do
|
|
slim :password
|
|
end
|
|
|
|
def change_password(params)
|
|
hashed_password = BCrypt::Password.create params["password"]
|
|
LifePex::User.where(id: current_user_id).update(hashed_password: hashed_password)
|
|
end
|
|
|
|
post "/password", auth: [], provides: 'html' do
|
|
if params["password"] != params["password_confirmation"]
|
|
slim :password, locals: { flash: { warning: "Password don't match" } }
|
|
else
|
|
change_password(params)
|
|
slim :password, locals: { flash: { success: "Password updated" } }
|
|
end
|
|
end
|
|
|
|
get "/about" do
|
|
slim :about
|
|
end
|
|
|
|
get "/preferences" do
|
|
show_preferences
|
|
end
|
|
|
|
UserPreferenceCookie = Struct.new(:cookie, :allow_blank, :convert, :html, :description)
|
|
USER_PREFERENCES = {
|
|
"inputRecapDays" => UserPreferenceCookie.new("recap_days", false, :to_i, { type: "text" }, "Amount of days to show in the recap"),
|
|
"inputLateDayOffset" => UserPreferenceCookie.new("late_day_offset", false, :to_f, { type: "number", min: "0", max: "24", step: "0.1" }, "Offset for today (so a few hours after midnight is still today)"),
|
|
"inputShowFullDate" => UserPreferenceCookie.new("show_full_date", true, :to_s, { type: "checkbox" }, "Show or hide the date of the current tab"),
|
|
}
|
|
|
|
post "/preferences" do
|
|
USER_PREFERENCES.each do |param_name, upc|
|
|
current_param = params[param_name]
|
|
next if !upc.allow_blank && current_param.blank?
|
|
|
|
cookies[upc.cookie] =
|
|
case upc.convert
|
|
when Symbol
|
|
current_param.send(upc.convert)
|
|
when Proc
|
|
upc.convert.call(current_param)
|
|
else
|
|
current_param
|
|
end
|
|
end
|
|
|
|
show_preferences
|
|
end
|
|
|
|
def show_preferences
|
|
slim :preferences
|
|
end
|
|
|
|
extend DocMyRoutes::Annotatable
|
|
register Sinatra::Namespace
|
|
namespace '/api/user/v1' do
|
|
summary 'Generate a authentication cookie for a registrated account'
|
|
notes ''
|
|
produces 'application/json'
|
|
status_codes [200]
|
|
parameter :username, required: true, type: 'string', in: 'body'
|
|
parameter :password, required: true, type: 'string', in: 'body'
|
|
post "/login", provides: 'json' do
|
|
if user = login(json_params)
|
|
{ message: 'Logged in' }.to_json
|
|
else
|
|
halt 400, { message: 'Invalid credentials' }.to_json
|
|
end
|
|
end
|
|
|
|
summary 'Register a new account if the username does not exists already'
|
|
notes ''
|
|
produces 'application/json'
|
|
status_codes [200]
|
|
parameter :username, required: true, type: 'string', in: 'body'
|
|
parameter :password, required: true, type: 'string', in: 'body'
|
|
post "/register", provides: 'json' do
|
|
if user_id = register(json_params)
|
|
{ message: "Registered as user_id=#{user_id}", user: { id: user_id, username: json_params["username"] } }.to_json
|
|
else
|
|
halt 400, { message: "Failed to register as #{json_params['username']}" }.to_json
|
|
end
|
|
end
|
|
|
|
summary 'Change the authentication password of the account'
|
|
produces 'application/json'
|
|
status_codes [200]
|
|
parameter :password, required: true, type: 'string', in: 'body'
|
|
parameter :auth, required: true, type: 'string', in: 'cookies'
|
|
post "/password", auth: [], provides: 'html' do
|
|
change_password(json_params)
|
|
{ message: 'password changed' }.to_json
|
|
end
|
|
end
|
|
include LifePex::Systems::ApiList
|
|
end
|