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 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
+