revo-ssl_requirement 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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