LifePex/src/systems/user.rb

135 lines
4.0 KiB
Ruby

require "yaml"
require_relative "./auth.rb"
require_relative "./csrf.rb"
class LifePex::Systems::UserSystem < LifePex::Systems::AuthSystem
include JSON::API
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 setup_user_cookie!(user_id)
cookies["auth"] = JWT.encode({ "user_id" => user_id }, LifePex::SECRET)
end
def login(params)
user = LifePex::User.where(username: params["username"]).first
if user && BCrypt::Password.new(user[:hashed_password]) == params["password"]
cookies["auth"] = JWT.encode({ "user_id" => user[:id] }, LifePex::SECRET)
user
else
nil
end
end
post "/login", provides: 'html' do
if user = login(params)
cookies["auth"] = JWT.encode({ "user_id" => user[:id] }, LifePex::SECRET)
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
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