ssl_requirement 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,43 @@
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 < ActiveRecord::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
+ You can overwrite the protected method ssl_required? to rely on other things
36
+ than just the declarative specification. Say, only premium accounts get SSL.
37
+
38
+ P.S.: Beware when you include the SslRequirement module. At the time of
39
+ inclusion, it'll add the before_filter that validates the declarations. Some
40
+ times you'll want to run other before_filters before that. They should then be
41
+ declared ahead of including this module.
42
+
43
+ Copyright (c) 2005 David Heinemeier Hansson, released under the MIT license
@@ -0,0 +1,62 @@
1
+ # Copyright (c) 2005 David Heinemeier Hansson
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+ module SslRequirement
22
+ def self.included(controller)
23
+ controller.extend(ClassMethods)
24
+ controller.before_filter(:ensure_proper_protocol)
25
+ end
26
+
27
+ module ClassMethods
28
+ # Specifies that the named actions requires an SSL connection to be performed (which is enforced by ensure_proper_protocol).
29
+ def ssl_required(*actions)
30
+ write_inheritable_array(:ssl_required_actions, actions)
31
+ end
32
+
33
+ def ssl_allowed(*actions)
34
+ write_inheritable_array(:ssl_allowed_actions, actions)
35
+ end
36
+ end
37
+
38
+ protected
39
+ # Returns true if the current action is supposed to run as SSL
40
+ def ssl_required?
41
+ (self.class.read_inheritable_attribute(:ssl_required_actions) || []).include?(action_name.to_sym)
42
+ end
43
+
44
+ def ssl_allowed?
45
+ (self.class.read_inheritable_attribute(:ssl_allowed_actions) || []).include?(action_name.to_sym)
46
+ end
47
+
48
+ private
49
+ def ensure_proper_protocol
50
+ return true if ssl_allowed?
51
+
52
+ if ssl_required? && !request.ssl?
53
+ redirect_to "https://" + request.host + request.request_uri
54
+ flash.keep
55
+ return false
56
+ elsif request.ssl? && !ssl_required?
57
+ redirect_to "http://" + request.host + request.request_uri
58
+ flash.keep
59
+ return false
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,132 @@
1
+ begin
2
+ require 'action_controller'
3
+ rescue LoadError
4
+ if ENV['ACTIONCONTROLLER_PATH'].nil?
5
+ abort <<MSG
6
+ Please set the ACTIONCONTROLLER_PATH environment variable to the directory
7
+ containing the action_controller.rb file.
8
+ MSG
9
+ else
10
+ $LOAD_PATH.unshift << ENV['ACTIONCONTROLLER_PATH']
11
+ begin
12
+ require 'action_controller'
13
+ rescue LoadError
14
+ abort "ActionController could not be found."
15
+ end
16
+ end
17
+ end
18
+
19
+ require 'action_controller/test_process'
20
+ require 'test/unit'
21
+ require "#{File.dirname(__FILE__)}/../lib/ssl_requirement"
22
+
23
+ ActionController::Base.logger = nil
24
+ ActionController::Routing::Routes.reload rescue nil
25
+
26
+ class SslRequirementController < ActionController::Base
27
+ include SslRequirement
28
+
29
+ ssl_required :a, :b
30
+ ssl_allowed :c
31
+
32
+ def a
33
+ render :nothing => true
34
+ end
35
+
36
+ def b
37
+ render :nothing => true
38
+ end
39
+
40
+ def c
41
+ render :nothing => true
42
+ end
43
+
44
+ def d
45
+ render :nothing => true
46
+ end
47
+
48
+ def set_flash
49
+ flash[:foo] = "bar"
50
+ end
51
+ end
52
+
53
+ class SslRequirementTest < Test::Unit::TestCase
54
+ def setup
55
+ @controller = SslRequirementController.new
56
+ @request = ActionController::TestRequest.new
57
+ @response = ActionController::TestResponse.new
58
+ end
59
+
60
+ def test_redirect_to_https_preserves_flash
61
+ get :set_flash
62
+ get :b
63
+ assert_response :redirect
64
+ assert_equal "bar", flash[:foo]
65
+ end
66
+
67
+ def test_not_redirecting_to_https_does_not_preserve_the_flash
68
+ get :set_flash
69
+ get :d
70
+ assert_response :success
71
+ assert_nil flash[:foo]
72
+ end
73
+
74
+ def test_redirect_to_http_preserves_flash
75
+ get :set_flash
76
+ @request.env['HTTPS'] = "on"
77
+ get :d
78
+ assert_response :redirect
79
+ assert_equal "bar", flash[:foo]
80
+ end
81
+
82
+ def test_not_redirecting_to_http_does_not_preserve_the_flash
83
+ get :set_flash
84
+ @request.env['HTTPS'] = "on"
85
+ get :a
86
+ assert_response :success
87
+ assert_nil flash[:foo]
88
+ end
89
+
90
+ def test_required_without_ssl
91
+ assert_not_equal "on", @request.env["HTTPS"]
92
+ get :a
93
+ assert_response :redirect
94
+ assert_match %r{^https://}, @response.headers['Location']
95
+ get :b
96
+ assert_response :redirect
97
+ assert_match %r{^https://}, @response.headers['Location']
98
+ end
99
+
100
+ def test_required_with_ssl
101
+ @request.env['HTTPS'] = "on"
102
+ get :a
103
+ assert_response :success
104
+ get :b
105
+ assert_response :success
106
+ end
107
+
108
+ def test_disallowed_without_ssl
109
+ assert_not_equal "on", @request.env["HTTPS"]
110
+ get :d
111
+ assert_response :success
112
+ end
113
+
114
+ def test_disallowed_with_ssl
115
+ @request.env['HTTPS'] = "on"
116
+ get :d
117
+ assert_response :redirect
118
+ assert_match %r{^http://}, @response.headers['Location']
119
+ end
120
+
121
+ def test_allowed_without_ssl
122
+ assert_not_equal "on", @request.env["HTTPS"]
123
+ get :c
124
+ assert_response :success
125
+ end
126
+
127
+ def test_allowed_with_ssl
128
+ @request.env['HTTPS'] = "on"
129
+ get :c
130
+ assert_response :success
131
+ end
132
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ssl_requirement
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - David Heinemeier Hansson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-01-12 00:00:00 -06:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ 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.
17
+ email: david@loudthinking.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README
24
+ files:
25
+ - README
26
+ - lib/ssl_requirement.rb
27
+ - test/ssl_requirement_test.rb
28
+ has_rdoc: true
29
+ homepage: http://github.com/rails/ssl_requirement
30
+ licenses: []
31
+
32
+ post_install_message:
33
+ rdoc_options:
34
+ - --charset=UTF-8
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: "0"
42
+ version:
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: "0"
48
+ version:
49
+ requirements: []
50
+
51
+ rubyforge_project:
52
+ rubygems_version: 1.3.5
53
+ signing_key:
54
+ specification_version: 3
55
+ summary: SSL Requirement plugin
56
+ test_files:
57
+ - test/ssl_requirement_test.rb