panmind-sslhelper 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,100 @@
1
+ SSLHelper: an SSL plugin for Rails
2
+ ==================================
3
+
4
+ Purpose
5
+ -------
6
+
7
+ This plugin implements the same features as Rails' ssl_requirement plugin,
8
+ plus builds on existing named route helpers by adding `plain_` and `ssl_`
9
+ counterparts.
10
+
11
+ Installation
12
+ ------------
13
+
14
+ Via RubyGems:
15
+
16
+ gem install panmind-sslhelper
17
+
18
+ Or via Rails Plugin:
19
+
20
+ script/plugin install git://github.com/Panmind/ssl_helper.git
21
+
22
+ Usage
23
+ -----
24
+
25
+ After you get the plugin loaded, you'll have `plain_` and `ssl_` counterparts
26
+ to all your named route helpers, e.g.: `ssl_root_url` or `plain_user_url(user)`
27
+
28
+ You can use them in your views, controllers and functional tests, as they were
29
+ built in into the framework.
30
+
31
+ Views:
32
+
33
+ <%= link_to 'login', ssl_login_url %>
34
+ <%= link_to 'home', plain_root_url %>
35
+
36
+ Controllers:
37
+
38
+ def foo
39
+ redirect_to ssl_foos_url
40
+ end
41
+
42
+ Functionals:
43
+
44
+ context "an admin" do
45
+ should "access admin area only via SSL" do
46
+ setup { login_as @admin }
47
+
48
+ without_ssl do
49
+ get :index
50
+ assert_redirected_to ssl_admin_url
51
+ end
52
+
53
+ with_ssl do
54
+ get :index
55
+ assert_response :success
56
+ end
57
+ end
58
+ end
59
+
60
+ The additional `with_ssl`, `without_ssl`, `use_ssl` and `forget_ssl` are
61
+ available in your tests. The first two ones accept blocks evaluated with
62
+ SSL set or unset, the others set/unset SSL for a number of consecutive
63
+ tests (e.g. use them in your `setup` method).
64
+
65
+
66
+ Compatibility
67
+ -------------
68
+
69
+ Tested with Rails 2.3.8 running under Ruby 1.9.1-p378.
70
+
71
+
72
+ Server configuration
73
+ --------------------
74
+
75
+ The plugin relies on the HTTPS server variable, that is set automatically by
76
+ Rails if the `X-Forwarded-Proto` header is set to `https`. To avoid clients
77
+ setting that header, take care to add a `proxy_set_header` in your nginx
78
+ config file, such as:
79
+
80
+ server {
81
+ listen 80;
82
+ #
83
+ # your configuration
84
+ #
85
+ location / {
86
+ proxy_set_header X-Forwarded-Proto http;
87
+ }
88
+ }
89
+
90
+ server {
91
+ listen 443;
92
+ #
93
+ # your configuration
94
+ #
95
+ location / {
96
+ proxy_set_header X-Forwarded-Proto https;
97
+ }
98
+ }
99
+
100
+ For Apache, you're on your own for now :-) more documentation will follow!
data/Rakefile ADDED
@@ -0,0 +1,49 @@
1
+ require 'rake'
2
+ require 'rake/rdoctask'
3
+
4
+ require 'lib/panmind/ssl_helper'
5
+
6
+ begin
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |gemspec|
9
+ gemspec.name = 'panmind-sslhelper'
10
+
11
+ gemspec.summary = 'SSL requirement filters and SSL-aware named route helpers for Rails apps'
12
+ gemspec.description = 'SSLHelper provides controller helpers to require/refuse SSL onto ' \
13
+ 'specific actions, test helpers to verify controller behaviours ' \
14
+ 'and named route counterparts (e.g. ssl_login_url) to clean up your '\
15
+ 'view and controller code. HTTP(S) ports are configurable.'
16
+
17
+ gemspec.authors = ['Marcello Barnaba']
18
+ gemspec.email = 'vjt@openssl.it'
19
+ gemspec.homepage = 'http://github.com/Panmind/ssl_helper'
20
+
21
+ gemspec.files = %w( README.md Rakefile rails/init.rb ) + Dir['lib/**/*']
22
+ gemspec.extra_rdoc_files = %w( README.md )
23
+ gemspec.has_rdoc = true
24
+
25
+ gemspec.version = Panmind::SSLHelper::Version
26
+ gemspec.date = '2010-07-31'
27
+
28
+ gemspec.require_path = 'lib'
29
+
30
+ gemspec.add_dependency('rails', '>= 2.3.8')
31
+ end
32
+ rescue LoadError
33
+ puts 'Jeweler not available. Install it with: gem install jeweler'
34
+ end
35
+
36
+ desc 'Generate the rdoc'
37
+ Rake::RDocTask.new do |rdoc|
38
+ rdoc.rdoc_files.add %w( README.md lib/**/*.rb )
39
+
40
+ rdoc.main = 'README.md'
41
+ rdoc.title = 'SSL requirement filters and SSL-aware named route helpers for Rails apps'
42
+ end
43
+
44
+ desc 'Will someone help write tests?'
45
+ task :default do
46
+ puts
47
+ puts 'Can you help in writing tests? Please do :-)'
48
+ puts
49
+ end
@@ -0,0 +1,13 @@
1
+ module Panmind
2
+ module SSLHelper
3
+
4
+ class Railtie
5
+ def self.insert
6
+ ActionController::Routing::Routes.extend(Panmind::SSLHelper::Routing)
7
+ ActionController::Base.instance_eval { include Panmind::SSLHelper::Filters }
8
+ ActiveSupport::TestCase.instance_eval { include Panmind::SSLHelper::TestHelpers } if Rails.env.test?
9
+ end
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,181 @@
1
+ require 'panmind/ssl_helper/railtie'
2
+
3
+ module Panmind
4
+ module SSLHelper
5
+ Version = '0.8.0'
6
+
7
+ WITH_SSL = {:protocol => 'https'}
8
+ WITHOUT_SSL = {:protocol => 'http' }
9
+
10
+ def self.set(options = {})
11
+ return if Rails.env.test? # Because tests make assumptions we cannot break
12
+
13
+ https_port = (options[:https_port] || 443).to_i
14
+ http_port = (options[:http_port] || 80 ).to_i
15
+
16
+ # if we use non-standard ports we must explictly use them in the URIs
17
+ if https_port != 443 || http_port != 80
18
+ WITH_SSL.update(:port => https_port)
19
+ WITHOUT_SSL.update(:port => http_port)
20
+ end
21
+ end
22
+
23
+ module Routing
24
+ def reload!
25
+ returning super do
26
+ helpers = create_ssl_helpers
27
+ return unless helpers # Not ready yet.
28
+
29
+ classes = [
30
+ ActionController::Base,
31
+ ActionController::Integration::Session,
32
+ ActionController::TestCase,
33
+
34
+ ActionView::Base
35
+ ]
36
+
37
+ # Include the helper_module into each class to patch.
38
+ #
39
+ classes.each {|k| k.instance_eval { include helpers } }
40
+
41
+ # Set the helpers as public in the AC::Integration::Session class
42
+ # for easy testing in the console.
43
+ #
44
+ ActionController::Integration::Session.module_eval do
45
+ public *helpers.instance_methods
46
+ end
47
+ end
48
+ end
49
+
50
+ # Populates the @ssl_helpers module with ssl_ and plain_ helper
51
+ # counterparts for all defined named route helpers.
52
+ #
53
+ # Tries to use the ActionController::Routing::Routes private Rails
54
+ # API, falls back to regexp filtering if it is not available.
55
+ #
56
+ def create_ssl_helpers
57
+ @ssl_helpers ||= Module.new
58
+ return @ssl_helpers if @ssl_helpers.frozen?
59
+
60
+ route_helpers =
61
+ if defined? ActionController::Routing::Routes.named_routes.helpers
62
+ # This is a Private Rails API, so we check whether it's defined
63
+ # and reject all the hash_for_*() and the *_path() helpers.
64
+ #
65
+ ActionController::Routing::Routes.named_routes.helpers.
66
+ reject { |h| h.to_s =~ /(^hash_for)|(path$)/ }
67
+ else
68
+ # Warn the developer and fall back.
69
+ #
70
+ Rails.logger.warn "SSLHelper: AC::Routing::Routes.named_routes disappeared"
71
+ Rails.logger.warn "SSLHelper: falling back to filtering controller methods"
72
+
73
+ ac = ActionController::Base
74
+ skip = /(^hash_for_|^formatted_|polymorphic_|^redirect_)/
75
+ ac.instance_methods.grep(/_url$/) - ac.instance_methods.grep(skip)
76
+ end
77
+
78
+ return if route_helpers.empty?
79
+
80
+ # Create a Module containing all the ssl_ and plain_ helpers
81
+ # that: [1] alter the args they receive with the SSL options
82
+ # and [2] forward the altered args to the Rails' helper.
83
+ #
84
+ @ssl_helpers.module_eval do
85
+ route_helpers.each do |helper|
86
+ ssl, plain = "ssl_#{helper}", "plain_#{helper}"
87
+
88
+ define_method(ssl) { |*args| send(helper, *ssl_alter(args, WITH_SSL)) }
89
+ define_method(plain) { |*args| send(helper, *ssl_alter(args, WITHOUT_SSL)) }
90
+
91
+ protected ssl, plain
92
+ end
93
+
94
+ private
95
+ def ssl_alter(args, with) #:nodoc:
96
+ return args if Rails.env.development?
97
+
98
+ options = args.last.kind_of?(Hash) ? args.pop : {}
99
+ args.push(options.update(with))
100
+ end
101
+ end
102
+
103
+ # No further modification allowed.
104
+ #
105
+ @ssl_helpers.freeze
106
+ end
107
+
108
+ end # REST
109
+
110
+ module Filters
111
+ def self.included(base)
112
+ base.extend(ClassMethods)
113
+ end
114
+
115
+ module ClassMethods
116
+ def require_ssl(options = {})
117
+ return if Rails.env.development?
118
+
119
+ skip_before_filter :ssl_refused, options
120
+ before_filter :ssl_required, options
121
+ end
122
+
123
+ def ignore_ssl(options = {})
124
+ return if Rails.env.development?
125
+
126
+ skip_before_filter :ssl_required, options
127
+ skip_before_filter :ssl_refused, options
128
+ end
129
+
130
+ def refuse_ssl(options = {})
131
+ return if Rails.env.development?
132
+
133
+ skip_before_filter :ssl_required, options
134
+ before_filter :ssl_refused, options
135
+ end
136
+ end
137
+
138
+ protected
139
+ def ssl_required
140
+ redirect_to WITH_SSL.dup unless request.ssl?
141
+ end
142
+
143
+ def ssl_refused
144
+ redirect_to WITHOUT_SSL.dup if request.ssl?
145
+ end
146
+ end # Filters
147
+
148
+ module TestHelpers
149
+ def with_ssl(&block)
150
+ save_ssl_and do
151
+ use_ssl
152
+ block.call
153
+ end
154
+ end
155
+
156
+ def without_ssl(&block)
157
+ save_ssl_and do
158
+ forget_ssl
159
+ block.call
160
+ end
161
+ end
162
+
163
+ def use_ssl
164
+ @request.env['HTTPS'] = 'on'
165
+ @request.env['SERVER_PORT'] = 443
166
+ end
167
+
168
+ def forget_ssl
169
+ @request.env['HTTPS'] = nil
170
+ @request.env['SERVER_PORT'] = 80
171
+ end
172
+
173
+ protected
174
+ def save_ssl_and
175
+ https, port = @request.env.values_at(*%w(HTTPS SERVER_PORT))
176
+ yield
177
+ @request.env.update('HTTPS' => https, 'SERVER_PORT' => port)
178
+ end
179
+ end # TestHelpers
180
+ end # SSLHelper
181
+ end # Panmind
data/rails/init.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'panmind/ssl_helper/railtie'
2
+ Panmind::SSLHelper::Railtie.insert
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: panmind-sslhelper
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 8
8
+ - 0
9
+ version: 0.8.0
10
+ platform: ruby
11
+ authors:
12
+ - Marcello Barnaba
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-07-31 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rails
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 2
29
+ - 3
30
+ - 8
31
+ version: 2.3.8
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ description: SSLHelper provides controller helpers to require/refuse SSL onto specific actions, test helpers to verify controller behaviours and named route counterparts (e.g. ssl_login_url) to clean up your view and controller code. HTTP(S) ports are configurable.
35
+ email: vjt@openssl.it
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files:
41
+ - README.md
42
+ files:
43
+ - README.md
44
+ - Rakefile
45
+ - lib/panmind/ssl_helper.rb
46
+ - lib/panmind/ssl_helper/railtie.rb
47
+ - rails/init.rb
48
+ has_rdoc: true
49
+ homepage: http://github.com/Panmind/ssl_helper
50
+ licenses: []
51
+
52
+ post_install_message:
53
+ rdoc_options:
54
+ - --charset=UTF-8
55
+ require_paths:
56
+ - lib
57
+ required_ruby_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ segments:
62
+ - 0
63
+ version: "0"
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ segments:
69
+ - 0
70
+ version: "0"
71
+ requirements: []
72
+
73
+ rubyforge_project:
74
+ rubygems_version: 1.3.6
75
+ signing_key:
76
+ specification_version: 3
77
+ summary: SSL requirement filters and SSL-aware named route helpers for Rails apps
78
+ test_files: []
79
+