revo-ssl_requirement 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ *.gem
data/README ADDED
@@ -0,0 +1,130 @@
1
+ SSL Requirement
2
+ ===============
3
+
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.
7
+
8
+ Example:
9
+
10
+ class ApplicationController < ActionController::Base
11
+ include SslRequirement
12
+ end
13
+
14
+ class AccountController < ApplicationController
15
+ ssl_required :signup, :payment
16
+ ssl_allowed :index
17
+
18
+ def signup
19
+ # Non-SSL access will be redirected to SSL
20
+ end
21
+
22
+ def payment
23
+ # Non-SSL access will be redirected to SSL
24
+ 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
33
+ end
34
+
35
+ If a majority (or all) of your actions require SSL, then use ssl_exceptions instead of ssl_required.
36
+ You can list out the actions that you do NOT want to be SSL protected. Calling ssl_exceptions without
37
+ any actions listed will make ALL actions SSL protected.
38
+
39
+ You can overwrite the protected method ssl_required? to rely on other things
40
+ than just the declarative specification. Say, only premium accounts get SSL.
41
+
42
+ For SSL domains that differ from the domain of the redirecting site, add the
43
+ following code to development.rb / test.rb / production.rb:
44
+
45
+ # Redirects to https://secure.example.com instead of the default
46
+ # https://www.example.com.
47
+ config.after_initialize do
48
+ SslRequirement.ssl_host = 'secure.example.com'
49
+ end
50
+
51
+ For non-SSL domains that differ from domain of redirecting site, add the
52
+ following code to development.rb / test.rb / production.rb:
53
+
54
+ # Redirects to http://nonsecure.example.com instead of the default
55
+ # http://www.example.com.
56
+ config.after_initialize do
57
+ SslRequirement.non_ssl_host = 'nonsecure.example.com'
58
+ end
59
+
60
+ You are able to turn disable ssl redirects by adding the following environment configuration file:
61
+
62
+ SslRequirement.disable_ssl_check = true
63
+
64
+ P.S.: Beware when you include the SslRequirement module. At the time of
65
+ inclusion, it'll add the before_filter that validates the declarations. Some
66
+ times you'll want to run other before_filters before that. They should then be
67
+ declared ahead of including this module.
68
+
69
+ SSL URL Helper
70
+ ==============
71
+ This plugin also adds a helper a :secure option to url_for and named_routes. This property
72
+ allows you to set a url as secure or not secure. It uses the disable_ssl_check to determine
73
+ if the option should be ignored or not so you can develop as normal. It also
74
+ will obey if you override SslRequirement.ssl_host or
75
+ SslRequirement.non_ssl_host (see above)
76
+
77
+ Here is an example of creating a secure url:
78
+
79
+ <%= url_for(:controller => "c", :action => "a", :secure => true) %>
80
+
81
+ If disable_ssl_check returns false url_for will return the following:
82
+
83
+ https://yoursite.com/c/a
84
+
85
+ Furthermore, you can use the secure option in a named route to create a secure form as follows:
86
+
87
+ <% form_tag session_path(:secure => true), :class => 'home_login' do -%>
88
+ <p>
89
+ <label for="name">Email</label>
90
+ <%= text_field_tag 'email', '', :class => 'text', :tabindex => 1 %>
91
+ </p>
92
+ <p>
93
+ <label for="password">Password</label>
94
+ <%= password_field_tag 'password', '', :class => 'text', :tabindex => 2 %>
95
+ </p>
96
+ <p>
97
+ <%= submit_tag "Login", :id => 'login_submit', :value => "", :alt => "Login" %>
98
+ </p>
99
+ <% end -%>
100
+
101
+ Testing with Shoulda
102
+ ====================
103
+
104
+ If you are using Shoulda, a few contexts and macros are provided:
105
+
106
+ class RegistrationsControllerTest < ActionController::TestCase
107
+ without_ssl_context do
108
+ context "GET to :new" do
109
+ setup do
110
+ get :new
111
+ end
112
+ should_redirect_to_ssl
113
+ end
114
+ end
115
+
116
+ with_ssl_context do
117
+ context "GET to :new" do
118
+ setup do
119
+ get :new
120
+ end
121
+ # your usual testing goes here
122
+ end
123
+ end
124
+ end
125
+
126
+
127
+ Copyright
128
+ =========
129
+
130
+ Copyright (c) 2005 David Heinemeier Hansson, released under the MIT license
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = "revo-ssl_requirement"
5
+ gemspec.summary = "Allow controller actions to force SSL on specific parts of the site."
6
+ gemspec.description = "SSL requirement adds a declarative way of specifying that certain actions should only be allowed to run under SSL, and if they're accessed without it, they should be redirected."
7
+ gemspec.email = 'percival@umamibud.com'
8
+ gemspec.homepage = 'http://github.com/revo/ssl_requirement'
9
+ gemspec.authors = ['RailsJedi', 'David Heinemeier Hansson', 'jcnetdev', 'bcurren', 'bmpercy']
10
+ end
11
+ rescue LoadError
12
+ puts "Jeweler not available. Install it with: gem install jeweler"
13
+ end
14
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.0
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + "/rails/init"
2
+
@@ -0,0 +1,86 @@
1
+ require "#{File.dirname(__FILE__)}/url_rewriter"
2
+
3
+ # Copyright (c) 2005 David Heinemeier Hansson
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ module SslRequirement
24
+ mattr_accessor :ssl_host, :non_ssl_host
25
+
26
+ def self.included(controller)
27
+ controller.extend(ClassMethods)
28
+ controller.before_filter(:ensure_proper_protocol)
29
+ end
30
+
31
+ def self.disable_ssl_check?
32
+ @@disable_ssl_check ||= false
33
+ end
34
+
35
+ def self.disable_ssl_check=(value)
36
+ @@disable_ssl_check = value
37
+ end
38
+
39
+ module ClassMethods
40
+ # Specifies that the named actions requires an SSL connection to be performed (which is enforced by ensure_proper_protocol).
41
+ def ssl_required(*actions)
42
+ write_inheritable_array(:ssl_required_actions, actions)
43
+ end
44
+
45
+ def ssl_exceptions(*actions)
46
+ write_inheritable_array(:ssl_required_except_actions, actions)
47
+ end
48
+
49
+ def ssl_allowed(*actions)
50
+ write_inheritable_array(:ssl_allowed_actions, actions)
51
+ end
52
+ end
53
+
54
+ protected
55
+ # Returns true if the current action is supposed to run as SSL
56
+ def ssl_required?
57
+ required = (self.class.read_inheritable_attribute(:ssl_required_actions) || [])
58
+ except = self.class.read_inheritable_attribute(:ssl_required_except_actions)
59
+
60
+ unless except
61
+ required.include?(action_name.to_sym)
62
+ else
63
+ !except.include?(action_name.to_sym)
64
+ end
65
+ end
66
+
67
+ def ssl_allowed?
68
+ (self.class.read_inheritable_attribute(:ssl_allowed_actions) || []).include?(action_name.to_sym)
69
+ end
70
+
71
+ private
72
+ def ensure_proper_protocol
73
+ return true if SslRequirement.disable_ssl_check?
74
+ return true if ssl_allowed?
75
+
76
+ if ssl_required? && !request.ssl?
77
+ redirect_to "https://" + (ssl_host || request.host) + request.request_uri
78
+ flash.keep
79
+ return false
80
+ elsif request.ssl? && !ssl_required?
81
+ redirect_to "http://" + (non_ssl_host || request.host) + request.request_uri
82
+ flash.keep
83
+ return false
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,49 @@
1
+ require 'action_controller/url_rewriter'
2
+
3
+ module ActionController
4
+ class UrlRewriter
5
+
6
+ # Add a secure option to the rewrite method.
7
+ def rewrite_with_secure_option(options = {})
8
+ secure = options.delete(:secure)
9
+
10
+ # if secure && ssl check is not disabled, convert to full url with https
11
+ if !secure.nil? && !SslRequirement.disable_ssl_check?
12
+ if secure == true || secure == 1 || secure.to_s.downcase == "true"
13
+ options.merge!({
14
+ :only_path => false,
15
+ :protocol => 'https'
16
+ })
17
+
18
+ # if we've been told to use different host for ssl, use it
19
+ unless SslRequirement.ssl_host.nil?
20
+ options.merge! :host => SslRequirement.ssl_host
21
+ end
22
+
23
+ # make it non-ssl and use specified options
24
+ else
25
+ options.merge!({
26
+ :protocol => 'http'
27
+ })
28
+ end
29
+ end
30
+
31
+ rewrite_without_secure_option(options)
32
+ end
33
+
34
+ # if full URL is requested for http and we've been told to use a
35
+ # non-ssl host override, then use it
36
+ def rewrite_with_non_ssl_host(options)
37
+ if !options[:only_path] && !SslRequirement.non_ssl_host.nil?
38
+ if !(/^https/ =~ (options[:protocol] || @request.protocol))
39
+ options.merge! :host => SslRequirement.non_ssl_host
40
+ end
41
+ end
42
+ rewrite_without_non_ssl_host(options)
43
+ end
44
+
45
+ # want with_secure_option to get run first (so chain it last)
46
+ alias_method_chain :rewrite, :non_ssl_host
47
+ alias_method_chain :rewrite, :secure_option
48
+ end
49
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'ssl_requirement'
@@ -0,0 +1,53 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{revo-ssl_requirement}
8
+ s.version = "1.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["RailsJedi", "David Heinemeier Hansson", "jcnetdev", "bcurren", "bmpercy"]
12
+ s.date = %q{2010-03-04}
13
+ s.description = %q{SSL requirement adds a declarative way of specifying that certain actions should only be allowed to run under SSL, and if they're accessed without it, they should be redirected.}
14
+ s.email = %q{percival@umamibud.com}
15
+ s.extra_rdoc_files = [
16
+ "README"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "README",
21
+ "Rakefile",
22
+ "VERSION",
23
+ "init.rb",
24
+ "lib/ssl_requirement.rb",
25
+ "lib/url_rewriter.rb",
26
+ "rails/init.rb",
27
+ "revo-ssl_requirement.gemspec",
28
+ "shoulda_macros/ssl_requirement_macros.rb",
29
+ "ssl_requirement.gemspec",
30
+ "test/ssl_requirement_test.rb",
31
+ "test/url_rewriter_test.rb"
32
+ ]
33
+ s.homepage = %q{http://github.com/revo/ssl_requirement}
34
+ s.rdoc_options = ["--charset=UTF-8"]
35
+ s.require_paths = ["lib"]
36
+ s.rubygems_version = %q{1.3.5}
37
+ s.summary = %q{Allow controller actions to force SSL on specific parts of the site.}
38
+ s.test_files = [
39
+ "test/url_rewriter_test.rb",
40
+ "test/ssl_requirement_test.rb"
41
+ ]
42
+
43
+ if s.respond_to? :specification_version then
44
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
45
+ s.specification_version = 3
46
+
47
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
48
+ else
49
+ end
50
+ else
51
+ end
52
+ end
53
+
@@ -0,0 +1,31 @@
1
+ Test::Unit::TestCase.class_eval do
2
+ def self.without_ssl_context
3
+ context "without ssl" do
4
+ setup do
5
+ @request.env['HTTPS'] = nil
6
+ end
7
+
8
+ context "" do
9
+ yield
10
+ end
11
+ end
12
+ end
13
+
14
+ def self.with_ssl_context
15
+ context "with ssl" do
16
+ setup do
17
+ @request.env['HTTPS'] = 'on'
18
+ end
19
+
20
+ context "" do
21
+ yield
22
+ end
23
+ end
24
+ end
25
+
26
+ def self.should_redirect_to_ssl
27
+ should 'redirect to ssl' do
28
+ assert_redirected_to "https://" + @request.host + @request.request_uri
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'revo-ssl_requirement'
3
+ s.version = '1.0.8'
4
+ s.date = '2009-06-22'
5
+
6
+ s.summary = "Allow controller actions to force SSL on specific parts of the site."
7
+ s.description = "SSL requirement adds a declarative way of specifying that certain actions should only be allowed to run under SSL, and if they're accessed without it, they should be redirected."
8
+
9
+ s.authors = ['RailsJedi', 'David Heinemeier Hansson', 'jcnetdev', 'bcurren', 'bmpercy']
10
+ s.email = 'percival@umamibud.com'
11
+ s.homepage = 'http://github.com/revo/ssl_requirement'
12
+
13
+ s.has_rdoc = true
14
+ s.rdoc_options = ["--main", "README"]
15
+ s.extra_rdoc_files = ["README"]
16
+
17
+ s.add_dependency 'rails', ['>= 2.2.2']
18
+
19
+ s.files = ["README",
20
+ "init.rb",
21
+ "lib/ssl_requirement.rb",
22
+ "lib/url_rewriter.rb",
23
+ "rails/init.rb",
24
+ "ssl_requirement.gemspec"]
25
+
26
+ s.test_files = ["test/ssl_requirement_test.rb",
27
+ "test/url_rewriter_test.rb"]
28
+ end
@@ -0,0 +1,300 @@
1
+ require 'set'
2
+ require 'rubygems'
3
+ require 'activesupport'
4
+ begin
5
+ require 'action_controller'
6
+ rescue LoadError
7
+ if ENV['ACTIONCONTROLLER_PATH'].nil?
8
+ abort <<MSG
9
+ Please set the ACTIONCONTROLLER_PATH environment variable to the directory
10
+ containing the action_controller.rb file.
11
+ MSG
12
+ else
13
+ $LOAD_PATH.unshift ENV['ACTIONCONTROLLER_PATH']
14
+ begin
15
+ require 'action_controller'
16
+ rescue LoadError
17
+ abort "ActionController could not be found."
18
+ end
19
+ end
20
+ end
21
+
22
+ require 'action_controller/test_process'
23
+ require 'test/unit'
24
+ require "#{File.dirname(__FILE__)}/../lib/ssl_requirement"
25
+
26
+ ActionController::Base.logger = nil
27
+ ActionController::Routing::Routes.reload rescue nil
28
+
29
+ # several test controllers to cover different combinations of requiring/
30
+ # allowing/exceptions-ing SSL for controller actions
31
+
32
+ # this first controller modifies the flash in every action so that flash
33
+ # set in set_flash is eventually expired (see NOTE below...)
34
+
35
+ class SslRequirementController < ActionController::Base
36
+ include SslRequirement
37
+
38
+ ssl_required :a, :b
39
+ ssl_allowed :c
40
+
41
+ def a
42
+ flash[:abar] = "foo"
43
+ render :nothing => true
44
+ end
45
+
46
+ def b
47
+ flash[:bbar] = "foo"
48
+ render :nothing => true
49
+ end
50
+
51
+ def c
52
+ flash[:cbar] = "foo"
53
+ render :nothing => true
54
+ end
55
+
56
+ def d
57
+ flash[:dbar] = "foo"
58
+ render :nothing => true
59
+ end
60
+
61
+ def set_flash
62
+ flash[:foo] = "bar"
63
+ end
64
+ end
65
+
66
+ class SslExceptionController < ActionController::Base
67
+ include SslRequirement
68
+
69
+ ssl_required :a
70
+ ssl_exceptions :b
71
+ ssl_allowed :d
72
+
73
+ def a
74
+ render :nothing => true
75
+ end
76
+
77
+ def b
78
+ render :nothing => true
79
+ end
80
+
81
+ def c
82
+ render :nothing => true
83
+ end
84
+
85
+ def d
86
+ render :nothing => true
87
+ end
88
+
89
+ end
90
+
91
+ class SslAllActionsController < ActionController::Base
92
+ include SslRequirement
93
+
94
+ ssl_exceptions
95
+
96
+ def a
97
+ render :nothing => true
98
+ end
99
+
100
+ end
101
+
102
+ # NOTE: The only way I could get the flash tests to work under Rails 2.3.2
103
+ # (without resorting to IntegrationTest with some artificial session
104
+ # store) was to use TestCase. In TestCases, it appears that flash
105
+ # messages are effectively persisted in session after the last controller
106
+ # action that consumed them...so that when the TestCase inspects
107
+ # the FlashHash, it will find the flash still populated, even though
108
+ # the subsequent controller action won't see it.
109
+ #
110
+ # In addition, if no changes are made to flash in subsequent requests, the
111
+ # flash is persisted forever. But if subsequent controller actions add to
112
+ # flash, the older flash messages eventually disappear.
113
+ #
114
+ # As a result, the flash-related tests now make two requests after the
115
+ # set_flash, each of these requests is also modifying flash. flash is
116
+ # inspected after the second request returns.
117
+ #
118
+ # This feels a little hacky, so if anyone can improve it, please do so!
119
+
120
+ class SslRequirementTest < ActionController::TestCase
121
+ def setup
122
+ @controller = SslRequirementController.new
123
+ @ssl_host_override = 'www.example.com:80443'
124
+ @non_ssl_host_override = 'www.example.com:8080'
125
+ end
126
+
127
+ # flash-related tests
128
+
129
+ def test_redirect_to_https_preserves_flash
130
+ assert_not_equal "on", @request.env["HTTPS"]
131
+ get :set_flash
132
+ get :b
133
+ assert_response :redirect # check redirect happens (flash still set)
134
+ get :b # get again to flush flash
135
+ assert_response :redirect # make sure it happens again
136
+ assert_equal "bar", flash[:foo] # the flash would be gone now if no redirect
137
+ end
138
+
139
+ def test_not_redirecting_to_https_does_not_preserve_the_flash
140
+ assert_not_equal "on", @request.env["HTTPS"]
141
+ get :set_flash
142
+ get :d
143
+ assert_response :success # check no redirect (flash still set)
144
+ get :d # get again to flush flash
145
+ assert_response :success # check no redirect
146
+ assert_nil flash[:foo] # the flash should be gone now
147
+ end
148
+
149
+ def test_redirect_to_http_preserves_flash
150
+ get :set_flash
151
+ @request.env['HTTPS'] = "on"
152
+ get :d
153
+ assert_response :redirect # check redirect happens (flash still set)
154
+ get :d # get again to flush flash
155
+ assert_response :redirect # make sure redirect happens
156
+ assert_equal "bar", flash[:foo] # flash would be gone now if no redirect
157
+ end
158
+
159
+ def test_not_redirecting_to_http_does_not_preserve_the_flash
160
+ get :set_flash
161
+ @request.env['HTTPS'] = "on"
162
+ get :a
163
+ assert_response :success # no redirect (flash still set)
164
+ get :a # get again to flush flash
165
+ assert_response :success # no redirect
166
+ assert_nil flash[:foo] # flash should be gone now
167
+ end
168
+
169
+ # ssl required/allowed/exceptions testing
170
+
171
+ def test_required_without_ssl
172
+ assert_not_equal "on", @request.env["HTTPS"]
173
+ get :a
174
+ assert_response :redirect
175
+ assert_match %r{^https://}, @response.headers['Location']
176
+ get :b
177
+ assert_response :redirect
178
+ assert_match %r{^https://}, @response.headers['Location']
179
+ end
180
+
181
+ def test_required_with_ssl
182
+ @request.env['HTTPS'] = "on"
183
+ get :a
184
+ assert_response :success
185
+ get :b
186
+ assert_response :success
187
+ end
188
+
189
+ def test_disallowed_without_ssl
190
+ assert_not_equal "on", @request.env["HTTPS"]
191
+ get :d
192
+ assert_response :success
193
+ end
194
+
195
+ def test_ssl_exceptions_without_ssl
196
+ @controller = SslExceptionController.new
197
+ assert_not_equal "on", @request.env["HTTPS"]
198
+ get :a
199
+ assert_response :redirect
200
+ assert_match %r{^https://}, @response.headers['Location']
201
+ get :b
202
+ assert_response :success
203
+ get :c # c is not explicity in ssl_required, but it is not listed in ssl_exceptions
204
+ assert_response :redirect
205
+ assert_match %r{^https://}, @response.headers['Location']
206
+ end
207
+
208
+ def test_ssl_exceptions_with_ssl
209
+ @controller = SslExceptionController.new
210
+ @request.env['HTTPS'] = "on"
211
+ get :a
212
+ assert_response :success
213
+ get :c
214
+ assert_response :success
215
+ end
216
+
217
+ def test_ssl_all_actions_without_ssl
218
+ @controller = SslAllActionsController.new
219
+ get :a
220
+ assert_response :redirect
221
+ assert_match %r{^https://}, @response.headers['Location']
222
+ end
223
+
224
+ def test_disallowed_with_ssl
225
+ @request.env['HTTPS'] = "on"
226
+ get :d
227
+ assert_response :redirect
228
+ assert_match %r{^http://}, @response.headers['Location']
229
+ end
230
+
231
+ def test_allowed_without_ssl
232
+ assert_not_equal "on", @request.env["HTTPS"]
233
+ get :c
234
+ assert_response :success
235
+ end
236
+
237
+ def test_allowed_with_ssl
238
+ @request.env['HTTPS'] = "on"
239
+ get :c
240
+ assert_response :success
241
+ end
242
+
243
+ def test_disable_ssl_check
244
+ SslRequirement.disable_ssl_check = true
245
+
246
+ assert_not_equal "on", @request.env["HTTPS"]
247
+ get :a
248
+ assert_response :success
249
+ get :b
250
+ assert_response :success
251
+ ensure
252
+ SslRequirement.disable_ssl_check = false
253
+ end
254
+
255
+ # testing overriding hostnames for ssl, non-ssl
256
+
257
+ # test for overriding (or not) the ssl_host and non_ssl_host variables
258
+ # using actions a (ssl required) and d (ssl not required or allowed)
259
+
260
+ def test_ssl_redirect_with_ssl_host
261
+ SslRequirement.ssl_host = @ssl_host_override
262
+ assert_not_equal "on", @request.env["HTTPS"]
263
+ get :a
264
+ assert_response :redirect
265
+ assert_match Regexp.new("^https://#{@ssl_host_override}"),
266
+ @response.headers['Location']
267
+ SslRequirement.ssl_host = nil
268
+ end
269
+
270
+ def test_ssl_redirect_without_ssl_host
271
+ SslRequirement.ssl_host = nil
272
+ assert_not_equal "on", @request.env["HTTPS"]
273
+ get :a
274
+ assert_response :redirect
275
+ assert_match Regexp.new("^https://"), @response.headers['Location']
276
+ assert_no_match Regexp.new("^https://#{@ssl_host_override}"),
277
+ @response.headers['Location']
278
+ end
279
+
280
+ def test_non_ssl_redirect_with_non_ssl_host
281
+ SslRequirement.non_ssl_host = @non_ssl_host_override
282
+ @request.env['HTTPS'] = 'on'
283
+ get :d
284
+ assert_response :redirect
285
+ assert_match Regexp.new("^http://#{@non_ssl_host_override}"),
286
+ @response.headers['Location']
287
+ SslRequirement.non_ssl_host = nil
288
+ end
289
+
290
+ def test_non_ssl_redirect_without_non_ssl_host
291
+ SslRequirement.non_ssl_host = nil
292
+ @request.env['HTTPS'] = 'on'
293
+ get :d
294
+ assert_response :redirect
295
+ assert_match Regexp.new("^http://"), @response.headers['Location']
296
+ assert_no_match Regexp.new("^http://#{@non_ssl_host_override}"),
297
+ @response.headers['Location']
298
+ end
299
+
300
+ end
@@ -0,0 +1,142 @@
1
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'rubygems'
4
+ require 'test/unit'
5
+ require 'action_controller'
6
+ require 'action_controller/test_process'
7
+
8
+ require "ssl_requirement"
9
+
10
+ # Show backtraces for deprecated behavior for quicker cleanup.
11
+ ActiveSupport::Deprecation.debug = true
12
+ ActionController::Base.logger = nil
13
+ ActionController::Routing::Routes.reload rescue nil
14
+
15
+ class UrlRewriterTest < Test::Unit::TestCase
16
+ def setup
17
+ @request = ActionController::TestRequest.new
18
+ @params = {}
19
+ @rewriter = ActionController::UrlRewriter.new(@request, @params)
20
+
21
+ @ssl_host_override = "www.example.com:80443"
22
+ @non_ssl_host_override = "www.example.com:8080"
23
+
24
+ SslRequirement.ssl_host = nil
25
+ SslRequirement.non_ssl_host = nil
26
+
27
+ puts @url_rewriter.to_s
28
+ end
29
+
30
+ def test_rewrite_secure_false
31
+ SslRequirement.disable_ssl_check = false
32
+ assert_equal('http://test.host/c/a',
33
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :secure => false)
34
+ )
35
+ assert_equal('/c/a',
36
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :secure => false,
37
+ :only_path => true)
38
+ )
39
+
40
+ SslRequirement.disable_ssl_check = true
41
+ assert_equal('http://test.host/c/a',
42
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :secure => false)
43
+ )
44
+ assert_equal('/c/a',
45
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :secure => false,
46
+ :only_path => true)
47
+ )
48
+ end
49
+
50
+ def test_rewrite_secure_true
51
+ SslRequirement.disable_ssl_check = false
52
+ assert_equal('https://test.host/c/a',
53
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :secure => true)
54
+ )
55
+ assert_equal('https://test.host/c/a',
56
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :secure => true, :only_path => true)
57
+ )
58
+
59
+ SslRequirement.disable_ssl_check = true
60
+ assert_equal('http://test.host/c/a',
61
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :secure => true)
62
+ )
63
+ assert_equal('/c/a',
64
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :secure => true, :only_path => true)
65
+ )
66
+ end
67
+
68
+ def test_rewrite_secure_not_specified
69
+ SslRequirement.disable_ssl_check = false
70
+ assert_equal('http://test.host/c/a',
71
+ @rewriter.rewrite(:controller => 'c', :action => 'a')
72
+ )
73
+ assert_equal('/c/a',
74
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :only_path => true)
75
+ )
76
+
77
+ SslRequirement.disable_ssl_check = true
78
+ assert_equal('http://test.host/c/a',
79
+ @rewriter.rewrite(:controller => 'c', :action => 'a')
80
+ )
81
+ assert_equal('/c/a',
82
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :only_path => true)
83
+ )
84
+ end
85
+
86
+ # tests for ssl_host overriding
87
+
88
+ def test_rewrite_secure_with_ssl_host
89
+ SslRequirement.disable_ssl_check = false
90
+ SslRequirement.ssl_host = @ssl_host_override
91
+ assert_equal("https://#{@ssl_host_override}/c/a",
92
+ @rewriter.rewrite(:controller => 'c', :action => 'a',
93
+ :secure => true))
94
+ assert_equal("https://#{@ssl_host_override}/c/a",
95
+ @rewriter.rewrite(:controller => 'c', :action => 'a',
96
+ :secure => true, :only_path => true))
97
+ SslRequirement.ssl_host = nil
98
+ end
99
+
100
+ def test_rewrite_non_secure_with_non_ssl_host
101
+ SslRequirement.disable_ssl_check = false
102
+ SslRequirement.non_ssl_host = @non_ssl_host_override
103
+
104
+ # with secure option
105
+ assert_equal("http://#{@non_ssl_host_override}/c/a",
106
+ @rewriter.rewrite(:controller => 'c', :action => 'a',
107
+ :secure => false))
108
+ assert_equal("/c/a",
109
+ @rewriter.rewrite(:controller => 'c', :action => 'a',
110
+ :secure => false, :only_path => true))
111
+
112
+ # without secure option
113
+ assert_equal("http://#{@non_ssl_host_override}/c/a",
114
+ @rewriter.rewrite(:controller => 'c', :action => 'a'))
115
+ assert_equal("/c/a",
116
+ @rewriter.rewrite(:controller => 'c', :action => 'a',
117
+ :only_path => true))
118
+ SslRequirement.non_ssl_host = nil
119
+ end
120
+
121
+ def test_rewrite_non_secure_with_non_ssl_host_disable_check
122
+ SslRequirement.disable_ssl_check = true
123
+ SslRequirement.non_ssl_host = @non_ssl_host_override
124
+
125
+ # with secure option
126
+ assert_equal("http://#{@non_ssl_host_override}/c/a",
127
+ @rewriter.rewrite(:controller => 'c', :action => 'a',
128
+ :secure => false))
129
+ assert_equal("/c/a",
130
+ @rewriter.rewrite(:controller => 'c', :action => 'a',
131
+ :secure => false, :only_path => true))
132
+
133
+ # without secure option
134
+ assert_equal("http://#{@non_ssl_host_override}/c/a",
135
+ @rewriter.rewrite(:controller => 'c', :action => 'a'))
136
+ assert_equal("/c/a",
137
+ @rewriter.rewrite(:controller => 'c', :action => 'a',
138
+ :only_path => true))
139
+ SslRequirement.non_ssl_host = nil
140
+ end
141
+
142
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: revo-ssl_requirement
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - RailsJedi
8
+ - David Heinemeier Hansson
9
+ - jcnetdev
10
+ - bcurren
11
+ - bmpercy
12
+ autorequire:
13
+ bindir: bin
14
+ cert_chain: []
15
+
16
+ date: 2010-03-04 00:00:00 +11:00
17
+ default_executable:
18
+ dependencies: []
19
+
20
+ description: SSL requirement adds a declarative way of specifying that certain actions should only be allowed to run under SSL, and if they're accessed without it, they should be redirected.
21
+ email: percival@umamibud.com
22
+ executables: []
23
+
24
+ extensions: []
25
+
26
+ extra_rdoc_files:
27
+ - README
28
+ files:
29
+ - .gitignore
30
+ - README
31
+ - Rakefile
32
+ - VERSION
33
+ - init.rb
34
+ - lib/ssl_requirement.rb
35
+ - lib/url_rewriter.rb
36
+ - rails/init.rb
37
+ - revo-ssl_requirement.gemspec
38
+ - shoulda_macros/ssl_requirement_macros.rb
39
+ - ssl_requirement.gemspec
40
+ - test/ssl_requirement_test.rb
41
+ - test/url_rewriter_test.rb
42
+ has_rdoc: true
43
+ homepage: http://github.com/revo/ssl_requirement
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --charset=UTF-8
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ requirements: []
64
+
65
+ rubyforge_project:
66
+ rubygems_version: 1.3.5
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: Allow controller actions to force SSL on specific parts of the site.
70
+ test_files:
71
+ - test/url_rewriter_test.rb
72
+ - test/ssl_requirement_test.rb