sanitize-rails 0.5.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 +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
|
+
|