Changeset 293

Show
Ignore:
Timestamp:
10/26/08 21:24:52 (2 months ago)
Author:
cstrom
Message:

Roll-up of a bunch of changes. Mostly upgrading to Rails 2.1. Also Fixes #59

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/app/controllers/author_controller.rb

    r157 r293  
    3030  protected 
    3131  def authorized? 
    32     current_user.author? 
     32    logged_in? && current_user.author? 
    3333  end 
    3434end 
  • trunk/app/controllers/sessions_controller.rb

    r263 r293  
    11# This controller handles the login/logout function of the site. 
    22class SessionsController < ApplicationController 
    3   # Be sure to include AuthenticationSystem in Application Controller instead 
    4   include AuthenticatedSystem 
     3  layout 'home' 
    54 
    6   layout 'master' 
     5  def show 
     6    if logged_in? && current_user.author? 
     7      redirect_to(:controller => 'author', :action => 'index') 
     8      return 
     9    end 
     10    redirect_to(:controller => 'home', :action => 'index') 
     11  end 
    712 
    813  # render new.rhtml 
     
    4045    self.current_user.forget_me if logged_in? 
    4146    cookies.delete :auth_token 
     47    cookies.delete :unsafe_login 
     48    cookies.delete :unsafe_roles 
    4249    reset_session 
    4350    flash[:notice] = "You have been logged out." 
    44     redirect_back_or_default('/') 
     51    redirect_back_or_default(:action => 'interstitial') 
     52  end 
     53 
     54  def interstitial 
     55    @redirect_delay = 5 
     56    @redirect_url = url_for(:controller => 'home', :action => 'index') 
     57 
     58    if logged_in? && current_user.author? 
     59      @redirect_url = url_for(:controller => 'author', :action => 'index') 
     60    end 
    4561  end 
    4662end 
  • trunk/app/helpers/application_helper.rb

    r98 r293  
    1 ##### 
     1#### 
    22# 
    33# Copyright 2007 Chris Strom, Robin Strom 
     
    104104  def wiki(text) 
    105105    return nil if text.blank? 
    106     textilize(wikify(text)) 
     106    RedCloth.new(wikify(text)).to_html 
    107107  end 
    108108 
    109109  def wiki_without_paragraph(text) 
    110110    return nil if text.blank? 
    111     wikify(textilize_without_paragraph('xxx '+text)[4..-1]) 
     111    wikify(RedCloth.new('xxx '+text, [:lite_mode]).to_html[4..-1]) 
    112112  end 
    113113end 
  • trunk/app/views/shared/_footer.rhtml

    r263 r293  
    1010 
    1111<p id="footnote-current-user-container" style="width: 100%; max-width: none; text-align: center; display: none"> 
    12 <b>Logged in as:</b> <a href="/account" id="footnote-current-user"></a> 
    13 (<%= link_to('logout', :controller => 'account', :action => 'logout') %>) 
     12<b>Logged in as:</b> <a href="/session" id="footnote-current-user"></a> 
     13(<%= link_to('logout', session_path, :method => 'delete') %>) 
    1414</p> 
    1515<script type="text/javascript"> 
     
    3232 
    3333<a href="http://creativecommons.org/licenses/by-nc/1.0/"> 
    34 <img id="eee-creativecommons-img" alt="Creative Commons License" src="http://creativecommons.org/images/public/somerights.gif" /></a> 
     34<!-- img id="eee-creativecommons-img" alt="Creative Commons License" src="http://creativecommons.org/images/public/somerights.gif" / --></a> 
    3535<!-- /Creative Commons License --> 
    3636 
  • trunk/config/environment.rb

    r284 r293  
    66 
    77# Specifies gem version of Rails to use when vendor/rails is not present 
    8 RAILS_GEM_VERSION = '2.1.1' unless defined? RAILS_GEM_VERSION 
     8RAILS_GEM_VERSION = '2.1.2' unless defined? RAILS_GEM_VERSION 
    99 
    1010# Bootstrap the Rails environment, frameworks, and default configuration 
     
    2626  # config.gem "hpricot", :version => '0.6', :source => "http://code.whytheluckystiff.net" 
    2727  # config.gem "aws-s3", :lib => "aws/s3" 
     28  config.gem "RedCloth", :version => '>=4.0.4' 
    2829 
    2930  # Only load the plugins named here, in the order given. By default, all plugins 
  • trunk/lib/authenticated_system.rb

    r147 r293  
    44    # Preloads @current_user with the user model if they're logged in. 
    55    def logged_in? 
    6       current_user != :false 
     6      !!current_user 
    77    end 
    88 
    9     # Accesses the current user from the session. 
     9    # Accesses the current user from the session.  
     10    # Future calls avoid the database because nil is not equal to false. 
    1011    def current_user 
    11       @current_user ||= (session[:user] && User.find_by_id(session[:user])) || :false 
     12      @current_user ||= (login_from_session || login_from_basic_auth || login_from_cookie) unless @current_user == false 
    1213    end 
    1314 
    14     # Store the given user in the session. 
     15    # Store the given user id in the session. 
    1516    def current_user=(new_user) 
    16       session[:user] = (new_user.nil? || new_user.is_a?(Symbol)) ? nil : new_user.id 
    17       @current_user = new_user 
     17      session[:user_id] = new_user ? new_user.id : nil 
     18      @current_user = new_user || false 
    1819    end 
    1920 
    20     # Check if the user is authorized. 
     21    # Check if the user is authorized 
    2122    # 
    2223    # Override this method in your controllers if you want to restrict access 
     
    2728    # 
    2829    #  # only allow nonbobs 
    29     #  def authorize
     30    #  def authorized
    3031    #    current_user.login != "bob" 
    3132    #  end 
    3233    def authorized? 
    33       true 
     34      logged_in? 
    3435    end 
    3536 
     
    4950    # 
    5051    def login_required 
    51       username, passwd = get_auth_data 
    52       self.current_user ||= User.authenticate(username, passwd) || :false if username && passwd 
    53       logged_in? && authorized? ? true : access_denied 
     52      authorized? || access_denied 
    5453    end 
    5554 
     
    6362    # simply close itself. 
    6463    def access_denied 
    65       respond_to do |accepts
    66         accepts.html do 
     64      respond_to do |format
     65        format.html do 
    6766          store_location 
    68           redirect_to :controller => '/account', :action => 'login' 
     67          redirect_to new_session_path 
    6968        end 
    70         accepts.xml do 
    71           headers["Status"]           = "Unauthorized" 
    72           headers["WWW-Authenticate"] = %(Basic realm="Web Password") 
    73           render :text => "Could't authenticate you", :status => '401 Unauthorized' 
     69        format.any do 
     70          request_http_basic_authentication 'Web Password' 
    7471        end 
    7572      end 
    76       false 
    7773    end 
    7874 
     
    8783    # to the passed default. 
    8884    def redirect_back_or_default(default) 
    89       session[:return_to] ? redirect_to(session[:return_to]) : redirect_to(default) 
     85      redirect_to(session[:return_to] || default) 
    9086      session[:return_to] = nil 
    9187    end 
     
    9793    end 
    9894 
    99     # When called with before_filter :login_from_cookie will check for an :auth_token 
    100     # cookie and log the user back in if apropriate 
    101     def login_from_cookie 
    102       return unless cookies[:auth_token] && !logged_in? 
    103       user = User.find_by_remember_token(cookies[:auth_token]) 
    104       if user && user.remember_token? 
    105         user.remember_me 
    106         self.current_user = user 
    107         cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at } 
    108         cookies[:login]      = { :value => self.current_user.login,           :expires => self.current_user.remember_token_expires_at } 
    109         cookies[:roles]      = { :value => self.current_user.roles.join(" "), :expires => self.current_user.remember_token_expires_at } 
    110         flash[:notice] = "Logged in successfully" 
     95    # Called from #current_user.  First attempt to login by the user id stored in the session. 
     96    def login_from_session 
     97      self.current_user = User.find_by_id(session[:user_id]) if session[:user_id] 
     98    end 
     99 
     100    # Called from #current_user.  Now, attempt to login by basic authentication information. 
     101    def login_from_basic_auth 
     102      authenticate_with_http_basic do |username, password| 
     103        self.current_user = User.authenticate(username, password) 
    111104      end 
    112105    end 
    113106 
    114   private 
    115     @@http_auth_headers = %w(X-HTTP_AUTHORIZATION HTTP_AUTHORIZATION Authorization) 
    116     # gets BASIC auth info 
    117     def get_auth_data 
    118       auth_key  = @@http_auth_headers.detect { |h| request.env.has_key?(h)
    119       auth_data = request.env[auth_key].to_s.split unless auth_key.blank? 
    120       return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nil, nil] 
     107    # Called from #current_user.  Finaly, attempt to login by an expiring token in the cookie. 
     108    def login_from_cookie 
     109      user = cookies[:auth_token] && User.find_by_remember_token(cookies[:auth_token]) 
     110      if user && user.remember_token? 
     111        cookies[:auth_token] = { :value => user.remember_token, :expires => user.remember_token_expires_at
     112        self.current_user = user 
     113      end 
    121114    end 
    122115end 
  • trunk/lib/authenticated_test_helper.rb

    r1 r293  
    22  # Sets the current user in the session from the user fixtures. 
    33  def login_as(user) 
    4     @request.session[:user] = user ? users(user).id : nil 
    5   end 
    6  
    7   def content_type(type) 
    8     @request.env['Content-Type'] = type 
    9   end 
    10  
    11   def accept(accept) 
    12     @request.env["HTTP_ACCEPT"] = accept 
     4    @request.session[:user_id] = user ? user.id : nil 
    135  end 
    146 
    157  def authorize_as(user) 
    16     if user 
    17       @request.env["HTTP_AUTHORIZATION"] = "Basic #{Base64.encode64("#{users(user).login}:test")}" 
    18       accept       'application/xml' 
    19       content_type 'application/xml' 
    20     else 
    21       @request.env["HTTP_AUTHORIZATION"] = nil 
    22       accept       nil 
    23       content_type nil 
    24     end 
    25   end 
    26  
    27   # http://project.ioni.st/post/217#post-217 
    28   # 
    29   #  def test_new_publication 
    30   #    assert_difference(Publication, :count) do 
    31   #      post :create, :publication => {...} 
    32   #      # ... 
    33   #    end 
    34   #  end 
    35   #  
    36   def assert_difference(object, method = nil, difference = 1) 
    37     initial_value = object.send(method) 
    38     yield 
    39     assert_equal initial_value + difference, object.send(method), "#{object}##{method}" 
    40   end 
    41  
    42   def assert_no_difference(object, method, &block) 
    43     assert_difference object, method, 0, &block 
    44   end 
    45  
    46   # Assert the block redirects to the login 
    47   #  
    48   #   assert_requires_login(:bob) { |c| c.get :edit, :id => 1 } 
    49   # 
    50   def assert_requires_login(login = nil) 
    51     yield HttpLoginProxy.new(self, login) 
    52   end 
    53  
    54   def assert_http_authentication_required(login = nil) 
    55     yield XmlLoginProxy.new(self, login) 
    56   end 
    57  
    58   def reset!(*instance_vars) 
    59     instance_vars = [:controller, :request, :response] unless instance_vars.any? 
    60     instance_vars.collect! { |v| "@#{v}".to_sym } 
    61     instance_vars.each do |var| 
    62       instance_variable_set(var, instance_variable_get(var).class.new) 
    63     end 
     8    @request.env["HTTP_AUTHORIZATION"] = user ? ActionController::HttpAuthentication::Basic.encode_credentials(user.login, 'test') : nil 
    649  end 
    6510end 
    66  
    67 class BaseLoginProxy 
    68   attr_reader :controller 
    69   attr_reader :options 
    70   def initialize(controller, login) 
    71     @controller = controller 
    72     @login      = login 
    73   end 
    74  
    75   private 
    76     def authenticated 
    77       raise NotImplementedError 
    78     end 
    79      
    80     def check 
    81       raise NotImplementedError 
    82     end 
    83      
    84     def method_missing(method, *args) 
    85       @controller.reset! 
    86       authenticate 
    87       @controller.send(method, *args) 
    88       check 
    89     end 
    90 end 
    91  
    92 class HttpLoginProxy < BaseLoginProxy 
    93   protected 
    94     def authenticate 
    95       @controller.login_as @login if @login 
    96     end 
    97      
    98     def check 
    99       @controller.assert_redirected_to :controller => 'account', :action => 'login' 
    100     end 
    101 end 
    102  
    103 class XmlLoginProxy < BaseLoginProxy 
    104   protected 
    105     def authenticate 
    106       @controller.accept 'application/xml' 
    107       @controller.authorize_as @login if @login 
    108     end 
    109      
    110     def check 
    111       @controller.assert_response 401 
    112     end 
    113 end 
  • trunk/script/spec

    r245 r293  
    11#!/usr/bin/env ruby 
    2 $LOAD_PATH.unshift(File.expand_path(File.dirname(__FILE__) + "/../vendor/plugins/rspec/lib")) 
     2require 'rubygems' 
    33require 'spec' 
    44exit ::Spec::Runner::CommandLine.run(::Spec::Runner::OptionParser.parse(ARGV, STDERR, STDOUT)) 
  • trunk/spec/controllers/author_controller_spec.rb

    r159 r293  
    4646 
    4747    get 'index' 
    48     response.should redirect_to(:controller => '/account', :action => 'login'
     48    response.should redirect_to(new_session_url
    4949  end 
    5050 
  • trunk/spec/controllers/meals_controller_spec.rb

    r233 r293  
    293293  it "should be authorized if the current user is an author" do 
    294294    @user.should_receive(:author?).and_return(false) 
    295     @controller.should_receive(:logged_in?).and_return(true) 
     295 
    296296    post 'update', :id => 7, :meal => { :foo => "bar" } 
    297     response.should redirect_to(:controller => '/account', :action => 'login'
     297    response.should redirect_to(new_session_url
    298298  end 
    299299end 
  • trunk/spec/controllers/recipes_controller_spec.rb

    r211 r293  
    315315  it "should be authorized if the current user is an author" do 
    316316    @user.should_receive(:author?).and_return(false) 
    317     @controller.should_receive(:logged_in?).and_return(true) 
    318317 
    319318    post 'update', :id => 7, :recipe => { :foo => "bar" } 
    320     response.should redirect_to(:controller => '/account', :action => 'login'
     319    response.should redirect_to(new_session_url
    321320  end 
    322321end 
  • trunk/spec/controllers/sessions_controller_spec.rb

    r264 r293  
    66 
    77describe SessionsController do 
    8   fixtures :users 
     8  before(:each) do 
     9    @user = User.create(:login                 => 'quentin', 
     10                        :email                 => 'nospam@eeecooks.com', 
     11                        :password              => 'test', 
     12                        :password_confirmation => 'test') 
     13  end 
    914 
    1015  it 'logins and redirects' do 
     
    2126 
    2227  it 'logs out' do 
    23     login_as :quentin 
     28    login_as @user 
    2429    get :destroy 
    2530    session[:user_id].should be_nil 
     
    3843 
    3944  it 'deletes token on logout' do 
    40     login_as :quentin 
     45    login_as @user 
    4146    get :destroy 
    4247    response.cookies["auth_token"].should == [] 
     
    4449 
    4550  it 'logs in with cookie' do 
    46     users(:quentin).remember_me 
    47     request.cookies["auth_token"] = cookie_for(:quentin
     51    @user.remember_me 
     52    request.cookies["auth_token"] = cookie_for(@user
    4853    get :new 
    4954    controller.send(:logged_in?).should be_true 
     
    5156 
    5257  it 'fails expired cookie login' do 
    53     users(:quentin).remember_me 
    54     users(:quentin).update_attribute :remember_token_expires_at, 5.minutes.ago 
    55     request.cookies["auth_token"] = cookie_for(:quentin
     58    @user.remember_me 
     59    @user.update_attribute :remember_token_expires_at, 5.minutes.ago 
     60    request.cookies["auth_token"] = cookie_for(@user
    5661    get :new 
    5762    controller.send(:logged_in?).should_not be_true 
     
    5964 
    6065  it 'fails cookie login' do 
    61     users(:quentin).remember_me 
     66    @user.remember_me 
    6267    request.cookies["auth_token"] = auth_token('invalid_auth_token') 
    6368    get :new 
     
    7075 
    7176  def cookie_for(user) 
    72     auth_token users(user).remember_token 
     77    auth_token user.remember_token 
    7378  end 
    7479end 
  • trunk/spec/helpers/application_helper_spec.rb

    r288 r293  
    131131  it "should do wiki by wikifying, then textilizing" do 
    132132    helper.should_receive(:wikify).with('text').and_return('wikified text') 
    133     helper.should_receive(:textilize).with('wikified text').and_return('textilized, wikified text') 
    134     helper.wiki('text').should == 'textilized, wikified text' 
     133    helper.wiki('text').should == '<p>wikified text</p>' 
    135134  end 
    136135 
    137136  it "should do wiki (without paragraph) by textilizing (without paragraph), then wikifying" do 
    138     helper.should_receive(:textilize_without_paragraph).with('xxx text').and_return('xxx textilized text') 
    139     helper.should_receive(:wikify).with('textilized text').and_return('wikified, textilized text') 
     137    helper.should_receive(:wikify).with('text').and_return('wikified, textilized text') 
    140138    helper.wiki_without_paragraph('text').should == 'wikified, textilized text' 
    141139  end