| [1] | 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(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 |
|---|