Skip to content

Commit fc8827e

Browse files
author
ralf user
committed
Add missing lib
1 parent 2c8ff94 commit fc8827e

5 files changed

+504
-0
lines changed

lib/authenticated_system.rb

+189
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
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
7+
end
8+
9+
# Accesses the current user from the session.
10+
# Future calls avoid the database because nil is not equal to false.
11+
def current_user
12+
@current_user ||= (login_from_session || login_from_basic_auth || login_from_cookie) unless @current_user == false
13+
end
14+
15+
# Store the given user id in the session.
16+
def current_user=(new_user)
17+
session[:user_id] = new_user ? new_user.id : nil
18+
@current_user = new_user || false
19+
end
20+
21+
# Check if the user is authorized
22+
#
23+
# Override this method in your controllers if you want to restrict access
24+
# to only a few actions or if you want to check if the user
25+
# has the correct rights.
26+
#
27+
# Example:
28+
#
29+
# # only allow nonbobs
30+
# def authorized?
31+
# current_user.login != "bob"
32+
# end
33+
#
34+
def authorized?(action = action_name, resource = nil)
35+
logged_in?
36+
end
37+
38+
# Filter method to enforce a login requirement.
39+
#
40+
# To require logins for all actions, use this in your controllers:
41+
#
42+
# before_filter :login_required
43+
#
44+
# To require logins for specific actions, use this in your controllers:
45+
#
46+
# before_filter :login_required, :only => [ :edit, :update ]
47+
#
48+
# To skip this in a subclassed controller:
49+
#
50+
# skip_before_filter :login_required
51+
#
52+
def login_required
53+
authorized? || 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 |format|
66+
format.html do
67+
store_location
68+
redirect_to new_session_path
69+
end
70+
# format.any doesn't work in rails version < http://dev.rubyonrails.org/changeset/8987
71+
# Add any other API formats here. (Some browsers, notably IE6, send Accept: */* and trigger
72+
# the 'format.any' block incorrectly. See http://bit.ly/ie6_borken or http://bit.ly/ie6_borken2
73+
# for a workaround.)
74+
format.any(:json, :xml) do
75+
request_http_basic_authentication 'Web Password'
76+
end
77+
end
78+
end
79+
80+
# Store the URI of the current request in the session.
81+
#
82+
# We can return to this location by calling #redirect_back_or_default.
83+
def store_location
84+
session[:return_to] = request.request_uri
85+
end
86+
87+
# Redirect to the URI stored by the most recent store_location call or
88+
# to the passed default. Set an appropriately modified
89+
# after_filter :store_location, :only => [:index, :new, :show, :edit]
90+
# for any controller you want to be bounce-backable.
91+
def redirect_back_or_default(default)
92+
redirect_to(session[:return_to] || default)
93+
session[:return_to] = nil
94+
end
95+
96+
# Inclusion hook to make #current_user and #logged_in?
97+
# available as ActionView helper methods.
98+
def self.included(base)
99+
base.send :helper_method, :current_user, :logged_in?, :authorized? if base.respond_to? :helper_method
100+
end
101+
102+
#
103+
# Login
104+
#
105+
106+
# Called from #current_user. First attempt to login by the user id stored in the session.
107+
def login_from_session
108+
self.current_user = User.find_by_id(session[:user_id]) if session[:user_id]
109+
end
110+
111+
# Called from #current_user. Now, attempt to login by basic authentication information.
112+
def login_from_basic_auth
113+
authenticate_with_http_basic do |login, password|
114+
self.current_user = User.authenticate(login, password)
115+
end
116+
end
117+
118+
#
119+
# Logout
120+
#
121+
122+
# Called from #current_user. Finaly, attempt to login by an expiring token in the cookie.
123+
# for the paranoid: we _should_ be storing user_token = hash(cookie_token, request IP)
124+
def login_from_cookie
125+
user = cookies[:auth_token] && User.find_by_remember_token(cookies[:auth_token])
126+
if user && user.remember_token?
127+
self.current_user = user
128+
handle_remember_cookie! false # freshen cookie token (keeping date)
129+
self.current_user
130+
end
131+
end
132+
133+
# This is ususally what you want; resetting the session willy-nilly wreaks
134+
# havoc with forgery protection, and is only strictly necessary on login.
135+
# However, **all session state variables should be unset here**.
136+
def logout_keeping_session!
137+
# Kill server-side auth cookie
138+
@current_user.forget_me if @current_user.is_a? User
139+
@current_user = false # not logged in, and don't do it for me
140+
kill_remember_cookie! # Kill client-side auth cookie
141+
session[:user_id] = nil # keeps the session but kill our variable
142+
# explicitly kill any other session variables you set
143+
end
144+
145+
# The session should only be reset at the tail end of a form POST --
146+
# otherwise the request forgery protection fails. It's only really necessary
147+
# when you cross quarantine (logged-out to logged-in).
148+
def logout_killing_session!
149+
logout_keeping_session!
150+
reset_session
151+
end
152+
153+
#
154+
# Remember_me Tokens
155+
#
156+
# Cookies shouldn't be allowed to persist past their freshness date,
157+
# and they should be changed at each login
158+
159+
# Cookies shouldn't be allowed to persist past their freshness date,
160+
# and they should be changed at each login
161+
162+
def valid_remember_cookie?
163+
return nil unless @current_user
164+
(@current_user.remember_token?) &&
165+
(cookies[:auth_token] == @current_user.remember_token)
166+
end
167+
168+
# Refresh the cookie auth token if it exists, create it otherwise
169+
def handle_remember_cookie!(new_cookie_flag)
170+
return unless @current_user
171+
case
172+
when valid_remember_cookie? then @current_user.refresh_token # keeping same expiry date
173+
when new_cookie_flag then @current_user.remember_me
174+
else @current_user.forget_me
175+
end
176+
send_remember_cookie!
177+
end
178+
179+
def kill_remember_cookie!
180+
cookies.delete :auth_token
181+
end
182+
183+
def send_remember_cookie!
184+
cookies[:auth_token] = {
185+
:value => @current_user.remember_token,
186+
:expires => @current_user.remember_token_expires_at }
187+
end
188+
189+
end

lib/authenticated_test_helper.rb

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
module AuthenticatedTestHelper
2+
# Sets the current user in the session from the user fixtures.
3+
def login_as(user)
4+
@request.session[:user_id] = user ? (user.is_a?(User) ? user.id : users(user).id) : nil
5+
end
6+
7+
def authorize_as(user)
8+
@request.env["HTTP_AUTHORIZATION"] = user ? ActionController::HttpAuthentication::Basic.encode_credentials(users(user).login, 'monkey') : nil
9+
end
10+
11+
end

lib/hijacker.rb

+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Hijacker class
2+
#
3+
# This class is used by RoleRequirementTestHelper to temporarily hijack a controller action for testing
4+
#
5+
# Example usage:
6+
# hijacker = Hijacker.new(ListingsController)
7+
# hijacker.hijack_instance_method("index", "render :text => 'hello world!'" )
8+
# get :index # will return "hello world"
9+
# hijacker.restore # put things back the way you found it
10+
11+
class Hijacker
12+
def initialize(klass)
13+
@target_klass = klass
14+
@method_stores = {}
15+
end
16+
17+
def hijack_class_method(method_name, eval_string = nil, arg_names = [], &block)
18+
hijack_method(class_self_instance, method_name, eval_string, arg_names, &block )
19+
end
20+
21+
def hijack_instance_method(method_name, eval_string = nil, arg_names = [], &block)
22+
hijack_method(@target_klass, method_name, eval_string, arg_names, &block )
23+
end
24+
25+
# restore all
26+
def restore
27+
@method_stores.each_pair{|klass, method_stores|
28+
method_stores.reverse_each{ |method_name, method|
29+
klass.send :undef_method, method_name
30+
klass.send :define_method, method_name, method if method
31+
}
32+
}
33+
@method_stores.clear
34+
true
35+
rescue
36+
false
37+
end
38+
39+
protected
40+
41+
def class_self_instance
42+
@target_klass.send :eval, "class << self; self; end;"
43+
end
44+
45+
def hijack_method(klass, method_name, eval_string = nil, arg_names = [], &block)
46+
method_name = method_name.to_s
47+
# You have got love ruby! What other language allows you to pillage and plunder a class like this?
48+
49+
(@method_stores[klass]||=[]) << [
50+
method_name,
51+
klass.instance_methods.include?(method_name) && klass.instance_method(method_name)
52+
]
53+
54+
klass.send :undef_method, method_name
55+
if Symbol === eval_string
56+
klass.send :define_method, method_name, klass.instance_methods(eval_string)
57+
elsif String === eval_string
58+
klass.class_eval <<-EOF
59+
def #{method_name}(#{arg_names * ','})
60+
#{eval_string}
61+
end
62+
EOF
63+
elsif block_given?
64+
klass.send :define_method, method_name, block
65+
end
66+
67+
true
68+
rescue
69+
false
70+
end
71+
72+
end

0 commit comments

Comments
 (0)