shenie-ssl_requirement 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -0,0 +1,14 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = "shenie-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.1.1
data/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + "/rails/init"
2
+
@@ -0,0 +1,119 @@
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
+
56
+ # Returns true if the current action is supposed to run as SSL
57
+ def ssl_required?
58
+ required = (self.class.read_inheritable_attribute(:ssl_required_actions) || [])
59
+ except = self.class.read_inheritable_attribute(:ssl_required_except_actions)
60
+
61
+ unless except
62
+ required.any? { |a| a == :all || a == action_name.to_sym }
63
+ else
64
+ !except.include?(action_name.to_sym)
65
+ end
66
+ end
67
+
68
+ def ssl_allowed?
69
+ (self.class.read_inheritable_attribute(:ssl_allowed_actions) || []).any? { |a| a == :all || a == action_name.to_sym }
70
+ end
71
+
72
+ # normal ports are the ports used when no port is specified by the user to the browser
73
+ # i.e. 80 if the protocol is http, 443 is the protocol is https
74
+ NORMAL_PORTS = [80, 443]
75
+
76
+ private
77
+ def ensure_proper_protocol
78
+ return true if SslRequirement.disable_ssl_check?
79
+ return true if ssl_allowed?
80
+
81
+ if ssl_required? && !request.ssl?
82
+ redirect_to determine_redirect_url(request, true)
83
+ flash.keep
84
+ return false
85
+ elsif request.ssl? && !ssl_required?
86
+ redirect_to determine_redirect_url(request, false)
87
+ flash.keep
88
+ return false
89
+ end
90
+ end
91
+
92
+ def determine_redirect_url(request, ssl)
93
+ protocol = ssl ? "https" : "http"
94
+ "#{protocol}://#{determine_host_and_port(request, ssl)}#{request.request_uri}"
95
+ end
96
+
97
+ def determine_host_and_port(request, ssl)
98
+ request_host = request.host
99
+ request_port = request.port
100
+
101
+ if ssl
102
+ "#{(ssl_host || request_host)}#{determine_port_string(request_port)}"
103
+ else
104
+ "#{(non_ssl_host || request_host)}#{determine_port_string(request_port)}"
105
+ end
106
+ end
107
+
108
+ def determine_port_string(port)
109
+ unless port_normal?(port)
110
+ ":#{port}"
111
+ else
112
+ ""
113
+ end
114
+ end
115
+
116
+ def port_normal?(port)
117
+ NORMAL_PORTS.include?(port)
118
+ end
119
+ 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
@@ -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{shenie-ssl_requirement}
8
+ s.version = "1.1.1"
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-08}
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
+ "shenie-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.6}
37
+ s.summary = %q{Allow controller actions to force SSL on specific parts of the site.}
38
+ s.test_files = [
39
+ "test/ssl_requirement_test.rb",
40
+ "test/url_rewriter_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,317 @@
1
+ require 'set'
2
+ require 'rubygems'
3
+ require 'active_support'
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
+ # port preservation tests
128
+
129
+ def test_redirect_to_https_preserves_non_normal_port
130
+ assert_not_equal "on", @request.env["HTTPS"]
131
+ @request.port = 4567
132
+ get :b
133
+ assert_response :redirect
134
+ assert_match %r{^https://.*:4567/}, @response.headers['Location']
135
+ end
136
+
137
+ def test_redirect_to_https_does_not_preserve_normal_port
138
+ assert_not_equal "on", @request.env["HTTPS"]
139
+ get :b
140
+ assert_response :redirect
141
+ assert_match %r{^https://.*[^:]/}, @response.headers['Location']
142
+ end
143
+
144
+ # flash-related tests
145
+
146
+ def test_redirect_to_https_preserves_flash
147
+ assert_not_equal "on", @request.env["HTTPS"]
148
+ get :set_flash
149
+ get :b
150
+ assert_response :redirect # check redirect happens (flash still set)
151
+ get :b # get again to flush flash
152
+ assert_response :redirect # make sure it happens again
153
+ assert_equal "bar", flash[:foo] # the flash would be gone now if no redirect
154
+ end
155
+
156
+ def test_not_redirecting_to_https_does_not_preserve_the_flash
157
+ assert_not_equal "on", @request.env["HTTPS"]
158
+ get :set_flash
159
+ get :d
160
+ assert_response :success # check no redirect (flash still set)
161
+ get :d # get again to flush flash
162
+ assert_response :success # check no redirect
163
+ assert_nil flash[:foo] # the flash should be gone now
164
+ end
165
+
166
+ def test_redirect_to_http_preserves_flash
167
+ get :set_flash
168
+ @request.env['HTTPS'] = "on"
169
+ get :d
170
+ assert_response :redirect # check redirect happens (flash still set)
171
+ get :d # get again to flush flash
172
+ assert_response :redirect # make sure redirect happens
173
+ assert_equal "bar", flash[:foo] # flash would be gone now if no redirect
174
+ end
175
+
176
+ def test_not_redirecting_to_http_does_not_preserve_the_flash
177
+ get :set_flash
178
+ @request.env['HTTPS'] = "on"
179
+ get :a
180
+ assert_response :success # no redirect (flash still set)
181
+ get :a # get again to flush flash
182
+ assert_response :success # no redirect
183
+ assert_nil flash[:foo] # flash should be gone now
184
+ end
185
+
186
+ # ssl required/allowed/exceptions testing
187
+
188
+ def test_required_without_ssl
189
+ assert_not_equal "on", @request.env["HTTPS"]
190
+ get :a
191
+ assert_response :redirect
192
+ assert_match %r{^https://}, @response.headers['Location']
193
+ get :b
194
+ assert_response :redirect
195
+ assert_match %r{^https://}, @response.headers['Location']
196
+ end
197
+
198
+ def test_required_with_ssl
199
+ @request.env['HTTPS'] = "on"
200
+ get :a
201
+ assert_response :success
202
+ get :b
203
+ assert_response :success
204
+ end
205
+
206
+ def test_disallowed_without_ssl
207
+ assert_not_equal "on", @request.env["HTTPS"]
208
+ get :d
209
+ assert_response :success
210
+ end
211
+
212
+ def test_ssl_exceptions_without_ssl
213
+ @controller = SslExceptionController.new
214
+ assert_not_equal "on", @request.env["HTTPS"]
215
+ get :a
216
+ assert_response :redirect
217
+ assert_match %r{^https://}, @response.headers['Location']
218
+ get :b
219
+ assert_response :success
220
+ get :c # c is not explicity in ssl_required, but it is not listed in ssl_exceptions
221
+ assert_response :redirect
222
+ assert_match %r{^https://}, @response.headers['Location']
223
+ end
224
+
225
+ def test_ssl_exceptions_with_ssl
226
+ @controller = SslExceptionController.new
227
+ @request.env['HTTPS'] = "on"
228
+ get :a
229
+ assert_response :success
230
+ get :c
231
+ assert_response :success
232
+ end
233
+
234
+ def test_ssl_all_actions_without_ssl
235
+ @controller = SslAllActionsController.new
236
+ get :a
237
+ assert_response :redirect
238
+ assert_match %r{^https://}, @response.headers['Location']
239
+ end
240
+
241
+ def test_disallowed_with_ssl
242
+ @request.env['HTTPS'] = "on"
243
+ get :d
244
+ assert_response :redirect
245
+ assert_match %r{^http://}, @response.headers['Location']
246
+ end
247
+
248
+ def test_allowed_without_ssl
249
+ assert_not_equal "on", @request.env["HTTPS"]
250
+ get :c
251
+ assert_response :success
252
+ end
253
+
254
+ def test_allowed_with_ssl
255
+ @request.env['HTTPS'] = "on"
256
+ get :c
257
+ assert_response :success
258
+ end
259
+
260
+ def test_disable_ssl_check
261
+ SslRequirement.disable_ssl_check = true
262
+
263
+ assert_not_equal "on", @request.env["HTTPS"]
264
+ get :a
265
+ assert_response :success
266
+ get :b
267
+ assert_response :success
268
+ ensure
269
+ SslRequirement.disable_ssl_check = false
270
+ end
271
+
272
+ # testing overriding hostnames for ssl, non-ssl
273
+
274
+ # test for overriding (or not) the ssl_host and non_ssl_host variables
275
+ # using actions a (ssl required) and d (ssl not required or allowed)
276
+
277
+ def test_ssl_redirect_with_ssl_host
278
+ SslRequirement.ssl_host = @ssl_host_override
279
+ assert_not_equal "on", @request.env["HTTPS"]
280
+ get :a
281
+ assert_response :redirect
282
+ assert_match Regexp.new("^https://#{@ssl_host_override}"),
283
+ @response.headers['Location']
284
+ SslRequirement.ssl_host = nil
285
+ end
286
+
287
+ def test_ssl_redirect_without_ssl_host
288
+ SslRequirement.ssl_host = nil
289
+ assert_not_equal "on", @request.env["HTTPS"]
290
+ get :a
291
+ assert_response :redirect
292
+ assert_match Regexp.new("^https://"), @response.headers['Location']
293
+ assert_no_match Regexp.new("^https://#{@ssl_host_override}"),
294
+ @response.headers['Location']
295
+ end
296
+
297
+ def test_non_ssl_redirect_with_non_ssl_host
298
+ SslRequirement.non_ssl_host = @non_ssl_host_override
299
+ @request.env['HTTPS'] = 'on'
300
+ get :d
301
+ assert_response :redirect
302
+ assert_match Regexp.new("^http://#{@non_ssl_host_override}"),
303
+ @response.headers['Location']
304
+ SslRequirement.non_ssl_host = nil
305
+ end
306
+
307
+ def test_non_ssl_redirect_without_non_ssl_host
308
+ SslRequirement.non_ssl_host = nil
309
+ @request.env['HTTPS'] = 'on'
310
+ get :d
311
+ assert_response :redirect
312
+ assert_match Regexp.new("^http://"), @response.headers['Location']
313
+ assert_no_match Regexp.new("^http://#{@non_ssl_host_override}"),
314
+ @response.headers['Location']
315
+ end
316
+
317
+ 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,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: shenie-ssl_requirement
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 1
8
+ - 1
9
+ version: 1.1.1
10
+ platform: ruby
11
+ authors:
12
+ - RailsJedi
13
+ - David Heinemeier Hansson
14
+ - jcnetdev
15
+ - bcurren
16
+ - bmpercy
17
+ autorequire:
18
+ bindir: bin
19
+ cert_chain: []
20
+
21
+ date: 2010-03-08 00:00:00 +11:00
22
+ default_executable:
23
+ dependencies: []
24
+
25
+ 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.
26
+ email: percival@umamibud.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README
33
+ files:
34
+ - .gitignore
35
+ - README
36
+ - Rakefile
37
+ - VERSION
38
+ - init.rb
39
+ - lib/ssl_requirement.rb
40
+ - lib/url_rewriter.rb
41
+ - rails/init.rb
42
+ - shenie-ssl_requirement.gemspec
43
+ - shoulda_macros/ssl_requirement_macros.rb
44
+ - ssl_requirement.gemspec
45
+ - test/ssl_requirement_test.rb
46
+ - test/url_rewriter_test.rb
47
+ has_rdoc: true
48
+ homepage: http://github.com/revo/ssl_requirement
49
+ licenses: []
50
+
51
+ post_install_message:
52
+ rdoc_options:
53
+ - --charset=UTF-8
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ segments:
61
+ - 0
62
+ version: "0"
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ segments:
68
+ - 0
69
+ version: "0"
70
+ requirements: []
71
+
72
+ rubyforge_project:
73
+ rubygems_version: 1.3.6
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: Allow controller actions to force SSL on specific parts of the site.
77
+ test_files:
78
+ - test/ssl_requirement_test.rb
79
+ - test/url_rewriter_test.rb