bcurren-ssl_requirement 1.0.3

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/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ require File.dirname(__FILE__) + "/rails/init"
2
+
@@ -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.included(controller)
31
+ controller.extend(ClassMethods)
32
+ controller.before_filter(:ensure_proper_protocol)
33
+ end
34
+
35
+ def self.disable_ssl_check?
36
+ @@disable_ssl_check ||= false
37
+ end
38
+
39
+ def self.disable_ssl_check=(value)
40
+ @@disable_ssl_check = value
41
+ end
42
+
43
+ module ClassMethods
44
+ # Specifies that the named actions requires an SSL connection to be performed (which is enforced by ensure_proper_protocol).
45
+ def ssl_required(*actions)
46
+ write_inheritable_array(:ssl_required_actions, actions)
47
+ end
48
+
49
+ def ssl_exceptions(*actions)
50
+ write_inheritable_array(:ssl_required_except_actions, actions)
51
+ end
52
+
53
+ def ssl_allowed(*actions)
54
+ write_inheritable_array(:ssl_allowed_actions, actions)
55
+ end
56
+ end
57
+
58
+ protected
59
+ # Returns true if the current action is supposed to run as SSL
60
+ def ssl_required?
61
+ required = (self.class.read_inheritable_attribute(:ssl_required_actions) || [])
62
+ except = self.class.read_inheritable_attribute(:ssl_required_except_actions)
63
+
64
+ unless except
65
+ required.include?(action_name.to_sym)
66
+ else
67
+ !except.include?(action_name.to_sym)
68
+ end
69
+ end
70
+
71
+ def ssl_allowed?
72
+ (self.class.read_inheritable_attribute(:ssl_allowed_actions) || []).include?(action_name.to_sym)
73
+ end
74
+
75
+ private
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,27 @@
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
+ if !secure.nil? && !SslRequirement.disable_ssl_check?
10
+ if secure == true || secure == 1 || secure.to_s.downcase == "true"
11
+ options.merge!({
12
+ :only_path => false,
13
+ :protocol => 'https'
14
+ })
15
+ else
16
+ options.merge!({
17
+ :only_path => false,
18
+ :protocol => 'http'
19
+ })
20
+ end
21
+ end
22
+
23
+ rewrite_without_secure_option(options)
24
+ end
25
+ alias_method_chain :rewrite, :secure_option
26
+ end
27
+ end
data/rails/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'ssl_requirement'
@@ -0,0 +1,27 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'ssl_requirement'
3
+ s.version = '1.0.3'
4
+ s.date = '2008-07-04'
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']
10
+ s.email = 'railsjedi@gmail.com'
11
+ s.homepage = 'http://github.com/jcnetdev/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.1']
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
+ 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
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bcurren-ssl_requirement
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.3
5
+ platform: ruby
6
+ authors:
7
+ - RailsJedi
8
+ - David Heinemeier Hansson
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2008-07-04 00:00:00 -07:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rails
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "2.1"
24
+ version:
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: railsjedi@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README
33
+ files:
34
+ - README
35
+ - init.rb
36
+ - lib/ssl_requirement.rb
37
+ - lib/url_rewriter.rb
38
+ - rails/init.rb
39
+ - ssl_requirement.gemspec
40
+ has_rdoc: true
41
+ homepage: http://github.com/jcnetdev/ssl_requirement
42
+ post_install_message:
43
+ rdoc_options:
44
+ - --main
45
+ - README
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.2.0
64
+ signing_key:
65
+ specification_version: 2
66
+ summary: Allow controller actions to force SSL on specific parts of the site.
67
+ test_files:
68
+ - test/ssl_requirement_test.rb