authenticated_system.rb
4.98 KB
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
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)
if session[:return_to]
redirect_to(session.delete(:return_to))
else
redirect_to(default)
end
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