sanitize-rails 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +54 -0
- data/Rakefile +43 -0
- data/lib/sanitize/rails.rb +188 -0
- data/lib/sanitize/railtie.rb +19 -0
- metadata +93 -0
data/README.md
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
Sanitize-Rails - sanitize .. on Rails.
|
2
|
+
======================================
|
3
|
+
|
4
|
+
Installation
|
5
|
+
------------
|
6
|
+
|
7
|
+
gem install sanitize-rails
|
8
|
+
|
9
|
+
Configuration
|
10
|
+
-------------
|
11
|
+
|
12
|
+
config/initializers/sanitizer.rb:
|
13
|
+
|
14
|
+
Sanitize::Rails.configure(
|
15
|
+
:elements => [ ... ],
|
16
|
+
:attribiutes => { ... },
|
17
|
+
...
|
18
|
+
)
|
19
|
+
|
20
|
+
Usage
|
21
|
+
-----
|
22
|
+
|
23
|
+
app/models/foo.rb:
|
24
|
+
|
25
|
+
sanitizes :field
|
26
|
+
sanitizes :some_other_field, :on => :create
|
27
|
+
sanitizes :yet_another_field, :on => :save
|
28
|
+
|
29
|
+
ActionView `sanitize` helper is overriden to use
|
30
|
+
the Sanitize gem - transparently.
|
31
|
+
|
32
|
+
Testing
|
33
|
+
-------
|
34
|
+
|
35
|
+
Only Test::Unit for now - please write matchers
|
36
|
+
and send a pull request :-)
|
37
|
+
|
38
|
+
test/test\_helper:
|
39
|
+
|
40
|
+
Sanitize::Rails::TestHelpers.setup(self,
|
41
|
+
:invalid => 'some <a>string',
|
42
|
+
:valid => 'some <a>string</a>'
|
43
|
+
)
|
44
|
+
|
45
|
+
your test:
|
46
|
+
|
47
|
+
assert_sanitizes(Model, :field, :some_other_field)
|
48
|
+
|
49
|
+
Compatibility
|
50
|
+
-------------
|
51
|
+
|
52
|
+
Tested with Rails 3.0.x under Ruby 1.8 and 1.9.
|
53
|
+
|
54
|
+
Have fun.
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
|
4
|
+
require 'lib/sanitize/rails'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'jeweler'
|
8
|
+
Jeweler::Tasks.new do |gemspec|
|
9
|
+
gemspec.name = 'sanitize-rails'
|
10
|
+
|
11
|
+
gemspec.summary = 'A sanitizer bridge for Rails applications'
|
12
|
+
gemspec.authors = ['Marcello Barnaba']
|
13
|
+
gemspec.email = 'vjt@openssl.it'
|
14
|
+
gemspec.homepage = 'http://github.com/vjt/sanitize-rails'
|
15
|
+
|
16
|
+
gemspec.files = %w( README.md Rakefile rails/init.rb ) + Dir['lib/**/*']
|
17
|
+
gemspec.extra_rdoc_files = %w( README.md )
|
18
|
+
gemspec.has_rdoc = true
|
19
|
+
|
20
|
+
gemspec.version = Sanitize::Rails::Version
|
21
|
+
gemspec.require_path = 'lib'
|
22
|
+
|
23
|
+
gemspec.add_dependency('rails', '~> 3.0')
|
24
|
+
gemspec.add_dependency('sanitize')
|
25
|
+
end
|
26
|
+
rescue LoadError
|
27
|
+
puts 'Jeweler not available. Install it with: gem install jeweler'
|
28
|
+
end
|
29
|
+
|
30
|
+
desc 'Generate the rdoc'
|
31
|
+
Rake::RDocTask.new do |rdoc|
|
32
|
+
rdoc.rdoc_files.add %w( README.md lib/**/*.rb )
|
33
|
+
|
34
|
+
rdoc.main = 'README.md'
|
35
|
+
rdoc.title = 'Sanitizer-Rails'
|
36
|
+
end
|
37
|
+
|
38
|
+
desc 'Will someone help write tests?'
|
39
|
+
task :default do
|
40
|
+
puts
|
41
|
+
puts 'Can you help in writing tests? Please do :-)'
|
42
|
+
puts
|
43
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
# Sanitize gem bridge and helpers
|
2
|
+
#
|
3
|
+
require 'sanitize'
|
4
|
+
require 'sanitize/railtie' if defined? Rails
|
5
|
+
|
6
|
+
module Sanitize::Rails
|
7
|
+
Version = '0.5.0'
|
8
|
+
|
9
|
+
# Configures the sanitizer with the given `config` hash.
|
10
|
+
#
|
11
|
+
# In your environment.rb, in the after_initialize block:
|
12
|
+
#
|
13
|
+
# Sanitize::Rails.configure(
|
14
|
+
# :elements => [ ... ],
|
15
|
+
# :attributes => [ ... ],
|
16
|
+
# ...
|
17
|
+
# )
|
18
|
+
#
|
19
|
+
def self.configure(config)
|
20
|
+
Engine.configure(config)
|
21
|
+
end
|
22
|
+
|
23
|
+
module Engine
|
24
|
+
extend self
|
25
|
+
|
26
|
+
def configure(config)
|
27
|
+
@@config = config.freeze
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns a memoized instance of the Engine with the
|
31
|
+
# configuration passed to the +configure+ method or with
|
32
|
+
# the Gem default configuration.
|
33
|
+
#
|
34
|
+
def cleaner
|
35
|
+
@sanitizer ||= ::Sanitize.new(@@config || {})
|
36
|
+
end
|
37
|
+
|
38
|
+
# Returns a copy of the given `string` after sanitizing it
|
39
|
+
#
|
40
|
+
def clean(string)
|
41
|
+
string.dup.tap {|s| clean!(s)} unless string.blank?
|
42
|
+
end
|
43
|
+
|
44
|
+
# Sanitizes the given string in place, forcing UTF-8 encoding on it.
|
45
|
+
#
|
46
|
+
def clean!(string)
|
47
|
+
cleaner.clean!(string) unless string.blank?
|
48
|
+
end
|
49
|
+
|
50
|
+
def callback_for(options) #:nodoc:
|
51
|
+
point = (options[:on] || 'save').to_s
|
52
|
+
|
53
|
+
unless %w( save create ).include?(point)
|
54
|
+
raise ArgumentError, "Invalid callback point #{point}, valid ones are :save and :create"
|
55
|
+
end
|
56
|
+
|
57
|
+
"before_#{point}".intern
|
58
|
+
end
|
59
|
+
|
60
|
+
def method_for(fields) #:nodoc:
|
61
|
+
"sanitize_#{fields.join('_')}".intern
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
module ActionView
|
66
|
+
def self.included(base)
|
67
|
+
base.class_eval do
|
68
|
+
# To make sure we're called *after* the method is defined
|
69
|
+
undef_method :sanitize
|
70
|
+
|
71
|
+
# Overrides ActionView's sanitize() helper to use +Engine#clean+
|
72
|
+
def sanitize(string)
|
73
|
+
Engine.clean(string)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
# Adds the +sanitizes+ method to ActiveRecord children classes
|
81
|
+
#
|
82
|
+
module ActiveRecord
|
83
|
+
# Generates before_save/before_create filters that implement
|
84
|
+
# sanitization on the given fields, in the given callback
|
85
|
+
# point.
|
86
|
+
#
|
87
|
+
# Usage:
|
88
|
+
#
|
89
|
+
# sanitizes :some_field, :some_other_field #, :on => :save
|
90
|
+
#
|
91
|
+
# Valid callback points are :save and :create, callbacks are installed "before_"
|
92
|
+
# by default. Generated callbacks are named with the "sanitize_" prefix follwed
|
93
|
+
# by the field names separated by an underscore.
|
94
|
+
#
|
95
|
+
def sanitizes(*fields)
|
96
|
+
options = fields.extract_options!
|
97
|
+
callback = Engine.callback_for(options)
|
98
|
+
sanitizer = Engine.method_for(fields)
|
99
|
+
|
100
|
+
define_method(sanitizer) do # def sanitize_fieldA_fieldB
|
101
|
+
fields.each do |field| # # Unrolled version
|
102
|
+
sanitized = Engine.clean(send(field)) # self.fieldA = Engine.clean(self.fieldA)
|
103
|
+
send("#{field}=", sanitized) # self.fieldB = Engine.clean(self.fieldB)
|
104
|
+
end # # For clarity :-)
|
105
|
+
end # end
|
106
|
+
|
107
|
+
protected sanitizer # protected :sanitize_fieldA_fieldB
|
108
|
+
send callback, sanitizer # before_save :sanitize_fieldA_fieldB
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Adds two `sanitize_as_html{,!}` helpers to String itself,
|
113
|
+
# that call +Engine#clean+ or +Engine#clean!+ in turn
|
114
|
+
#
|
115
|
+
module String
|
116
|
+
# Calls +Engine#clean+ on this String instance
|
117
|
+
#
|
118
|
+
def sanitize_as_html
|
119
|
+
Engine.clean(self)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Calls +Engine#clean!+ on this String instance
|
123
|
+
#
|
124
|
+
def sanitize_as_html!
|
125
|
+
Engine.clean!(self)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Test instrumentation
|
130
|
+
#
|
131
|
+
module TestHelpers
|
132
|
+
class << self
|
133
|
+
# Instruments the given base class with the +assert_sanitizes+
|
134
|
+
# helper, and memoizes the given options, accessible from the
|
135
|
+
# helper itself via the +valid+ and +invalid+ methods.
|
136
|
+
#
|
137
|
+
# Those methods contains two HTML strings, one assumed to be
|
138
|
+
# "invalid" and the other, well, "valid".
|
139
|
+
#
|
140
|
+
# In your ActiveSupport::Testcase:
|
141
|
+
#
|
142
|
+
# Sanitize::Rails::TestHelpers.setup(self,
|
143
|
+
# :invalid => 'some <a>string',
|
144
|
+
# :valid => 'some <a>string</a>'
|
145
|
+
# )
|
146
|
+
#
|
147
|
+
def setup(base, options = {})
|
148
|
+
base.instance_eval { include TestHelpers }
|
149
|
+
@@options = options
|
150
|
+
end
|
151
|
+
|
152
|
+
def valid; @@options[:valid] rescue nil end
|
153
|
+
def invalid; @@options[:invalid] rescue nil end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Verifies that the given `klass` sanitizes the given `fields`, by
|
157
|
+
# checking both the presence of the sanitize callback and that it
|
158
|
+
# works as expected, by setting the +invalid+ string first, invoking
|
159
|
+
# the callback and then checking that the string has been changed
|
160
|
+
# into the +valid+ one.
|
161
|
+
#
|
162
|
+
# If you pass an Hash as the last argument, it can contain `:valid`,
|
163
|
+
# `:invalid` and `:object` keys. The first two ones override the
|
164
|
+
# configured defaults, while the third executes assertions on the
|
165
|
+
# specified object. If no :object is given, a new object is instantiated
|
166
|
+
# by the given `klass` with no arguments.
|
167
|
+
#
|
168
|
+
# If neither `:valid`/`:invalid` strings are configured nor are passed
|
169
|
+
# via the options, the two default strings in the method source are
|
170
|
+
# used.
|
171
|
+
#
|
172
|
+
def assert_sanitizes(klass, *fields)
|
173
|
+
options = fields.extract_options!
|
174
|
+
sanitizer = Engine.method_for(fields)
|
175
|
+
|
176
|
+
# Verify the callback works
|
177
|
+
invalid = options[:invalid] || TestHelpers.invalid || '<b>ntani<br>'
|
178
|
+
valid = options[:valid] || TestHelpers.valid || '<b>ntani<br /></b>'
|
179
|
+
object = options[:object] || klass.new
|
180
|
+
|
181
|
+
fields.each {|field| object.send("#{field}=", invalid) }
|
182
|
+
|
183
|
+
object.send sanitizer
|
184
|
+
|
185
|
+
fields.each {|field| assert_equal(valid, object.send(field)) }
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'sanitize/rails'
|
2
|
+
|
3
|
+
class Sanitize::Railtie < ::Rails::Railtie
|
4
|
+
initializer 'sanitize-rails.insert_into_action_view' do
|
5
|
+
ActiveSupport.on_load :action_view do
|
6
|
+
ActionView::Helpers::SanitizeHelper.instance_eval { include Sanitize::Rails::ActionView }
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
initializer 'sanitize-rails.insert_into_active_record' do
|
11
|
+
ActiveSupport.on_load :active_record do
|
12
|
+
ActiveRecord::Base.extend Sanitize::Rails::ActiveRecord
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
initializer 'sanitie-rails.insert_into_string' do
|
17
|
+
::String.instance_eval { include Sanitize::Rails::String }
|
18
|
+
end
|
19
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sanitize-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 5
|
8
|
+
- 0
|
9
|
+
version: 0.5.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Marcello Barnaba
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-03-29 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
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ~>
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 3
|
30
|
+
- 0
|
31
|
+
version: "3.0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: sanitize
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
segments:
|
43
|
+
- 0
|
44
|
+
version: "0"
|
45
|
+
type: :runtime
|
46
|
+
version_requirements: *id002
|
47
|
+
description:
|
48
|
+
email: vjt@openssl.it
|
49
|
+
executables: []
|
50
|
+
|
51
|
+
extensions: []
|
52
|
+
|
53
|
+
extra_rdoc_files:
|
54
|
+
- README.md
|
55
|
+
files:
|
56
|
+
- README.md
|
57
|
+
- Rakefile
|
58
|
+
- lib/sanitize/rails.rb
|
59
|
+
- lib/sanitize/railtie.rb
|
60
|
+
has_rdoc: true
|
61
|
+
homepage: http://github.com/vjt/sanitize-rails
|
62
|
+
licenses: []
|
63
|
+
|
64
|
+
post_install_message:
|
65
|
+
rdoc_options: []
|
66
|
+
|
67
|
+
require_paths:
|
68
|
+
- lib
|
69
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ">="
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
version: "0"
|
77
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
|
+
none: false
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
segments:
|
83
|
+
- 0
|
84
|
+
version: "0"
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 1.3.7
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: A sanitizer bridge for Rails applications
|
92
|
+
test_files: []
|
93
|
+
|