Permalink
Browse files

Bugfix: make Sanitizy work for multiple configs

Sanitizy wasn't behaving appropriately when assigning different
allowable tags/attributes options on different columns. It does now.
  • Loading branch information...
1 parent d401fd3 commit db39cbbcf4bafcb9b82964b0ee707806e569c0e6 GIT_AUTHOR_NAME committed with GIT_AUTHOR_NAME Jan 28, 2009
Showing with 114 additions and 20 deletions.
  1. +45 −12 lib/sanitizy.rb
  2. +69 −8 spec/lib/sanitizy_spec.rb
View
@@ -1,32 +1,65 @@
module Sanitizy
+ class Sanitizer < HTML::WhiteListSanitizer
+ attr_reader :columns
+ def initialize(*columns)
+ @columns = columns
+ end
+ [:attributes,:tags].each do |acc|
+ class_eval <<-CODE
+ alias default_allowed_#{acc} allowed_#{acc}
+ def allowed_#{acc}
+ @allowed_#{acc} ||= default_allowed_#{acc}.dup
+ end
+ def allowed_#{acc}=(#{acc})
+ @allowed_#{acc} = Set.new(#{acc})
+ end
+ CODE
+ end
+ end
+
def self.included(base)
base.extend(ClassMethods)
base.before_save :sanitize_declared_columns
- base.class_inheritable_array :sanitizy_columns
+ base.class_inheritable_accessor :sanitizy_columns
+ base.sanitizy_columns = {}
end
module ClassMethods
def cleanse_columns(*columns, &block)
- self.sanitizy_columns = columns
- sanitizy_columns.each do |column|
- class_inheritable_accessor sanitizer_attr_name_for(column)
- send("#{self.sanitizer_attr_name_for(column)}=", HTML::WhiteListSanitizer.new)
- yield sanitizer_for(column)
+ columns.each do |column|
+ name = sanitizer_attr_name_for(column)
+ class_eval <<-CODE
+ def #{name}
+ self.class.sanitizy_columns["#{column}"]
+ end
+ def #{name}=(sanitizer)
+ self.class.sanitizy_columns["#{column}"] = sanitizer
+ end
+ CODE
end
+
+ sanitizer = Sanitizy::Sanitizer.new *columns
+ yield sanitizer
+ columns.each do |column|
+ self.sanitizy_columns[column.to_s] = sanitizer
+ end
+ sanitizer
end
+ alias cleanse_column cleanse_columns
def sanitizer_attr_name_for(column)
"#{column}_sanitizer"
end
-
- def sanitizer_for(column)
- send(sanitizer_attr_name_for(column))
- end
end
def sanitize_declared_columns
- self.class.sanitizy_columns.each do |column, options|
- self.send("#{column}=", self.class.sanitizer_for(column).sanitize(self.send(column)))
+ self.class.sanitizy_columns.each do |column, sanitizer|
+ options = {
+ :tags => sanitizer.allowed_tags.to_a,
+ :attributes => sanitizer.allowed_attributes.to_a
+ }
+ sanitized = sanitizer.sanitize(self.send(column), options)
+ self.send("#{column}=", sanitized)
end
end
end
View
@@ -1,34 +1,34 @@
require File.dirname(__FILE__) + '/../spec_helper'
# dummy class on which to test, just uses users table to avoisserrors
-class TestSanitizy < ActiveRecord::Base
+class SingularSanitizy < ActiveRecord::Base
include Sanitizy
set_table_name "news_items"
cleanse_columns(:video_embed) do |sanitizer|
- sanitizer.allowed_tags.replace(%w(object param embed a img))
- sanitizer.allowed_attributes.replace(%w(width height name src value allowFullScreen type href allowScriptAccess style wmode pluginspage classid codebase data quality))
+ sanitizer.allowed_tags = %w(object param embed a img)
+ sanitizer.allowed_attributes = %w(width height name src value allowFullScreen type href allowScriptAccess style wmode pluginspage classid codebase data quality)
end
end
describe "Sanitizy library" do
before do
- @sanitized = TestSanitizy.new
+ @sanitized = SingularSanitizy.new
end
describe "#cleanse_columns" do
it "should set a class attribute called 'video_embed_sanitizer'" do
- TestSanitizy.should respond_to(:video_embed_sanitizer)
+ @sanitized.should respond_to(:video_embed_sanitizer)
end
it "should create an instance of a sanitizer" do
@sanitized.sanitize_declared_columns
- TestSanitizy.video_embed_sanitizer.should be_an_instance_of(HTML::WhiteListSanitizer)
+ @sanitized.video_embed_sanitizer.should be_an_instance_of(Sanitizy::Sanitizer)
end
it "should set the allowed attributes on the sanitizer" do
@sanitized.sanitize_declared_columns
- TestSanitizy.video_embed_sanitizer.allowed_attributes.should_not be_empty
- TestSanitizy.video_embed_sanitizer.allowed_attributes.should be_a_kind_of(Set)
+ @sanitized.video_embed_sanitizer.allowed_attributes.should_not be_empty
+ @sanitized.video_embed_sanitizer.allowed_attributes.should be_a_kind_of(Set)
end
describe "sanitizing the contents of the field" do
@@ -77,3 +77,64 @@ class TestSanitizy < ActiveRecord::Base
end
+class MultipleSanitizy < ActiveRecord::Base
+ include Sanitizy
+ set_table_name 'news_items'
+ cleanse_column(:short_description) do |s|
+ s.allowed_tags = %w(baz quuz)
+ end
+ cleanse_column(:video_embed) do |s|
+ s.allowed_tags = %w(foo bar)
+ end
+end
+
+describe "Multiple sanitizers on a model" do
+ before do
+ @sanitized = MultipleSanitizy.new
+ end
+
+ it "should have two columns stored in self.class.sanitizy_columns" do
+ MultipleSanitizy.sanitizy_columns.size.should == 2
+ end
+
+ describe "short description" do
+ it "should only allow baz and quuz tags" do
+ @sanitized.short_description_sanitizer.allowed_tags.should == ['baz', 'quuz'].to_set
+ end
+ end
+ describe "video embed" do
+ it "should only allow foo and bar tags" do
+ @sanitized.video_embed_sanitizer.allowed_tags.should == ['foo', 'bar'].to_set
+ end
+
+ it "should be a new instance of a sanitizer" do
+ @sanitized.video_embed_sanitizer.should_not == @sanitized.short_description_sanitizer
+ end
+ end
+end
+
+class SetSanitizy < ActiveRecord::Base
+ include Sanitizy
+ set_table_name 'news_items'
+ cleanse_column(:short_description) do |s|
+ s.allowed_tags.delete('div')
+ end
+ cleanse_column(:video_embed) do |s|
+ s.allowed_tags.replace(['object'])
+ end
+end
+
+describe "when using Set operations" do
+ before do
+ @sanitized = SetSanitizy.new
+ end
+
+ it "should allow deleting tags" do
+ @sanitized.short_description_sanitizer.allowed_tags.should_not include('div')
+ end
+
+ it "should allow replacing tags" do
+ @sanitized.video_embed_sanitizer.allowed_tags.should == ['object'].to_set
+ end
+end
+

0 comments on commit db39cbb

Please sign in to comment.