module Hobo module AuthenticationSupport # Filter method to enforce a login requirement. def logged_in? not current_user.guest? 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 authorize? # current_user.login != "bob" # end def authorized? true end # # 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(user_model=nil) auth_model = user_model || User.default_user_model if current_user.guest? username, passwd = get_auth_data self.current_user = auth_model.authenticate(username, passwd) || nil if username && passwd && auth_model end if logged_in? && authorized? && (user_model.nil? || current_user.is_a?(user_model)) true else access_denied(auth_model) end 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(user_model) respond_to do |accepts| accepts.html do store_location redirect_to(login_url(user_model)) end accepts.xml do headers["Status"] = "Unauthorized" headers["WWW-Authenticate"] = %(Basic realm="Web Password") render :text => "Could't authenticate you", :status => '401 Unauthorized' end end false 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) session[:return_to] ? redirect_to(session[:return_to]) : redirect_to(default) session[:return_to] = nil end # When called with before_filter :login_from_cookie will check for an :auth_token # cookie and log the user back in if apropriate def login_from_cookie return unless (token = cookies[:auth_token]) && !logged_in? user_model = token[:user_model].constantize user = user_model.find_by_remember_token(token) if user && user.remember_token? user.remember_me current_user = user create_auth_cookie end end def create_auth_cookie cookies[:auth_token] = { :value => current_user.remember_token , :expires => current_user.remember_token_expires_at, :user_model => current_user.model } end private @@http_auth_headers = %w(X-HTTP_AUTHORIZATION HTTP_AUTHORIZATION Authorization) # gets BASIC auth info def get_auth_data auth_key = @@http_auth_headers.detect { |h| request.env.has_key?(h) } auth_data = request.env[auth_key].to_s.split unless auth_key.blank? username, pw = if auth_data && auth_data[0] == 'Basic' Base64.decode64(auth_data[1]).split(':')[0..1] else [nil, nil] end end end end