Commit b69fae3e authored by Oliver Feldt's avatar Oliver Feldt
Browse files

Added login component (incomplete); changed ID schema

parent ae04d3b2
......@@ -25,12 +25,13 @@ Gem::Specification.new do |spec|
spec.add_runtime_dependency "thin", "~> 1.6", ">= 1.6.3"
# web framework
spec.add_runtime_dependency "sinatra", "~> 1.4", ">= 1.4.5"
spec.add_runtime_dependency "sinatra-contrib", "~>1.4", ">= 1.4.2"
spec.add_runtime_dependency "sinatra-assetpack", "~> 0.3", ">= 0.3.3"
spec.add_runtime_dependency "sinatra-contrib", "~>1.4", ">= 1.4.2"
spec.add_runtime_dependency 'sinatra-flash', '0.3.0'
# auth
spec.add_runtime_dependency 'warden', '1.2.1'
spec.add_runtime_dependency 'bcrypt-ruby', '~> 3.1', ">= 3.1.5"
# views
spec.add_runtime_dependency "slim", "~> 3.0", ">= 3.0.0"
spec.add_runtime_dependency "sass", "~> 3.4", ">= 3.4.9"
......
require "sinatra"
require "bcrypt"
require "json"
require "sinatra/json"
require "sinatra/flash"
require "sinatra/assetpack"
require "data_mapper"
require "slim"
......@@ -9,10 +11,36 @@ require "warden"
require "ccc_roc/setup_storage"
Warden::Strategies.add(:password) do
def valid?
params['user'] && params['user']['username'] && params['user']['password']
end
def authenticate!
user = CCC::ROC::User.first(username: params['user']['username'])
if user.nil?
throw(:warden, message: "The username you entered does not exist.")
elsif user.authenticate(params['user']['password'])
success!(user)
else
throw(:warden, message: "The username and password combination ")
end
end
end
module CCC
module ROC
class Application < Sinatra::Base
helpers Sinatra::JSON
helpers do
def radio_id_check
unless params[:radio_id] =~ /^\d{5,5}$/ || params[:radio_id] =~ /^\d+$/
halt 400, json(error: "Unknown ID format")
end
end
end
set :json_encoder, :to_json
set :static, true
set :public_folder, File.join(Gem.datadir("ccc_roc"), "public")
......@@ -20,7 +48,10 @@ module CCC
set :slim, { format: :html }
set :sass, { load_paths: [File.join(Gem.datadir("ccc_roc"), "assets/stylesheets")] }
enable :sessions
register Sinatra::AssetPack
register Sinatra::Flash
assets do
serve '/stylesheets', from: File.join(Gem.datadir("ccc_roc"), "assets/stylesheets")
......@@ -32,18 +63,69 @@ module CCC
css_compression :sass
end
helpers do
def radio_id_check
unless params[:radio_id] =~ /^ROC\d{1,8}$/
halt 400, json(error: "Unknown ID format")
end
not_found { :fourofour }
use Warden::Manager do |config|
# Tell Warden how to save our User info into a session.
# Sessions can only take strings, not Ruby code, we'll store
# the User's `id`
config.serialize_into_session{|user| user.id }
# Now tell Warden how to take what we've stored in the session
# and get a User from that information.
config.serialize_from_session{|id| User.get(id) }
config.scope_defaults :default,
# "strategies" is an array of named methods with which to
# attempt authentication. We have to define this later.
strategies: [:password],
# The action is a route to send the user to when
# warden.authenticate! returns a false answer. We'll show
# this route below.
action: 'auth/unauthenticated'
# When a user tries to log in and cannot, this specifies the
# app to send the user to.
config.failure_app = self
end
Warden::Manager.before_failure do |env, options|
env['REQUEST_METHOD'] = 'POST'
end
get "/auth/login" do
slim :login
end
post "/auth/login" do
env['warden'].authenticate!
flash[:success] = env['warden'].message
if session[:return_to].nil?
redirect '/'
else
redirect session[:return_to]
end
end
not_found { :fourofour }
get '/auth/logout' do
env['warden'].raw_session.inspect
env['warden'].logout
flash[:success] = 'Successfully logged out'
redirect '/'
end
post '/auth/unauthenticated' do
session[:return_to] = env['warden.options'][:attempted_path] if session[:return_to].nil?
# Set the error and use a fallback if the message is not defined
flash[:error] = env['warden.options'][:message] || "You must log in"
redirect '/auth/login'
end
# Business Logic
get "/" do
@radios = Radio.all
@radios = Radio.all(order: [:name.desc])
slim :index
end
......
......@@ -2,8 +2,10 @@ DataMapper.setup(:default, "sqlite3://#{Dir.pwd}/ccc_roc.db")
require "ccc_roc/radio"
require "ccc_roc/checkout"
require "ccc_roc/user"
CCC::ROC::Radio.auto_upgrade!
CCC::ROC::Checkout.auto_upgrade!
CCC::ROC::User.auto_upgrade!
DataMapper.finalize
module CCC
module ROC
class User
include DataMapper::Resource
include ::BCrypt
property :id, Serial, key: true
property :username, String, length: 128
property :password, BCryptHash
def authenticate(attempted_password)
# The BCrypt class, which `self.password` is an instance of, has `==` defined to compare a
# test plain text string to the encrypted string and converts `attempted_password` to a BCrypt
# for the comparison.
#
# But don't take my word for it, check out the source: https://github.com/codahale/bcrypt-ruby/blob/master/lib/bcrypt/password.rb#L64-L67
self.password == attempted_password
end
end
end
end
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment