ref: master
app/concerns/authenticated_system.rb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
module AuthenticatedSystem protected extend ActiveSupport::Concern included do if self < ActionController::Base around_filter :user_set_current before_filter :override_user before_filter :login_from_cookie end # Inclusion hook to make #current_user and #logged_in? # available as ActionView helper methods. helper_method :current_user, :logged_in? end # Returns true or false if the user is logged in. # Preloads @current_user with the user model if they're logged in. def logged_in? current_user != nil end # Accesses the current user from the session. def current_user user_id = session[:user] @current_user ||= begin user = User.find_by id: user_id if user_id user.session = session if user User.current = user user end end # Store the given user in the session. def current_user=(new_user) if new_user.nil? session.delete(:user) else session[:user] = new_user.id new_user.session = session new_user.register_login end @current_user = User.current = new_user end # See impl. from http://stackoverflow.com/a/2513456/670229 def user_set_current User.current = current_user yield ensure # to address the thread variable leak issues in Puma/Thin webserver User.current = nil 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 # 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 # def login_required username, passwd = get_auth_data if username && passwd self.current_user ||= User.authenticate(username, passwd) || nil end if logged_in? && authorized? true else if params[:require_login_popup] render :json => { :require_login_popup => true } else access_denied end 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 respond_to do |accepts| accepts.html do if request.xhr? render :text => _('Access denied'), :status => 401 else store_location redirect_to :controller => '/account', :action => 'login' end 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(location = request.url) session[:return_to] = location end # Redirect to the URI stored by the most recent store_location call or # to the passed default. def redirect_back_or_default(default) uri = session.delete(:return_to) || default # break cache after login if uri.is_a? String uri = URI.parse uri new_query_ar = URI.decode_www_form(uri.query || '') << ["_", Time.now.to_i.to_s] uri.query = URI.encode_www_form new_query_ar uri = uri.to_s elsif uri.is_a? Hash uri.merge! _: Time.now.to_i end redirect_to uri end def override_user return if params[:override_user].blank? return unless logged_in? and user.is_admin? environment @current_user = nil current_user params[:override_user] end def override_user return if params[:override_user].blank? return unless logged_in? and user.is_admin? environment @current_user = nil current_user params[:override_user] 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 if cookies[:auth_token].blank? or logged_in? user = User.where(remember_token: cookies[:auth_token]).first self.current_user = user if user and user.remember_token? 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? return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nil, nil] end end |