Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
18 changed files
with
602 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# This controller handles the login/logout function of the site. | ||
class SessionsController < ApplicationController | ||
# Be sure to include AuthenticationSystem in Application Controller instead | ||
include AuthenticatedSystem | ||
|
||
# render new.rhtml | ||
def new | ||
end | ||
|
||
def create | ||
self.current_user = User.authenticate(params[:login], params[:password]) | ||
if logged_in? | ||
if params[:remember_me] == "1" | ||
self.current_user.remember_me | ||
cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at } | ||
end | ||
redirect_back_or_default('/') | ||
flash[:notice] = "Logged in successfully" | ||
else | ||
render :action => 'new' | ||
end | ||
end | ||
|
||
def destroy | ||
self.current_user.forget_me if logged_in? | ||
cookies.delete :auth_token | ||
reset_session | ||
flash[:notice] = "You have been logged out." | ||
redirect_back_or_default('/') | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
class TestController < ApplicationController | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
class UsersController < ApplicationController | ||
# Be sure to include AuthenticationSystem in Application Controller instead | ||
include AuthenticatedSystem | ||
|
||
|
||
# render new.rhtml | ||
def new | ||
end | ||
|
||
def create | ||
cookies.delete :auth_token | ||
# protects against session fixation attacks, wreaks havoc with | ||
# request forgery protection. | ||
# uncomment at your own risk | ||
# reset_session | ||
@user = User.new(params[:user]) | ||
@user.save | ||
if @user.errors.empty? | ||
self.current_user = @user | ||
redirect_back_or_default('/') | ||
flash[:notice] = "Thanks for signing up!" | ||
else | ||
render :action => 'new' | ||
end | ||
end | ||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
module SessionsHelper | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
module TestHelper | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
module UsersHelper | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
require 'digest/sha1' | ||
class User < ActiveRecord::Base | ||
# Virtual attribute for the unencrypted password | ||
attr_accessor :password | ||
|
||
validates_presence_of :login, :email | ||
validates_presence_of :password, :if => :password_required? | ||
validates_presence_of :password_confirmation, :if => :password_required? | ||
validates_length_of :password, :within => 4..40, :if => :password_required? | ||
validates_confirmation_of :password, :if => :password_required? | ||
validates_length_of :login, :within => 3..40 | ||
validates_length_of :email, :within => 3..100 | ||
validates_uniqueness_of :login, :email, :case_sensitive => false | ||
before_save :encrypt_password | ||
|
||
# prevents a user from submitting a crafted form that bypasses activation | ||
# anything else you want your user to change should be added here. | ||
attr_accessible :login, :email, :password, :password_confirmation | ||
|
||
# Authenticates a user by their login name and unencrypted password. Returns the user or nil. | ||
def self.authenticate(login, password) | ||
u = find_by_login(login) # need to get the salt | ||
u && u.authenticated?(password) ? u : nil | ||
end | ||
|
||
# Encrypts some data with the salt. | ||
def self.encrypt(password, salt) | ||
Digest::SHA1.hexdigest("--#{salt}--#{password}--") | ||
end | ||
|
||
# Encrypts the password with the user salt | ||
def encrypt(password) | ||
self.class.encrypt(password, salt) | ||
end | ||
|
||
def authenticated?(password) | ||
crypted_password == encrypt(password) | ||
end | ||
|
||
def remember_token? | ||
remember_token_expires_at && Time.now.utc < remember_token_expires_at | ||
end | ||
|
||
# These create and unset the fields required for remembering users between browser closes | ||
def remember_me | ||
remember_me_for 2.weeks | ||
end | ||
|
||
def remember_me_for(time) | ||
remember_me_until time.from_now.utc | ||
end | ||
|
||
def remember_me_until(time) | ||
self.remember_token_expires_at = time | ||
self.remember_token = encrypt("#{email}--#{remember_token_expires_at}") | ||
save(false) | ||
end | ||
|
||
def forget_me | ||
self.remember_token_expires_at = nil | ||
self.remember_token = nil | ||
save(false) | ||
end | ||
|
||
protected | ||
# before filter | ||
def encrypt_password | ||
return if password.blank? | ||
self.salt = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{login}--") if new_record? | ||
self.crypted_password = encrypt(password) | ||
end | ||
|
||
def password_required? | ||
crypted_password.blank? || !password.blank? | ||
end | ||
|
||
|
||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
<% form_tag session_path do -%> | ||
<p><label for="login">Login</label><br/> | ||
<%= text_field_tag 'login' %></p> | ||
|
||
<p><label for="password">Password</label><br/> | ||
<%= password_field_tag 'password' %></p> | ||
|
||
<!-- Uncomment this if you want this functionality | ||
<p><label for="remember_me">Remember me:</label> | ||
<%= check_box_tag 'remember_me' %></p> | ||
--> | ||
|
||
<p><%= submit_tag 'Log in' %></p> | ||
<% end -%> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
<%= error_messages_for :user %> | ||
<% form_for :user, :url => users_path do |f| -%> | ||
<p><label for="login">Login</label><br/> | ||
<%= f.text_field :login %></p> | ||
|
||
<p><label for="email">Email</label><br/> | ||
<%= f.text_field :email %></p> | ||
|
||
<p><label for="password">Password</label><br/> | ||
<%= f.password_field :password %></p> | ||
|
||
<p><label for="password_confirmation">Confirm Password</label><br/> | ||
<%= f.password_field :password_confirmation %></p> | ||
|
||
<p><%= submit_tag 'Sign up' %></p> | ||
<% end -%> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
class CreateUsers < ActiveRecord::Migration | ||
def self.up | ||
create_table "users", :force => true do |t| | ||
t.column :login, :string | ||
t.column :email, :string | ||
t.column :crypted_password, :string, :limit => 40 | ||
t.column :salt, :string, :limit => 40 | ||
t.column :created_at, :datetime | ||
t.column :updated_at, :datetime | ||
t.column :remember_token, :string | ||
t.column :remember_token_expires_at, :datetime | ||
|
||
|
||
end | ||
end | ||
|
||
def self.down | ||
drop_table "users" | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
module AuthenticatedSystem | ||
protected | ||
# Returns true or false if the user is logged in. | ||
# Preloads @current_user with the user model if they're logged in. | ||
def logged_in? | ||
current_user != :false | ||
end | ||
|
||
# Accesses the current user from the session. Set it to :false if login fails | ||
# so that future calls do not hit the database. | ||
def current_user | ||
@current_user ||= (login_from_session || login_from_basic_auth || login_from_cookie || :false) | ||
end | ||
|
||
# Store the given user id in the session. | ||
def current_user=(new_user) | ||
session[:user_id] = (new_user.nil? || new_user.is_a?(Symbol)) ? nil : new_user.id | ||
@current_user = new_user || :false | ||
end | ||
|
||
# Check if the user is authorized | ||
# | ||
# Override this method in your controllers if you want to restrict access | ||
# to only a few actions or if you want to check if the user | ||
# has the correct rights. | ||
# | ||
# Example: | ||
# | ||
# # only allow nonbobs | ||
# def authorized? | ||
# current_user.login != "bob" | ||
# end | ||
def authorized? | ||
logged_in? | ||
end | ||
|
||
# Filter method to enforce a login requirement. | ||
# | ||
# To require logins for all actions, use this in your controllers: | ||
# | ||
# before_filter :login_required | ||
# | ||
# To require logins for specific actions, use this in your controllers: | ||
# | ||
# before_filter :login_required, :only => [ :edit, :update ] | ||
# | ||
# To skip this in a subclassed controller: | ||
# | ||
# skip_before_filter :login_required | ||
# | ||
def login_required | ||
authorized? || access_denied | ||
end | ||
|
||
# Redirect as appropriate when an access request fails. | ||
# | ||
# The default action is to redirect to the login screen. | ||
# | ||
# Override this method in your controllers if you want to have special | ||
# behavior in case the user is not authorized | ||
# to access the requested action. For example, a popup window might | ||
# simply close itself. | ||
def access_denied | ||
respond_to do |format| | ||
format.html do | ||
store_location | ||
redirect_to new_session_path | ||
end | ||
format.any do | ||
request_http_basic_authentication 'Web Password' | ||
end | ||
end | ||
end | ||
|
||
# Store the URI of the current request in the session. | ||
# | ||
# We can return to this location by calling #redirect_back_or_default. | ||
def store_location | ||
session[:return_to] = request.request_uri | ||
end | ||
|
||
# Redirect to the URI stored by the most recent store_location call or | ||
# to the passed default. | ||
def redirect_back_or_default(default) | ||
redirect_to(session[:return_to] || default) | ||
session[:return_to] = nil | ||
end | ||
|
||
# Inclusion hook to make #current_user and #logged_in? | ||
# available as ActionView helper methods. | ||
def self.included(base) | ||
base.send :helper_method, :current_user, :logged_in? | ||
end | ||
|
||
# Called from #current_user. First attempt to login by the user id stored in the session. | ||
def login_from_session | ||
self.current_user = User.find(session[:user_id]) if session[:user_id] | ||
end | ||
|
||
# Called from #current_user. Now, attempt to login by basic authentication information. | ||
def login_from_basic_auth | ||
authenticate_with_http_basic do |username, password| | ||
self.current_user = User.authenticate(username, password) | ||
end | ||
end | ||
|
||
# Called from #current_user. Finaly, attempt to login by an expiring token in the cookie. | ||
def login_from_cookie | ||
user = cookies[:auth_token] && User.find_by_remember_token(cookies[:auth_token]) | ||
if user && user.remember_token? | ||
user.remember_me | ||
cookies[:auth_token] = { :value => user.remember_token, :expires => user.remember_token_expires_at } | ||
self.current_user = user | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module AuthenticatedTestHelper | ||
# Sets the current user in the session from the user fixtures. | ||
def login_as(user) | ||
@request.session[:user_id] = user ? users(user).id : nil | ||
end | ||
|
||
def authorize_as(user) | ||
@request.env["HTTP_AUTHORIZATION"] = user ? ActionController::HttpAuthentication::Basic.encode_credentials(users(user).login, 'test') : nil | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
quentin: | ||
id: 1 | ||
login: quentin | ||
email: quentin@example.com | ||
salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd | ||
crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1 # test | ||
created_at: <%= 5.days.ago.to_s :db %> | ||
|
||
|
||
|
||
aaron: | ||
id: 2 | ||
login: aaron | ||
email: aaron@example.com | ||
salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd | ||
crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1 # test | ||
created_at: <%= 1.days.ago.to_s :db %> | ||
|
||
|
Oops, something went wrong.