]> projects.mako.cc - selectricity/blob - lib/authenticated_system.rb
840d89aac08c489ed964271dd262f20cf9318876
[selectricity] / lib / authenticated_system.rb
1 module AuthenticatedSystem
2   protected
3     # Returns true or false if the user is logged in.
4     # Preloads @current_user with the user model if they're logged in.
5     def logged_in?
6       current_user != :false
7     end
8     
9     # Accesses the current user from the session.
10     def current_user
11       @current_user ||= (session[:user] && User.find_by_id(session[:user])) || :false
12     end
13     
14     # Store the given user in the session.
15     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
18     end
19     
20     # Check if the user is authorized.
21     #
22     # Override this method in your controllers if you want to restrict access
23     # to only a few actions or if you want to check if the user
24     # has the correct rights.
25     #
26     # Example:
27     #
28     #  # only allow nonbobs
29     #  def authorize?
30     #    current_user.login != "bob"
31     #  end
32     def authorized?
33       true
34     end
35
36     # Filter method to enforce a login requirement.
37     #
38     # To require logins for all actions, use this in your controllers:
39     #
40     #   before_filter :login_required
41     #
42     # To require logins for specific actions, use this in your controllers:
43     #
44     #   before_filter :login_required, :only => [ :edit, :update ]
45     #
46     # To skip this in a subclassed controller:
47     #
48     #   skip_before_filter :login_required
49     #
50     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
54     end
55     
56     # Redirect as appropriate when an access request fails.
57     #
58     # The default action is to redirect to the login screen.
59     #
60     # Override this method in your controllers if you want to have special
61     # behavior in case the user is not authorized
62     # to access the requested action.  For example, a popup window might
63     # simply close itself.
64     def access_denied
65       respond_to do |accepts|
66         accepts.html do
67           store_location
68           redirect_to :controller => '/account', :action => 'login'
69         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'
74         end
75       end
76       false
77     end  
78     
79     # Store the URI of the current request in the session.
80     #
81     # We can return to this location by calling #redirect_back_or_default.
82     def store_location
83       session[:return_to] = request.request_uri
84     end
85     
86     # Redirect to the URI stored by the most recent store_location call or
87     # to the passed default.
88     def redirect_back_or_default(default)
89       session[:return_to] ? redirect_to_url(session[:return_to]) : redirect_to(default)
90       session[:return_to] = nil
91     end
92     
93     # Inclusion hook to make #current_user and #logged_in?
94     # available as ActionView helper methods.
95     def self.included(base)
96       base.send :helper_method, :current_user, :logged_in?
97     end
98
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         flash[:notice] = "Logged in successfully"
109       end
110     end
111
112   private
113     @@http_auth_headers = %w(X-HTTP_AUTHORIZATION HTTP_AUTHORIZATION Authorization)
114     # gets BASIC auth info
115     def get_auth_data
116       auth_key  = @@http_auth_headers.detect { |h| request.env.has_key?(h) }
117       auth_data = request.env[auth_key].to_s.split unless auth_key.blank?
118       return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nil, nil] 
119     end
120 end

Benjamin Mako Hill || Want to submit a patch?