Don't show timeout message for empty diffs (ie. blank file added)
[gitorious.git] / lib / authenticated_system.rb
bloba6a04dd72105a0d26110a1abf4bb80139db38270
1 #--
2 #   Copyright (C) 2012-2014 Gitorious AS
4 #   This program is free software: you can redistribute it and/or modify
5 #   it under the terms of the GNU Affero General Public License as published by
6 #   the Free Software Foundation, either version 3 of the License, or
7 #   (at your option) any later version.
9 #   This program is distributed in the hope that it will be useful,
10 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
11 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 #   GNU Affero General Public License for more details.
14 #   You should have received a copy of the GNU Affero General Public License
15 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 #++
18 module AuthenticatedSystem
19   protected
20     # Returns true or false if the user is logged in.
21     # Preloads @current_user with the user model if they're logged in.
22     def logged_in?
23       !!current_user
24     end
26     # Accesses the current user from the session.
27     def current_user
28       return @current_user if instance_variable_defined?(:@current_user)
29       @current_user = login_from_session || login_from_basic_auth || login_from_cookie
30     end
32     # Store the given user in the session.
33     def current_user=(user)
34       if user
35         session[:user_id] = user.id
36         set_varnish_auth_cookie
37       else
38         session.delete(:user_id)
39         cookies.delete(:auth_token)
40         clear_varnish_auth_cookie
41       end
43       @current_user = user
44     end
46     def set_varnish_auth_cookie
47       cookies["_logged_in"] = {
48         :value => "true",
49         :domain => ".#{Gitorious.host}",
50         :expires => 3.weeks.from_now,
51         :httponly => true,
52         :secure => true
53       }
54     end
56     def clear_varnish_auth_cookie
57       cookies.delete "_logged_in", :domain => ".#{Gitorious.host}"
58     end
60     # Check if the user is authorized
61     #
62     # Override this method in your controllers if you want to restrict access
63     # to only a few actions or if you want to check if the user
64     # has the correct rights.
65     #
66     # Example:
67     #
68     #  # only allow nonbobs
69     #  def authorized?
70     #    current_user.login != "bob"
71     #  end
72     def authorized?
73       logged_in?
74     end
76     # Filter method to enforce a login requirement.
77     #
78     # To require logins for all actions, use this in your controllers:
79     #
80     #   before_filter :login_required
81     #
82     # To require logins for specific actions, use this in your controllers:
83     #
84     #   before_filter :login_required, :only => [ :edit, :update ]
85     #
86     # To skip this in a subclassed controller:
87     #
88     #   skip_before_filter :login_required
89     #
90     def login_required
91       authorized? || access_denied
92     end
94     # Redirect as appropriate when an access request fails.
95     #
96     # The default action is to redirect to the login screen.
97     #
98     # Override this method in your controllers if you want to have special
99     # behavior in case the user is not authorized
100     # to access the requested action.  For example, a popup window might
101     # simply close itself.
102     def access_denied
103       respond_to do |accepts|
104         accepts.html do
105           store_location
106           flash[:error] = "Action requires login"
107           redirect_to(main_app.new_sessions_path)
108         end
109         accepts.xml do
110           headers["Status"]           = "Unauthorized"
111           headers["WWW-Authenticate"] = %(Basic realm="Web Password")
112           render :text => "Could't authenticate you", :status => '401 Unauthorized'
113         end
114       end
115       false
116     end
118     # Store the URI of the current request in the session.
119     #
120     # We can return to this location by calling #redirect_back_or_default.
121     def store_location(location = request.fullpath)
122       session[:return_to] = location
123     end
125     # Redirect to the URI stored by the most recent store_location call or
126     # to the passed default.
127     def redirect_back_or_default(default)
128       session[:return_to] ? redirect_to(session[:return_to]) : redirect_to(default)
129       session[:return_to] = nil
130     end
132     # Inclusion hook to make #current_user and #logged_in?
133     # available as ActionView helper methods.
134     def self.included(base)
135       if base.respond_to?(:helper_method)
136         base.send(:helper_method, :current_user, :logged_in?)
137       end
138     end
140     # Called from #current_user.  First attempt to login by the user id stored in the session.
141     def login_from_session
142       self.current_user = User.find_by_id(session[:user_id], :conditions => { :suspended_at => nil }) if session[:user_id]
143     end
145     # Called from #current_user.  Now, attempt to login by basic authentication information.
146     def login_from_basic_auth
147       username, passwd = get_auth_data
148       self.current_user = User.authenticate(username, passwd) if username && passwd
149     end
151     # Called from #current_user.  Finaly, attempt to login by an expiring token in the cookie.
152     def login_from_cookie
153       user = cookies[:auth_token] && User.find_by_remember_token(cookies[:auth_token])
154       if user && user.remember_token?
155         user.remember_me
156         cookies[:auth_token] = {
157           :value => user.remember_token,
158           :expires => user.remember_token_expires_at,
159           :secure => true
160         }
161         self.current_user = user
162       end
163     end
165   private
166     @@http_auth_headers = %w(X-HTTP_AUTHORIZATION HTTP_AUTHORIZATION Authorization)
167     # gets BASIC auth info
168     def get_auth_data
169       auth_key  = @@http_auth_headers.detect { |h| request.env.has_key?(h) }
170       auth_data = request.env[auth_key].to_s.split unless auth_key.blank?
171       return auth_data && auth_data[0] == 'Basic' ? Base64.decode64(auth_data[1]).split(':')[0..1] : [nil, nil]
172     end