| Module | Systems::Authenticated |
| In: |
lib/systems/authenticated.rb
|
Inclusion hook to make current_user and logged_in? available as ActionView helper methods.
# File lib/systems/authenticated.rb, line 148
148: def self.included(base)
149: base.send :helper_method, :current_user, :logged_in?, :authorized? if base.respond_to? :helper_method
150: 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.
# File lib/systems/authenticated.rb, line 107
107: def access_denied(message = '')
108: respond_to do |format|
109: format.html do
110: store_location
111: flash.now[:error] = t('errors.restricted') + message
112: if request.xhr?
113: render :update do |page|
114: error(page, flash[:error], 0)
115: end
116: else
117: render :template => '/sessions/denied'
118: end
119: end
120: # format.any doesn't work in rails version < http://dev.rubyonrails.org/changeset/8987
121: # Add any other API formats here. (Some browsers, notably IE6, send Accept: */* and trigger
122: # the 'format.any' block incorrectly. See http://bit.ly/ie6_borken or http://bit.ly/ie6_borken2
123: # for a workaround.)
124: format.any(:json, :xml) do
125: request_http_basic_authentication 'Web Password'
126: end
127: end
128: end
# File lib/systems/authenticated.rb, line 37
37: def admin_required
38: redirect_back_or_default('/') unless admin_user?
39: # flash.now[:error] = "The Admin Section is temporarily partly disabled." if admin_user?
40: # redirect_back_or_default('/') unless super_user?
41: end
# File lib/systems/authenticated.rb, line 29
29: def admin_user?
30: @is_admin_user ||= logged_in? && current_user.admin?
31: 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
# File lib/systems/authenticated.rb, line 77
77: def authorized?(action = action_name, resource = nil)
78: logged_in?
79: end
Accesses the current user from the session. Future calls avoid the database because nil is not equal to false.
# File lib/systems/authenticated.rb, line 54
54: def current_user
55: @current_user ||= (login_from_session || login_from_basic_auth || login_from_cookie) unless @current_user == false
56: end
Store the given user id in the session.
# File lib/systems/authenticated.rb, line 59
59: def current_user=(new_user)
60: session[:user_id] = new_user ? new_user.id : nil
61: @current_user = new_user || false
62: end
# File lib/systems/authenticated.rb, line 43
43: def failed_logins(default = nil, &block)
44: logins = ::Param.first(:conditions => { :name => current_visit.ip_address })
45: logins ? yield(logins) : default
46: end
Refresh the cookie auth token if it exists, create it otherwise
# File lib/systems/authenticated.rb, line 219
219: def handle_remember_cookie!(new_cookie_flag)
220: return unless @current_user
221: case
222: when valid_remember_cookie? then @current_user.refresh_token # keeping same expiry date
223: when new_cookie_flag then @current_user.remember_me
224: else @current_user.forget_me
225: end
226: send_remember_cookie!
227: end
# File lib/systems/authenticated.rb, line 229
229: def kill_remember_cookie!
230: cookies.delete :auth_token
231: end
Returns true or false if the user is logged in. Preloads @current_user with the user model if they‘re logged in.
# File lib/systems/authenticated.rb, line 6 6: def logged_in? 7: !!current_user 8: end
# File lib/systems/authenticated.rb, line 48
48: def login_attempts
49: failed_logins(0) { |l| l.value.to_i }
50: end
Called from current_user. Now, attempt to login by basic authentication information.
# File lib/systems/authenticated.rb, line 162
162: def login_from_basic_auth
163: authenticate_with_http_basic do |login, password|
164: self.current_user = ::User.authenticate(login, password)
165: end
166: end
Called from current_user. Finaly, attempt to login by an expiring token in the cookie. for the paranoid: we should be storing user_token = hash(cookie_token, request IP)
# File lib/systems/authenticated.rb, line 174
174: def login_from_cookie
175: user = cookies[:auth_token] && ::User.find_by_remember_token(cookies[:auth_token])
176: if user && user.remember_token?
177: self.current_user = user
178: handle_remember_cookie! false # freshen cookie token (keeping date)
179: self.current_user
180: end
181: end
Called from current_user. First attempt to login by the user id stored in the session.
# File lib/systems/authenticated.rb, line 157
157: def login_from_session
158: self.current_user = ::User.find_by_id(session[:user_id]) if session[:user_id]
159: 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
# File lib/systems/authenticated.rb, line 95
95: def login_required(message = '')
96: authorized? || access_denied(message)
97: end
# File lib/systems/authenticated.rb, line 10
10: def login_required?(page)
11: nice_login_required if @@login_required[page] ||= ::Param.login_required?(page)
12: end
This is ususally what you want; resetting the session willy-nilly wreaks havoc with forgery protection, and is only strictly necessary on login. However, **all session state variables should be unset here**.
# File lib/systems/authenticated.rb, line 186
186: def logout_keeping_session!
187: # Kill server-side auth cookie
188: @current_user.forget_me if @current_user.is_a? User
189: @current_user = false # not logged in, and don't do it for me
190: kill_remember_cookie! # Kill client-side auth cookie
191: session[:user_id] = nil # keeps the session but kill our variable
192: # explicitly kill any other session variables you set
193: end
The session should only be reset at the tail end of a form POST — otherwise the request forgery protection fails. It‘s only really necessary when you cross quarantine (logged-out to logged-in).
# File lib/systems/authenticated.rb, line 198
198: def logout_killing_session!
199: logout_keeping_session!
200: reset_session
201: end
# File lib/systems/authenticated.rb, line 18
18: def logout_required
19: if logged_in?
20: flash.now[:error] = t('errors.logout')
21: redirect_to :root
22: end
23: end
# File lib/systems/authenticated.rb, line 14
14: def nice_login_required
15: login_required(render_to_string(:partial => 'shared/nice_deny'))
16: end
Redirect to the URI stored by the most recent store_location call or to the passed default. Set an appropriately modified after_filter :store_location, :only => [:index, :new, :show, :edit] for any controller you want to be bounce-backable.
# File lib/systems/authenticated.rb, line 141
141: def redirect_back_or_default(default)
142: redirect_to(session[:return_to] || default)
143: session[:return_to] = nil
144: end
# File lib/systems/authenticated.rb, line 233
233: def send_remember_cookie!
234: cookies[:auth_token] = {
235: :value => @current_user.remember_token,
236: :expires => @current_user.remember_token_expires_at }
237: end
Store the URI of the current request in the session.
We can return to this location by calling redirect_back_or_default.
# File lib/systems/authenticated.rb, line 133
133: def store_location
134: session[:return_to] = request.request_uri
135: end
# File lib/systems/authenticated.rb, line 33
33: def super_user_required
34: redirect_back_or_default('/') unless admin_user?
35: end
Cookies shouldn‘t be allowed to persist past their freshness date, and they should be changed at each login
# File lib/systems/authenticated.rb, line 212
212: def valid_remember_cookie?
213: return nil unless @current_user
214: (@current_user.remember_token?) &&
215: (cookies[:auth_token] == @current_user.remember_token)
216: end