quantipay-ssl_requirement 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,89 @@
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
+ You are able to turn disable ssl redirects by adding the following environment configuration file:
52
+ SslRequirement.disable_ssl_check = true
53
+
54
+ P.S.: Beware when you include the SslRequirement module. At the time of
55
+ inclusion, it'll add the before_filter that validates the declarations. Some
56
+ times you'll want to run other before_filters before that. They should then be
57
+ declared ahead of including this module.
58
+
59
+ SSL URL Helper
60
+ ==============
61
+ This plugin also adds a helper a :secure option to url_for and named_routes. This property
62
+ allows you to set a url as secure or not secure. It uses the disable_ssl_check to determine
63
+ if the option should be ignored or not so you can develop as normal.
64
+
65
+ Here is an example of creating a secure url:
66
+
67
+ <%= url_for(:controller => "c", :action => "a", :secure => true) %>
68
+
69
+ If disable_ssl_check returns false url_for will return the following:
70
+
71
+ https://yoursite.com/c/a
72
+
73
+ Furthermore, you can use the secure option in a named route to create a secure form as follows:
74
+
75
+ <% form_tag session_path(:secure => true), :class => 'home_login' do -%>
76
+ <p>
77
+ <label for="name">Email</label>
78
+ <%= text_field_tag 'email', '', :class => 'text', :tabindex => 1 %>
79
+ </p>
80
+ <p>
81
+ <label for="password">Password</label>
82
+ <%= password_field_tag 'password', '', :class => 'text', :tabindex => 2 %>
83
+ </p>
84
+ <p>
85
+ <%= submit_tag "Login", :id => 'login_submit', :value => "", :alt => "Login" %>
86
+ </p>
87
+ <% end -%>
88
+
89
+ Copyright (c) 2005 David Heinemeier Hansson, released under the MIT license
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ patch: 1
3
+ major: 1
4
+ minor: 1
@@ -0,0 +1,90 @@
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_reader :ssl_host
25
+
26
+ def self.ssl_host=(host)
27
+ @@ssl_host = host
28
+ end
29
+
30
+ def self.disable_ssl_check?
31
+ @@disable_ssl_check ||= false
32
+ end
33
+
34
+ def self.disable_ssl_check=(value)
35
+ @@disable_ssl_check = value
36
+ end
37
+
38
+ module ClassMethods
39
+ # Specifies that the named actions requires an SSL connection to be performed (which is enforced by ensure_proper_protocol).
40
+ def ssl_required(*actions)
41
+ write_inheritable_array(:ssl_required_actions, actions)
42
+ end
43
+
44
+ def ssl_exceptions(*actions)
45
+ write_inheritable_array(:ssl_required_except_actions, actions)
46
+ end
47
+
48
+ def ssl_allowed(*actions)
49
+ write_inheritable_array(:ssl_allowed_actions, actions)
50
+ end
51
+ end
52
+
53
+ protected
54
+ # Returns true if the current action is supposed to run as SSL
55
+ def ssl_required?
56
+ required = (self.class.read_inheritable_attribute(:ssl_required_actions) || [])
57
+ except = self.class.read_inheritable_attribute(:ssl_required_except_actions)
58
+
59
+ unless except
60
+ required.include?(action_name.to_sym)
61
+ else
62
+ !except.include?(action_name.to_sym)
63
+ end
64
+ end
65
+
66
+ def ssl_allowed?
67
+ (self.class.read_inheritable_attribute(:ssl_allowed_actions) || []).include?(action_name.to_sym)
68
+ end
69
+
70
+ private
71
+ def self.included(controller)
72
+ controller.extend(ClassMethods)
73
+ controller.before_filter(:ensure_proper_protocol)
74
+ end
75
+
76
+ def ensure_proper_protocol
77
+ return true if SslRequirement.disable_ssl_check?
78
+ return true if ssl_allowed?
79
+
80
+ if ssl_required? && !request.ssl?
81
+ redirect_to "https://" + (ssl_host || request.host) + request.request_uri
82
+ flash.keep
83
+ return false
84
+ elsif request.ssl? && !ssl_required?
85
+ redirect_to "http://" + request.host + request.request_uri
86
+ flash.keep
87
+ return false
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,25 @@
1
+ require 'action_controller/url_rewriter'
2
+ require 'action_controller/routing/optimisations'
3
+
4
+ module ActionController
5
+ class UrlRewriter
6
+ # Add a secure option to the rewrite method.
7
+ def rewrite_with_secure_option(options = {})
8
+ secure = options.delete(:secure)
9
+ options.merge!(:only_path => false, :protocol => secure ? 'https' : 'http') unless SslRequirement.disable_ssl_check?
10
+ rewrite_without_secure_option options
11
+ end
12
+ alias_method_chain :rewrite, :secure_option
13
+ end
14
+
15
+ module Routing
16
+ module Optimisation
17
+ class PositionalArgumentsWithAdditionalParams
18
+ def guard_conditions_with_secure_option
19
+ guard_conditions_without_secure_option + ['!args.last.has_key?(:secure)']
20
+ end
21
+ alias_method_chain :guard_conditions, :secure_option
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,220 @@
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
+ class SslRequirementController < ActionController::Base
30
+ include SslRequirement
31
+
32
+ ssl_required :a, :b
33
+ ssl_allowed :c
34
+
35
+ def a
36
+ render :nothing => true
37
+ end
38
+
39
+ def b
40
+ render :nothing => true
41
+ end
42
+
43
+ def c
44
+ render :nothing => true
45
+ end
46
+
47
+ def d
48
+ render :nothing => true
49
+ end
50
+
51
+ def set_flash
52
+ flash[:foo] = "bar"
53
+ end
54
+ end
55
+
56
+ class SslExceptionController < ActionController::Base
57
+ include SslRequirement
58
+
59
+ ssl_required :a
60
+ ssl_exceptions :b
61
+ ssl_allowed :d
62
+
63
+ def a
64
+ render :nothing => true
65
+ end
66
+
67
+ def b
68
+ render :nothing => true
69
+ end
70
+
71
+ def c
72
+ render :nothing => true
73
+ end
74
+
75
+ def d
76
+ render :nothing => true
77
+ end
78
+
79
+ def set_flash
80
+ flash[:foo] = "bar"
81
+ end
82
+ end
83
+
84
+ class SslAllActionsController < ActionController::Base
85
+ include SslRequirement
86
+
87
+ ssl_exceptions
88
+
89
+ def a
90
+ render :nothing => true
91
+ end
92
+
93
+ end
94
+
95
+ class SslRequirementTest < Test::Unit::TestCase
96
+ def setup
97
+ @controller = SslRequirementController.new
98
+ @request = ActionController::TestRequest.new
99
+ @response = ActionController::TestResponse.new
100
+ end
101
+
102
+ def test_redirect_to_https_preserves_flash
103
+ get :set_flash
104
+ get :b
105
+ assert_response :redirect
106
+ assert_equal "bar", flash[:foo]
107
+ end
108
+
109
+ def test_not_redirecting_to_https_does_not_preserve_the_flash
110
+ get :set_flash
111
+ get :d
112
+ assert_response :success
113
+ assert_nil flash[:foo]
114
+ end
115
+
116
+ def test_redirect_to_http_preserves_flash
117
+ get :set_flash
118
+ @request.env['HTTPS'] = "on"
119
+ get :d
120
+ assert_response :redirect
121
+ assert_equal "bar", flash[:foo]
122
+ end
123
+
124
+ def test_not_redirecting_to_http_does_not_preserve_the_flash
125
+ get :set_flash
126
+ @request.env['HTTPS'] = "on"
127
+ get :a
128
+ assert_response :success
129
+ assert_nil flash[:foo]
130
+ end
131
+
132
+ def test_required_without_ssl
133
+ assert_not_equal "on", @request.env["HTTPS"]
134
+ get :a
135
+ assert_response :redirect
136
+ assert_match %r{^https://}, @response.headers['Location']
137
+ get :b
138
+ assert_response :redirect
139
+ assert_match %r{^https://}, @response.headers['Location']
140
+ end
141
+
142
+ def test_required_with_ssl
143
+ @request.env['HTTPS'] = "on"
144
+ get :a
145
+ assert_response :success
146
+ get :b
147
+ assert_response :success
148
+ end
149
+
150
+ def test_disallowed_without_ssl
151
+ assert_not_equal "on", @request.env["HTTPS"]
152
+ get :d
153
+ assert_response :success
154
+ end
155
+
156
+ def test_ssl_exceptions_without_ssl
157
+ @controller = SslExceptionController.new
158
+ get :a
159
+ assert_response :redirect
160
+ assert_match %r{^https://}, @response.headers['Location']
161
+
162
+ get :b
163
+ assert_response :success
164
+
165
+ get :c # c is not explicity in ssl_required, but it is not listed in ssl_exceptions
166
+ assert_response :redirect
167
+ assert_match %r{^https://}, @response.headers['Location']
168
+ end
169
+
170
+ def test_ssl_exceptions_with_ssl
171
+ @controller = SslExceptionController.new
172
+ @request.env['HTTPS'] = "on"
173
+ get :a
174
+ assert_response :success
175
+
176
+ @request.env['HTTPS'] = "on"
177
+ get :c
178
+ assert_response :success
179
+ end
180
+
181
+ def test_ssl_all_actions_without_ssl
182
+ @controller = SslAllActionsController.new
183
+ get :a
184
+
185
+ assert_response :redirect
186
+ assert_match %r{^https://}, @response.headers['Location']
187
+ end
188
+
189
+ def test_disallowed_with_ssl
190
+ @request.env['HTTPS'] = "on"
191
+ get :d
192
+ assert_response :redirect
193
+ assert_match %r{^http://}, @response.headers['Location']
194
+ end
195
+
196
+ def test_allowed_without_ssl
197
+ assert_not_equal "on", @request.env["HTTPS"]
198
+ get :c
199
+ assert_response :success
200
+ end
201
+
202
+ def test_allowed_with_ssl
203
+ @request.env['HTTPS'] = "on"
204
+ get :c
205
+ assert_response :success
206
+ end
207
+
208
+ def test_disable_ssl_check
209
+ SslRequirement.disable_ssl_check = true
210
+
211
+ assert_not_equal "on", @request.env["HTTPS"]
212
+ get :a
213
+ assert_response :success
214
+ get :b
215
+ assert_response :success
216
+ ensure
217
+ SslRequirement.disable_ssl_check = false
218
+ end
219
+
220
+ end
@@ -0,0 +1,77 @@
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
+ puts @url_rewriter.to_s
22
+ end
23
+
24
+ def test_rewrite_secure_false
25
+ SslRequirement.disable_ssl_check = false
26
+ assert_equal('http://test.host/c/a',
27
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :secure => false)
28
+ )
29
+ assert_equal('http://test.host/c/a',
30
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :secure => false, :only_path => true)
31
+ )
32
+
33
+ SslRequirement.disable_ssl_check = true
34
+ assert_equal('http://test.host/c/a',
35
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :secure => false)
36
+ )
37
+ assert_equal('/c/a',
38
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :secure => false, :only_path => true)
39
+ )
40
+ end
41
+
42
+ def test_rewrite_secure_true
43
+ SslRequirement.disable_ssl_check = false
44
+ assert_equal('https://test.host/c/a',
45
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :secure => true)
46
+ )
47
+ assert_equal('https://test.host/c/a',
48
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :secure => true, :only_path => true)
49
+ )
50
+
51
+ SslRequirement.disable_ssl_check = true
52
+ assert_equal('http://test.host/c/a',
53
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :secure => true)
54
+ )
55
+ assert_equal('/c/a',
56
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :secure => true, :only_path => true)
57
+ )
58
+ end
59
+
60
+ def test_rewrite_secure_not_specified
61
+ SslRequirement.disable_ssl_check = false
62
+ assert_equal('http://test.host/c/a',
63
+ @rewriter.rewrite(:controller => 'c', :action => 'a')
64
+ )
65
+ assert_equal('/c/a',
66
+ @rewriter.rewrite(:controller => 'c', :action => 'a', :only_path => true)
67
+ )
68
+
69
+ SslRequirement.disable_ssl_check = true
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
+ end
77
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: quantipay-ssl_requirement
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.1
5
+ platform: ruby
6
+ authors:
7
+ - RailsJedi
8
+ - David Heinemeier Hansson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-02-19 00:00:00 -08:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rails
18
+ type: :runtime
19
+ version_requirement:
20
+ version_requirements: !ruby/object:Gem::Requirement
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "2.1"
25
+ version:
26
+ 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.
27
+ email: railsjedi@gmail.com
28
+ executables: []
29
+
30
+ extensions: []
31
+
32
+ extra_rdoc_files:
33
+ - README
34
+ files:
35
+ - VERSION.yml
36
+ - lib/ssl_requirement.rb
37
+ - lib/url_rewriter.rb
38
+ - test/ssl_requirement_test.rb
39
+ - test/url_rewriter_test.rb
40
+ - README
41
+ has_rdoc: true
42
+ homepage: http://github.com/tbmcmullen/ssl_requirement
43
+ post_install_message:
44
+ rdoc_options:
45
+ - --main
46
+ - README
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ requirements: []
62
+
63
+ rubyforge_project:
64
+ rubygems_version: 1.2.0
65
+ signing_key:
66
+ specification_version: 2
67
+ summary: Allow controller actions to force SSL on specific parts of the site.
68
+ test_files: []
69
+