panmind-sslhelper 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +100 -0
- data/Rakefile +49 -0
- data/lib/panmind/ssl_helper/railtie.rb +13 -0
- data/lib/panmind/ssl_helper.rb +181 -0
- data/rails/init.rb +2 -0
- metadata +79 -0
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
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
|
+
|