Skip to content
This repository has been archived by the owner. It is now read-only.

Commit aa2dded

Browse files
committed
[ssl_requirement plugin] add unit tests and ssl_allowed option (for actions that optionally support SSL)
1 parent 79ded84 commit aa2dded

File tree

3 files changed

+126
-11
lines changed

3 files changed

+126
-11
lines changed

README

+18-11
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
SSL Requirement
22
===============
33

4-
SSL requirement adds a declarative way of specifying that certain actions should
5-
only be allowed to run under SSL, and if they're accessed without it, they should
6-
be redirected.
7-
8-
The methods are: account_url, account_host, and account_domain.
4+
SSL requirement adds a declarative way of specifying that certain actions
5+
should only be allowed to run under SSL, and if they're accessed without it,
6+
they should be redirected.
97

108
Example:
119

@@ -15,6 +13,7 @@ Example:
1513

1614
class AccountController < ApplicationController
1715
ssl_required :signup, :payment
16+
ssl_allowed :index
1817

1918
def signup
2019
# Non-SSL access will be redirected to SSL
@@ -23,14 +22,22 @@ Example:
2322
def payment
2423
# Non-SSL access will be redirected to SSL
2524
end
25+
26+
def index
27+
# This action will work either with or without SSL
28+
end
29+
30+
def other
31+
# SSL access will be redirected to non-SSL
32+
end
2633
end
2734

28-
You can overwrite the protected method ssl_required? to rely on other things than
29-
just the declarative specification. Say, only premium accounts get SSL.
35+
You can overwrite the protected method ssl_required? to rely on other things
36+
than just the declarative specification. Say, only premium accounts get SSL.
3037

31-
P.S.: Beware when you include the SslRequirement module. At the time of inclusion,
32-
it'll add the before_filter that validates the declarations. Some times you'll want to
33-
run other before_filters before that. They should then be declared ahead of including
34-
this module.
38+
P.S.: Beware when you include the SslRequirement module. At the time of
39+
inclusion, it'll add the before_filter that validates the declarations. Some
40+
times you'll want to run other before_filters before that. They should then be
41+
declared ahead of including this module.
3542

3643
Copyright (c) 2005 David Heinemeier Hansson, released under the MIT license

lib/ssl_requirement.rb

+10
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,26 @@ module ClassMethods
2929
def ssl_required(*actions)
3030
write_inheritable_array(:ssl_required_actions, actions)
3131
end
32+
33+
def ssl_allowed(*actions)
34+
write_inheritable_array(:ssl_allowed_actions, actions)
35+
end
3236
end
3337

3438
protected
3539
# Returns true if the current action is supposed to run as SSL
3640
def ssl_required?
3741
(self.class.read_inheritable_attribute(:ssl_required_actions) || []).include?(action_name.to_sym)
3842
end
43+
44+
def ssl_allowed?
45+
(self.class.read_inheritable_attribute(:ssl_allowed_actions) || []).include?(action_name.to_sym)
46+
end
3947

4048
private
4149
def ensure_proper_protocol
50+
return true if ssl_allowed?
51+
4252
if ssl_required? && !request.ssl?
4353
redirect_to "https://" + request.host + request.request_uri
4454
return false

test/ssl_requirement_test.rb

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
begin
2+
require 'action_controller'
3+
rescue LoadError
4+
if ENV['ACTIONCONTROLLER_PATH'].nil?
5+
abort <<MSG
6+
Please set the ACTIONCONTROLLER_PATH environment variable to the directory
7+
containing the action_controller.rb file.
8+
MSG
9+
else
10+
$LOAD_PATH.unshift << ENV['ACTIONCONTROLLER_PATH']
11+
begin
12+
require 'action_controller'
13+
rescue LoadError
14+
abort "ActionController could not be found."
15+
end
16+
end
17+
end
18+
19+
require 'action_controller/test_process'
20+
require 'test/unit'
21+
require "#{File.dirname(__FILE__)}/../lib/ssl_requirement"
22+
23+
ActionController::Base.logger = nil
24+
ActionController::Routing::Routes.reload rescue nil
25+
26+
class SslRequirementController < ActionController::Base
27+
include SslRequirement
28+
29+
ssl_required :a, :b
30+
ssl_allowed :c
31+
32+
def a
33+
render :nothing => true
34+
end
35+
36+
def b
37+
render :nothing => true
38+
end
39+
40+
def c
41+
render :nothing => true
42+
end
43+
44+
def d
45+
render :nothing => true
46+
end
47+
end
48+
49+
class SslRequirementTest < Test::Unit::TestCase
50+
def setup
51+
@controller = SslRequirementController.new
52+
@request = ActionController::TestRequest.new
53+
@response = ActionController::TestResponse.new
54+
end
55+
56+
def test_required_without_ssl
57+
assert_not_equal "on", @request.env["HTTPS"]
58+
get :a
59+
assert_response :redirect
60+
assert_match %r{^https://}, @response.headers['location']
61+
get :b
62+
assert_response :redirect
63+
assert_match %r{^https://}, @response.headers['location']
64+
end
65+
66+
def test_required_with_ssl
67+
@request.env['HTTPS'] = "on"
68+
get :a
69+
assert_response :success
70+
get :b
71+
assert_response :success
72+
end
73+
74+
def test_disallowed_without_ssl
75+
assert_not_equal "on", @request.env["HTTPS"]
76+
get :d
77+
assert_response :success
78+
end
79+
80+
def test_disallowed_with_ssl
81+
@request.env['HTTPS'] = "on"
82+
get :d
83+
assert_response :redirect
84+
assert_match %r{^http://}, @response.headers['location']
85+
end
86+
87+
def test_allowed_without_ssl
88+
assert_not_equal "on", @request.env["HTTPS"]
89+
get :c
90+
assert_response :success
91+
end
92+
93+
def test_allowed_with_ssl
94+
@request.env['HTTPS'] = "on"
95+
get :c
96+
assert_response :success
97+
end
98+
end

0 commit comments

Comments
 (0)