Skip to content

Instantly share code, notes, and snippets.

@grk
Created October 21, 2009 13:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save grk/35ef33590789a1dc5e0c to your computer and use it in GitHub Desktop.
Save grk/35ef33590789a1dc5e0c to your computer and use it in GitHub Desktop.
require 'rubygems'
require 'sinatra'
require 'environment'
class SomeApp < Sinatra::Base
configure do
set :views, "#{File.dirname(__FILE__)}/views"
end
#error do
# e = request.env['sinatra.error']
# Kernel.puts e.backtrace.join("\n")
# 'Application error'
#end
helpers do
include Rack::Utils
alias_method :h, :escape_html
def current_user
env['warden'].user
end
end
# root page
get '/' do
erb :root
end
post '/unauthenticated/?' do
status 401
erb :login
end
get '/login/?' do
erb :login
end
post '/login/?' do
env['warden'].authenticate!
redirect "/"
end
get '/logout/?' do
env['warden'].logout
redirect '/'
end
end
require 'lib/login_management'
require 'application'
set :run, false
set :environment, :development
FileUtils.mkdir_p 'log' unless File.exists?('log')
log = File.new("log/sinatra.log", "a+")
$stdout.reopen(log)
$stderr.reopen(log)
use Rack::Session::Cookie
use Warden::Manager do |manager|
manager.default_strategies :password
manager.failure_app = SomeApp
end
run SomeApp
require 'rubygems'
require 'mongomapper'
require 'sinatra' unless defined?(Sinatra)
configure do
MongoMapper.database = 'test'
# load models
$LOAD_PATH.unshift("#{File.dirname(__FILE__)}/lib")
Dir.glob("#{File.dirname(__FILE__)}/lib/*.rb") { |lib| require File.basename(lib, '.*') }
end
require 'digest/sha1'
require 'bcrypt'
class Account
include MongoMapper::Document
key :email, String, :required => true
key :crypted_password, String
key :reset_password_code, String
key :reset_passwrod_code_until, Time
timestamps!
many :sites
RegEmailName = '[\w\.%\+\-]+'
RegDomainHead = '(?:[A-Z0-9\-]+\.)+'
RegDomainTLD = '(?:[A-Z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum|edu)'
RegEmailOk = /\A#{RegEmailName}@#{RegDomainHead}#{RegDomainTLD}\z/i
def self.authenticate(email, secret)
a = Account.first(:conditions => {:email => email.downcase})
a && a.authenticated?(secret) ? a : nil
end
validates_length_of :email, :within => 6..100, :allow_blank => true
validates_format_of :email, :with => RegEmailOk, :allow_blank => true
PasswordRequired = Proc.new { |a| a.password_required? }
validates_presence_of :password, :if => PasswordRequired
validates_confirmation_of :password, :if => PasswordRequired, :allow_nil => true
validates_length_of :password, :minimum => 6, :if => PasswordRequired, :allow_nil => true
def authenticated?(secret)
password == secret ? true : false
end
def password
if crypted_password.present?
@password ||= BCrypt::Password.new(crypted_password)
else
nil
end
end
def password=(value)
if value.present?
@password = value
self.crypted_password = BCrypt::Password.create(value)
end
end
def email=(new_email)
new_email.downcase! unless new_email.nil?
write_attribute(:email, new_email)
end
def password_required?
crypted_password.blank? || !password.blank?
end
def set_password_code!
seed = "#{email}#{Time.now.to_s.split(//).sort_by {rand}.join}"
self.reset_password_code_until = 1.day.from_now
self.reset_password_code = Digest::SHA1.hexdigest(seed)
save!
end
end
require 'warden'
Warden::Manager.serialize_into_session{|account| account.id }
Warden::Manager.serialize_from_session{|id| Account.find_by_id(id) }
Warden::Manager.before_failure do |env,opts|
# Sinatra is very sensitive to the request method
# since authentication could fail on any type of method, we need
# to set it for the failure app so it is routed to the correct block
env['REQUEST_METHOD'] = "POST"
end
Warden::Strategies.add(:password) do
def valid?
params["email"] || params["password"]
end
def authenticate!
a = Account.authenticate(params["email"], params["password"])
a.nil? ? fail!("Could not log in") : success!(a)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment